From 56299fa5018e0c3abc145be3d31588232c295e59 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Sat, 3 Dec 2011 12:58:47 -0500 Subject: [PATCH] commit bash-20040702 snapshot --- CHANGES | 21 + CHANGES~ | 124 +- CWRU/CWRU.chlog | 49 + CWRU/CWRU.chlog~ | 49 + NEWS | 15 +- NEWS~ | 7 + bashline.c | 32 +- bashline.c~ | 28 +- doc/FAQ-3.0 | 1791 ++++++++++++ doc/FAQ-3.0~ | 1771 ++++++++++++ doc/bashref.info | 260 +- doc/texinfo.tex | 6689 +++++++++++++++++++++++++++++++++++++++++++- execute_cmd.c | 9 + execute_cmd.c~ | 12 +- lib/readline/ansi_stdlib.h | 55 +- lib/readline/complete.c | 3 +- lib/readline/complete.c~ | 2189 +++++++++++++++ lib/readline/doc/fdl.texi | 453 ++- lib/readline/posixdir.h | 62 +- lib/readline/posixjmp.h | 41 +- lib/readline/posixstat.h | 143 +- lib/readline/tilde.c | 459 ++- lib/readline/tilde.h | 79 +- parser-built | 52 + po/Rules-builtins | 2 +- po/en@boldquot.gmo | Bin 119955 -> 120143 bytes po/en@boldquot.po | 14 +- po/en@quot.gmo | Bin 118403 -> 118583 bytes po/en@quot.po | 14 +- subst.c | 28 +- subst.c~ | 13 +- support/mkconffiles | 0 support/mkversion.sh | 0 support/rlvers.sh | 0 tests/run-read | 2 + variables.c | 4 + variables.c~ | 20 +- y.tab.c | 2737 +++++++++--------- y.tab.h | 90 +- 39 files changed, 15617 insertions(+), 1700 deletions(-) create mode 100644 doc/FAQ-3.0 create mode 100644 doc/FAQ-3.0~ mode change 120000 => 100644 doc/texinfo.tex mode change 120000 => 100644 lib/readline/ansi_stdlib.h create mode 100644 lib/readline/complete.c~ mode change 120000 => 100644 lib/readline/doc/fdl.texi mode change 120000 => 100644 lib/readline/posixdir.h mode change 120000 => 100644 lib/readline/posixjmp.h mode change 120000 => 100644 lib/readline/posixstat.h mode change 120000 => 100644 lib/readline/tilde.c mode change 120000 => 100644 lib/readline/tilde.h mode change 100644 => 100755 support/mkconffiles mode change 100644 => 100755 support/mkversion.sh mode change 100644 => 100755 support/rlvers.sh diff --git a/CHANGES b/CHANGES index 3f5ae28..32d62fd 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,19 @@ o. Fixed a problem with calls to getcwd() so that bash now operates better p. The `trap' builtin now reports an error if a single non-signal argument is specified. +q. Fixed a bug that caused `umask' to not work correctly when presented + with a mask of all 0s. + +r. When `getopts' reaches the end of options, OPTARG is unset, as POSIX + appears to specify. + +s. Interactive mode now depends on whether or not stdin and stderr are + connected to a tty; formerly it was stdin and stdout. POSIX requires + this. + +t. Fixed vi-mode completion to work more as POSIX specifies (e.g., doing the + right kind of filename generation). + 2. Changes to Readline a. Fixed a problem that could cause readline to refer to freed memory when @@ -69,6 +82,9 @@ d. Fixed a bug in vi-mode that caused multi-digit count arguments to work e. Fixed a problem in vi-mode that caused the last text modification command to not be remembered across different command lines. +f. Fixed problems with changing characters and changing case at the end of + the line. + 3. New Features in Bash a. The `jobs', `kill', and `wait' builtins now accept job control notation @@ -78,6 +94,11 @@ b. The historical behavior of `trap' that allows a missing `action' argument to cause each specified signal's handling to be reset to its default is now only supported when `trap' is given a single non-option argument. +4. New Features in Readline + +a. When listing completions, directories have a `/' appended if the + `mark-directories' option has been enabled. + ------------------------------------------------------------------------------ This document details the changes between this version, bash-3.0-beta1, and the previous version, bash-3.0-alpha. diff --git a/CHANGES~ b/CHANGES~ index acc4cec..32d62fd 100644 --- a/CHANGES~ +++ b/CHANGES~ @@ -1,3 +1,105 @@ +This document details the changes between this version, bash-3.0-rc1, +and the previous version, bash-3.0-beta1. + +1. Changes to Bash + +a. Fixed a bug that caused incorrect behavior when referecing element 0 of + an array using $array, element 0 was unset, and `set -u' was enabled. + +b. System-specific changes for: SCO Unix 3.2, Tandem. + +c. Fixed a bug that caused inappropriate word splitting when a variable was + expanded within a double-quoted string that also included $@. + +d. Fixed a bug that caused `pwd' to not display anything in physical mode + when the file system had changed underneath the shell. + +e. Fixed a bug in the pre- and post- increment and decrement parsing in the + expression evaluator that caused errors when the operands and corresponding + operators were separated by whitespace. + +f. Fixed a bug that caused `history -p' to add an entry to the history list, + counter to the documentation. (Keeps the history expansions invoked by + emacs-mode command line editing from doing that as well.) + +g. Fixed a bug that could cause a core dump if `cd' is asked to print out a + pathname longer than PATH_MAX characters. + +h. Fixed a bug that caused jobs to be put into the wrong process group under + some circumstances after enabling job control with `set -m'. + +i. `unalias' now returns failure if no alias name arguments are supplied. + +j. Documented the characters not allowed to appear in an alias name. + +k. $* is no longer expanded as if in double quotes when it appears in the + body of a here document, as the SUS seems to require. + +l. The `bashbug' script now uses a directory in $TMPDIR for exclusive + access rather than trying to guess how the underlying OS provides for + secure temporary file creation. + +m. Fixed a few problems with `cd' and `pwd' when asked to operate on pathnames + longer than PATH_MAX characters. + +n. Fixed a memory leak caused when creating multiple local array variables + with identical names. + +o. Fixed a problem with calls to getcwd() so that bash now operates better + when the full pathname to the current directory is longer than PATH_MAX + bytes. + +p. The `trap' builtin now reports an error if a single non-signal argument + is specified. + +q. Fixed a bug that caused `umask' to not work correctly when presented + with a mask of all 0s. + +r. When `getopts' reaches the end of options, OPTARG is unset, as POSIX + appears to specify. + +s. Interactive mode now depends on whether or not stdin and stderr are + connected to a tty; formerly it was stdin and stdout. POSIX requires + this. + +t. Fixed vi-mode completion to work more as POSIX specifies (e.g., doing the + right kind of filename generation). + +2. Changes to Readline + +a. Fixed a problem that could cause readline to refer to freed memory when + moving between history lines while doing searches. + +b. Improvements to the code that expands and displays prompt strings + containing multibyte characters. + +c. Fixed a problem with vi-mode not correctly remembering the numeric argument + to the last `c'hange command for later use with `.'. + +d. Fixed a bug in vi-mode that caused multi-digit count arguments to work + incorrectly. + +e. Fixed a problem in vi-mode that caused the last text modification command + to not be remembered across different command lines. + +f. Fixed problems with changing characters and changing case at the end of + the line. + +3. New Features in Bash + +a. The `jobs', `kill', and `wait' builtins now accept job control notation + even if job control is not enabled. + +b. The historical behavior of `trap' that allows a missing `action' argument + to cause each specified signal's handling to be reset to its default is + now only supported when `trap' is given a single non-option argument. + +4. New Features in Readline + +a. When listing completions, directories have a `/' appended if the + `mark-directories' option has been enabled. + +------------------------------------------------------------------------------ This document details the changes between this version, bash-3.0-beta1, and the previous version, bash-3.0-alpha. @@ -57,7 +159,7 @@ q. Fixed a bug that could cause core dumps when checking whether a quoted command name was being completed. r. Fixes to the pattern removal and pattern replacement expansions to deal - with multibyte characters better. + with multibyte characters better (and faster). s. Fix to the substring expansion (${param:off[:len]}) to deal with (possibly multibyte) characters instead of raw bytes. @@ -75,6 +177,12 @@ w. Fixed a bug that caused "$@" to expand incorrectly when used as the right hand side of a parameter expansion such as ${word:="$@"} if the first character of $IFS was not a space. +x. Fixed a slight cosmetic problem when printing commands containing a + `>&word' redirection. + +y. Fixed a problem that could cause here documents to not be created correctly + if the system temporary directory did not allow writing. + 2. Changes to Readline a. Change to history expansion functions to treat `^' as equivalent to word @@ -101,6 +209,9 @@ g. Fixed some display (and other) bugs encountered in multibyte locales h. Fixed some display bugs caused by multibyte characters in prompt strings. +i. Fixed a problem with history expansion caused by non-whitespace characters + used as history word delimiters. + 3. New Features in Bash a. printf builtin understands two new escape sequences: \" and \?. @@ -112,6 +223,10 @@ c. The GNU `gettext' package and libintl have been integrated; the shell's d. The `\W' prompt expansion now abbreviates $HOME as `~', like `\w'. +e. The error message printed when bash cannot open a shell script supplied + as argument 1 now includes the name of the shell, to better identify + the error as coming from bash. + 4. New Features in Readline a. New application variable, rl_completion_quote_character, set to any @@ -126,6 +241,13 @@ c. New application variable, rl_completion_found_quote, set to a non-zero value if readline determines that the word to be completed is quoted. Set before readline calls any application completion function. +d. New function hook, rl_completion_word_break_hook, called when readline + needs to break a line into words when completion is attempted. Allows + the word break characters to vary based on position in the line. + +e. New bindable command: unix-filename-rubout. Does the same thing as + unix-word-rubout, but adds `/' to the set of word delimiters. + ------------------------------------------------------------------------------ This document details the changes between this version, bash-3.0-alpha, and the previous version, bash-2.05b-release. diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index f4c134e..b408bc4 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9555,3 +9555,52 @@ lib/readline/vi_mode.c builtins/echo.def - call clearerr(stdout) before writing anything and testing its failure or success + + 6/29 + ---- +bashline.c + - only set rl_explicit_arg in bash_glob_complete_word if readline is + in emacs mode; let bash_vi_complete take care of setting it in vi + mode + - fix bash_vi_complete to only set rl_explicit_arg unless the posix + conditions are met: no globbing characters in the vi `bigword' + being completed + + 6/30 + ---- +[bash-3.0-rc1 released] + + 7/1 + --- +lib/readline/complete.c + - make sure `extension_char' is initialized before deciding whether + or not the append a `/' to a possible completion when visible-stats + is not enabled + + 7/2 + --- +subst.c + - fix a boundary overrun in string_extract_double_quoted that could + occur when the word completion code attempts to expand an incomplete + construct (like a quoted unclosed command substitution) + + 7/4 + --- +subst.c + - set tempenv_assign_error to non-zero if an assignment to the + temporary environment fails for some reason (e.g., attempted + assignment to a readonly variable) + +execute_cmd.c + - fix execute_simple_command to force a non-interactive shell in + POSIX mode to exit if an assignment to the temporary environment + preceding a special builtin fails (bug report from + llattanzi@apple.com) + + 7/5 + --- +bashline.c + - in bash_directory_completion_hook, don't perform word expansions + if the filename appears to have been completed from the file + system rather than typed in by the user. Bug reported by Tim + Waugh diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index cd7662d..7b384e2 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -9547,3 +9547,52 @@ lib/readline/vi_mode.c command - fix rl_vi_change_char so that replacing characters up to EOL works rather than generating rl_ding + - fix rl_vi_change_case so that replacing characters up to EOL works + rather than generating rl_ding + + 6/28 + ---- +builtins/echo.def + - call clearerr(stdout) before writing anything and testing its + failure or success + + 6/29 + ---- +bashline.c + - only set rl_explicit_arg in bash_glob_complete_word if readline is + in emacs mode; let bash_vi_complete take care of setting it in vi + mode + - fix bash_vi_complete to only set rl_explicit_arg unless the posix + conditions are met: no globbing characters in the vi `bigword' + being completed + + 6/30 + ---- +[bash-3.0-rc1 released] + + 7/1 + --- +lib/readline/complete.c + - make sure `extension_char' is initialized before deciding whether + or not the append a `/' to a possible completion when visible-stats + is not enabled + + 7/2 + --- +subst.c + - fix a boundary overrun in string_extract_double_quoted that could + occur when the word completion code attempts to expand an incomplete + construct (like a quoted unclosed command substitution) + + 7/4 + --- +subst.c + - set tempenv_assign_error to non-zero if an assignment to the + temporary environment fails for some reason (e.g., attempted + assignment to a readonly variable) + +execute_cmd.c + - fix execute_simple_command to force a non-interactive shell in + POSIX mode to exit if an assignment to the temporary environment + preceding a special builtin fails (bug report from + llattanzi@apple.com) diff --git a/NEWS b/NEWS index 90533fe..a8e0512 100644 --- a/NEWS +++ b/NEWS @@ -128,19 +128,13 @@ ll. The error message printed when bash cannot open a shell script supplied as argument 1 now includes the name of the shell, to better identify the error as coming from bash. -mm. A bug that caused here documents to not work if the directory the shell - used for the temporary files was not writable has been fixed. - -nn. The parameter pattern removal and substitution expansions are now much +mm. The parameter pattern removal and substitution expansions are now much faster and more efficient when using multibyte characters. -oo. Fixed a bug in the `shift' builtin that could cause core dumps when - reporting an out-of-range argument. - -pp. The `jobs', `kill', and `wait' builtins now accept job control notation +nn. The `jobs', `kill', and `wait' builtins now accept job control notation even if job control is not enabled. -qq. The historical behavior of `trap' that allows a missing `action' argument +oo. The historical behavior of `trap' that allows a missing `action' argument to cause each specified signal's handling to be reset to its default is now only supported when `trap' is given a single non-option argument. @@ -194,6 +188,9 @@ l. New function hook, rl_completion_word_break_hook, called when readline m. New bindable command: unix-filename-rubout. Does the same thing as unix-word-rubout, but adds `/' to the set of word delimiters. +n. When listing completions, directories have a `/' appended if the + `mark-directories' option has been enabled. + ------------------------------------------------------------------------------- This is a terse description of the new features added to bash-2.05b since the release of bash-2.05a. As always, the manual page (doc/bash.1) is diff --git a/NEWS~ b/NEWS~ index f711693..ba5feab 100644 --- a/NEWS~ +++ b/NEWS~ @@ -140,6 +140,10 @@ oo. Fixed a bug in the `shift' builtin that could cause core dumps when pp. The `jobs', `kill', and `wait' builtins now accept job control notation even if job control is not enabled. +qq. The historical behavior of `trap' that allows a missing `action' argument + to cause each specified signal's handling to be reset to its default is + now only supported when `trap' is given a single non-option argument. + 2. New Features in Readline a. History expansion has a new `a' modifier equivalent to the `g' modifier @@ -190,6 +194,9 @@ l. New function hook, rl_completion_word_break_hook, called when readline m. New bindable command: unix-filename-rubout. Does the same thing as unix-word-rubout, but adds `/' to the set of word delimiters. +n. When listing completions, directories have a `/' appended if the + `mark-directories' option has been enabled. + ------------------------------------------------------------------------------- This is a terse description of the new features added to bash-2.05b since the release of bash-2.05a. As always, the manual page (doc/bash.1) is diff --git a/bashline.c b/bashline.c index ec3125f..6a4963a 100644 --- a/bashline.c +++ b/bashline.c @@ -2196,6 +2196,7 @@ bash_directory_completion_hook (dirname) char *local_dirname, *new_dirname, *t; int return_value, should_expand_dirname; WORD_LIST *wl; + struct stat sb; return_value = should_expand_dirname = 0; local_dirname = *dirname; @@ -2213,6 +2214,13 @@ bash_directory_completion_hook (dirname) } #endif +#if defined (HAVE_LSTAT) + if (should_expand_dirname && lstat (local_dirname, &sb) == 0) +#else + if (should_expand_dirname && stat (local_dirname, &sb) == 0) +#endif + should_expand_dirname = 0; + if (should_expand_dirname) { new_dirname = savestring (local_dirname); @@ -2566,7 +2574,8 @@ bash_glob_complete_word (count, key) int r; rl_quote_func_t *orig_quoting_function; - rl_explicit_arg = 1; /* force `*' append */ + if (rl_editing_mode == EMACS_EDITING_MODE) + rl_explicit_arg = 1; /* force `*' append */ orig_quoting_function = rl_filename_quoting_function; rl_filename_quoting_function = bash_glob_quote_filename; @@ -2624,7 +2633,8 @@ bash_vi_complete (count, key) int count, key; { #if defined (SPECIFIC_COMPLETION_FUNCTIONS) - int r; + int p, r; + char *t; if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { @@ -2633,7 +2643,23 @@ bash_vi_complete (count, key) rl_point++; } - rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ + /* Find boundaries of current word, according to vi definition of a + `bigword'. */ + t = 0; + if (rl_point > 0) + { + p = rl_point; + rl_vi_bWord (1, 'B'); + r = rl_point; + rl_point = p; + p = r; + + t = substring (rl_line_buffer, p, rl_point); + } + + if (t && glob_pattern_p (t) == 0) + rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ + FREE (t); if (key == '*') /* Expansion and replacement. */ r = bash_glob_expand_word (count, key); diff --git a/bashline.c~ b/bashline.c~ index 11843f8..0db8068 100644 --- a/bashline.c~ +++ b/bashline.c~ @@ -2196,6 +2196,7 @@ bash_directory_completion_hook (dirname) char *local_dirname, *new_dirname, *t; int return_value, should_expand_dirname; WORD_LIST *wl; + struct stat sb; return_value = should_expand_dirname = 0; local_dirname = *dirname; @@ -2213,6 +2214,9 @@ bash_directory_completion_hook (dirname) } #endif + if (should_expand_dirname && lstat (local_dirname, &sb) == 0) + should_expand_dirname = 0; + if (should_expand_dirname) { new_dirname = savestring (local_dirname); @@ -2566,7 +2570,8 @@ bash_glob_complete_word (count, key) int r; rl_quote_func_t *orig_quoting_function; - rl_explicit_arg = 1; /* force `*' append */ + if (rl_editing_mode == EMACS_EDITING_MODE) + rl_explicit_arg = 1; /* force `*' append */ orig_quoting_function = rl_filename_quoting_function; rl_filename_quoting_function = bash_glob_quote_filename; @@ -2624,7 +2629,8 @@ bash_vi_complete (count, key) int count, key; { #if defined (SPECIFIC_COMPLETION_FUNCTIONS) - int r; + int p, r; + char *t; if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) { @@ -2633,7 +2639,23 @@ bash_vi_complete (count, key) rl_point++; } - rl_explicit_arg = 1; /* XXX - force `*' to be appended */ + /* Find boundaries of current word, according to vi definition of a + `bigword'. */ + t = 0; + if (rl_point > 0) + { + p = rl_point; + rl_vi_bWord (1, 'B'); + r = rl_point; + rl_point = p; + p = r; + + t = substring (rl_line_buffer, p, rl_point); + } + + if (t && glob_pattern_p (t) == 0) + rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ + FREE (t); if (key == '*') /* Expansion and replacement. */ r = bash_glob_expand_word (count, key); diff --git a/doc/FAQ-3.0 b/doc/FAQ-3.0 new file mode 100644 index 0000000..a15aad2 --- /dev/null +++ b/doc/FAQ-3.0 @@ -0,0 +1,1791 @@ +This is the Bash FAQ, version 3.27, for Bash version 3.0. + +This document contains a set of frequently-asked questions concerning +Bash, the GNU Bourne-Again Shell. Bash is a freely-available command +interpreter with advanced features for both interactive use and shell +programming. + +Another good source of basic information about shells is the collection +of FAQ articles periodically posted to comp.unix.shell. + +Questions and comments concerning this document should be sent to +chet@po.cwru.edu. + +This document is available for anonymous FTP with the URL + +ftp://ftp.cwru.edu/pub/bash/FAQ + +The Bash home page is http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html + +---------- +Contents: + +Section A: The Basics + +A1) What is it? +A2) What's the latest version? +A3) Where can I get it? +A4) On what machines will bash run? +A5) Will bash run on operating systems other than Unix? +A6) How can I build bash with gcc? +A7) How can I make bash my login shell? +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? +A9) What's the `POSIX Shell and Utilities standard'? +A10) What is the bash `posix mode'? + +Section B: The latest version + +B1) What's new in version 3.0? +B2) Are there any user-visible incompatibilities between bash-3.0 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? +E12) Why don't negative offsets in substring expansion work like I expect? + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? +G5) How do I get the current directory into my prompt? +G6) How can I rename "*.foo" to "*.bar"? +G7) How can I translate a filename from uppercase to lowercase? +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? +H2) What kind of bash documentation is there? +H3) What's coming in future versions? +H4) What's on the bash `wish list'? +H5) When will the next release appear? + +---------- +Section A: The Basics + +A1) What is it? + +Bash is a Unix command interpreter (shell). It is an implementation of +the Posix 1003.2 shell standard, and resembles the Korn and System V +shells. + +Bash contains a number of enhancements over those shells, both +for interactive use and shell programming. Features geared +toward interactive use include command line editing, command +history, job control, aliases, and prompt expansion. Programming +features include additional variable expansions, shell +arithmetic, and a number of variables and options to control +shell behavior. + +Bash was originally written by Brian Fox of the Free Software +Foundation. The current developer and maintainer is Chet Ramey +of Case Western Reserve University. + +A2) What's the latest version? + +The latest version is 3.0, first made available on xxx, 2004. + +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-3.0.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-3.0.tar.gz + +Formatted versions of the documentation are available with the URLs: + +ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-3.0.tar.gz +ftp://ftp.cwru.edu/pub/bash/bash-doc-3.0.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 and later versions 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 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. + +Bash-3.0 compiles and runs with no modifications under Microsoft's Services +for Unix (SFU), once known as Interix. + +A6) How can I build bash with gcc? + +Bash configures to use gcc by default if it is available. Read the +file INSTALL in the distribution for more information. + +A7) How can I make bash my login shell? + +Some machines let you use `chsh' to change your login shell. Other +systems use `passwd -s' or `passwd -e'. If one of these works for +you, that's all you need. Note that many systems require the full +pathname to a shell to appear in /etc/shells before you can make it +your login shell. For this, you may need the assistance of your +friendly local system administrator. + +If you cannot do this, you can still use bash as your login shell, but +you need to perform some tricks. The basic idea is to add a command +to your login shell's startup file to replace your login shell with +bash. + +For example, if your login shell is csh or tcsh, and you have installed +bash in /usr/gnu/bin/bash, add the following line to ~/.login: + + if ( -f /usr/gnu/bin/bash ) exec /usr/gnu/bin/bash --login + +(the `--login' tells bash that it is a login shell). + +It's not a good idea to put this command into ~/.cshrc, because every +csh you run without the `-f' option, even ones started to run csh scripts, +reads that file. If you must put the command in ~/.cshrc, use something +like + + if ( $?prompt ) exec /usr/gnu/bin/bash --login + +to ensure that bash is exec'd only when the csh is interactive. + +If your login shell is sh or ksh, you have to do two things. + +First, create an empty file in your home directory named `.bash_profile'. +The existence of this file will prevent the exec'd bash from trying to +read ~/.profile, and re-execing itself over and over again. ~/.bash_profile +is the first file bash tries to read initialization commands from when +it is invoked as a login shell. + +Next, add a line similar to the above to ~/.profile: + + [ -f /usr/gnu/bin/bash ] && [ -x /usr/gnu/bin/bash ] && \ + exec /usr/gnu/bin/bash --login + +This will cause login shells to replace themselves with bash running as +a login shell. Once you have this working, you can copy your initialization +code from ~/.profile to ~/.bash_profile. + +I have received word that the recipe supplied above is insufficient for +machines running CDE. CDE has a maze of twisty little startup files, all +slightly different. + +If you cannot change your login shell in the password file to bash, you +will have to (apparently) live with CDE using the shell in the password +file to run its startup scripts. If you have changed your shell to bash, +there is code in the CDE startup files (on Solaris, at least) that attempts +to do the right thing. It is, however, often broken, and may require that +you use the $BASH_ENV trick described below. + +`dtterm' claims to use $SHELL as the default program to start, so if you +can change $SHELL in the CDE startup files, you should be able to use bash +in your terminal windows. + +Setting DTSOURCEPROFILE in ~/.dtprofile will cause the `Xsession' program +to read your login shell's startup files. You may be able to use bash for +the rest of the CDE programs by setting SHELL to bash in ~/.dtprofile as +well, but I have not tried this. + +You can use the above `exec' recipe to start bash when not logging in with +CDE by testing the value of the DT variable: + + if [ -n "$DT" ]; then + [ -f /usr/gnu/bin/bash ] && exec /usr/gnu/bin/bash --login + fi + +If CDE starts its shells non-interactively during login, the login shell +startup files (~/.profile, ~/.bash_profile) will not be sourced at login. +To get around this problem, append a line similar to the following to your +~/.dtprofile: + + BASH_ENV=${HOME}/.bash_profile ; export BASH_ENV + +and add the following line to the beginning of ~/.bash_profile: + + unset BASH_ENV + +A8) I just changed my login shell to bash, and now I can't FTP into my + machine. Why not? + +You must add the full pathname to bash to the file /etc/shells. As +noted in the answer to the previous question, many systems require +this before you can make bash your login shell. + +Most versions of ftpd use this file to prohibit `special' users +such as `uucp' and `news' from using FTP. + +A9) What's the `POSIX Shell and Utilities standard'? + +POSIX is a name originally coined by Richard Stallman for a +family of open system standards based on UNIX. There are a +number of aspects of UNIX under consideration for +standardization, from the basic system services at the system +call and C library level to applications and tools to system +administration and management. Each area of standardization is +assigned to a working group in the 1003 series. + +The POSIX Shell and Utilities standard was originally developed by +IEEE Working Group 1003.2 (POSIX.2). Today it has been merged with +the original 1003.1 Working Group and is maintained by the Austin +Group (a joint working group of the IEEE, The Open Group and +ISO/IEC SC22/WG15). Today the Shell and Utilities are a volume +within the set of documents that make up IEEE Std 1003.1-2001, and +thus now the former POSIX.2 (from 1992) is now part of the current +POSIX.1 standard (POSIX 1003.1-2001). + +The Shell and Utilities volume concentrates on the command +interpreter interface and utility programs commonly executed from +the command line or by other programs. The standard is freely +available on the web at http://www.UNIX-systems.org/version3/ . +Work continues at the Austin Group on maintenance issues; see +http://www.opengroup.org/austin/ to join the discussions. + +Bash is concerned with the aspects of the shell's behavior defined +by the POSIX Shell and Utilities volume. The shell command +language has of course been standardized, including the basic flow +control and program execution constructs, I/O redirection and +pipelining, argument handling, variable expansion, and quoting. + +The `special' builtins, which must be implemented as part of the +shell to provide the desired functionality, are specified as +being part of the shell; examples of these are `eval' and +`export'. Other utilities appear in the sections of POSIX not +devoted to the shell which are commonly (and in some cases must +be) implemented as builtin commands, such as `read' and `test'. +POSIX also specifies aspects of the shell's interactive +behavior as part of the UPE, including job control and command +line editing. Only vi-style line editing commands have been +standardized; emacs editing commands were left out due to +objections. + +The latest version of the POSIX Shell and Utilities standard is +available (now updated to the 2004 Edition) as part of the Single +UNIX Specification Version 3 at + +http://www.UNIX-systems.org/version3/ + +A10) What is the bash `posix mode'? + +Although bash is an implementation of the POSIX shell +specification, there are areas where the bash default behavior +differs from that spec. The bash `posix mode' changes the bash +behavior in these areas so that it obeys the spec more closely. + +Posix mode is entered by starting bash with the --posix or +'-o posix' option or executing `set -o posix' after bash is running. + +The specific aspects of bash which change when posix mode is +active are listed in the file POSIX in the bash distribution. +They are also listed in a section in the Bash Reference Manual +(from which that file is generated). + +Section B: The latest version + +B1) What's new in version 3.0? + +Bash-3.0 is the third major release of bash. The features introduced +in the intermediate releases following bash-2.05 have been completed. +Support for the bash debugger (a separate project) has been integrated. + +Bash-3.0 contains the following new features (see the manual page for +complete descriptions and the CHANGES and NEWS files in the bash-3.0 +distribution): + +o Features to support the bash debugger have been implemented, and there + is a new `extdebug' option to turn the non-default options on + +o HISTCONTROL is now a colon-separated list of options and has been + extended with a new `erasedups' option that will result in only one + copy of a command being kept in the history list + +o Brace expansion has been extended with a new {x..y} form, producing + sequences of digits or characters + +o Timestamps are now kept with history entries, with an option to save + and restore them from the history file; there is a new HISTTIMEFORMAT + variable describing how to display the timestamps when listing history + entries + +o The `[[' command can now perform extended regular expression (egrep-like) + matching, with matched subexpressions placed in the BASH_REMATCH array + variable + +o A new `pipefail' option causes a pipeline to return a failure status if + any command in it fails + +o The `jobs', `kill', and `wait' builtins now accept job control notation + in their arguments even if job control is not enabled + +o The `gettext' package and libintl have been integrated, and the shell + messages may be translated into other languages + +A short feature history dating from Bash-2.0: + +Bash-2.05b introduced the following new features: + +o support for multibyte characters has been added to both bash and readline + +o the DEBUG trap is now run *before* simple commands, ((...)) commands, + [[...]] conditional commands, and for ((...)) loops + +o the shell now performs arithmetic in the largest integer size the machine + supports (intmax_t) + +o there is a new \D{...} prompt expansion; passes the `...' to strftime(3) + and inserts the result into the expanded prompt + +o there is a new `here-string' redirection operator: <<< word + +o when displaying variables, function attributes and definitions are shown + separately, allowing them to be re-used as input (attempting to re-use + the old output would result in syntax errors). + +o `read' has a new `-u fd' option to read from a specified file descriptor + +o the bash debugger in examples/bashdb has been modified to work with the + new DEBUG trap semantics, the command set has been made more gdb-like, + and the changes to $LINENO make debugging functions work better + +o the expansion of $LINENO inside a shell function is only relative to the + function start if the shell is interactive -- if the shell is running a + script, $LINENO expands to the line number in the script. This is as + POSIX-2001 requires + +Bash-2.05a introduced the following new features: + +o The `printf' builtin has undergone major work + +o There is a new read-only `shopt' option: login_shell, which is set by + login shells and unset otherwise + +o New `\A' prompt string escape sequence; expanding to time in 24-hour + HH:MM format + +o New `-A group/-g' option to complete and compgen; goes group name + completion + +o New [+-]O invocation option to set and unset `shopt' options at startup + +o ksh-like `ERR' trap + +o `for' loops now allow empty word lists after the `in' reserved word + +o new `hard' and `soft' arguments for the `ulimit' builtin + +o Readline can be configured to place the user at the same point on the line + when retrieving commands from the history list + +o Readline can be configured to skip `hidden' files (filenames with a leading + `.' on Unix) when performing completion + +Bash-2.05 introduced the following new features: + +o This version has once again reverted to using locales and strcoll(3) when + processing pattern matching bracket expressions, as POSIX requires. +o Added a new `--init-file' invocation argument as a synonym for `--rcfile', + per the new GNU coding standards. +o The /dev/tcp and /dev/udp redirections now accept service names as well as + port numbers. +o `complete' and `compgen' now take a `-o value' option, which controls some + of the aspects of that compspec. Valid values are: + + default - perform bash default completion if programmable + completion produces no matches + dirnames - perform directory name completion if programmable + completion produces no matches + filenames - tell readline that the compspec produces filenames, + so it can do things like append slashes to + directory names and suppress trailing spaces +o A new loadable builtin, realpath, which canonicalizes and expands symlinks + in pathname arguments. +o When `set' is called without options, it prints function defintions in a + way that allows them to be reused as input. This affects `declare' and + `declare -p' as well. This only happens when the shell is not in POSIX + mode, since POSIX.2 forbids this behavior. + +Bash-2.04 introduced the following new features: + +o Programmable word completion with the new `complete' and `compgen' builtins; + examples are provided in examples/complete/complete-examples +o `history' has a new `-d' option to delete a history entry +o `bind' has a new `-x' option to bind key sequences to shell commands +o The prompt expansion code has new `\j' and `\l' escape sequences +o The `no_empty_cmd_completion' shell option, if enabled, inhibits + command completion when TAB is typed on an empty line +o `help' has a new `-s' option to print a usage synopsis +o New arithmetic operators: var++, var--, ++var, --var, expr1,expr2 (comma) +o New ksh93-style arithmetic for command: + for ((expr1 ; expr2; expr3 )); do list; done +o `read' has new options: `-t', `-n', `-d', `-s' +o The redirection code handles several filenames specially: /dev/fd/N, + /dev/stdin, /dev/stdout, /dev/stderr +o The redirection code now recognizes /dev/tcp/HOST/PORT and + /dev/udp/HOST/PORT and tries to open a TCP or UDP socket, respectively, + to the specified port on the specified host +o The ${!prefix*} expansion has been implemented +o A new FUNCNAME variable, which expands to the name of a currently-executing + function +o The GROUPS variable is no longer readonly +o A new shopt `xpg_echo' variable, to control the behavior of echo with + respect to backslash-escape sequences at runtime +o The NON_INTERACTIVE_LOGIN_SHELLS #define has returned + +The version of Readline released with Bash-2.04, Readline-4.1, had several +new features as well: + +o Parentheses matching is always compiled into readline, and controllable + with the new `blink-matching-paren' variable +o The history-search-forward and history-search-backward functions now leave + point at the end of the line when the search string is empty, like + reverse-search-history, and forward-search-history +o A new function for applications: rl_on_new_line_with_prompt() +o New variables for applications: rl_already_prompted, and rl_gnu_readline_p + + +Bash-2.03 had very few new features, in keeping with the convention +that odd-numbered releases provide mainly bug fixes. A number of new +features were added to Readline, mostly at the request of the Cygnus +folks. + +A new shopt option, `restricted_shell', so that startup files can test + whether or not the shell was started in restricted mode +Filename generation is now performed on the words between ( and ) in + compound array assignments (this is really a bug fix) +OLDPWD is now auto-exported, as POSIX.2 requires +ENV and BASH_ENV are read-only variables in a restricted shell +Bash may now be linked against an already-installed Readline library, + as long as the Readline library is version 4 or newer +All shells begun with the `--login' option will source the login shell + startup files, even if the shell is not interactive + +There were lots of changes to the version of the Readline library released +along with Bash-2.03. For a complete list of the changes, read the file +CHANGES in the Bash-2.03 distribution. + +Bash-2.02 contained the following new features: + +a new version of malloc (based on the old GNU malloc code in previous + bash versions) that is more page-oriented, more conservative + with memory usage, does not `orphan' large blocks when they + are freed, is usable on 64-bit machines, and has allocation + checking turned on unconditionally +POSIX.2-style globbing character classes ([:alpha:], [:alnum:], etc.) +POSIX.2-style globbing equivalence classes +POSIX.2-style globbing collating symbols +the ksh [[...]] extended conditional command +the ksh egrep-style extended pattern matching operators +a new `printf' builtin +the ksh-like $(, &>, >|, <<<, [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 + debugger support, including `caller' builtin and new variables + RETURN trap + + +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' + debugger support + RETURN trap + Timestamps in history entries + {x..y} brace expansion + +Things ksh88 has or uses that bash does not: + tracked aliases (alias -t) + variables: ERRNO, FPATH, EDITOR, VISUAL + co-processes (|&, >&p, <&p) + weirdly-scoped functions + typeset +f to list all function names without definitions + text of command history kept in a file, not memory + builtins: alias -x, cd old new, newgrp, print, + read -p/-s/var?prompt, set -A/-o gmacs/ + -o bgnice/-o markdirs/-o trackall/-o viraw/-s, + typeset -H/-L/-R/-Z/-A/-ft/-fu/-fx/-l/-u/-t, whence + using environment to pass attributes of exported variables + arithmetic evaluation done on arguments to some builtins + reads .profile from $PWD when invoked as login shell + +Implementation differences: + ksh runs last command of a pipeline in parent shell context + bash has brace expansion by default (ksh88 compile-time option) + bash has fixed startup file for all interactive shells; ksh reads $ENV + bash has exported functions + bash command search finds functions before builtins + bash waits for all commands in pipeline to exit before returning status + emacs-mode editing has some slightly different key bindings + +C3) Which new features in ksh-93 are not in bash, and which are? + +New things in ksh-93 not in bash-3.0: + associative arrays + floating point arithmetic and variables + math library functions + ${!name[sub]} name of subscript for associative array + `.' is allowed in variable names to create a hierarchical namespace + more extensive compound assignment syntax + discipline functions + `sleep' and `getconf' builtins (bash has loadable versions) + typeset -n and `nameref' variables + KEYBD trap + variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version, + .sh.name, .sh.subscript, .sh.value, .sh.match, HISTEDIT + backreferences in pattern matching (\N) + `&' operator in pattern lists for matching + print -f (bash uses printf) + `fc' has been renamed to `hist' + `.' can execute shell functions + exit statuses between 0 and 255 + `+=' variable assignment operator + FPATH and PATH mixing + getopts -a + -I invocation option + printf %H, %P, %T, %Z modifiers, output base for %d + lexical scoping for local variables in `ksh' functions + no scoping for local variables in `POSIX' functions + +New things in ksh-93 present in bash-3.0: + [n]<&word- and [n]>&word- redirections (combination dup and close) + for (( expr1; expr2; expr3 )) ; do list; done - arithmetic for command + ?:, ++, --, `expr1 , expr2' arithmetic operators + expansions: ${!param}, ${param:offset[:len]}, ${param/pat[/str]}, + ${!param*} + compound array assignment + the `!' reserved word + loadable builtins -- but ksh uses `builtin' while bash uses `enable' + `command', `builtin', `disown' builtins + new $'...' and $"..." quoting + FIGNORE (but bash uses GLOBIGNORE), HISTCMD + set -o notify/-C + changes to kill builtin + read -A (bash uses read -a) + read -t/-d + trap -p + exec -c/-a + `.' restores the positional parameters when it completes + POSIX.2 `test' + umask -S + unalias -a + command and arithmetic substitution performed on PS1, PS4, and ENV + command name completion + ENV processed only for interactive shells + set -o pipefail + +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 updated POSIX standard has changed this: the word list +is no longer required. Bash versions 2.05a and later accept the +new syntax. + +E8) Why does the arithmetic evaluation code complain about `08'? + +The bash arithmetic evaluation code (used for `let', $(()), (()), and in +other places), interprets a leading `0' in numeric constants as denoting +an octal number, and a leading `0x' as denoting hexadecimal. This is +in accordance with the POSIX.2 spec, section 2.9.2.1, which states that +arithmetic constants should be handled as signed long integers as defined +by the ANSI/ISO C standard. + +The POSIX.2 interpretation committee has confirmed this: + +http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-173.html + +E9) Why does the pattern matching expression [A-Z]* match files beginning + with every letter except `z'? + +Bash-2.03, Bash-2.05 and later versions honor the current locale setting +when processing ranges within pattern matching bracket expressions ([A-Z]). +This is what POSIX.2 and SUSv3/XPG6 specify. + +The behavior of the matcher in bash-2.05 and later versions depends on the +current LC_COLLATE setting. Setting this variable to `C' or `POSIX' will +result in the traditional behavior ([A-Z] matches all uppercase ASCII +characters). Many other locales, including the en_US locale (the default +on many US versions of Linux) collate the upper and lower case letters like +this: + + AaBb...Zz + +which means that [A-Z] matches every letter except `z'. Others collate like + + aAbBcC...zZ + +which means that [A-Z] matches every letter except `a'. + +The portable way to specify upper case letters is [:upper:] instead of +A-Z; lower case may be specified as [:lower:] instead of a-z. + +Look at the manual pages for setlocale(3), strcoll(3), and, if it is +present, locale(1). If you have locale(1), you can use it to find +your current locale information even if you do not have any of the +LC_ variables set. + +My advice is to put + + export LC_COLLATE=C + +into /etc/profile and inspect any shell scripts run from cron for +constructs like [A-Z]. This will prevent things like + + rm [A-Z]* + +from removing every file in the current directory except those beginning +with `z' and still allow individual users to change the collation order. +Users may put the above command into their own profiles as well, of course. + +E10) Why does `cd //' leave $PWD as `//'? + +POSIX.2, in its description of `cd', says that *three* or more leading +slashes may be replaced with a single slash when canonicalizing the +current working directory. + +This is, I presume, for historical compatibility. Certain versions of +Unix, and early network file systems, used paths of the form +//hostname/path to access `path' on server `hostname'. + +E11) If I resize my xterm while another program is running, why doesn't bash + notice the change? + +This is another issue that deals with job control. + +The kernel maintains a notion of a current terminal process group. Members +of this process group (processes whose process group ID is equal to the +current terminal process group ID) receive terminal-generated signals like +SIGWINCH. (For more details, see the JOB CONTROL section of the bash +man page.) + +If a terminal is resized, the kernel sends SIGWINCH to each member of +the terminal's current process group (the `foreground' process group). + +When bash is running with job control enabled, each pipeline (which may be +a single command) is run in its own process group, different from bash's +process group. This foreground process group receives the SIGWINCH; bash +does not. Bash has no way of knowing that the terminal has been resized. + +There is a `checkwinsize' option, settable with the `shopt' builtin, that +will cause bash to check the window size and adjust its idea of the +terminal's dimensions each time a process stops or exits and returns control +of the terminal to bash. Enable it with `shopt -s checkwinsize'. + +E12) Why don't negative offsets in substring expansion work like I expect? + +When substring expansion of the form ${param:offset[:length} is used, +an `offset' that evaluates to a number less than zero counts back from +the end of the expanded value of $param. + +When a negative `offset' begins with a minus sign, however, unexpected things +can happen. Consider + + a=12345678 + echo ${a:-4} + +intending to print the last four characters of $a. The problem is that +${param:-word} already has a well-defined meaning: expand to word if the +expanded value of param is unset or null, and $param otherwise. + +To use negative offsets that begin with a minus sign, separate the +minus sign and the colon with a space. + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? + +The problem is `cmdtool' and bash fighting over the input. When +scrolling is enabled in a cmdtool window, cmdtool puts the tty in +`raw mode' to permit command-line editing using the mouse for +applications that cannot do it themselves. As a result, bash and +cmdtool each try to read keyboard input immediately, with neither +getting enough of it to be useful. + +This mode also causes cmdtool to not implement many of the +terminal functions and control sequences appearing in the +`sun-cmd' termcap entry. For a more complete explanation, see +that file examples/suncmd.termcap in the bash distribution. + +`xterm' is a better choice, and gets along with bash much more +smoothly. + +If you must use cmdtool, you can use the termcap description in +examples/suncmd.termcap. Set the TERMCAP variable to the terminal +description contained in that file, i.e. + +TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:' + +Then export TERMCAP and start a new cmdtool window from that shell. +The bash command-line editing should behave better in the new +cmdtool. If this works, you can put the assignment to TERMCAP +in your bashrc file. + +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? + +This is the consequence of building bash on SunOS 5 and linking +with the libraries in /usr/ucblib, but using the definitions +and structures from files in /usr/include. + +The actual conflict is between the dirent structure in +/usr/include/dirent.h and the struct returned by the version of +`readdir' in libucb.a (a 4.3-BSD style `struct direct'). + +Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH +when configuring and building bash. This will ensure that you +use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you +link with libc before libucb. + +If you have installed the Sun C compiler, you may also need to +put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before +/usr/ucb. + +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? + +This is a famous and long-standing bug in the SunOS YP (sorry, NIS) +client library, which is part of libc. + +The YP library code keeps static state -- a pointer into the data +returned from the server. When YP initializes itself (setpwent), +it looks at this pointer and calls free on it if it's non-null. +So far, so good. + +If one of the YP functions is interrupted during getpwent (the +exact function is interpretwithsave()), and returns NULL, the +pointer is freed without being reset to NULL, and the function +returns. The next time getpwent is called, it sees that this +pointer is non-null, calls free, and the bash free() blows up +because it's being asked to free freed memory. + +The traditional Unix mallocs allow memory to be freed multiple +times; that's probably why this has never been fixed. You can +run configure with the `--without-gnu-malloc' option to use +the C library malloc and avoid the problem. + +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? + +The `@' character is the default `line kill' character in most +versions of System V, including SVR4.2. You can change this +character to whatever you want using `stty'. For example, to +change the line kill character to control-u, type + + stty kill ^U + +where the `^' and `U' can be two separate characters. + +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? + +The actual command in question is something like + + < file ( command ) + +According to the grammar given in the POSIX.2 standard, this construct +is, in fact, a syntax error. Redirections may only precede `simple +commands'. A subshell construct such as the above is one of the shell's +`compound commands'. A redirection may only follow a compound command. + +This affects the mechanical transformation of commands that use `cat' +to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on +comp.unix.shell). While most commands of the form + + cat file | command + +can be converted to `< file command', shell control structures such as +loops and subshells require `command < file'. + +The file CWRU/sh-redir-hack in the bash distribution is an +(unofficial) patch to parse.y that will modify the grammar to +support this construct. It will not apply with `patch'; you must +modify parse.y by hand. Note that if you apply this, you must +recompile with -DREDIRECTION_HACK. This introduces a large +number of reduce/reduce conflicts into the shell grammar. + +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? + +The short answer is that Red Hat screwed up. + +The long answer is that they shipped an /etc/inputrc that only works +for emacs mode editing, and then screwed all the vi users by setting +INPUTRC to /etc/inputrc in /etc/profile. + +The short fix is to do one of the following: remove or rename +/etc/inputrc, set INPUTRC=~/.inputrc in ~/.bashrc (or .bash_profile, +but make sure you export it if you do), remove the assignment to +INPUTRC from /etc/profile, add + + set keymap emacs + +to the beginning of /etc/inputrc, or bracket the key bindings in +/etc/inputrc with these lines + + $if mode=emacs + [...] + $endif + +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +HP/UX's support for long double is imperfect at best. + +GCC will support it without problems, but the HP C library functions +like strtold(3) and printf(3) don't actually work with long doubles. +HP implemented a `long_double' type as a 4-element array of 32-bit +ints, and that is what the library functions use. The ANSI C +`long double' type is a 128-bit floating point scalar. + +The easiest fix, until HP fixes things up, is to edit the generated +config.h and #undef the HAVE_LONG_DOUBLE line. After doing that, +the compilation should complete successfully. + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? + +This is a process requiring several steps. + +First, you must ensure that the `physical' data path is a full eight +bits. For xterms, for example, the `vt100' resources `eightBitInput' +and `eightBitOutput' should be set to `true'. + +Once you have set up an eight-bit path, you must tell the kernel and +tty driver to leave the eighth bit of characters alone when processing +keyboard input. Use `stty' to do this: + + stty cs8 -istrip -parenb + +For old BSD-style systems, you can use + + stty pass8 + +You may also need + + stty even odd + +Finally, you need to tell readline that you will be inputting and +displaying eight-bit characters. You use readline variables to do +this. These variables can be set in your .inputrc or using the bash +`bind' builtin. Here's an example using `bind': + + bash$ bind 'set convert-meta off' + bash$ bind 'set meta-flag on' + bash$ bind 'set output-meta on' + +The `set' commands between the single quotes may also be placed +in ~/.inputrc. + +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? + +This is why the `command' and `builtin' builtins exist. The +`command' builtin executes the command supplied as its first +argument, skipping over any function defined with that name. The +`builtin' builtin executes the builtin command given as its first +argument directly. + +For example, to write a function to replace `cd' that writes the +hostname and current directory to an xterm title bar, use +something like the following: + + cd() + { + builtin cd "$@" && xtitle "$HOST: $PWD" + } + +This could also be written using `command' instead of `builtin'; +the version above is marginally more efficient. + +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? + +Versions of Bash newer than Bash-2.0 support this directly. You can use + + ${!var} + +For example, the following sequence of commands will echo `z': + + var1=var2 + var2=z + echo ${!var1} + +For sh compatibility, use the `eval' builtin. The important +thing to remember is that `eval' expands the arguments you give +it again, so you need to quote the parts of the arguments that +you want `eval' to act on. + +For example, this expression prints the value of the last positional +parameter: + + eval echo \"\$\{$#\}\" + +The expansion of the quoted portions of this expression will be +deferred until `eval' runs, while the `$#' will be expanded +before `eval' is executed. In versions of bash later than bash-2.0, + + echo ${!#} + +does the same thing. + +This is not the same thing as ksh93 `nameref' variables, though the syntax +is similar. I may add namerefs in a future bash version. + +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? + +The bash command timing code looks for a variable `TIMEFORMAT' and +uses its value as a format string to decide how to display the +timing statistics. + +The value of TIMEFORMAT is a string with `%' escapes expanded in a +fashion similar in spirit to printf(3). The manual page explains +the meanings of the escape sequences in the format string. + +If TIMEFORMAT is not set, bash acts as if the following assignment had +been performed: + + TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS' + +The POSIX.2 default time format (used by `time -p command') is + + TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S' + +The BSD /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys' + +The System V /usr/bin/time format can be emulated with: + + TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S' + +The ksh format can be emulated with: + + TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS' + +G5) How do I get the current directory into my prompt? + +Bash provides a number of backslash-escape sequences which are expanded +when the prompt string (PS1 or PS2) is displayed. The full list is in +the manual page. + +The \w expansion gives the full pathname of the current directory, with +a tilde (`~') substituted for the current value of $HOME. The \W +expansion gives the basename of the current directory. To put the full +pathname of the current directory into the path without any tilde +subsitution, use $PWD. Here are some examples: + + PS1='\w$ ' # current directory with tilde + PS1='\W$ ' # basename of current directory + PS1='$PWD$ ' # full pathname of current directory + +The single quotes are important in the final example to prevent $PWD from +being expanded when the assignment to PS1 is performed. + +G6) How can I rename "*.foo" to "*.bar"? + +Use the pattern removal functionality described in D3. The following `for' +loop will do the trick: + + for f in *.foo; do + mv $f ${f%foo}bar + done + +G7) How can I translate a filename from uppercase to lowercase? + +The script examples/functions/lowercase, originally written by John DuBois, +will do the trick. The converse is left as an exercise. + +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +You must have set the `extglob' shell option using `shopt -s extglob' to use +this: + + echo .!(.|) * + +A solution that works without extended globbing is given in the Unix Shell +FAQ, posted periodically to comp.unix.shell. + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? + +Use the `bashbug' script to report bugs. It is built and +installed at the same time as bash. It provides a standard +template for reporting a problem and automatically includes +information about your configuration and build environment. + +`bashbug' sends its reports to bug-bash@gnu.org, which +is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug. + +Bug fixes, answers to questions, and announcements of new releases +are all posted to gnu.bash.bug. Discussions concerning bash features +and problems also take place there. + +To reach the bash maintainers directly, send mail to +bash-maintainers@gnu.org. + +H2) What kind of bash documentation is there? + +First, look in the doc directory in the bash distribution. It should +contain at least the following files: + +bash.1 an extensive, thorough Unix-style manual page +builtins.1 a manual page covering just bash builtin commands +bashref.texi a reference manual in GNU tex`info format +bashref.info an info version of the reference manual +FAQ this file +article.ms text of an article written for The Linux Journal +readline.3 a man page describing readline + +Postscript, HTML, and ASCII files created from the above source are +available in the documentation distribution. + +There is additional documentation available for anonymous FTP from host +ftp.cwru.edu in the `pub/bash' directory. + +Cameron Newham and Bill Rosenblatt have written a book on bash, published +by O'Reilly and Associates. The book is based on Bill Rosenblatt's Korn +Shell book. The title is ``Learning the Bash Shell'', and the ISBN number +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 +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 2005. Never make predictions. + +This document is Copyright 1995-2004 by Chester Ramey. + +Permission is hereby granted, without written agreement and +without license or royalty fees, to use, copy, and distribute +this document for any purpose, provided that the above copyright +notice appears in all copies of this document and that the +contents of this document remain unaltered. diff --git a/doc/FAQ-3.0~ b/doc/FAQ-3.0~ new file mode 100644 index 0000000..f0f3d1b --- /dev/null +++ b/doc/FAQ-3.0~ @@ -0,0 +1,1771 @@ +This is the Bash FAQ, version 3.26, 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 Shell and Utilities 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? +E12) Why don't negative offsets in substring expansion work like I expect? + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? +F6) Why can't I use vi-mode editing on Red Hat Linux 6.1? +F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on + HP/UX 11.x? + +Section G: How can I get bash to do certain common things? + +G1) How can I get bash to read and display eight-bit characters? +G2) How do I write a function `x' to replace builtin command `x', but + still invoke the command from within the function? +G3) How can I find the value of a shell variable whose name is the value + of another shell variable? +G4) How can I make the bash `time' reserved word print timing output that + looks like the output from my system's /usr/bin/time? +G5) How do I get the current directory into my prompt? +G6) How can I rename "*.foo" to "*.bar"? +G7) How can I translate a filename from uppercase to lowercase? +G8) How can I write a filename expansion (globbing) pattern that will match + all files in the current directory except "." and ".."? + +Section H: Where do I go from here? + +H1) How do I report bugs in bash, and where should I look for fixes and + advice? +H2) What kind of bash documentation is there? +H3) What's coming in future versions? +H4) What's on the bash `wish list'? +H5) When will the next release appear? + +---------- +Section A: The Basics + +A1) What is it? + +Bash is a Unix command interpreter (shell). It is an implementation of +the Posix 1003.2 shell standard, and resembles the Korn and System V +shells. + +Bash contains a number of enhancements over those shells, both +for interactive use and shell programming. Features geared +toward interactive use include command line editing, command +history, job control, aliases, and prompt expansion. Programming +features include additional variable expansions, shell +arithmetic, and a number of variables and options to control +shell behavior. + +Bash was originally written by Brian Fox of the Free Software +Foundation. The current developer and maintainer is Chet Ramey +of Case Western Reserve University. + +A2) What's the latest version? + +The latest version is 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 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 Shell and Utilities standard'? + +POSIX is a name originally coined by Richard Stallman for a +family of open system standards based on UNIX. There are a +number of aspects of UNIX under consideration for +standardization, from the basic system services at the system +call and C library level to applications and tools to system +administration and management. Each area of standardization is +assigned to a working group in the 1003 series. + +The POSIX Shell and Utilities standard was originally developed by +IEEE Working Group 1003.2 (POSIX.2). Today it has been merged with +the original 1003.1 Working Group and is maintained by the Austin +Group (a joint working group of the IEEE, The Open Group and +ISO/IEC SC22/WG15). Today the Shell and Utilities are a volume +within the set of documents that make up IEEE Std 1003.1-2001, and +thus now the former POSIX.2 (from 1992) is now part of the current +POSIX.1 standard (POSIX 1003.1-2001). + +The Shell and Utilities volume concentrates on the command +interpreter interface and utility programs commonly executed from +the command line or by other programs. The standard is freely +available on the web at http://www.UNIX-systems.org/version3/ . +Work continues at the Austin Group on maintenance issues; see +http://www.opengroup.org/austin/ to join the discussions. + +Bash is concerned with the aspects of the shell's behavior defined +by the POSIX Shell and Utilities volume. The shell command +language has of course been standardized, including the basic flow +control and program execution constructs, I/O redirection and +pipelining, argument handling, variable expansion, and quoting. + +The `special' builtins, which must be implemented as part of the +shell to provide the desired functionality, are specified as +being part of the shell; examples of these are `eval' and +`export'. Other utilities appear in the sections of POSIX not +devoted to the shell which are commonly (and in some cases must +be) implemented as builtin commands, such as `read' and `test'. +POSIX also specifies aspects of the shell's interactive +behavior as part of the UPE, including job control and command +line editing. Only vi-style line editing commands have been +standardized; emacs editing commands were left out due to +objections. + +The latest version of the POSIX Shell and Utilities standard is +available (now updated to the 2003 Edition incorporating the +Technical Corrigendum 1), as part of the Single UNIX Specification +Version 3 at + +http://www.UNIX-systems.org/version3/ + +A10) What is the bash `posix mode'? + +Although bash is an implementation of the POSIX shell +specification, there are areas where the bash default behavior +differs from that spec. The bash `posix mode' changes the bash +behavior in these areas so that it obeys the spec more closely. + +Posix mode is entered by starting bash with the --posix or +'-o posix' option or executing `set -o posix' after bash is running. + +The specific aspects of bash which change when posix mode is +active are listed in the file POSIX in the bash distribution. +They are also listed in a section in the Bash Reference Manual +(from which that file is generated). + +Section B: The latest version + +B1) What's new in version 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 $(, &>, >|, <<<, [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'. + +E12) Why don't negative offsets in substring expansion work like I expect? + +When substring expansion of the form ${param:offset[:length} is used, +an `offset' that evaluates to a number less than zero counts back from +the end of the expanded value of $param. + +When a negative `offset' begins with a minus sign, however, unexpected things +can happen. Consider + + a=12345678 + echo ${a:-4} + +intending to print the last four characters of $a. The problem is that +${param:-word} already has a well-defined meaning: expand to word if the +expanded value of param is unset or null, and $param otherwise. + +To use negative offsets that begin with a minus sign, separate the +minus sign and the colon with a space. + +Section F: Things to watch out for on certain Unix versions + +F1) Why can't I use command line editing in my `cmdtool'? + +The problem is `cmdtool' and bash fighting over the input. When +scrolling is enabled in a cmdtool window, cmdtool puts the tty in +`raw mode' to permit command-line editing using the mouse for +applications that cannot do it themselves. As a result, bash and +cmdtool each try to read keyboard input immediately, with neither +getting enough of it to be useful. + +This mode also causes cmdtool to not implement many of the +terminal functions and control sequences appearing in the +`sun-cmd' termcap entry. For a more complete explanation, see +that file examples/suncmd.termcap in the bash distribution. + +`xterm' is a better choice, and gets along with bash much more +smoothly. + +If you must use cmdtool, you can use the termcap description in +examples/suncmd.termcap. Set the TERMCAP variable to the terminal +description contained in that file, i.e. + +TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:' + +Then export TERMCAP and start a new cmdtool window from that shell. +The bash command-line editing should behave better in the new +cmdtool. If this works, you can put the assignment to TERMCAP +in your bashrc file. + +F2) I built bash on Solaris 2. Why do globbing expansions and filename + completion chop off the first few characters of each filename? + +This is the consequence of building bash on SunOS 5 and linking +with the libraries in /usr/ucblib, but using the definitions +and structures from files in /usr/include. + +The actual conflict is between the dirent structure in +/usr/include/dirent.h and the struct returned by the version of +`readdir' in libucb.a (a 4.3-BSD style `struct direct'). + +Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH +when configuring and building bash. This will ensure that you +use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you +link with libc before libucb. + +If you have installed the Sun C compiler, you may also need to +put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before +/usr/ucb. + +F3) Why does bash dump core after I interrupt username completion or + `~user' tilde expansion on a machine running NIS? + +This is a famous and long-standing bug in the SunOS YP (sorry, NIS) +client library, which is part of libc. + +The YP library code keeps static state -- a pointer into the data +returned from the server. When YP initializes itself (setpwent), +it looks at this pointer and calls free on it if it's non-null. +So far, so good. + +If one of the YP functions is interrupted during getpwent (the +exact function is interpretwithsave()), and returns NULL, the +pointer is freed without being reset to NULL, and the function +returns. The next time getpwent is called, it sees that this +pointer is non-null, calls free, and the bash free() blows up +because it's being asked to free freed memory. + +The traditional Unix mallocs allow memory to be freed multiple +times; that's probably why this has never been fixed. You can +run configure with the `--without-gnu-malloc' option to use +the C library malloc and avoid the problem. + +F4) I'm running SVR4.2. Why is the line erased every time I type `@'? + +The `@' character is the default `line kill' character in most +versions of System V, including SVR4.2. You can change this +character to whatever you want using `stty'. For example, to +change the line kill character to control-u, type + + stty kill ^U + +where the `^' and `U' can be two separate characters. + +F5) Why does bash report syntax errors when my C News scripts use a + redirection before a subshell command? + +The actual command in question is something like + + < file ( command ) + +According to the grammar given in the POSIX.2 standard, this construct +is, in fact, a syntax error. Redirections may only precede `simple +commands'. A subshell construct such as the above is one of the shell's +`compound commands'. A redirection may only follow a compound command. + +This affects the mechanical transformation of commands that use `cat' +to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on +comp.unix.shell). While most commands of the form + + cat file | command + +can be converted to `< file command', shell control structures such as +loops and subshells require `command < file'. + +The file CWRU/sh-redir-hack in the bash-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 2003. Never make predictions. + + +This document is Copyright 1995-2003 by Chester Ramey. + +Permission is hereby granted, without written agreement and +without license or royalty fees, to use, copy, and distribute +this document for any purpose, provided that the above copyright +notice appears in all copies of this document and that the +contents of this document remain unaltered. diff --git a/doc/bashref.info b/doc/bashref.info index 04b945b..a29688d 100644 --- a/doc/bashref.info +++ b/doc/bashref.info @@ -1,10 +1,10 @@ -This is bashref.info, produced by makeinfo version 4.5 from -/usr/homes/chet/src/bash/src/doc/bashref.texi. +This is bashref.info, produced by makeinfo version 4.2 from +/Users/chet/src/bash/src/doc/bashref.texi. This text is a brief description of the features that are present in -the Bash shell (version 3.0-rc1, 27 May 2004). +the Bash shell (version 3.0-rc1, 26 June 2004). - This is Edition 3.0, last updated 27 May 2004, of `The GNU Bash + This is Edition 3.0, last updated 26 June 2004, of `The GNU Bash Reference Manual', for `Bash', Version 3.0-rc1. Copyright (C) 1988-2004 Free Software Foundation, Inc. @@ -37,9 +37,9 @@ Bash Features ************* This text is a brief description of the features that are present in -the Bash shell (version 3.0-rc1, 27 May 2004).. +the Bash shell (version 3.0-rc1, 26 June 2004).. - This is Edition 3.0, last updated 27 May 2004, of `The GNU Bash + This is Edition 3.0, last updated 26 June 2004, of `The GNU Bash Reference Manual', for `Bash', Version 3.0-rc1. Bash contains features that appear in other popular shells, and some @@ -731,7 +731,6 @@ syntax, it may be replaced with one or more newlines. command in LIST that is executed, or false if any of the expressions is invalid. - The `break' and `continue' builtins (*note Bourne Shell Builtins::) may be used to control loop execution. @@ -896,7 +895,6 @@ Conditional Constructs value of EXPRESSION1 is sufficient to determine the return value of the entire conditional expression. -  File: bashref.info, Node: Command Grouping, Prev: Conditional Constructs, Up: Compound Commands @@ -1301,7 +1299,6 @@ the expanded value. `~-N' The string that would be displayed by `dirs -N' -  File: bashref.info, Node: Shell Parameter Expansion, Next: Command Substitution, Prev: Tilde Expansion, Up: Shell Expansions @@ -1448,7 +1445,6 @@ if the colon is omitted, the operator tests only for existence. member of the array in turn, and the expansion is the resultant list. -  File: bashref.info, Node: Command Substitution, Next: Arithmetic Expansion, Prev: Shell Parameter Expansion, Up: Shell Expansions @@ -1756,7 +1752,6 @@ redirections, as described in the following table: integer port number or service name, Bash attempts to open a UDP connection to the corresponding socket. - A failure to open or create a file causes the redirection to fail. Redirecting Input @@ -2718,7 +2713,6 @@ POSIX 1003.2 standard. `-x KEYSEQ:SHELL-COMMAND' Cause SHELL-COMMAND to be executed whenever KEYSEQ is entered. - The return status is zero unless an invalid option is supplied or an error occurs. @@ -3014,7 +3008,6 @@ POSIX 1003.2 standard. `-u FD' Read input from file descriptor FD. - `shopt' shopt [-pqsu] [-o] [OPTNAME ...] Toggle the values of variables controlling optional shell behavior. @@ -3224,7 +3217,6 @@ POSIX 1003.2 standard. If set, the `echo' builtin expands backslash-escape sequences by default. - The return status when listing options is zero if all OPTNAMES are enabled, non-zero otherwise. When setting or unsetting options, the return status is zero unless an OPTNAME is not a valid shell @@ -3318,7 +3310,6 @@ POSIX 1003.2 standard. `-v' The maximum amount of virtual memory available to the process. - If LIMIT is given, it is the new value of the specified resource; the special LIMIT values `hard', `soft', and `unlimited' stand for the current hard limit, the current soft limit, and no limit, @@ -3339,7 +3330,6 @@ POSIX 1003.2 standard. Remove each NAME from the list of aliases. If `-a' is supplied, all aliases are removed. Aliases are described in *Note Aliases::. -  File: bashref.info, Node: The Set Builtin, Next: Special Builtins, Prev: Bash Builtins, Up: Shell Builtin Commands @@ -3686,7 +3676,6 @@ shell. In some cases, Bash assigns a default value to the variable. `PS2' The secondary prompt string. The default value is `> '. -  File: bashref.info, Node: Bash Variables, Prev: Bourne Shell Variables, Up: Shell Variables @@ -3779,7 +3768,6 @@ Variables::). `BASH_VERSINFO[5]' The value of `MACHTYPE'. - `BASH_VERSION' The version number of the current instance of Bash. @@ -4165,7 +4153,6 @@ Variables::). The numeric real user id of the current user. This variable is readonly. -  File: bashref.info, Node: Bash Features, Next: Job Control, Prev: Shell Variables, Up: Top @@ -4263,7 +4250,6 @@ the single-character options to be recognized. Show version information for this instance of Bash on the standard output and exit successfully. - There are several single-character options that may be supplied at invocation which are not available with the `set' builtin. @@ -4315,7 +4301,6 @@ invocation which are not available with the `set' builtin. processing. Any arguments after the `--' are treated as filenames and arguments. - A _login_ shell is one whose first character of argument zero is `-', or one invoked with the `--login' option. @@ -4467,8 +4452,8 @@ What is an Interactive Shell? An interactive shell is one started without non-option arguments, unless `-s' is specified, without specifiying the `-c' option, and -whose input and output are both connected to terminals (as determined -by `isatty(3)'), or one started with the `-i' option. +whose input and error output are both connected to terminals (as +determined by `isatty(3)'), or one started with the `-i' option. An interactive shell generally reads from and writes to a user's terminal. @@ -4707,7 +4692,6 @@ checked. If the FILE argument to one of the primaries is one of greater than or equal to ARG2, respectively. ARG1 and ARG2 may be positive or negative integers. -  File: bashref.info, Node: Shell Arithmetic, Next: Aliases, Prev: Bash Conditional Expressions, Up: Bash Features @@ -5025,7 +5009,6 @@ Directory Stack Builtins Makes the current working directory be the top of the stack, and then executes the equivalent of ``cd' DIR'. `cd's to DIR. -  File: bashref.info, Node: Printing a Prompt, Next: The Restricted Shell, Prev: The Directory Stack, Up: Bash Features @@ -5542,7 +5525,6 @@ Job Control Builtins signal. The `-f' option means to suspend even if the shell is a login shell. - When job control is not active, the `kill' and `wait' builtins do not accept JOBSPEC arguments. They must be supplied process IDs. @@ -5569,7 +5551,6 @@ Job Control Variables a prefix of a stopped job's name; this provides functionality analogous to the `%' job ID. -  File: bashref.info, Node: Command Line Editing, Next: Installing Bash, Prev: Using History Interactively, Up: Top @@ -5776,7 +5757,6 @@ available to be yanked back later, when you are typing another line. Kill from the cursor to the previous whitespace. This is different than `M-' because the word boundaries differ. - Here is how to "yank" the text back into the line. Yanking means to copy the most-recently-killed text from the kill buffer. @@ -6054,7 +6034,6 @@ Variable Settings appended to the filename when listing possible completions. The default is `off'. - 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 @@ -6109,7 +6088,6 @@ Key Bindings ` <[> <1> <1> <~>' is bound to insert the text `Function Key 1'. - The following GNU Emacs style escape sequences are available when specifying key sequences: @@ -6175,7 +6153,6 @@ Key Bindings the line: "\C-x\\": "\\" -  File: bashref.info, Node: Conditional Init Constructs, Next: Sample Init File, Prev: Readline Init File Syntax, Up: Readline Init File @@ -6407,7 +6384,6 @@ Commands For Moving `redraw-current-line ()' Refresh the current line. By default, this is unbound. -  File: bashref.info, Node: Commands For History, Next: Commands For Text, Prev: Commands For Moving, Up: Bindable Readline Commands @@ -6478,7 +6454,6 @@ Commands For Manipulating The History through the history list, inserting the last argument of each line in turn. -  File: bashref.info, Node: Commands For Text, Next: Commands For Killing, Prev: Commands For History, Up: Bindable Readline Commands @@ -6543,7 +6518,6 @@ Commands For Changing Text By default, this command is unbound. -  File: bashref.info, Node: Commands For Killing, Next: Numeric Arguments, Prev: Commands For Text, Up: Bindable Readline Commands @@ -6724,7 +6698,6 @@ Letting Readline Type For You completions enclosed within braces so the list is available to the shell (*note Brace Expansion::). -  File: bashref.info, Node: Keyboard Macros, Next: Miscellaneous Commands, Prev: Commands For Completion, Up: Bindable Readline Commands @@ -6742,7 +6715,6 @@ Keyboard Macros Re-execute the last keyboard macro defined, by making the characters in the macro appear as if typed at the keyboard. -  File: bashref.info, Node: Miscellaneous Commands, Prev: Keyboard Macros, Up: Bindable Readline Commands @@ -6877,7 +6849,6 @@ Some Miscellaneous Commands result as shell commands. Bash attempts to invoke `$VISUAL', `$EDITOR', and `emacs' as the editor, in that order. -  File: bashref.info, Node: Readline vi Mode, Next: Programmable Completion, Prev: Bindable Readline Commands, Up: Command Line Editing @@ -7210,7 +7181,6 @@ completion facilities. for a NAME for which no specification exists, or an error occurs adding a completion specification. -  File: bashref.info, Node: Using History Interactively, Next: Command Line Editing, Prev: Job Control, Up: Top @@ -7369,12 +7339,10 @@ and history file. The ARGs are added to the end of the history list as a single entry. - When any of the `-w', `-r', `-a', or `-n' options is used, if FILENAME is given, then it is used as the history file. If not, then the value of the `HISTFILE' variable is used. -  File: bashref.info, Node: History Interaction, Prev: Bash History Builtins, Up: Using History Interactively @@ -7464,7 +7432,6 @@ history list. `!#' The entire command line typed so far. -  File: bashref.info, Node: Word Designators, Next: Modifiers, Prev: Event Designators, Up: History Interaction @@ -7523,7 +7490,6 @@ line separated by single spaces. `X-' Abbreviates `X-$' like `X*', but omits the last word. - If a word designator is supplied without an event specification, the previous command is used as the event. @@ -7578,7 +7544,6 @@ more of the following modifiers, each preceded by a `:'. `G' Apply the following `s' modifier once to each word in the event. -  File: bashref.info, Node: Installing Bash, Next: Reporting Bugs, Prev: Command Line Editing, Up: Top @@ -8012,7 +7977,6 @@ does not provide the necessary support. Specification, version 2. *Note Bash Builtins::, for a description of the escape sequences that `echo' recognizes. - The file `config-top.h' contains C Preprocessor `#define' statements for options which are not settable from `configure'. Some of these are not meant to be changed; beware of the consequences if you do. Read @@ -9266,7 +9230,7 @@ Concept Index  Tag Table: -Node: Top1359 +Node: Top1357 Node: Introduction3504 Node: What is Bash?3729 Node: What is a shell?4817 @@ -9287,108 +9251,108 @@ Node: Pipelines20515 Node: Lists22381 Node: Compound Commands24003 Node: Looping Constructs24775 -Node: Conditional Constructs27209 -Node: Command Grouping34262 -Node: Shell Functions35698 -Node: Shell Parameters39960 -Node: Positional Parameters41531 -Node: Special Parameters42422 -Node: Shell Expansions45080 -Node: Brace Expansion47000 -Node: Tilde Expansion49316 -Node: Shell Parameter Expansion51648 -Node: Command Substitution58902 -Node: Arithmetic Expansion60224 -Node: Process Substitution61065 -Node: Word Splitting62102 -Node: Filename Expansion63554 -Node: Pattern Matching65678 -Node: Quote Removal68999 -Node: Redirections69285 -Node: Executing Commands76760 -Node: Simple Command Expansion77427 -Node: Command Search and Execution79348 -Node: Command Execution Environment81345 -Node: Environment84107 -Node: Exit Status85758 -Node: Signals86953 -Node: Shell Scripts88908 -Node: Shell Builtin Commands91419 -Node: Bourne Shell Builtins92994 -Node: Bash Builtins109942 -Node: The Set Builtin138064 -Node: Special Builtins146282 -Node: Shell Variables147254 -Node: Bourne Shell Variables147690 -Node: Bash Variables149667 -Node: Bash Features169378 -Node: Invoking Bash170260 -Node: Bash Startup Files176071 -Node: Interactive Shells180941 -Node: What is an Interactive Shell?181343 -Node: Is this Shell Interactive?181978 -Node: Interactive Shell Behavior182784 -Node: Bash Conditional Expressions186051 -Node: Shell Arithmetic189471 -Node: Aliases192211 -Node: Arrays194774 -Node: The Directory Stack197794 -Node: Directory Stack Builtins198500 -Node: Printing a Prompt201379 -Node: The Restricted Shell204088 -Node: Bash POSIX Mode205913 -Node: Job Control212559 -Node: Job Control Basics213025 -Node: Job Control Builtins217310 -Node: Job Control Variables221622 -Node: Command Line Editing222772 -Node: Introduction and Notation223770 -Node: Readline Interaction225387 -Node: Readline Bare Essentials226573 -Node: Readline Movement Commands228353 -Node: Readline Killing Commands229309 -Node: Readline Arguments231218 -Node: Searching232253 -Node: Readline Init File234430 -Node: Readline Init File Syntax235484 -Node: Conditional Init Constructs247128 -Node: Sample Init File249652 -Node: Bindable Readline Commands252835 -Node: Commands For Moving254034 -Node: Commands For History254883 -Node: Commands For Text257772 -Node: Commands For Killing260433 -Node: Numeric Arguments262563 -Node: Commands For Completion263690 -Node: Keyboard Macros267271 -Node: Miscellaneous Commands267830 -Node: Readline vi Mode273129 -Node: Programmable Completion274038 -Node: Programmable Completion Builtins279845 -Node: Using History Interactively287207 -Node: Bash History Facilities287886 -Node: Bash History Builtins290576 -Node: History Interaction294428 -Node: Event Designators296979 -Node: Word Designators297983 -Node: Modifiers299613 -Node: Installing Bash301010 -Node: Basic Installation302144 -Node: Compilers and Options304829 -Node: Compiling For Multiple Architectures305563 -Node: Installation Names307220 -Node: Specifying the System Type308031 -Node: Sharing Defaults308740 -Node: Operation Controls309405 -Node: Optional Features310356 -Node: Reporting Bugs318628 -Node: Major Differences From The Bourne Shell319803 -Node: Copying This Manual335551 -Node: GNU Free Documentation License335805 -Node: Builtin Index358198 -Node: Reserved Word Index361825 -Node: Variable Index363301 -Node: Function Index370351 -Node: Concept Index374964 +Node: Conditional Constructs27208 +Node: Command Grouping34260 +Node: Shell Functions35696 +Node: Shell Parameters39958 +Node: Positional Parameters41529 +Node: Special Parameters42420 +Node: Shell Expansions45078 +Node: Brace Expansion46998 +Node: Tilde Expansion49314 +Node: Shell Parameter Expansion51645 +Node: Command Substitution58898 +Node: Arithmetic Expansion60220 +Node: Process Substitution61061 +Node: Word Splitting62098 +Node: Filename Expansion63550 +Node: Pattern Matching65674 +Node: Quote Removal68995 +Node: Redirections69281 +Node: Executing Commands76755 +Node: Simple Command Expansion77422 +Node: Command Search and Execution79343 +Node: Command Execution Environment81340 +Node: Environment84102 +Node: Exit Status85753 +Node: Signals86948 +Node: Shell Scripts88903 +Node: Shell Builtin Commands91414 +Node: Bourne Shell Builtins92989 +Node: Bash Builtins109937 +Node: The Set Builtin138054 +Node: Special Builtins146272 +Node: Shell Variables147244 +Node: Bourne Shell Variables147680 +Node: Bash Variables149656 +Node: Bash Features169365 +Node: Invoking Bash170247 +Node: Bash Startup Files176056 +Node: Interactive Shells180926 +Node: What is an Interactive Shell?181328 +Node: Is this Shell Interactive?181969 +Node: Interactive Shell Behavior182775 +Node: Bash Conditional Expressions186042 +Node: Shell Arithmetic189461 +Node: Aliases192201 +Node: Arrays194764 +Node: The Directory Stack197784 +Node: Directory Stack Builtins198490 +Node: Printing a Prompt201368 +Node: The Restricted Shell204077 +Node: Bash POSIX Mode205902 +Node: Job Control212548 +Node: Job Control Basics213014 +Node: Job Control Builtins217299 +Node: Job Control Variables221610 +Node: Command Line Editing222759 +Node: Introduction and Notation223757 +Node: Readline Interaction225374 +Node: Readline Bare Essentials226560 +Node: Readline Movement Commands228340 +Node: Readline Killing Commands229296 +Node: Readline Arguments231204 +Node: Searching232239 +Node: Readline Init File234416 +Node: Readline Init File Syntax235470 +Node: Conditional Init Constructs247111 +Node: Sample Init File249635 +Node: Bindable Readline Commands252818 +Node: Commands For Moving254017 +Node: Commands For History254865 +Node: Commands For Text257753 +Node: Commands For Killing260413 +Node: Numeric Arguments262543 +Node: Commands For Completion263670 +Node: Keyboard Macros267250 +Node: Miscellaneous Commands267808 +Node: Readline vi Mode273106 +Node: Programmable Completion274015 +Node: Programmable Completion Builtins279822 +Node: Using History Interactively287183 +Node: Bash History Facilities287862 +Node: Bash History Builtins290552 +Node: History Interaction294402 +Node: Event Designators296953 +Node: Word Designators297956 +Node: Modifiers299585 +Node: Installing Bash300981 +Node: Basic Installation302115 +Node: Compilers and Options304800 +Node: Compiling For Multiple Architectures305534 +Node: Installation Names307191 +Node: Specifying the System Type308002 +Node: Sharing Defaults308711 +Node: Operation Controls309376 +Node: Optional Features310327 +Node: Reporting Bugs318598 +Node: Major Differences From The Bourne Shell319773 +Node: Copying This Manual335521 +Node: GNU Free Documentation License335775 +Node: Builtin Index358168 +Node: Reserved Word Index361795 +Node: Variable Index363271 +Node: Function Index370321 +Node: Concept Index374934  End Tag Table diff --git a/doc/texinfo.tex b/doc/texinfo.tex deleted file mode 120000 index 1d74826..0000000 --- a/doc/texinfo.tex +++ /dev/null @@ -1 +0,0 @@ -texinfo.tex.20030205 \ No newline at end of file diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..555a077 --- /dev/null +++ b/doc/texinfo.tex @@ -0,0 +1,6688 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2003-02-03.16} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +% +% This texinfo.tex file 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 texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +% In other words, you are welcome to use, share and improve this program. +% You are forbidden to forbid anyone else to use, share and improve +% what you give them. Help stamp out software-hoarding! +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% ftp://ftp.gnu.org/gnu/texinfo/texinfo.tex +% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html) +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org), +% and /home/gd/gnu/doc/texinfo.tex on the GNU machines. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. +% +% The texinfo.tex in any given Texinfo distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\message{Basics,} +\chardef\other=12 + +% We never want plain's outer \+ definition in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some parts of plain tex whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi + +% In some macros, we cannot use the `\? notation---the left quote is +% in some cases the escape char. +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dotChar = `\. +\chardef\equalChar = `\= +\chardef\exclamChar= `\! +\chardef\questChar = `\? +\chardef\semiChar = `\; +\chardef\spaceChar = `\ % +\chardef\underChar = `\_ + +% Ignore a token. +% +\def\gobble#1{} + +% True if #1 is the empty string, i.e., called like `\ifempty{}'. +% +\def\ifempty#1{\ifemptyx #1\emptymarkA\emptymarkB}% +\def\ifemptyx#1#2\emptymarkB{\ifx #1\emptymarkA}% + +% Hyphenation fixes. +\hyphenation{ap-pen-dix} +\hyphenation{mini-buf-fer mini-buf-fers} +\hyphenation{eshell} +\hyphenation{white-space} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines\maxdimen +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \escapechar = `\\ % use backslash in output files. + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfmkdest{\the\pageno} \fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \normalturnoffactive + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg#1{% + \let\next = #1% + \begingroup + \obeylines + \futurelet\temp\parseargx +} + +% If the next token is an obeyed space (from an @example environment or +% the like), remove it and recurse. Otherwise, we're done. +\def\parseargx{% + % \obeyedspace is defined far below, after the definition of \sepspaces. + \ifx\obeyedspace\temp + \expandafter\parseargdiscardspace + \else + \expandafter\parseargline + \fi +} + +% Remove a single space (as the delimiter token to the macro call). +{\obeyspaces % + \gdef\parseargdiscardspace {\futurelet\temp\parseargx}} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + % + % First remove any @c comment, then any @comment. + % Result of each macro is put in \toks0. + \argremovec #1\c\relax % + \expandafter\argremovecomment \the\toks0 \comment\relax % + % + % Call the caller's macro, saved as \next in \parsearg. + \expandafter\next\expandafter{\the\toks0}% + }% +} + +% Since all \c{,omment} does is throw away the argument, we can let TeX +% do that for us. The \relax here is matched by the \relax in the call +% in \parseargline; it could be more or less anything, its purpose is +% just to delimit the argument to the \c. +\def\argremovec#1\c#2\relax{\toks0 = {#1}} +\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}} + +% \argremovec{,omment} might leave us with trailing spaces, though; e.g., +% @end itemize @c foo +% will have two active spaces as part of the argument with the +% `itemize'. Here we remove all active spaces from #1, and assign the +% result to \toks0. +% +% This loses if there are any *other* active characters besides spaces +% in the argument -- _ ^ +, for example -- since they get expanded. +% Fortunately, Texinfo does not define any such commands. (If it ever +% does, the catcode of the characters in questionwill have to be changed +% here.) But this means we cannot call \removeactivespaces as part of +% \argremovec{,omment}, since @c uses \parsearg, and thus the argument +% that \parsearg gets might well have any character at all in it. +% +\def\removeactivespaces#1{% + \begingroup + \ignoreactivespaces + \edef\temp{#1}% + \global\toks0 = \expandafter{\temp}% + \endgroup +} + +% Change the active space to expand to nothing. +% +\begingroup + \obeyspaces + \gdef\ignoreactivespaces{\obeyspaces\let =\empty} +\endgroup + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +%% These are used to keep @begin/@end levels from running away +%% Call \inENV within environments (after a \begingroup) +\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi} +\def\ENVcheck{% +\ifENV\errmessage{Still within an environment; press RETURN to continue} +\endgroup\fi} % This is not perfect, but it should reduce lossage + +% @begin foo is the same as @foo, for now. +\newhelp\EMsimple{Press RETURN to continue.} + +\outer\def\begin{\parsearg\beginxxx} + +\def\beginxxx #1{% +\expandafter\ifx\csname #1\endcsname\relax +{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else +\csname #1\endcsname\fi} + +% @end foo executes the definition of \Efoo. +% +\def\end{\parsearg\endxxx} +\def\endxxx #1{% + \removeactivespaces{#1}% + \edef\endthing{\the\toks0}% + % + \expandafter\ifx\csname E\endthing\endcsname\relax + \expandafter\ifx\csname \endthing\endcsname\relax + % There's no \foo, i.e., no ``environment'' foo. + \errhelp = \EMsimple + \errmessage{Undefined command `@end \endthing'}% + \else + \unmatchedenderror\endthing + \fi + \else + % Everything's ok; the right environment has been started. + \csname E\endthing\endcsname + \fi +} + +% There is an environment #1, but it hasn't been started. Give an error. +% +\def\unmatchedenderror#1{% + \errhelp = \EMsimple + \errmessage{This `@end #1' doesn't have a matching `@#1'}% +} + +% Define the control sequence \E#1 to give an unmatched @end error. +% +\def\defineunmatchedend#1{% + \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}% +} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux file. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=3000 } + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=3000 } + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=3000 } + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\def\group{\begingroup + \ifnum\catcode13=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + % + % The \vtop we start below produces a box with normal height and large + % depth; thus, TeX puts \baselineskip glue before it, and (when the + % next line of text is done) \lineskip glue after it. (See p.82 of + % the TeXbook.) Thus, space below is not quite equal to space + % above. But it's pretty close. + \def\Egroup{% + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \copy\groupbox + \endgroup % End the \group. + }% + % + \setbox\groupbox = \vtop\bgroup + % We have to put a strut on the last line in case the @group is in + % the midst of an example, rather than completely enclosing it. + % Otherwise, the interline space between the last line of the group + % and the first line afterwards is too small. But we can't put the + % strut in \Egroup, since there it would be on a line by itself. + % Hence this just inserts a strut at the beginning of each line. + \everypar = {\strut}% + % + % Since we have a strut on every line, we don't need any of TeX's + % normal interline spacing. + \offinterlineskip + % + % OK, but now we have to do something about blank + % lines in the input in @example-like environments, which normally + % just turn into \lisppar, which will insert no space now that we've + % turned off the interline space. Simplest is to make them be an + % empty paragraph. + \ifx\par\lisppar + \edef\par{\leavevmode \par}% + % + % Reset ^^M's definition to new definition of \par. + \obeylines + \fi + % + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +\def\need{\parsearg\needx} + +% Old definition--didn't work. +%\def\needx #1{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\def\needx#1{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break + +\let\br = \par + +% @dots{} output an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \leavevmode + \hbox to 2em{% + \hskip 0pt plus 0.25fil minus 0.25fil + .\hss.\hss.\hss.% + \hskip 0pt plus 0.5fil minus 0.5fil + }% + \spacefactor=3000 +} + + +% @page forces the start of a new page +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\def\exdent{\parsearg\exdentyyy} +\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}} + +% This defn is used inside nofill environments such as @example. +\def\nofillexdent{\parsearg\nofillexdentyyy} +\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount +\leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% Allow normal characters that we make active in the argument (a file name). +\def\include{\begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\includezzz} +% Restore active chars for included file. +\def\includezzz#1{\endgroup\begingroup + % Read the included file in a group so nested @include's work. + \def\thisfile{#1}% + \let\value=\expandablevalue + \input\thisfile +\endgroup} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\def\center{\parsearg\docenter} +\def\docenter#1{{% + \ifhmode \hfil\break \fi + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{\hfil \ignorespaces#1\unskip \hfil}% + \ifhmode \break \fi +}} + +% @sp n outputs n lines of vertical space + +\def\sp{\parsearg\spxxx} +\def\spxxx #1{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% We cannot implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\def\paragraphindent{\parsearg\doparagraphindent} +\def\doparagraphindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\def\exampleindent{\parsearg\doexampleindent} +\def\doexampleindent#1{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% We don't use $'s directly in the definition of \math because we need +% to set catcodes according to plain TeX first, to allow for subscripts, +% superscripts, special math chars, etc. +% +\let\implicitmath = $%$ font-lock fix +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ within @math be active (mathcode "8000), and distinguish by seeing +% if the current family is \slfam, which is what @var uses. +% +{\catcode\underChar = \active +\gdef\mathunderscore{% + \catcode\underChar=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% +}} +% +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathcode`\_="8000 \mathunderscore + \let\\ = \mathbackslash + \mathactive + \implicitmath\finishmath} +\def\finishmath#1{#1\implicitmath\Etex} + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an +% argument to a command which set the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{\implicitmath\ptexbullet\implicitmath} +\def\minus{\implicitmath-\implicitmath} + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \iflinks + \readauxfile + \fi % \openindices needs to do some work in any case. + \openindices + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \global\let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + % Just to be on the safe side, close the input stream before the \input. + \openin 1 texinfo.cnf + \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi + \closein1 + \temp + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +\ifx\pdfoutput\undefined + \pdffalse + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\else + \pdftrue + \pdfoutput = 1 + \input pdfcolor + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}% + \def\imageheight{#3}% + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifx\empty\imagewidth\else width \imagewidth \fi + \ifx\empty\imageheight\else height \imageheight \fi + \ifnum\pdftexversion<13 + #1.pdf% + \else + {#1.pdf}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{{\normalturnoffactive \pdfdest name{#1} xyz}} + \def\pdfmkpgn#1{#1} + \let\linkcolor = \Blue % was Cyan, but that seems light? + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + \def\pdfmakeoutlines{{% + \openin 1 \jobname.toc + \ifeof 1\else\begingroup + \closein 1 + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + \def\chapentry ##1##2##3{} + \def\secentry ##1##2##3##4{\advancenumber{chap##2}} + \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}} + \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \input \jobname.toc + \def\chapentry ##1##2##3{% + \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}} + \def\secentry ##1##2##3##4{% + \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}} + \def\subsecentry ##1##2##3##4##5{% + \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}} + \def\subsubsecentry ##1##2##3##4##5##6{% + \pdfoutline goto name{\pdfmkpgn{##6}}{##1}} + \let\appendixentry = \chapentry + \let\unnumbchapentry = \chapentry + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + % + % Make special characters normal for writing to the pdf file. + % + \indexnofonts + \let\tt=\relax + \turnoffactive + \input \jobname.toc + \endgroup\fi + }} + \def\makelinks #1,{% + \def\params{#1}\def\E{END}% + \ifx\params\E + \let\nextmakelinks=\relax + \else + \let\nextmakelinks=\makelinks + \ifnum\lnkcount>0,\fi + \picknum{#1}% + \startlink attr{/Border [0 0 0]} + goto name{\pdfmkpgn{\the\pgn}}% + \linkcolor #1% + \advance\lnkcount by 1% + \endlink + \fi + \nextmakelinks + } + \def\picknum#1{\expandafter\pn#1} + \def\pn#1{% + \def\p{#1}% + \ifx\p\lbrace + \let\nextpn=\ppn + \else + \let\nextpn=\ppnn + \def\first{#1} + \fi + \nextpn + } + \def\ppn#1{\pgn=#1\gobble} + \def\ppnn{\pgn=\first} + \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + \def\pdfurl#1{% + \begingroup + \normalturnoffactive\def\@{@}% + \let\value=\expandablevalue + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + % #1 + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS| + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \linkcolor #1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi % \ifx\pdfoutput + + +\message{fonts,} +% Font-change commands. + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf analogous to plain's \rm, etc. +\newfam\sffam +\def\sf{\fam=\sffam \tensf} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this one. +\def\ttsl{\tenttsl} + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +\newcount\mainmagstep +\ifx\bigger\relax + % not really supported. + \mainmagstep=\magstep1 + \setfont\textrm\rmshape{12}{1000} + \setfont\texttt\ttshape{12}{1000} +\else + \mainmagstep=\magstephalf + \setfont\textrm\rmshape{10}{\mainmagstep} + \setfont\texttt\ttshape{10}{\mainmagstep} +\fi +% Instead of cmb10, you may want to use cmbx10. +% cmbx10 is a prettier font on its own, but cmb10 +% looks better when embedded in a line with cmr10 +% (in Bob's opinion). +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun, etc. +\setfont\defbf\bxshape{10}{\magstep1} %was 1314 +\setfont\deftt\ttshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page: +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter (and unnumbered) fonts (17.28pt). +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% Subsection fonts (13.15pt). +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{\magstep1} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 +% The smallcaps and symbol fonts should actually be scaled \magstep1.5, +% but that is not a standard magnification. + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this so that font changes will continue to work +% in math mode, where it is the current \fam that is relevant in most +% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam +% \tenbf}, for example. By redefining \tenbf, we obviate the need to +% redefine \bf itself. +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf? +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \smallerfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish we used A4 paper on this side of the Atlantic. +% +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bxshape{12}{1000} +\setfont\shortcontsl\slshape{12}{1000} +\setfont\shortconttt\ttshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic +\let\cite=\smartslanted + +\def\b#1{{\bf #1}} +\let\strong=\b + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\catcode`@=11 + \def\frenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + } +\catcode`@=\other + +\def\t#1{% + {\tt \rawbackslash \frenchspacing #1}% + \null +} +\let\ttfont=\t +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \frenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in \code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \let-\codedash + \catcode`\_=\active \let_\codeunder + \codex + } + % + % If we end up with any active - characters when handling the index, + % just treat them as a normal -. + \global\def\indexbreaks{\catcode`\-=\active \let-\realdash} +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\def\kbdinputstyle{\parsearg\kbdinputstylexxx} +\def\kbdinputstylexxx#1{% + \def\arg{#1}% + \ifx\arg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\arg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\arg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle `\arg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @url, @env, @command quotes seem unnecessary, so use \code. +\let\url=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym downcases the argument and prints in smallcaps. +\def\acronym#1{{\smallcaps \lowercase{#1}}} + +% @pounds{} is a sterling sign. +\def\pounds{{\it\$}} + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\def\shorttitlepage{\parsearg\shorttitlepagezzz} +\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\def\titlepage{\begingroup \parindent=0pt \textfonts + \let\subtitlerm=\tenrm + \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}% + % + \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt}% + % + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % + % Now you can print the title using @title. + \def\title{\parsearg\titlezzz}% + \def\titlezzz##1{\leftline{\titlefonts\rm ##1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt}% + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Now you can put text using @subtitle. + \def\subtitle{\parsearg\subtitlezzz}% + \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}% + % + % @author should come last, but may come many times. + \def\author{\parsearg\authorzzz}% + \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi + {\authorfont \leftline{##1}}}% + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \oldpage + \let\page = \oldpage + \hbox{}}% +% \def\page{\oldpage \hbox{}} +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make Tex use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + +\def\evenheading{\parsearg\evenheadingxxx} +\def\oddheading{\parsearg\oddheadingxxx} +\def\everyheading{\parsearg\everyheadingxxx} + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\oddfooting{\parsearg\oddfootingxxx} +\def\everyfooting{\parsearg\everyfootingxxx} + +{\catcode`\@=0 % + +\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish} +\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish} +\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish} +\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish} +\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}} +% +}% unbind the catcode of @. + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{ +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{ +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg\settitlezzz} +\def\settitlezzz #1{\gdef\thistitle{#1}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @vtable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz} +\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz} + +\def\internalBkitem{\smallbreak \parsearg\kitemzzz} +\def\internalBkitemx{\itemxpar \parsearg\kitemzzz} + +\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}% + \itemzzz {#1}} + +\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}% + \itemzzz {#1}} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemfont{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. (Unfortunately + % we can't prevent a possible page break at the following + % \baselineskip glue.) However, if what follows is an environment + % such as @example, there will be no \parskip glue; then + % the negative vskip we just would cause the example and the item to + % crash together. So we use this bizarre value of 10001 as a signal + % to \aboveenvbreak to insert \parskip glue after all. + % (Possibly there are other commands that could be followed by + % @example which need the same treatment, but not section titles; or + % maybe section titles are the only special case and they should be + % penalty 10001...) + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a table}} +\def\itemx{\errmessage{@itemx while not in a table}} +\def\kitem{\errmessage{@kitem while not in a table}} +\def\kitemx{\errmessage{@kitemx while not in a table}} +\def\xitem{\errmessage{@xitem while not in a table}} +\def\xitemx{\errmessage{@xitemx while not in a table}} + +% Contains a kludge to get @end[description] to work. +\def\description{\tablez{\dontindex}{1}{}{}{}{}} + +% @table, @ftable, @vtable. +\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex} +{\obeylines\obeyspaces% +\gdef\tablex #1^^M{% +\tabley\dontindex#1 \endtabley}} + +\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex} +{\obeylines\obeyspaces% +\gdef\ftablex #1^^M{% +\tabley\fnitemindex#1 \endtabley +\def\Eftable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex} +{\obeylines\obeyspaces% +\gdef\vtablex #1^^M{% +\tabley\vritemindex#1 \endtabley +\def\Evtable{\endgraf\afterenvbreak\endgroup}% +\let\Etable=\relax}} + +\def\dontindex #1{} +\def\fnitemindex #1{\doind {fn}{\code{#1}}}% +\def\vritemindex #1{\doind {vr}{\code{#1}}}% + +{\obeyspaces % +\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup% +\tablez{#1}{#2}{#3}{#4}{#5}{#6}}} + +\def\tablez #1#2#3#4#5#6{% +\aboveenvbreak % +\begingroup % +\def\Edescription{\Etable}% Necessary kludge. +\let\itemindex=#1% +\ifnum 0#3>0 \advance \leftskip by #3\mil \fi % +\ifnum 0#4>0 \tableindent=#4\mil \fi % +\ifnum 0#5>0 \advance \rightskip by #5\mil \fi % +\def\itemfont{#2}% +\itemmax=\tableindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \tableindent % +\exdentamount=\tableindent +\parindent = 0pt +\parskip = \smallskipamount +\ifdim \parskip=0pt \parskip=2pt \fi% +\def\Etable{\endgraf\afterenvbreak\endgroup}% +\let\item = \internalBitem % +\let\itemx = \internalBitemx % +\let\kitem = \internalBkitem % +\let\kitemx = \internalBkitemx % +\let\xitem = \internalBxitem % +\let\xitemx = \internalBxitemx % +} + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\def\itemize{\parsearg\itemizezzz} + +\def\itemizezzz #1{% + \begingroup % ended by the @end itemize + \itemizey {#1}{\Eitemize} +} + +\def\itemizey #1#2{% +\aboveenvbreak % +\itemmax=\itemindent % +\advance \itemmax by -\itemmargin % +\advance \leftskip by \itemindent % +\exdentamount=\itemindent +\parindent = 0pt % +\parskip = \smallskipamount % +\ifdim \parskip=0pt \parskip=2pt \fi% +\def#2{\endgraf\afterenvbreak\endgroup}% +\def\itemcontents{#1}% +\let\item=\itemizeitem} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\def\enumerate{\parsearg\enumeratezzz} +\def\enumeratezzz #1{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + \begingroup % ended by the @end enumerate + % + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a . + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call itemizey, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \itemizey{#1.}\Eenumerate\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + +% Definition of @item while inside @itemize. + +\def\itemizeitem{% +\advance\itemno by 1 +{\let\par=\endgraf \smallbreak}% +\ifhmode \errmessage{In hmode at itemizeitem}\fi +{\parskip=0in \hskip 0pt +\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}% +\vadjust{\penalty 1200}}% +\flushcr} + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. +% +% For those who want to use more than one line's worth of words in +% the preamble, break the line within one argument and it +% will parse correctly, i.e., +% +% @multitable {Column 1 template} {Column 2 template} {Column 3 +% template} +% Not: +% @multitable {Column 1 template} {Column 2 template} +% {Column 3 template} + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab, @multitable or @end multitable do not need to be on their +% own lines, but it will not hurt if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the part of the @columnfraction before the decimal point, which +% is presumably either 0 or the empty string (but we don't check, we +% just throw it away). #2 is the decimal part, which we use as the +% percent of \hsize for this column. +\def\pickupwholefraction#1.#2 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% @multitable ... @end multitable definitions: +% +\def\multitable{\parsearg\dotable} +\def\dotable#1{\bgroup + \vskip\parskip + \let\item=\crcrwithfootnotes + % A \tab used to include \hskip1sp. But then the space in a template + % line is not enough. That is bad. So let's go back to just & until + % we encounter the problem it was intended to solve again. --karl, + % nathan@acm.org, 20apr99. + \let\tab=&% + \let\startfootins=\startsavedfootnote + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + \def\Emultitable{% + \global\setpercentfalse + \crcrwithfootnotes\crcr + \egroup\egroup + }% + % + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % \everycr will reset column counter, \colcount, at the end of + % each line. Every column entry will cause \colcount to advance by one. + % The table preamble + % looks at the current \colcount to find the correct column width. + \everycr{\noalign{% + % + % \filbreak%% keeps underfull box messages off when table breaks over pages. + % Maybe so, but it also creates really weird page breaks when the table + % breaks over pages. Wouldn't \vfil be better? Wait until the problem + % manifests itself, so it can be fixed for real --karl. + \global\colcount=0\relax}}% + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup&\global\advance\colcount by 1\relax + \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively marking + % characters. + \noindent\ignorespaces##\unskip\multistrut}\cr +} + +\def\setmultitablespacing{% test to see if user has set \multitablelinespace. +% If so, do nothing. If not, give it an appropriate dimension based on +% current baselineskip. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +%% strut to put in table in case some entry doesn't have descenders, +%% to keep lines equally spaced +\let\multistrut = \strut +\else +%% FIXME: what is \box0 supposed to be? +\gdef\multistrut{\vrule height\multitablelinespace depth\dp0 +width0pt\relax} \fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + +% In case a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is +% finished. Otherwise, the insertion is lost, it never migrates to the +% main vertical list. --kasal, 22jan03. +% +\newbox\savedfootnotes +% +% \dotable \let's \startfootins to this, so that \dofootnote will call +% it instead of starting the insertion right away. +\def\startsavedfootnote{% + \global\setbox\savedfootnotes = \vbox\bgroup + \unvbox\savedfootnotes +} +\def\crcrwithfootnotes{% + \crcr + \ifvoid\savedfootnotes \else + \noalign{\insert\footins{\box\savedfootnotes}}% + \fi +} + +\message{conditionals,} +% Prevent errors for section commands. +% Used in @ignore and in failing conditionals. +\def\ignoresections{% + \let\chapter=\relax + \let\unnumbered=\relax + \let\top=\relax + \let\unnumberedsec=\relax + \let\unnumberedsection=\relax + \let\unnumberedsubsec=\relax + \let\unnumberedsubsection=\relax + \let\unnumberedsubsubsec=\relax + \let\unnumberedsubsubsection=\relax + \let\section=\relax + \let\subsec=\relax + \let\subsubsec=\relax + \let\subsection=\relax + \let\subsubsection=\relax + \let\appendix=\relax + \let\appendixsec=\relax + \let\appendixsection=\relax + \let\appendixsubsec=\relax + \let\appendixsubsection=\relax + \let\appendixsubsubsec=\relax + \let\appendixsubsubsection=\relax + \let\contents=\relax + \let\smallbook=\relax + \let\titlepage=\relax +} + +% Used in nested conditionals, where we have to parse the Texinfo source +% and so want to turn off most commands, in case they are used +% incorrectly. +% +% We use \empty instead of \relax for the @def... commands, so that \end +% doesn't throw an error. For instance: +% @ignore +% @deffn ... +% @end deffn +% @end ignore +% +% The @end deffn is going to get expanded, because we're trying to allow +% nested conditionals. But we don't want to expand the actual @deffn, +% since it might be syntactically correct and intended to be ignored. +% Since \end checks for \relax, using \empty does not cause an error. +% +\def\ignoremorecommands{% + \let\defcodeindex = \relax + \let\defcv = \empty + \let\defcvx = \empty + \let\Edefcv = \empty + \let\deffn = \empty + \let\deffnx = \empty + \let\Edeffn = \empty + \let\defindex = \relax + \let\defivar = \empty + \let\defivarx = \empty + \let\Edefivar = \empty + \let\defmac = \empty + \let\defmacx = \empty + \let\Edefmac = \empty + \let\defmethod = \empty + \let\defmethodx = \empty + \let\Edefmethod = \empty + \let\defop = \empty + \let\defopx = \empty + \let\Edefop = \empty + \let\defopt = \empty + \let\defoptx = \empty + \let\Edefopt = \empty + \let\defspec = \empty + \let\defspecx = \empty + \let\Edefspec = \empty + \let\deftp = \empty + \let\deftpx = \empty + \let\Edeftp = \empty + \let\deftypefn = \empty + \let\deftypefnx = \empty + \let\Edeftypefn = \empty + \let\deftypefun = \empty + \let\deftypefunx = \empty + \let\Edeftypefun = \empty + \let\deftypeivar = \empty + \let\deftypeivarx = \empty + \let\Edeftypeivar = \empty + \let\deftypemethod = \empty + \let\deftypemethodx = \empty + \let\Edeftypemethod = \empty + \let\deftypeop = \empty + \let\deftypeopx = \empty + \let\Edeftypeop = \empty + \let\deftypevar = \empty + \let\deftypevarx = \empty + \let\Edeftypevar = \empty + \let\deftypevr = \empty + \let\deftypevrx = \empty + \let\Edeftypevr = \empty + \let\defun = \empty + \let\defunx = \empty + \let\Edefun = \empty + \let\defvar = \empty + \let\defvarx = \empty + \let\Edefvar = \empty + \let\defvr = \empty + \let\defvrx = \empty + \let\Edefvr = \empty + \let\clear = \relax + \let\down = \relax + \let\evenfooting = \relax + \let\evenheading = \relax + \let\everyfooting = \relax + \let\everyheading = \relax + \let\headings = \relax + \let\include = \relax + \let\item = \relax + \let\lowersections = \relax + \let\oddfooting = \relax + \let\oddheading = \relax + \let\printindex = \relax + \let\pxref = \relax + \let\raisesections = \relax + \let\ref = \relax + \let\set = \relax + \let\setchapternewpage = \relax + \let\setchapterstyle = \relax + \let\settitle = \relax + \let\up = \relax + \let\verbatiminclude = \relax + \let\xref = \relax +} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescriptionword{documentdescription} +\def\documentdescription{\doignore{documentdescription}} +\def\html{\doignore{html}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory = \comment + +% Ignore text until a line `@end #1'. +% +\def\doignore#1{\begingroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define a command to swallow text until we reach `@end #1'. + % This @ is a catcode 12 token (that is the normal catcode of @ in + % this texinfo.tex file). We change the catcode of @ below to match. + \long\def\doignoretext##1@end #1{\enddoignore}% + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \catcode\spaceChar = 10 + % + % Ignore braces, too, so mismatched braces don't cause trouble. + \catcode`\{ = 9 + \catcode`\} = 9 + % + % We must not have @c interpreted as a control sequence. + \catcode`\@ = 12 + % + \def\ignoreword{#1}% + \ifx\ignoreword\documentdescriptionword + % The c kludge breaks documentdescription, since + % `documentdescription' contains a `c'. Means not everything will + % be ignored inside @documentdescription, but oh well... + \else + % Make the letter c a comment character so that the rest of the line + % will be ignored. This way, the document can have (for example) + % @c @end ifinfo + % and the @end ifinfo will be properly ignored. + % (We've just changed @ to catcode 12.) + \catcode`\c = 14 + \fi + % + % And now expand the command defined above. + \doignoretext +} + +% What we do to finish off ignored text. +% +\def\enddoignore{\endgroup\ignorespaces}% + +\newif\ifwarnedobs\warnedobsfalse +\def\obstexwarn{% + \ifwarnedobs\relax\else + % We need to warn folks that they may have trouble with TeX 3.0. + % This uses \immediate\write16 rather than \message to get newlines. + \immediate\write16{} + \immediate\write16{WARNING: for users of Unix TeX 3.0!} + \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).} + \immediate\write16{If you are running another version of TeX, relax.} + \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.} + \immediate\write16{ Then upgrade your TeX installation if you can.} + \immediate\write16{ (See ftp://ftp.gnu.org/non-gnu/TeX.README.)} + \immediate\write16{If you are stuck with version 3.0, run the} + \immediate\write16{ script ``tex3patch'' from the Texinfo distribution} + \immediate\write16{ to use a workaround.} + \immediate\write16{} + \global\warnedobstrue + \fi +} + +% **In TeX 3.0, setting text in \nullfont hangs tex. For a +% workaround (which requires the file ``dummy.tfm'' to be installed), +% uncomment the following line: +%%%%%\font\nullfont=dummy\let\obstexwarn=\relax + +% Ignore text, except that we keep track of conditional commands for +% purposes of nesting, up to an `@end #1' command. +% +\def\nestedignore#1{% + \obstexwarn + % We must actually expand the ignored text to look for the @end + % command, so that nested ignore constructs work. Thus, we put the + % text into a \vbox and then do nothing with the result. To minimize + % the chance of memory overflow, we follow the approach outlined on + % page 401 of the TeXbook. + % + \setbox0 = \vbox\bgroup + % Don't complain about control sequences we have declared \outer. + \ignoresections + % + % Define `@end #1' to end the box, which will in turn undefine the + % @end command again. + \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}% + % + % We are going to be parsing Texinfo commands. Most cause no + % trouble when they are used incorrectly, but some commands do + % complicated argument parsing or otherwise get confused, so we + % undefine them. + % + % We can't do anything about stray @-signs, unfortunately; + % they'll produce `undefined control sequence' errors. + \ignoremorecommands + % + % Set the current font to be \nullfont, a TeX primitive, and define + % all the font commands to also use \nullfont. We don't use + % dummy.tfm, as suggested in the TeXbook, because some sites + % might not have that installed. Therefore, math mode will still + % produce output, but that should be an extremely small amount of + % stuff compared to the main input. + % + \nullfont + \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont + \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont + \let\tensf=\nullfont + % Similarly for index fonts. + \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont + \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont + \let\smallsf=\nullfont + % Similarly for smallexample fonts. + \let\smallerrm=\nullfont \let\smallerit=\nullfont \let\smallersl=\nullfont + \let\smallerbf=\nullfont \let\smallertt=\nullfont \let\smallersc=\nullfont + \let\smallersf=\nullfont + % + % Don't complain when characters are missing from the fonts. + \tracinglostchars = 0 + % + % Don't bother to do space factor calculations. + \frenchspacing + % + % Don't report underfull hboxes. + \hbadness = 10000 + % + % Do minimal line-breaking. + \pretolerance = 10000 + % + % Do not execute instructions in @tex. + \def\tex{\doignore{tex}}% + % Do not execute macro definitions. + % `c' is a comment character, so the word `macro' will get cut off. + \def\macro{\doignore{ma}}% +} + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. Make sure the catcode of space is correct to avoid +% losing inside @example, for instance. +% +\def\set{\begingroup\catcode` =10 + \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR. + \parsearg\setxxx} +\def\setxxx#1{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + \def\temp{#2}% + \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty + \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted. + \fi + \endgroup +} +% Can't use \xdef to pre-expand #2 and save some time, since \temp or +% \next or other control sequences that we've defined might get us into +% an infinite loop. Consider `@set foo @cite{bar}'. +\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\def\clear{\parsearg\clearxxx} +\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax} + +% @value{foo} gets the text saved in variable foo. +{ + \catcode`\_ = \active + % + % We might end up with active _ or - characters in the argument if + % we're called from @code, as @code{@value{foo-bar_}}. So \let any + % such active characters to their normal equivalents. + \gdef\value{\begingroup + \catcode`\-=\other \catcode`\_=\other + \indexbreaks \let_\normalunderscore + \valuexxx} +} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we \let\value to this in \indexdummies). Ones +% whose names contain - or _ still won't work, but we can't do anything +% about that. The command has to be fully expandable (if the variable +% is set), since the result winds up in the index file. This means that +% if the variable's value contains other Texinfo commands, it's almost +% certain it will fail (although perhaps we could fix that with +% sufficient work to do a one-level expansion on the result, instead of +% complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +\def\ifset{\parsearg\doifset} +\def\doifset#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifsetfail + \else + \let\next=\ifsetsucceed + \fi + \next +} +\def\ifsetsucceed{\conditionalsucceed{ifset}} +\def\ifsetfail{\nestedignore{ifset}} +\defineunmatchedend{ifset} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +\def\ifclear{\parsearg\doifclear} +\def\doifclear#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \let\next=\ifclearsucceed + \else + \let\next=\ifclearfail + \fi + \next +} +\def\ifclearsucceed{\conditionalsucceed{ifclear}} +\def\ifclearfail{\nestedignore{ifclear}} +\defineunmatchedend{ifclear} + +% @iftex, @ifnothtml, @ifnotinfo, @ifnotplaintext always succeed; we +% read the text following, through the first @end iftex (etc.). Make +% `@end iftex' (etc.) valid only after an @iftex. +% +\def\iftex{\conditionalsucceed{iftex}} +\def\ifnothtml{\conditionalsucceed{ifnothtml}} +\def\ifnotinfo{\conditionalsucceed{ifnotinfo}} +\def\ifnotplaintext{\conditionalsucceed{ifnotplaintext}} +\defineunmatchedend{iftex} +\defineunmatchedend{ifnothtml} +\defineunmatchedend{ifnotinfo} +\defineunmatchedend{ifnotplaintext} + +% True conditional. Since \set globally defines its variables, we can +% just start and end a group (to keep the @end definition undefined at +% the outer level). +% +\def\conditionalsucceed#1{\begingroup + \expandafter\def\csname E#1\endcsname{\endgroup}% +} + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within \newindex. +{\catcode`\@=11 +\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % \definedummyword defines \#1 as \realbackslash #1\space, thus + % effectively preventing its expansion. This is used only for control + % words, not control letters, because the \space would be incorrect + % for control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% For the aux file, @ is the escape character. So we want to redefine +% everything using @ instead of \realbackslash. When everything uses +% @, this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % (See comments in \indexdummies.) + \def\definedummyword##1{% + \expandafter\def\csname ##1\endcsname{@##1\space}% + }% + \def\definedummyletter##1{% + \expandafter\def\csname ##1\endcsname{@##1}% + }% + % + % Do the redefinitions. + \commondummies +} + +% Called from \indexdummies and \atdummies. \definedummyword and +% \definedummyletter must be defined first. +% +\def\commondummies{% + % + \normalturnoffactive + % + % Control letters and accents. + \definedummyletter{_}% + \definedummyletter{,}% + \definedummyletter{"}% + \definedummyletter{`}% + \definedummyletter{'}% + \definedummyletter{^}% + \definedummyletter{~}% + \definedummyletter{=}% + \definedummyword{u}% + \definedummyword{v}% + \definedummyword{H}% + \definedummyword{dotaccent}% + \definedummyword{ringaccent}% + \definedummyword{tieaccent}% + \definedummyword{ubaraccent}% + \definedummyword{udotaccent}% + \definedummyword{dotless}% + % + % Other non-English letters. + \definedummyword{AA}% + \definedummyword{AE}% + \definedummyword{L}% + \definedummyword{OE}% + \definedummyword{O}% + \definedummyword{aa}% + \definedummyword{ae}% + \definedummyword{l}% + \definedummyword{oe}% + \definedummyword{o}% + \definedummyword{ss}% + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword{bf}% + \definedummyword{gtr}% + \definedummyword{hat}% + \definedummyword{less}% + \definedummyword{sf}% + \definedummyword{sl}% + \definedummyword{tclose}% + \definedummyword{tt}% + % + % Texinfo font commands. + \definedummyword{b}% + \definedummyword{i}% + \definedummyword{r}% + \definedummyword{sc}% + \definedummyword{t}% + % + \definedummyword{TeX}% + \definedummyword{acronym}% + \definedummyword{cite}% + \definedummyword{code}% + \definedummyword{command}% + \definedummyword{dfn}% + \definedummyword{dots}% + \definedummyword{emph}% + \definedummyword{env}% + \definedummyword{file}% + \definedummyword{kbd}% + \definedummyword{key}% + \definedummyword{math}% + \definedummyword{option}% + \definedummyword{samp}% + \definedummyword{strong}% + \definedummyword{uref}% + \definedummyword{url}% + \definedummyword{var}% + \definedummyword{w}% + % + % Assorted special characters. + \definedummyword{bullet}% + \definedummyword{copyright}% + \definedummyword{dots}% + \definedummyword{enddots}% + \definedummyword{equiv}% + \definedummyword{error}% + \definedummyword{expansion}% + \definedummyword{minus}% + \definedummyword{pounds}% + \definedummyword{point}% + \definedummyword{print}% + \definedummyword{result}% + % + % Handle some cases of @value -- where the variable name does not + % contain - or _, and the value does not contain any + % (non-fully-expandable) commands. + \let\value = \expandablevalue + % + % Normal spaces, not active ones. + \unsepspaces + % + % No macro expansion. + \turnoffmacros +} + +% If an index command is used in an @example environment, any spaces +% therein should become regular spaces in the raw index file, not the +% expansion of \tie (\leavevmode \penalty \@M \ ). +{\obeyspaces + \gdef\unsepspaces{\obeyspaces\let =\space}} + + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexdummytex{TeX} +\def\indexdummydots{...} +% +\def\indexnofonts{% + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + \let\,=\asis + \let\"=\asis + \let\`=\asis + \let\'=\asis + \let\^=\asis + \let\~=\asis + \let\==\asis + \let\u=\asis + \let\v=\asis + \let\H=\asis + \let\dotaccent=\asis + \let\ringaccent=\asis + \let\tieaccent=\asis + \let\ubaraccent=\asis + \let\udotaccent=\asis + \let\dotless=\asis + % + % Other non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + % Texinfo font commands. + \let\b=\asis + \let\i=\asis + \let\r=\asis + \let\sc=\asis + \let\t=\asis + % + \let\TeX=\indexdummytex + \let\acronym=\asis + \let\cite=\asis + \let\code=\asis + \let\command=\asis + \let\dfn=\asis + \let\dots=\indexdummydots + \let\emph=\asis + \let\env=\asis + \let\file=\asis + \let\kbd=\asis + \let\key=\asis + \let\math=\asis + \let\option=\asis + \let\samp=\asis + \let\strong=\asis + \let\uref=\asis + \let\url=\asis + \let\var=\asis + \let\w=\asis +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% For \ifx comparisons. +\def\emptymacro{\empty} + +% Most index entries go through here, but \dosubind is the general case. +% +\def\doind#1#2{\dosubind{#1}{#2}\empty} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% \empty if called from \doind, as we usually are. The main exception +% is with defuns, which call us directly. +% +\def\dosubind#1#2#3{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}% + \fi + {% + \count255=\lastpenalty + {% + \indexdummies % Must do this here, since \bf, etc expand at this stage + \escapechar=`\\ + {% + \let\folio = 0% We will expand all macros now EXCEPT \folio. + \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % The main index entry text. + \toks0 = {#2}% + % + % If third arg is present, precede it with space in sort key. + \def\thirdarg{#3}% + \ifx\thirdarg\emptymacro \else + % If the third (subentry) arg is present, add it to the index + % line to write. + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\csname#1indfile\endcsname{% + \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}% + }% + % + % If a skip is the last thing on the list now, preserve it + % by backing up by \lastskip, doing the \write, then inserting + % the skip again. Otherwise, the whatsit generated by the + % \write will make \lastskip zero. The result is that sequences + % like this: + % @end defun + % @tindex whatever + % @defun ... + % will have extra space inserted, because the \medbreak in the + % start of the @defun won't see the skip inserted by the @end of + % the previous defun. + % + % But don't do any of this if we're not in vertical mode. We + % don't want to do a \vskip and prematurely end a paragraph. + % + % Avoid page breaks due to these extra skips, too. + % + \iflinks + \ifvmode + \skip0 = \lastskip + \ifdim\lastskip = 0pt \else \nobreak\vskip-\skip0 \fi + \fi + % + \temp % do the write + % + \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi + \fi + }% + }% + \penalty\count255 + }% +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\def\printindex{\parsearg\doprintindex} +\def\doprintindex#1{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \indexbreaks + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\rawbackslashxx}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \penalty -300 + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + \vskip .33\baselineskip plus .1\baselineskip + % + % Do our best not to break after the initial. + \nobreak +}} + +% This typesets a paragraph consisting of #1, dot leaders, and then #2 +% flush to the right margin. It is used for index and table of contents +% entries. The paragraph is indented by \leftskip. +% +\def\entry#1#2{\begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing columns. + \vskip 0pt plus1pt + % + % Start a ``paragraph'' for the index entry so the line breaking + % parameters we've set above will have an effect. + \noindent + % + % Insert the text of the index entry. TeX will do line-breaking on it. + #1% + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#2}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd\ \else% + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + \ #2% The page number ends the paragraph. + \fi + \fi% + \par +\endgroup} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% \def\appendixletter{\char\the\appendixno} +% We do the following for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raise/lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% Choose a numbered-heading macro +% #1 is heading level if unmodified by @raisesections or @lowersections +% #2 is text for heading +\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \chapterzzz{#2} +\or + \seczzz{#2} +\or + \numberedsubseczzz{#2} +\or + \numberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \chapterzzz{#2} + \else + \numberedsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses appendix heading levels +\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \appendixzzz{#2} +\or + \appendixsectionzzz{#2} +\or + \appendixsubseczzz{#2} +\or + \appendixsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \appendixzzz{#2} + \else + \appendixsubsubseczzz{#2} + \fi +\fi +} + +% like \numhead, but chooses numberless heading levels +\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1 +\ifcase\absseclevel + \unnumberedzzz{#2} +\or + \unnumberedseczzz{#2} +\or + \unnumberedsubseczzz{#2} +\or + \unnumberedsubsubseczzz{#2} +\else + \ifnum \absseclevel<0 + \unnumberedzzz{#2} + \else + \unnumberedsubsubseczzz{#2} + \fi +\fi +} + +% @chapter, @appendix, @unnumbered. +\def\thischaptername{No Chapter Title} +\outer\def\chapter{\parsearg\chapteryyy} +\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}% + \chapmacro {#1}{\the\chapno}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. + \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% + \writetocentry{chap}{#1}{{\the\chapno}} + \donoderef + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +% we use \chapno to avoid indenting back +\def\appendixbox#1{% + \setbox0 = \hbox{\putwordAppendix{} \the\chapno}% + \hbox to \wd0{#1\hss}} + +\outer\def\appendix{\parsearg\appendixyyy} +\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + \global\advance \appendixno by 1 + \message{\putwordAppendix\space \appendixletter}% + \chapmacro {#1}{\appendixbox{\putwordAppendix{} \appendixletter}}% + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% + \writetocentry{appendix}{#1}{{\appendixletter}} + \appendixnoderef + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\def\centerchap{\parsearg\centerchapyyy} +\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}} + +% @top is like @unnumbered. +\outer\def\top{\parsearg\unnumberedyyy} + +\outer\def\unnumbered{\parsearg\unnumberedyyy} +\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz #1{% + \secno=0 \subsecno=0 \subsubsecno=0 + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the to achieve this: TeX expands \the only once, + % simply yielding the contents of . (We also do this for + % the toc entries.) + \toks0 = {#1}\message{(\the\toks0)}% + % + \unnumbchapmacro {#1}% + \gdef\thischapter{#1}\gdef\thissection{#1}% + \writetocentry{unnumbchap}{#1}{{\the\chapno}} + \unnumbnoderef + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% Sections. +\outer\def\numberedsec{\parsearg\secyyy} +\def\secyyy #1{\numhead1{#1}} % normally calls seczzz +\def\seczzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}% + \writetocentry{sec}{#1}{{\the\chapno}{\the\secno}} + \donoderef + \nobreak +} + +\outer\def\appendixsection{\parsearg\appendixsecyyy} +\outer\def\appendixsec{\parsearg\appendixsecyyy} +\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz #1{% + \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 % + \gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}% + \writetocentry{sec}{#1}{{\appendixletter}{\the\secno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy} +\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz #1{% + \plainsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsec}{#1}{{\the\chapno}{\the\secno}} + \unnumbnoderef + \nobreak +} + +% Subsections. +\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy} +\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy} +\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz #1{% + \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 % + \subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}% + \writetocentry{subsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy} +\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz #1{% + \plainsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}} + \unnumbnoderef + \nobreak +} + +% Subsubsections. +\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy} +\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \donoderef + \nobreak +} + +\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy} +\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz #1{% + \gdef\thissection{#1}\global\advance \subsubsecno by 1 % + \subsubsecheading {#1} + {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}% + \writetocentry{subsubsec}{#1}{{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \appendixnoderef + \nobreak +} + +\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy} +\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz #1{% + \plainsubsubsecheading {#1}\gdef\thissection{#1}% + \writetocentry{unnumbsubsubsec}{#1}{{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}} + \unnumbnoderef + \nobreak +} + +% These are variants which are not "outer", so they can appear in @ifinfo. +% Actually, they should now be obsolete; ordinary section commands should work. +\def\infotop{\parsearg\unnumberedzzz} +\def\infounnumbered{\parsearg\unnumberedzzz} +\def\infounnumberedsec{\parsearg\unnumberedseczzz} +\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz} +\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz} + +\def\infoappendix{\parsearg\appendixzzz} +\def\infoappendixsec{\parsearg\appendixseczzz} +\def\infoappendixsubsec{\parsearg\appendixsubseczzz} +\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz} + +\def\infochapter{\parsearg\chapterzzz} +\def\infosection{\parsearg\sectionzzz} +\def\infosubsection{\parsearg\subsectionzzz} +\def\infosubsubsection{\parsearg\subsubsectionzzz} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\global\let\section = \numberedsec +\global\let\subsection = \numberedsubsec +\global\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{\parsearg\majorheadingzzz} +\def\majorheadingzzz #1{% + {\advance\chapheadingskip by 10pt \chapbreak }% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +\def\chapheading{\parsearg\chapheadingzzz} +\def\chapheadingzzz #1{\chapbreak % + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\penalty 200} + +% @heading, @subheading, @subsubheading. +\def\heading{\parsearg\plainsecheading} +\def\subheading{\parsearg\plainsubsecheading} +\def\subsubheading{\parsearg\plainsubsubsecheading} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{ +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +\def\CHAPFplain{ +\global\let\chapmacro=\chfplain +\global\let\unnumbchapmacro=\unnchfplain +\global\let\centerchapmacro=\centerchfplain} + +% Plain chapter opening. +% #1 is the text, #2 the chapter number or empty if unnumbered. +\def\chfplain#1#2{% + \pchapsepmacro + {% + \chapfonts \rm + \def\chapnum{#2}% + \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}% + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% Plain opening for unnumbered. +\def\unnchfplain#1{\chfplain{#1}{}} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerchfplain#1{{% + \def\centerparametersmaybe{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt + }% + \chfplain{#1}{}% +}} + +\CHAPFplain % The default + +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} + +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} + +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} + +\def\CHAPFopen{ +\global\let\chapmacro=\chfopen +\global\let\unnumbchapmacro=\unnchfopen +\global\let\centerchapmacro=\centerchfopen} + + +% Section titles. +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip {-1000}} +\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}} +\def\plainsecheading#1{\sectionheading{sec}{}{#1}} + +% Subsection titles. +\newskip \subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}} +\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}} +\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}} + +% Subsubsection titles. +\let\subsubsecheadingskip = \subsecheadingskip +\let\subsubsecheadingbreak = \subsecheadingbreak +\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}} +\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}} + + +% Print any size section title. +% +% #1 is the section type (sec/subsec/subsubsec), #2 is the section +% number (maybe empty), #3 the text. +\def\sectionheading#1#2#3{% + {% + \expandafter\advance\csname #1headingskip\endcsname by \parskip + \csname #1headingbreak\endcsname + }% + {% + % Switch to the right set of fonts. + \csname #1fonts\endcsname \rm + % + % Only insert the separating space if we have a section number. + \def\secnum{#2}% + \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}% + % + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent = \wd0 % zero if no section number + \unhbox0 #3}% + }% + % Add extra space after the heading -- either a line space or a + % paragraph space, whichever is more. (Some people like to set + % \parskip to large values for some reason.) Don't allow stretch, though. + \nobreak + \ifdim\parskip>\normalbaselineskip + \kern\parskip + \else + \kern\normalbaselineskip + \fi + \nobreak +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. We supply {\folio} at the end of the +% argument, which will end up as the last argument to the \...entry macro. +% +% Usage: \writetocentry{chap}{The Name of The Game}{{\the\chapno}} +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% +\newif\iftocfileopened +\def\writetocentry#1#2#3{% + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + \toks0 = {#2}% + \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}#3{\folio}}}% + \temp + \fi + % + % Tell \shipout to create a page destination if we're doing pdf, which + % will be the target of the links in the table of contents. We can't + % just do it on every page because the title pages are numbered 1 and + % 2 (the page numbers aren't printed), and so are the first two pages + % of the document. Thus, we'd have two destinations named `1', and + % two named `2'. + \ifpdf \pdfmakepagedesttrue \fi +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Finish up the main text and prepare to read what we've written +% to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \unnumbchapmacro{#1}\def\thischapter{}% + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 + % We can't do this, because then an actual ^ in a section + % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. + %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \pdfmakeoutlines + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\chapentry = \shortchapentry + \let\appendixentry = \shortappendixentry + \let\unnumbchapentry = \shortunnumberedentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\secentry ##1##2##3##4{} + \def\subsecentry ##1##2##3##4##5{} + \def\subsubsecentry ##1##2##3##4##5##6{} + \let\unnumbsecentry = \secentry + \let\unnumbsubsecentry = \subsecentry + \let\unnumbsubsubsecentry = \subsubsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \closein 1 + \input \jobname.toc + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +\ifpdf + \pdfcatalog{/PageMode /UseOutlines}% +\fi + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}% +} + +% Appendices, in the main contents. +\def\appendixentry#1#2#3{% + \dochapentry{\appendixbox{\putwordAppendix{} #2}\labelspace#1}{#3}} +% +% Appendices, in the short toc. +\let\shortappendixentry = \shortchapentry + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `Appendix A' for an appendix, or `3' for a chapter. +% We could simplify the code here by writing out an \appendixentry +% command in the toc file for appendices, instead of using \chapentry +% for both, but it doesn't seem worth it. +% +\newdimen\shortappendixwidth +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + \dimen0 = 1em + \hbox to \dimen0{#1\hss}% +} + +% Unnumbered chapters. +\def\unnumbchapentry#1#2#3{\dochapentry{#1}{#3}} +\def\shortunnumberedentry#1#2#3{\tocentry{#1}{\doshortpageno\bgroup#3\egroup}} + +% Sections. +\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}} +\def\unnumbsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}} +\def\unnumbsubsecentry#1#2#3#4#5{\dosubsecentry{#1}{#5}} + +% And subsubsections. +\def\subsubsecentry#1#2#3#4#5#6{% + \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}} +\def\unnumbsubsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#1}{#6}} + +% This parameter controls the indentation of the various levels. +\newdimen\tocindent \tocindent = 3pc + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% Final typesetting of a toc entry; we use the same \entry macro as for +% the index entries, but we want to suppress hyphenation here. (We +% can't do that in the \entry macro, since index entries might consist +% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.) +\def\tocentry#1#2{\begingroup + \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks + % Do not use \turnoffactive in these arguments. Since the toc is + % typeset in cmr, characters such as _ would come out wrong; we + % have to do the usual translation tricks. + \entry{#1}{#2}% +\endgroup} + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\let\subsecentryfonts = \textfonts +\let\subsubsecentryfonts = \textfonts + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} +% +\global\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{ + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\def\tex{\begingroup + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\==\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\*=\ptexstar + \let\t=\ptext + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +\let\Etex=\endgroup} + +% Define @lisp ... @end lisp. +% @lisp does a \begingroup so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% Make each space character in the input produce a normal interword +% space in the output. Don't allow a line break at this space, as this +% is used only in environments like @example, where each line of input +% should produce a line of output anyway. +% +{\obeyspaces % +\gdef\sepspaces{\obeyspaces\let =\tie}} + +% Define \obeyedspace to be our active space, whatever it is. This is +% for use in \parsearg. +{\sepspaces% +\global\let\obeyedspace= } + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty>10000 \else \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\def\cartouche{% +\par % can't be in the midst of a paragraph. +\begingroup + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt %we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either +% side, and for 6pt waste from +% each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing=\comment + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \hsize=\cartinner + \kern3pt + \begingroup + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip +\def\Ecartouche{% + \endgroup + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup +\endgroup +}} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \inENV % This group ends at the end of the body + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + % @cartouche defines \nonarrowing to inhibit narrowing + % at next level down. + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \let\exdent=\nofillexdent + \let\nonarrowing=\relax + \fi +} + +% Define the \E... control sequence only if we are inside the particular +% environment, so the error checking in \end will work. +% +% To end an @example-like environment, we first end the paragraph (via +% \afterenvbreak's vertical glue), and then the group. That way we keep +% the zero \parskip that the environments set -- \parskip glue will be +% inserted at the beginning of the next paragraph in the document, after +% the environment. +% +\def\nonfillfinish{\afterenvbreak\endgroup} + +% @lisp: indented, narrowed, typewriter font. +\def\lisp{\begingroup + \nonfillstart + \let\Elisp = \nonfillfinish + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @example: Same as @lisp. +\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp} + +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +\def\smalllisp{\begingroup + \def\Esmalllisp{\nonfillfinish\endgroup}% + \def\Esmallexample{\nonfillfinish\endgroup}% + \smallexamplefonts + \lisp +} +\let\smallexample = \smalllisp + + +% @display: same as @lisp except keep current font. +% +\def\display{\begingroup + \nonfillstart + \let\Edisplay = \nonfillfinish + \gobble +} +% +% @smalldisplay: @display plus smaller fonts. +% +\def\smalldisplay{\begingroup + \def\Esmalldisplay{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \display +} + +% @format: same as @display except don't narrow margins. +% +\def\format{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eformat = \nonfillfinish + \gobble +} +% +% @smallformat: @format plus smaller fonts. +% +\def\smallformat{\begingroup + \def\Esmallformat{\nonfillfinish\endgroup}% + \smallexamplefonts \rm + \format +} + +% @flushleft (same as @format). +% +\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format} + +% @flushright. +% +\def\flushright{\begingroup + \let\nonarrowing = t + \nonfillstart + \let\Eflushright = \nonfillfinish + \advance\leftskip by 0pt plus 1fill + \gobble +} + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. +% +\def\quotation{% + \begingroup\inENV %This group ends at the end of the @quotation body + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % We have retained a nonzero parskip for the environment, since we're + % doing normal filling. So to avoid extra space below the environment... + \def\Equotation{\parskip = 0pt \nonfillfinish}% + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \let\nonarrowing = \relax + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{...} +% If we want to allow any as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=12}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } +\endgroup +\def\setupverbatim{% + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'#1'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=12\catcode`\}=12 + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +%% Include LaTeX hack for completeness -- never know +%% \begingroup +%% \catcode`|=0 \catcode`[=1 +%% \catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\ =\active +%% \catcode`\\=12|gdef|doverbatim#1@end verbatim[ +%% #1|endgroup|def|Everbatim[]|end[verbatim]] +%% |endgroup +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \gdef\doverbatim#1^^M#2@end verbatim{#2\end{verbatim}}% +\endgroup +% +\def\verbatim{% + \def\Everbatim{\nonfillfinish\endgroup}% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim\doverbatim +} + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +% Allow normal characters that we make active in the argument (a file name). +\def\verbatiminclude{% + \begingroup + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \parsearg\doverbatiminclude +} +\def\setupverbatiminclude{% + \begingroup + \nonfillstart + \advance\leftskip by -\defbodyindent + \begingroup\setupverbatim +} +% +\def\doverbatiminclude#1{% + % Restore active chars for included file. + \endgroup + \begingroup + \let\value=\expandablevalue + \def\thisfile{#1}% + \expandafter\expandafter\setupverbatiminclude\input\thisfile + \endgroup + \nonfillfinish + \endgroup +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. Many commands won't be +% allowed in this context, but that's ok. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\begingroup + % Define a command to swallow text until we reach `@end copying'. + % \ is the escape char in this texinfo.tex file, so it is the + % delimiter for the command; @ will be the escape char when we read + % it, but that doesn't matter. + \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}% + % + % We must preserve ^^M's in the input file; see \insertcopying below. + \catcode`\^^M = \active + \docopying +} + +% What we do to finish off the copying text. +% +\def\enddocopying{\endgroup\ignorespaces} + +% @insertcopying. Here we must play games with ^^M's. On the one hand, +% we need them to delimit commands such as `@end quotation', so they +% must be active. On the other hand, we certainly don't want every +% end-of-line to be a \par, as would happen with the normal active +% definition of ^^M. On the third hand, two ^^M's in a row should still +% generate a \par. +% +% Our approach is to make ^^M insert a space and a penalty1 normally; +% then it can also check if \lastpenalty=1. If it does, then manually +% do \par. +% +% This messes up the normal definitions of @c[omment], so we redefine +% it. Similarly for @ignore. (These commands are used in the gcc +% manual for man page generation.) +% +% Seems pretty fragile, most line-oriented commands will presumably +% fail, but for the limited use of getting the copying text (which +% should be quite simple) inserted, we can hope it's ok. +% +{\catcode`\^^M=\active % +\gdef\insertcopying{\begingroup % + \parindent = 0pt % looks wrong on title page + \def^^M{% + \ifnum \lastpenalty=1 % + \par % + \else % + \space \penalty 1 % + \fi % + }% + % + % Fix @c[omment] for catcode 13 ^^M's. + \def\c##1^^M{\ignorespaces}% + \let\comment = \c % + % + % Don't bother jumping through all the hoops that \doignore does, it + % would be very hard since the catcodes are already set. + \long\def\ignore##1\end ignore{\ignorespaces}% + % + \copyingtext % +\endgroup}% +} + +\message{defuns,} +% @defun etc. + +% Allow user to change definition object font (\df) internally +\def\setdeffont#1 {\csname DEF#1\endcsname} + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt + +\newcount\parencount + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\&=\active + \catcode`\[=\active \catcode`\]=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +{\activeparens % Now, smart parens don't turn on until &foo (see \amprm) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +\global\let(=\lparen \global\let)=\rparen +\global\let[=\lbrack \global\let]=\rbrack + +\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 } +\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} +% This is used to turn on special parens +% but make & act ordinary (given that it's active). +\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr} + +% Definitions of (, ) and & used in args for functions. +% This is the definition of ( outside of all parentheses. +\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested + \global\advance\parencount by 1 +} +% +% This is the definition of ( when already inside a level of parens. +\gdef\opnested{\char`\(\global\advance\parencount by 1 } +% +\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0. + % also in that case restore the outer-level definition of (. + \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi + \global\advance \parencount by -1 } +% If we encounter &foo, then turn on ()-hacking afterwards +\gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ } +% +\gdef\normalparens{\boldbrax\let&=\ampnr} +} % End of definition inside \activeparens +%% These parens (in \boldbrax) actually are a little bolder than the +%% contained text. This is especially needed for [ and ] +\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 } +\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 } +\let\ampnr = \& +\def\lbrb{{\bf\char`\[}} +\def\rbrb{{\bf\char`\]}} + +% Active &'s sneak into the index arguments, so make sure it's defined. +{ + \catcode`& = \active + \global\let& = \ampnr +} + +% \defname, which formats the name of the @def (not the args). +% #1 is the function name. +% #2 is the type of definition, such as "Function". +% +\def\defname#1#2{% + % How we'll output the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \ifempty{#2}% + \def\defnametype{}% + \else + \def\defnametype{[\rm #2]}% + \fi + % + % Get the values of \leftskip and \rightskip as they were outside the @def... + \dimen2=\leftskip + \advance\dimen2 by -\defbodyindent + % + % Figure out values for the paragraph shape. + \setbox0=\hbox{\hskip \deflastargmargin{\defnametype}}% + \dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line + \dimen1=\hsize \advance \dimen1 by -\defargsindent % size for continuations + \parshape 2 0in \dimen0 \defargsindent \dimen1 + % + % Output arg 2 ("Function" or some such) but stuck inside a box of + % width 0 so it does not interfere with linebreaking. + \noindent + % + {% Adjust \hsize to exclude the ambient margins, + % so that \rightline will obey them. + \advance \hsize by -\dimen2 + \dimen3 = 0pt % was -1.25pc + \rlap{\rightline{\defnametype\kern\dimen3}}% + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \advance\leftskip by -\defbodyindent + \exdentamount=\defbodyindent + {\df #1}\enskip % output function name + % \defunargs will be called next to output the arguments, if any. +} + +% Common pieces to start any @def... +% #1 is the \E... control sequence to end the definition (which we define). +% #2 is the \...x control sequence (which our caller defines). +% #3 is the control sequence to process the header, such as \defunheader. +% +\def\parsebodycommon#1#2#3{% + \begingroup\inENV + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we want to allow a + % break after all. Check for penalty 10002 (inserted by + % \defargscommonending) instead of 10000, since the sectioning + % commands insert a \penalty10000, and we don't want to allow a break + % between a section heading and a defun. + \ifnum\lastpenalty=10002 \penalty0 \fi + \medbreak + % + % Define the \E... end token that this defining construct specifies + % so that it will exit this group. + \def#1{\endgraf\endgroup\medbreak}% + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +% Common part of the \...x definitions. +% +\def\defxbodycommon{% + % As with \parsebodycommon above, allow line break if we have multiple + % x headers in a row. It's not a great place, though. + \ifnum\lastpenalty=10000 \penalty1000 \fi + % + \begingroup\obeylines +} + +% Process body of @defun, @deffn, @defmac, etc. +% +\def\defparsebody#1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \activeparens \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines\activeparens + \spacesplit#3% +} + +% #1, #2, #3 are the common arguments (see \parsebodycommon above). +% #4, delimited by the space, is the class name. +% +\def\defmethparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \activeparens \spacesplit{#3{##1}}}% + \begingroup\obeylines\activeparens + % The \empty here prevents misinterpretation of a construct such as + % @deffn {whatever} {Enharmonic comma} + % See comments at \deftpparsebody, although in our case we don't have + % to remove the \empty afterwards, since it is empty. + \spacesplit{#3{#4}}\empty +} + +% Used for @deftypemethod and @deftypeivar. +% #1, #2, #3 are the common arguments (see \defparsebody). +% #4, delimited by a space, is the class name. +% #5 is the method's return type. +% +\def\deftypemethparsebody#1#2#3#4 #5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\defxbodycommon \activeparens \spacesplit{#3{##1}{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#4}{#5}}% +} + +% Used for @deftypeop. The change from \deftypemethparsebody is an +% extra argument at the beginning which is the `category', instead of it +% being the hardwired string `Method' or `Instance Variable'. We have +% to account for this both in the \...x definition and in parsing the +% input at hand. Thus also need a control sequence (passed as #5) for +% the \E... definition to assign the category name to. +% +\def\deftypeopparsebody#1#2#3#4#5 #6 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 ##3 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}{##3}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}{#6}}% +} + +% For @defop. +\def\defopparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \activeparens \spacesplit{#3{##2}}}% + \begingroup\obeylines\activeparens + \spacesplit{#3{#5}}% +} + +% These parsing functions are similar to the preceding ones +% except that they do not make parens into active characters. +% These are used for "variables" since they have no arguments. +% +\def\defvarparsebody #1#2#3{% + \parsebodycommon{#1}{#2}{#3}% + \def#2{\defxbodycommon \spacesplit#3}% + \catcode\equalChar=\active + \begingroup\obeylines + \spacesplit#3% +} + +% @defopvar. +\def\defopvarparsebody #1#2#3#4#5 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 ##2 {\def#4{##1}% + \defxbodycommon \spacesplit{#3{##2}}}% + \begingroup\obeylines + \spacesplit{#3{#5}}% +} + +\def\defvrparsebody#1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{#3{#4}}% +} + +% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the +% type is just `struct', because we lose the braces in `{struct +% termios}' when \spacesplit reads its undelimited argument. Sigh. +% \let\deftpparsebody=\defvrparsebody +% +% So, to get around this, we put \empty in with the type name. That +% way, TeX won't find exactly `{...}' as an undelimited argument, and +% won't strip off the braces. +% +\def\deftpparsebody #1#2#3#4 {% + \parsebodycommon{#1}{#2}{#3}% + \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}% + \begingroup\obeylines + \spacesplit{\parsetpheaderline{#3{#4}}}\empty +} + +% Fine, but then we have to eventually remove the \empty *and* the +% braces (if any). That's what this does. +% +\def\removeemptybraces\empty#1\relax{#1} + +% After \spacesplit has done its work, this is called -- #1 is the final +% thing to call, #2 the type name (which starts with \empty), and #3 +% (which might be empty) the arguments. +% +\def\parsetpheaderline#1#2#3{% + #1{\removeemptybraces#2\relax}{#3}% +}% + +% Split up #2 (the rest of the input line) at the first space token. +% call #1 with two arguments: +% the first is all of #2 before the space token, +% the second is all of #2 after that space token. +% If #2 contains no space token, all of it is passed as the first arg +% and the second is passed as empty. +% +{\obeylines % + \gdef\spacesplit#1#2^^M{\endgroup\spacesplitx{#1}#2 \relax\spacesplitx}% + \long\gdef\spacesplitx#1#2 #3#4\spacesplitx{% + \ifx\relax #3% + #1{#2}{}% + \else % + #1{#2}{#3#4}% + \fi}% +} + +% Define @defun. + +% This is called to end the arguments processing for all the @def... commands. +% +\def\defargscommonending{% + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \parsebodycommon. +} + +% This expands the args and terminates the paragraph they comprise. +% +\def\defunargs#1{\functionparens \sl +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Set the font temporarily and use \font in case \setfont made \tensl a macro. +{\tensl\hyphenchar\font=0}% +#1% +{\tensl\hyphenchar\font=45}% +\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi% + \defargscommonending +} + +\def\deftypefunargs #1{% +% Expand, preventing hyphenation at `-' chars. +% Note that groups don't affect changes in \hyphenchar. +% Use \boldbraxnoamp, not \functionparens, so that & is not special. +\boldbraxnoamp +\tclose{#1}% avoid \code because of side effects on active chars + \defargscommonending +} + +% Do complete processing of one @defun or @defunx line already parsed. + +% @deffn Command forward-char nchars + +\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader} + +\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}% +\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defun == @deffn Function + +\def\defun{\defparsebody\Edefun\defunx\defunheader} + +\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDeffunc}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefun int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader} + +% #1 is the data type. #2 is the name and args. +\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax} +% #1 is the data type, #2 the name, #3 the args. +\def\deftypefunheaderx #1#2 #3\relax{% +\doind {fn}{\code{#2}}% Make entry in function index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypefun}% +\deftypefunargs {#3}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar}) + +\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader} + +% \defheaderxcond#1\relax$.$ +% puts #1 in @code, followed by a space, but does nothing if #1 is null. +\def\defheaderxcond#1#2$.${\ifx#1\relax\else\code{#1#2} \fi} + +% #1 is the classification. #2 is the data type. #3 is the name and args. +\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax} +% #1 is the classification, #2 the data type, #3 the name, #4 the args. +\def\deftypefnheaderx #1#2#3 #4\relax{% +\doind {fn}{\code{#3}}% Make entry in function index +\begingroup +\normalparens % notably, turn off `&' magic, which prevents +% at least some C++ text from working +\defname {\defheaderxcond#2\relax$.$#3}{#1}% +\deftypefunargs {#4}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defmac == @deffn Macro + +\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader} + +\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefmac}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defspec == @deffn Special Form + +\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader} + +\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index +\begingroup\defname {#1}{\putwordDefspec}% +\defunargs {#2}\endgroup % +\catcode\equalChar=\other % Turn off change made in \defparsebody +} + +% @defop CATEGORY CLASS OPERATION ARG... +% +\def\defop #1 {\def\defoptype{#1}% +\defopparsebody\Edefop\defopx\defopheader\defoptype} +% +\def\defopheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% function index entry + \begingroup + \defname{#2}{\defoptype\ \putwordon\ #1}% + \defunargs{#3}% + \endgroup +} + +% @deftypeop CATEGORY CLASS TYPE OPERATION ARG... +% +\def\deftypeop #1 {\def\deftypeopcategory{#1}% + \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader + \deftypeopcategory} +% +% #1 is the class name, #2 the data type, #3 the operation name, #4 the args. +\def\deftypeopheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\deftypeopcategory\ \putwordon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypemethod CLASS TYPE METHOD ARG... +% +\def\deftypemethod{% + \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader} +% +% #1 is the class name, #2 the data type, #3 the method name, #4 the args. +\def\deftypemethodheader#1#2#3#4{% + \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3}{\putwordMethodon\ \code{#1}}% + \deftypefunargs{#4}% + \endgroup +} + +% @deftypeivar CLASS TYPE VARNAME +% +\def\deftypeivar{% + \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader} +% +% #1 is the class name, #2 the data type, #3 the variable name. +\def\deftypeivarheader#1#2#3{% + \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index + \begingroup + \defname{\defheaderxcond#2\relax$.$#3} + {\putwordInstanceVariableof\ \code{#1}}% + \defvarargs{#3}% + \endgroup +} + +% @defmethod == @defop Method +% +\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader} +% +% #1 is the class name, #2 the method name, #3 the args. +\def\defmethodheader#1#2#3{% + \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index + \begingroup + \defname{#2}{\putwordMethodon\ \code{#1}}% + \defunargs{#3}% + \endgroup +} + +% @defcv {Class Option} foo-class foo-flag + +\def\defcv #1 {\def\defcvtype{#1}% +\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype} + +\def\defcvarheader #1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% variable index entry + \begingroup + \defname{#2}{\defcvtype\ \putwordof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME +% +\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader} +% +\def\defivarheader#1#2#3{% + \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% entry in var index + \begingroup + \defname{#2}{\putwordInstanceVariableof\ #1}% + \defvarargs{#3}% + \endgroup +} + +% @defvar +% First, define the processing that is wanted for arguments of @defvar. +% This is actually simple: just print them in roman. +% This must expand the args and terminate the paragraph they make up +\def\defvarargs #1{\normalparens #1% + \defargscommonending +} + +% @defvr Counter foo-count + +\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader} + +\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}% +\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup} + +% @defvar == @defvr Variable + +\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader} + +\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefvar}% +\defvarargs {#2}\endgroup % +} + +% @defopt == @defvr {User Option} + +\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader} + +\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index +\begingroup\defname {#1}{\putwordDefopt}% +\defvarargs {#2}\endgroup % +} + +% @deftypevar int foobar + +\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader} + +% #1 is the data type. #2 is the name, perhaps followed by text that +% is actually part of the data type, which should not be put into the index. +\def\deftypevarheader #1#2{% +\dovarind#2 \relax% Make entry in variables index +\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypevar}% + \defargscommonending +\endgroup} +\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}} + +% @deftypevr {Global Flag} int enable + +\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader} + +\def\deftypevrheader #1#2#3{\dovarind#3 \relax% +\begingroup\defname {\defheaderxcond#2\relax$.$#3}{#1} + \defargscommonending +\endgroup} + +% Now define @deftp +% Args are printed in bold, a slight difference from @defvar. + +\def\deftpargs #1{\bf \defvarargs{#1}} + +% @deftp Class window height width ... + +\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader} + +\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}% +\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup} + +% These definitions are used if you use @defunx (etc.) +% anywhere other than immediately after a @defun or @defunx. +% +\def\defcvx#1 {\errmessage{@defcvx in invalid context}} +\def\deffnx#1 {\errmessage{@deffnx in invalid context}} +\def\defivarx#1 {\errmessage{@defivarx in invalid context}} +\def\defmacx#1 {\errmessage{@defmacx in invalid context}} +\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}} +\def\defoptx #1 {\errmessage{@defoptx in invalid context}} +\def\defopx#1 {\errmessage{@defopx in invalid context}} +\def\defspecx#1 {\errmessage{@defspecx in invalid context}} +\def\deftpx#1 {\errmessage{@deftpx in invalid context}} +\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}} +\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}} +\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}} +\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}} +\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}} +\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}} +\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}} +\def\defunx#1 {\errmessage{@defunx in invalid context}} +\def\defvarx#1 {\errmessage{@defvarx in invalid context}} +\def\defvrx#1 {\errmessage{@defvrx in invalid context}} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scanmacro#1{% + \begingroup \newlinechar`\^^M + % Undo catcode changes of \startcontents and \doprintindex + \catcode`\@=0 \catcode`\\=\other \escapechar=`\@ + % Append \endinput to make sure that TeX does not see the ending newline. + \toks0={#1\endinput}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \let\xeatspaces\eatspaces + \input \jobname.tmp + \endgroup +} +\else +\def\scanmacro#1{% +\begingroup \newlinechar`\^^M +% Undo catcode changes of \startcontents and \doprintindex +\catcode`\@=0 \catcode`\\=\other \escapechar=`\@ +\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup} +\fi + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? +\def\macrolist{} % List of all defined macros in the form + % \do\macro1\do\macro2... + +% Utility routines. +% Thisdoes \let #1 = #2, except with \csnames. +\def\cslet#1#2{% +\expandafter\expandafter +\expandafter\let +\expandafter\expandafter +\csname#1\endcsname +\csname#2\endcsname} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\macrobodyctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\{=\other + \catcode`\}=\other + \catcode`\@=\other + \catcode`\^^M=\other + \usembodybackslash} + +\def\macroargctxt{% + \catcode`\~=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\+=\other + \catcode`\@=\other + \catcode`\\=\other} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + % Add the macroname to \macrolist + \toks0 = \expandafter{\macrolist\do}% + \xdef\macrolist{\the\toks0 + \expandafter\noexpand\csname\the\macname\endcsname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\def\unmacro{\parsearg\dounmacro} +\def\dounmacro#1{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\do\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx#1\relax + % remove this + \else + \noexpand\do \noexpand #1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + +% We mant to disable all macros during \shipout so that they are not +% expanded by \write. +\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% + \edef\next{\macrolist}\expandafter\endgroup\next} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{\ignoreactivespaces +\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=% + \expandafter\noexpand\csname#2\endcsname}% +\expandafter\endgroup\next} + + +\message{cross references,} +% @xref etc. + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's job is to define \lastnode. +\def\node{\ENVcheck\parsearg\nodezzz} +\def\nodezzz#1{\nodexxx [#1,]} +\def\nodexxx[#1,#2]{\gdef\lastnode{#1}} +\let\nwnode=\node +\let\lastnode=\relax + +% The sectioning commands (@chapter, etc.) call these. +\def\donoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Ysectionnumberandtype}% + \global\let\lastnode=\relax + \fi +} +\def\unnumbnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}% + \global\let\lastnode=\relax + \fi +} +\def\appendixnoderef{% + \ifx\lastnode\relax\else + \expandafter\expandafter\expandafter\setref{\lastnode}% + {Yappendixletterandtype}% + \global\let\lastnode=\relax + \fi +} + + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), namely NAME-title (the corresponding @chapter/etc. name), +% NAME-pg (the page number), and NAME-snt (section number and type). +% Called from \foonoderef. +% +% We have to set \indexdummies so commands such as @code in a section +% title aren't expanded. It would be nicer not to expand the titles in +% the first place, but there's so many layers that that is hard to do. +% +% Likewise, use \turnoffactive so that punctuation chars such as underscore +% and backslash work in node names. +% +\def\setref#1#2{{% + \atdummies + \pdfmkdest{#1}% + % + \turnoffactive + \dosetq{#1-title}{Ytitle}% + \dosetq{#1-pg}{Ypagenumber}% + \dosetq{#1-snt}{#2}% +}} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printednodename{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual}% + \setbox0=\hbox{\printednodename}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printednodename{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printednodename{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printednodename{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printednodename{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifpdf + \leavevmode + \getfilename{#4}% + {\turnoffactive \otherbackslash + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{#1}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{#1}% + \fi + }% + \linkcolor + \fi + % + \ifdim \wd1 > 0pt + \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive \otherbackslash + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % [mynode], + [\printednodename],\space + % page 3 + \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% + \fi + \endlink +\endgroup} + +% \dosetq is called from \setref to do the actual \write (\iflinks). +% +\def\dosetq#1#2{% + {\let\folio=0% + \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}% + \iflinks \next \fi + }% +} + +% \internalsetq{foo}{page} expands into +% CHARACTERS @xrdef{foo}{...expansion of \page...} +\def\internalsetq#1#2{@xrdef{#1}{\csname #2\endcsname}} + +% Things to be expanded by \internalsetq. +% +\def\Ypagenumber{\folio} +\def\Ytitle{\thissection} +\def\Ynothing{} +\def\Ysectionnumberandtype{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +\def\Yappendixletterandtype{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{\the\inputlineno:\space} +\fi + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname X#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. +% +\def\xrdef#1{\expandafter\gdef\csname X#1\endcsname} + +% Read the last existing aux file, if any. No error if none exists. +\def\readauxfile{\begingroup + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % Make the characters 128-255 be printing characters + {% + \count 1=128 + \def\loop{% + \catcode\count 1=\other + \advance\count 1 by 1 + \ifnum \count 1<256 \loop \fi + }% + }% + % + % Turn off \ as an escape so we do not lose on + % entries which were dumped with control sequences in their names. + % For example, @xrdef{$\leq $-fun}{page ...} made by @defun ^^ + % Reference to such entries still does not work the way one would wish, + % but at least they do not bomb out when the aux file is read in. + \catcode`\\=\other + % + % @ is our escape character in .aux files. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 + % + \openin 1 \jobname.aux + \ifeof 1 \else + \closein 1 + \input \jobname.aux + \global\havexrefstrue + \global\warnedobstrue + \fi + % Open the new aux file. TeX will close it automatically at exit. + \openout\auxfile=\jobname.aux +\endgroup} + + +% Footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +\let\ptexfootnote=\footnote + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset and anything else that uses +% \parseargline fail inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +% The start of the footnote looks usually like this: +\gdef\startfootins{\insert\footins\bgroup} +% +% ... but this macro is redefined inside @multitable. +% +\gdef\dofootnote{% + \startfootins + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + \closein 1 + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup\hss + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \hss \egroup \bigbreak \fi % space after the image +\endgroup} + + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\def\documentlanguage{\parsearg\dodocumentlanguage} +\def\dodocumentlanguage#1{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \let\temp = \relax + \else + \def\temp{\input txi-#1.tex }% + \fi + \temp + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; 3) voffset; +% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) +% physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}% + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.5 (or so) format. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {\voffset}{.25in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{51\baselineskip}{160mm} + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\def\pagesizes{\parsearg\pagesizesxxx} +\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1 + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in ttfont +% where it can probably just be output, and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% Set up an active definition for =, but don't enable it most of the time. +{\catcode`\==\active +\global\def={{\tt \char 61}}} + +\catcode`+=\active +\catcode`\_=\active + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +\catcode`\@=0 + +% \rawbackslashxx outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\rawbackslashxx=`\\ + +% \rawbackslash defines an active \ to do \rawbackslashxx. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +{\catcode`\\=\active + @gdef@rawbackslash{@let\=@rawbackslashxx} + @gdef@otherbackslash{@let\=@realbackslash} +} + +% \realbackslash is an actual character `\' with catcode other. +{\catcode`\\=\other @gdef@realbackslash{\}} + +% \normalbackslash outputs one backslash in fixed width font. +\def\normalbackslash{{\tt\rawbackslashxx}} + +\catcode`\\=\active + +% Used sometimes to turn off (effectively) the active characters +% even after parsing them. +@def@turnoffactive{% + @let"=@normaldoublequote + @let\=@realbackslash + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix +} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. (Thus, \ is not expandable when this is in +% effect.) +% +@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\{ in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also back turn on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + +@c Set initial fonts. +@textfonts +@rm + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: diff --git a/execute_cmd.c b/execute_cmd.c index 09ae320..44426fd 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -102,6 +102,7 @@ extern int parse_and_execute_level, running_trap; extern int command_string_index, line_number; extern int dot_found_in_search; extern int already_making_children; +extern int tempenv_assign_error; extern char *the_printed_command, *shell_name; extern pid_t last_command_subst_pid; extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin; @@ -2842,6 +2843,14 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) 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; diff --git a/execute_cmd.c~ b/execute_cmd.c~ index 3aefd2f..7a36715 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -526,8 +526,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, { pid_t paren_pid; -if (asynchronous) -itrace("execute_command_internal: making child: asynchronous = 1 job_control = %d", job_control); /* Fork a subshell, turn off the subshell bit, turn off job control and call execute_command () on the command again. */ paren_pid = make_child (savestring (make_command_string (command)), @@ -1185,8 +1183,6 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN); -itrace("execute_in_subshell: job_control = %d user_subshell = %d", job_control, user_subshell); - /* 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), @@ -2846,6 +2842,14 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) 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; diff --git a/lib/readline/ansi_stdlib.h b/lib/readline/ansi_stdlib.h deleted file mode 120000 index 0bfba50..0000000 --- a/lib/readline/ansi_stdlib.h +++ /dev/null @@ -1 +0,0 @@ -../../include/ansi_stdlib.h \ No newline at end of file diff --git a/lib/readline/ansi_stdlib.h b/lib/readline/ansi_stdlib.h new file mode 100644 index 0000000..db13cd2 --- /dev/null +++ b/lib/readline/ansi_stdlib.h @@ -0,0 +1,54 @@ +/* ansi_stdlib.h -- An ANSI Standard stdlib.h. */ +/* A minimal stdlib.h containing extern declarations for those functions + that bash uses. */ + +/* Copyright (C) 1993 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_STDLIB_H_) +#define _STDLIB_H_ 1 + +/* String conversion functions. */ +extern int atoi (); + +extern double atof (); +extern double strtod (); + +/* Memory allocation functions. */ +/* Generic pointer type. */ +#ifndef PTR_T + +#if defined (__STDC__) +# define PTR_T void * +#else +# define PTR_T char * +#endif + +#endif /* PTR_T */ + +extern PTR_T malloc (); +extern PTR_T realloc (); +extern void free (); + +/* Other miscellaneous functions. */ +extern void abort (); +extern void exit (); +extern char *getenv (); +extern void qsort (); + +#endif /* _STDLIB_H */ diff --git a/lib/readline/complete.c b/lib/readline/complete.c index a128d62..d212f61 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -685,6 +685,7 @@ print_filename (to_print, full_pathname) int printed_len, extension_char, slen, tlen; char *s, c, *new_full_pathname; + extension_char = 0; printed_len = fnprint (to_print); #if defined (VISIBLE_STATS) @@ -737,7 +738,7 @@ print_filename (to_print, full_pathname) extension_char = stat_char (s); else #endif - if (path_isdir (new_full_pathname)) + if (path_isdir (s)) extension_char = '/'; } diff --git a/lib/readline/complete.c~ b/lib/readline/complete.c~ new file mode 100644 index 0000000..a128d62 --- /dev/null +++ b/lib/readline/complete.c~ @@ -0,0 +1,2189 @@ +/* complete.c -- filename completion for readline. */ + +/* Copyright (C) 1987-2004 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include +#if defined (HAVE_SYS_FILE_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif /* HAVE_UNISTD_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include + +#include +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +#include + +#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 if _POSIX_SOURCE is + defined. */ +#if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE) +extern struct passwd *getpwent PARAMS((void)); +#endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */ + +/* If non-zero, then this is the address of a function to call when + completing a word would normally display the list of possible matches. + This function is called instead of actually doing the display. + It takes three arguments: (char **matches, int num_matches, int max_length) + where MATCHES is the array of strings that matched, NUM_MATCHES is the + number of strings in that array, and MAX_LENGTH is the length of the + longest string in that array. */ +rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL; + +#if defined (VISIBLE_STATS) +# if !defined (X_OK) +# define X_OK 1 +# endif +static int stat_char PARAMS((char *)); +#endif + +static int path_isdir PARAMS((const char *)); + +static char *rl_quote_filename PARAMS((char *, int, char *)); + +static void set_completion_defaults PARAMS((int)); +static int get_y_or_n PARAMS((int)); +static int _rl_internal_pager PARAMS((int)); +static char *printable_part PARAMS((char *)); +static int fnwidth PARAMS((const char *)); +static int fnprint PARAMS((const char *)); +static int print_filename PARAMS((char *, char *)); + +static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); + +static char **remove_duplicate_matches PARAMS((char **)); +static void insert_match PARAMS((char *, int, int, char *)); +static int append_to_match PARAMS((char *, int, int, int)); +static void insert_all_matches PARAMS((char **, int, char *)); +static void display_matches PARAMS((char **)); +static int compute_lcd_of_matches PARAMS((char **, int, const char *)); +static int postprocess_matches PARAMS((char ***, int)); + +static char *make_quoted_replacement PARAMS((char *, int, char *)); + +/* **************************************************************** */ +/* */ +/* Completion matching, from readline's point of view. */ +/* */ +/* **************************************************************** */ + +/* Variables known only to the readline library. */ + +/* If non-zero, non-unique completions always show the list of matches. */ +int _rl_complete_show_all = 0; + +/* If non-zero, non-unique completions show the list of matches, unless it + is not possible to do partial completion and modify the line. */ +int _rl_complete_show_unmodified = 0; + +/* If non-zero, completed directory names have a slash appended. */ +int _rl_complete_mark_directories = 1; + +/* If non-zero, the symlinked directory completion behavior introduced in + readline-4.2a is disabled, and symlinks that point to directories have + a slash appended (subject to the value of _rl_complete_mark_directories). + This is user-settable via the mark-symlinked-directories variable. */ +int _rl_complete_mark_symlink_dirs = 0; + +/* If non-zero, completions are printed horizontally in alphabetical order, + like `ls -x'. */ +int _rl_print_completions_horizontally; + +/* Non-zero means that case is not significant in filename completion. */ +#if defined (__MSDOS__) && !defined (__DJGPP__) +int _rl_completion_case_fold = 1; +#else +int _rl_completion_case_fold; +#endif + +/* If non-zero, don't match hidden files (filenames beginning with a `.' on + Unix) when doing filename completion. */ +int _rl_match_hidden_files = 1; + +/* Global variables available to applications using readline. */ + +#if defined (VISIBLE_STATS) +/* Non-zero means add an additional character to each filename displayed + during listing completion iff rl_filename_completion_desired which helps + to indicate the type of file being listed. */ +int rl_visible_stats = 0; +#endif /* VISIBLE_STATS */ + +/* If non-zero, then this is the address of a function to call when + completing on a directory name. The function is called with + the address of a string (the current directory name) as an arg. */ +rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL; + +rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; + +/* Non-zero means readline completion functions perform tilde expansion. */ +int rl_complete_with_tilde_expansion = 0; + +/* Pointer to the generator function for completion_matches (). + NULL means to use rl_filename_completion_function (), the default filename + completer. */ +rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL; + +/* Pointer to alternative function to create matches. + Function is called with TEXT, START, and END. + START and END are indices in RL_LINE_BUFFER saying what the boundaries + of TEXT are. + If this function exists and returns NULL then call the value of + rl_completion_entry_function to try to match, otherwise use the + array of strings returned. */ +rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL; + +/* Non-zero means to suppress normal filename completion after the + user-specified completion function has been called. */ +int rl_attempted_completion_over = 0; + +/* Set to a character indicating the type of completion being performed + by rl_complete_internal, available for use by application completion + functions. */ +int rl_completion_type = 0; + +/* Up to this many items will be displayed in response to a + possible-completions call. After that, we ask the user if + she is sure she wants to see them all. */ +int rl_completion_query_items = 100; + +int _rl_page_completions = 1; + +/* The basic list of characters that signal a break between words for the + completer routine. The contents of this variable is what breaks words + in the shell, i.e. " \t\n\"\\'`@$><=" */ +const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */ + +/* List of basic quoting characters. */ +const char *rl_basic_quote_characters = "\"'"; + +/* The list of characters that signal a break between words for + rl_complete_internal. The default list is the contents of + rl_basic_word_break_characters. */ +/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL; + +/* Hook function to allow an application to set the completion word + break characters before readline breaks up the line. Allows + position-dependent word break characters. */ +rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL; + +/* List of characters which can be used to quote a substring of the line. + Completion occurs on the entire substring, and within the substring + rl_completer_word_break_characters are treated as any other character, + unless they also appear within this list. */ +const char *rl_completer_quote_characters = (const char *)NULL; + +/* List of characters that should be quoted in filenames by the completer. */ +const char *rl_filename_quote_characters = (const char *)NULL; + +/* List of characters that are word break characters, but should be left + in TEXT when it is passed to the completion function. The shell uses + this to help determine what kind of completing to do. */ +const char *rl_special_prefixes = (const char *)NULL; + +/* If non-zero, then disallow duplicates in the matches. */ +int rl_ignore_completion_duplicates = 1; + +/* Non-zero means that the results of the matches are to be treated + as filenames. This is ALWAYS zero on entry, and can only be changed + within a completion entry finder function. */ +int rl_filename_completion_desired = 0; + +/* Non-zero means that the results of the matches are to be quoted using + double quotes (or an application-specific quoting mechanism) if the + filename contains any characters in rl_filename_quote_chars. This is + ALWAYS non-zero on entry, and can only be changed within a completion + entry finder function. */ +int rl_filename_quoting_desired = 1; + +/* This function, if defined, is called by the completer when real + filename completion is done, after all the matching names have been + generated. It is passed a (char**) known as matches in the code below. + It consists of a NULL-terminated array of pointers to potential + matching strings. The 1st element (matches[0]) is the maximal + substring that is common to all matches. This function can re-arrange + the list of matches as required, but all elements of the array must be + free()'d if they are deleted. The main intent of this function is + to implement FIGNORE a la SunOS csh. */ +rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL; + +/* Set to a function to quote a filename in an application-specific fashion. + Called with the text to quote, the type of match found (single or multiple) + and a pointer to the quoting character to be used, which the function can + reset if desired. */ +rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename; + +/* Function to call to remove quoting characters from a filename. Called + before completion is attempted, so the embedded quotes do not interfere + with matching names in the file system. Readline doesn't do anything + with this; it's set only by applications. */ +rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL; + +/* Function to call to decide whether or not a word break character is + quoted. If a character is quoted, it does not break words for the + completer. */ +rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL; + +/* If non-zero, the completion functions don't append anything except a + possible closing quote. This is set to 0 by rl_complete_internal and + may be changed by an application-specific completion function. */ +int rl_completion_suppress_append = 0; + +/* Character appended to completed words when at the end of the line. The + default is a space. */ +int rl_completion_append_character = ' '; + +/* If non-zero, the completion functions don't append any closing quote. + This is set to 0 by rl_complete_internal and may be changed by an + application-specific completion function. */ +int rl_completion_suppress_quote = 0; + +/* Set to any quote character readline thinks it finds before any application + completion function is called. */ +int rl_completion_quote_character; + +/* Set to a non-zero value if readline found quoting anywhere in the word to + be completed; set before any application completion function is called. */ +int rl_completion_found_quote; + +/* If non-zero, a slash will be appended to completed filenames that are + symbolic links to directory names, subject to the value of the + mark-directories variable (which is user-settable). This exists so + that application completion functions can override the user's preference + (set via the mark-symlinked-directories variable) if appropriate. + It's set to the value of _rl_complete_mark_symlink_dirs in + rl_complete_internal before any application-specific completion + function is called, so without that function doing anything, the user's + preferences are honored. */ +int rl_completion_mark_symlink_dirs; + +/* If non-zero, inhibit completion (temporarily). */ +int rl_inhibit_completion; + +/* Variables local to this file. */ + +/* Local variable states what happened during the last completion attempt. */ +static int completion_changed_buffer; + +/*************************************/ +/* */ +/* Bindable completion functions */ +/* */ +/*************************************/ + +/* Complete the word at or before point. You have supplied the function + that does the initial simple matching selection algorithm (see + rl_completion_matches ()). The default is to do filename completion. */ +int +rl_complete (ignore, invoking_key) + int ignore, invoking_key; +{ + if (rl_inhibit_completion) + return (_rl_insert_char (ignore, invoking_key)); + else if (rl_last_func == rl_complete && !completion_changed_buffer) + return (rl_complete_internal ('?')); + else if (_rl_complete_show_all) + return (rl_complete_internal ('!')); + else if (_rl_complete_show_unmodified) + return (rl_complete_internal ('@')); + else + return (rl_complete_internal (TAB)); +} + +/* List the possible completions. See description of rl_complete (). */ +int +rl_possible_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + return (rl_complete_internal ('?')); +} + +int +rl_insert_completions (ignore, invoking_key) + int ignore, invoking_key; +{ + return (rl_complete_internal ('*')); +} + +/* Return the correct value to pass to rl_complete_internal performing + the same tests as rl_complete. This allows consecutive calls to an + application's completion function to list possible completions and for + an application-specific completion function to honor the + show-all-if-ambiguous readline variable. */ +int +rl_completion_mode (cfunc) + rl_command_func_t *cfunc; +{ + if (rl_last_func == cfunc && !completion_changed_buffer) + return '?'; + else if (_rl_complete_show_all) + return '!'; + else if (_rl_complete_show_unmodified) + return '@'; + else + return TAB; +} + +/************************************/ +/* */ +/* Completion utility functions */ +/* */ +/************************************/ + +/* Set default values for readline word completion. These are the variables + that application completion functions can change or inspect. */ +static void +set_completion_defaults (what_to_do) + int what_to_do; +{ + /* Only the completion entry function can change these. */ + rl_filename_completion_desired = 0; + rl_filename_quoting_desired = 1; + rl_completion_type = what_to_do; + rl_completion_suppress_append = rl_completion_suppress_quote = 0; + + /* The completion entry function may optionally change this. */ + rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs; +} + +/* The user must press "y" or "n". Non-zero return means "y" pressed. */ +static int +get_y_or_n (for_pager) + int for_pager; +{ + int c; + + for (;;) + { + RL_SETSTATE(RL_STATE_MOREINPUT); + c = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + + if (c == 'y' || c == 'Y' || c == ' ') + return (1); + if (c == 'n' || c == 'N' || c == RUBOUT) + return (0); + if (c == ABORT_CHAR) + _rl_abort_internal (); + if (for_pager && (c == NEWLINE || c == RETURN)) + return (2); + if (for_pager && (c == 'q' || c == 'Q')) + return (0); + rl_ding (); + } +} + +static int +_rl_internal_pager (lines) + int lines; +{ + int i; + + fprintf (rl_outstream, "--More--"); + fflush (rl_outstream); + i = get_y_or_n (1); + _rl_erase_entire_line (); + if (i == 0) + return -1; + else if (i == 2) + return (lines - 1); + else + return 0; +} + +static int +path_isdir (filename) + const char *filename; +{ + struct stat finfo; + + return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)); +} + +#if defined (VISIBLE_STATS) +/* Return the character which best describes FILENAME. + `@' for symbolic links + `/' for directories + `*' for executables + `=' for sockets + `|' for FIFOs + `%' for character special devices + `#' for block special devices */ +static int +stat_char (filename) + char *filename; +{ + struct stat finfo; + int character, r; + +#if defined (HAVE_LSTAT) && defined (S_ISLNK) + r = lstat (filename, &finfo); +#else + r = stat (filename, &finfo); +#endif + + if (r == -1) + return (0); + + character = 0; + if (S_ISDIR (finfo.st_mode)) + character = '/'; +#if defined (S_ISCHR) + else if (S_ISCHR (finfo.st_mode)) + character = '%'; +#endif /* S_ISCHR */ +#if defined (S_ISBLK) + else if (S_ISBLK (finfo.st_mode)) + character = '#'; +#endif /* S_ISBLK */ +#if defined (S_ISLNK) + else if (S_ISLNK (finfo.st_mode)) + character = '@'; +#endif /* S_ISLNK */ +#if defined (S_ISSOCK) + else if (S_ISSOCK (finfo.st_mode)) + character = '='; +#endif /* S_ISSOCK */ +#if defined (S_ISFIFO) + else if (S_ISFIFO (finfo.st_mode)) + character = '|'; +#endif + else if (S_ISREG (finfo.st_mode)) + { + if (access (filename, X_OK) == 0) + character = '*'; + } + return (character); +} +#endif /* VISIBLE_STATS */ + +/* Return the portion of PATHNAME that should be output when listing + possible completions. If we are hacking filename completion, we + are only interested in the basename, the portion following the + final slash. Otherwise, we return what we were passed. Since + printing empty strings is not very informative, if we're doing + filename completion, and the basename is the empty string, we look + for the previous slash and return the portion following that. If + there's no previous slash, we just return what we were passed. */ +static char * +printable_part (pathname) + char *pathname; +{ + char *temp, *x; + + if (rl_filename_completion_desired == 0) /* don't need to do anything */ + return (pathname); + + temp = strrchr (pathname, '/'); +#if defined (__MSDOS__) + if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') + temp = pathname + 1; +#endif + + if (temp == 0 || *temp == '\0') + return (pathname); + /* If the basename is NULL, we might have a pathname like '/usr/src/'. + Look for a previous slash and, if one is found, return the portion + following that slash. If there's no previous slash, just return the + pathname we were passed. */ + else if (temp[1] == '\0') + { + for (x = temp - 1; x > pathname; x--) + if (*x == '/') + break; + return ((*x == '/') ? x + 1 : pathname); + } + else + return ++temp; +} + +/* Compute width of STRING when displayed on screen by print_filename */ +static int +fnwidth (string) + const char *string; +{ + int width, pos; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + int left, w; + size_t clen; + wchar_t wc; + + left = strlen (string) + 1; + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + width = pos = 0; + while (string[pos]) + { + if (CTRL_CHAR (*string) || *string == RUBOUT) + { + width += 2; + pos++; + } + else + { +#if defined (HANDLE_MULTIBYTE) + clen = mbrtowc (&wc, string + pos, left - pos, &ps); + if (MB_INVALIDCH (clen)) + { + width++; + pos++; + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (MB_NULLWCH (clen)) + break; + else + { + pos += clen; + w = wcwidth (wc); + width += (w >= 0) ? w : 1; + } +#else + width++; + pos++; +#endif + } + } + + return width; +} + +static int +fnprint (to_print) + const char *to_print; +{ + int printed_len; + const char *s; +#if defined (HANDLE_MULTIBYTE) + mbstate_t ps; + const char *end; + size_t tlen; + + end = to_print + strlen (to_print) + 1; + memset (&ps, 0, sizeof (mbstate_t)); +#endif + + printed_len = 0; + s = to_print; + while (*s) + { + if (CTRL_CHAR (*s)) + { + putc ('^', rl_outstream); + putc (UNCTRL (*s), rl_outstream); + printed_len += 2; + s++; +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + } + else if (*s == RUBOUT) + { + putc ('^', rl_outstream); + putc ('?', rl_outstream); + printed_len += 2; + s++; +#if defined (HANDLE_MULTIBYTE) + memset (&ps, 0, sizeof (mbstate_t)); +#endif + } + else + { +#if defined (HANDLE_MULTIBYTE) + tlen = mbrlen (s, end - s, &ps); + if (MB_INVALIDCH (tlen)) + { + tlen = 1; + memset (&ps, 0, sizeof (mbstate_t)); + } + else if (MB_NULLWCH (tlen)) + break; + fwrite (s, 1, tlen, rl_outstream); + s += tlen; +#else + putc (*s, rl_outstream); + s++; +#endif + printed_len++; + } + } + + return printed_len; +} + +/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we + are using it, check for and output a single character for `special' + filenames. Return the number of characters we output. */ + +static int +print_filename (to_print, full_pathname) + char *to_print, *full_pathname; +{ + int printed_len, extension_char, slen, tlen; + char *s, c, *new_full_pathname; + + printed_len = fnprint (to_print); + +#if defined (VISIBLE_STATS) + if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories)) +#else + if (rl_filename_completion_desired && _rl_complete_mark_directories) +#endif + { + /* If to_print != full_pathname, to_print is the basename of the + path passed. In this case, we try to expand the directory + name before checking for the stat character. */ + if (to_print != full_pathname) + { + /* Terminate the directory name. */ + c = to_print[-1]; + to_print[-1] = '\0'; + + /* If setting the last slash in full_pathname to a NUL results in + full_pathname being the empty string, we are trying to complete + files in the root directory. If we pass a null string to the + bash directory completion hook, for example, it will expand it + to the current directory. We just want the `/'. */ + s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/"); + 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); + new_full_pathname[slen] = '/'; + strcpy (new_full_pathname + slen + 1, to_print); + +#if defined (VISIBLE_STATS) + if (rl_visible_stats) + extension_char = stat_char (new_full_pathname); + else +#endif + if (path_isdir (new_full_pathname)) + extension_char = '/'; + + free (new_full_pathname); + to_print[-1] = c; + } + else + { + s = tilde_expand (full_pathname); +#if defined (VISIBLE_STATS) + if (rl_visible_stats) + extension_char = stat_char (s); + else +#endif + if (path_isdir (new_full_pathname)) + extension_char = '/'; + } + + free (s); + if (extension_char) + { + putc (extension_char, rl_outstream); + printed_len++; + } + } + + return printed_len; +} + +static char * +rl_quote_filename (s, rtype, qcp) + char *s; + int rtype; + char *qcp; +{ + char *r; + + r = (char *)xmalloc (strlen (s) + 2); + *r = *rl_completer_quote_characters; + strcpy (r + 1, s); + if (qcp) + *qcp = *rl_completer_quote_characters; + return r; +} + +/* Find the bounds of the current word for completion purposes, and leave + rl_point set to the end of the word. This function skips quoted + substrings (characters between matched pairs of characters in + rl_completer_quote_characters). First we try to find an unclosed + quoted substring on which to do matching. If one is not found, we use + the word break characters to find the boundaries of the current word. + We call an application-specific function to decide whether or not a + particular word break character is quoted; if that function returns a + non-zero result, the character does not break a word. This function + returns the opening quote character if we found an unclosed quoted + substring, '\0' otherwise. FP, if non-null, is set to a value saying + which (shell-like) quote characters we found (single quote, double + quote, or backslash) anywhere in the string. DP, if non-null, is set to + the value of the delimiter character that caused a word break. */ + +char +_rl_find_completion_word (fp, dp) + int *fp, *dp; +{ + int scan, end, found_quote, delimiter, pass_next, isbrk; + char quote_char, *brkchars; + + end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + brkchars = 0; + if (rl_completion_word_break_hook) + brkchars = (*rl_completion_word_break_hook) (); + if (brkchars == 0) + brkchars = rl_completer_word_break_characters; + + if (rl_completer_quote_characters) + { + /* We have a list of characters which can be used in pairs to + quote substrings for the completer. Try to find the start + of an unclosed quoted substring. */ + /* FOUND_QUOTE is set so we know what kind of quotes we found. */ +#if defined (HANDLE_MULTIBYTE) + for (scan = pass_next = 0; scan < end; + scan = ((MB_CUR_MAX == 1 || rl_byte_oriented) + ? (scan + 1) + : _rl_find_next_mbchar (rl_line_buffer, scan, 1, MB_FIND_ANY))) +#else + for (scan = pass_next = 0; scan < end; scan++) +#endif + { + 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. */ +#if defined (HANDLE_MULTIBYTE) + while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY)) +#else + while (--rl_point) +#endif + { + scan = rl_line_buffer[rl_point]; + + if (strchr (brkchars, scan) == 0) + continue; + + /* Call the application-specific function to tell us whether + this word break character is quoted and should be skipped. */ + if (rl_char_is_quoted_p && found_quote && + (*rl_char_is_quoted_p) (rl_line_buffer, rl_point)) + continue; + + /* Convoluted code, but it avoids an n^2 algorithm with calls + to char_is_quoted. */ + break; + } + } + + /* If we are at an unquoted word break, then advance past it. */ + scan = rl_line_buffer[rl_point]; + + /* If there is an application-specific function to say whether or not + a character is quoted and we found a quote character, let that + function decide whether or not a character is a word break, even + if it is found in rl_completer_word_break_characters. Don't bother + if we're at the end of the line, though. */ + if (scan) + { + if (rl_char_is_quoted_p) + isbrk = (found_quote == 0 || + (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && + strchr (brkchars, scan) != 0; + else + isbrk = strchr (brkchars, scan) != 0; + + if (isbrk) + { + /* If the character that caused the word break was a quoting + character, then remember it as the delimiter. */ + if (rl_basic_quote_characters && + strchr (rl_basic_quote_characters, scan) && + (end - rl_point) > 1) + delimiter = scan; + + /* If the character isn't needed to determine something special + about what kind of completion to perform, then advance past it. */ + if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0) + rl_point++; + } + } + + if (fp) + *fp = found_quote; + if (dp) + *dp = delimiter; + + return (quote_char); +} + +static char ** +gen_completion_matches (text, start, end, our_func, found_quote, quote_char) + char *text; + int start, end; + rl_compentry_func_t *our_func; + int found_quote, quote_char; +{ + char **matches, *temp; + + rl_completion_found_quote = found_quote; + rl_completion_quote_character = quote_char; + + /* If the user wants to TRY to complete, but then wants to give + up and use the default completion function, they set the + variable rl_attempted_completion_function. */ + if (rl_attempted_completion_function) + { + matches = (*rl_attempted_completion_function) (text, start, end); + + if (matches || rl_attempted_completion_over) + { + rl_attempted_completion_over = 0; + return (matches); + } + } + + /* Beware -- we're stripping the quotes here. Do this only if we know + we are doing filename completion and the application has defined a + filename dequoting function. */ + temp = (char *)NULL; + + if (found_quote && our_func == rl_filename_completion_function && + rl_filename_dequoting_function) + { + /* delete single and double quotes */ + temp = (*rl_filename_dequoting_function) (text, quote_char); + text = temp; /* not freeing text is not a memory leak */ + } + + matches = rl_completion_matches (text, our_func); + FREE (temp); + return matches; +} + +/* Filter out duplicates in MATCHES. This frees up the strings in + MATCHES. */ +static char ** +remove_duplicate_matches (matches) + char **matches; +{ + char *lowest_common; + int i, j, newlen; + char dead_slot; + char **temp_array; + + /* Sort the items. */ + for (i = 0; matches[i]; i++) + ; + + /* Sort the array without matches[0], since we need it to + stay in place no matter what. */ + if (i) + qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); + + /* Remember the lowest common denominator for it may be unique. */ + lowest_common = savestring (matches[0]); + + for (i = newlen = 0; matches[i + 1]; i++) + { + if (strcmp (matches[i], matches[i + 1]) == 0) + { + free (matches[i]); + matches[i] = (char *)&dead_slot; + } + else + newlen++; + } + + /* We have marked all the dead slots with (char *)&dead_slot. + Copy all the non-dead entries into a new array. */ + temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *)); + for (i = j = 1; matches[i]; i++) + { + if (matches[i] != (char *)&dead_slot) + temp_array[j++] = matches[i]; + } + temp_array[j] = (char *)NULL; + + if (matches[0] != (char *)&dead_slot) + free (matches[0]); + + /* Place the lowest common denominator back in [0]. */ + temp_array[0] = lowest_common; + + /* If there is one string left, and it is identical to the + lowest common denominator, then the LCD is the string to + insert. */ + if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0) + { + free (temp_array[1]); + temp_array[1] = (char *)NULL; + } + return (temp_array); +} + +/* Find the common prefix of the list of matches, and put it into + matches[0]. */ +static int +compute_lcd_of_matches (match_list, matches, text) + char **match_list; + int matches; + const char *text; +{ + register int i, c1, c2, si; + int low; /* Count of max-matched characters. */ + char *dtext; /* dequoted TEXT, if needed */ +#if defined (HANDLE_MULTIBYTE) + int v; + mbstate_t ps1, ps2; + wchar_t wc1, wc2; +#endif + + /* If only one match, just use that. Otherwise, compare each + member of the list with the next, finding out where they + stop matching. */ + if (matches == 1) + { + match_list[0] = match_list[1]; + match_list[1] = (char *)NULL; + return 1; + } + + for (i = 1, low = 100000; i < matches; i++) + { +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + memset (&ps1, 0, sizeof (mbstate_t)); + memset (&ps2, 0, sizeof (mbstate_t)); + } +#endif + if (_rl_completion_case_fold) + { + for (si = 0; + (c1 = _rl_to_lower(match_list[i][si])) && + (c2 = _rl_to_lower(match_list[i + 1][si])); + si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); + mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); + wc1 = towlower (wc1); + wc2 = towlower (wc2); + if (wc1 != wc2) + break; + else if (v > 1) + si += v - 1; + } + else +#endif + if (c1 != c2) + break; + } + else + { + for (si = 0; + (c1 = match_list[i][si]) && + (c2 = match_list[i + 1][si]); + si++) +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + mbstate_t ps_back = ps1; + if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) + break; + else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) + si += v - 1; + } + else +#endif + if (c1 != c2) + break; + } + + if (low > si) + low = si; + } + + /* If there were multiple matches, but none matched up to even the + first character, and the user typed something, use that as the + value of matches[0]. */ + if (low == 0 && text && *text) + { + match_list[0] = (char *)xmalloc (strlen (text) + 1); + strcpy (match_list[0], text); + } + else + { + match_list[0] = (char *)xmalloc (low + 1); + + /* XXX - this might need changes in the presence of multibyte chars */ + + /* If we are ignoring case, try to preserve the case of the string + the user typed in the face of multiple matches differing in case. */ + if (_rl_completion_case_fold) + { + /* We're making an assumption here: + IF we're completing filenames AND + the application has defined a filename dequoting function AND + we found a quote character AND + the application has requested filename quoting + THEN + we assume that TEXT was dequoted before checking against + the file system and needs to be dequoted here before we + check against the list of matches + FI */ + dtext = (char *)NULL; + if (rl_filename_completion_desired && + rl_filename_dequoting_function && + rl_completion_found_quote && + rl_filename_quoting_desired) + { + dtext = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); + text = dtext; + } + + /* sort the list to get consistent answers. */ + qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); + + si = strlen (text); + if (si <= low) + { + for (i = 1; i <= matches; i++) + if (strncmp (match_list[i], text, si) == 0) + { + strncpy (match_list[0], match_list[i], low); + break; + } + /* no casematch, use first entry */ + if (i > matches) + strncpy (match_list[0], match_list[1], low); + } + else + /* otherwise, just use the text the user typed. */ + strncpy (match_list[0], text, low); + + FREE (dtext); + } + else + strncpy (match_list[0], match_list[1], low); + + match_list[0][low] = '\0'; + } + + return matches; +} + +static int +postprocess_matches (matchesp, matching_filenames) + char ***matchesp; + int matching_filenames; +{ + char *t, **matches, **temp_matches; + int nmatch, i; + + matches = *matchesp; + + if (matches == 0) + return 0; + + /* It seems to me that in all the cases we handle we would like + to ignore duplicate possiblilities. Scan for the text to + insert being identical to the other completions. */ + if (rl_ignore_completion_duplicates) + { + temp_matches = remove_duplicate_matches (matches); + free (matches); + matches = temp_matches; + } + + /* If we are matching filenames, then here is our chance to + do clever processing by re-examining the list. Call the + ignore function with the array as a parameter. It can + munge the array, deleting matches as it desires. */ + if (rl_ignore_some_completions_function && matching_filenames) + { + for (nmatch = 1; matches[nmatch]; nmatch++) + ; + (void)(*rl_ignore_some_completions_function) (matches); + if (matches == 0 || matches[0] == 0) + { + FREE (matches); + *matchesp = (char **)0; + return 0; + } + else + { + /* If we removed some matches, recompute the common prefix. */ + for (i = 1; matches[i]; i++) + ; + if (i > 1 && i < nmatch) + { + t = matches[0]; + compute_lcd_of_matches (matches, i - 1, t); + FREE (t); + } + } + } + + *matchesp = matches; + return (1); +} + +/* A convenience function for displaying a list of strings in + columnar format on readline's output stream. MATCHES is the list + of strings, in argv format, LEN is the number of strings in MATCHES, + and MAX is the length of the longest string in MATCHES. */ +void +rl_display_match_list (matches, len, max) + char **matches; + int len, max; +{ + int count, limit, printed_len, lines; + int i, j, k, l; + char *temp; + + /* How many items of MAX length can we fit in the screen window? */ + max += 2; + limit = _rl_screenwidth / max; + if (limit != 1 && (limit * max == _rl_screenwidth)) + limit--; + + /* Avoid a possible floating exception. If max > _rl_screenwidth, + limit will be 0 and a divide-by-zero fault will result. */ + if (limit == 0) + limit = 1; + + /* How many iterations of the printing loop? */ + count = (len + (limit - 1)) / limit; + + /* Watch out for special case. If LEN is less than LIMIT, then + just do the inner printing loop. + 0 < len <= limit implies count = 1. */ + + /* Sort the items if they are not already sorted. */ + if (rl_ignore_completion_duplicates == 0) + qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); + + rl_crlf (); + + lines = 0; + if (_rl_print_completions_horizontally == 0) + { + /* Print the sorted items, up-and-down alphabetically, like ls. */ + for (i = 1; i <= count; i++) + { + for (j = 0, l = i; j < limit; j++) + { + if (l > len || matches[l] == 0) + break; + else + { + temp = printable_part (matches[l]); + printed_len = print_filename (temp, matches[l]); + + if (j + 1 < limit) + for (k = 0; k < max - printed_len; k++) + putc (' ', rl_outstream); + } + l += count; + } + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } + } + } + else + { + /* Print the sorted items, across alphabetically, like ls -x. */ + for (i = 1; matches[i]; i++) + { + temp = printable_part (matches[i]); + printed_len = print_filename (temp, matches[i]); + /* Have we reached the end of this line? */ + if (matches[i+1]) + { + if (i && (limit > 1) && (i % limit) == 0) + { + rl_crlf (); + lines++; + if (_rl_page_completions && lines >= _rl_screenheight - 1) + { + lines = _rl_internal_pager (lines); + if (lines < 0) + return; + } + } + else + for (k = 0; k < max - printed_len; k++) + putc (' ', rl_outstream); + } + } + rl_crlf (); + } +} + +/* Display MATCHES, a list of matching filenames in argv format. This + handles the simple case -- a single match -- first. If there is more + than one match, we compute the number of strings in the list and the + length of the longest string, which will be needed by the display + function. If the application wants to handle displaying the list of + matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the + address of a function, and we just call it. If we're handling the + display ourselves, we just call rl_display_match_list. We also check + that the list of matches doesn't exceed the user-settable threshold, + and ask the user if he wants to see the list if there are more matches + than RL_COMPLETION_QUERY_ITEMS. */ +static void +display_matches (matches) + char **matches; +{ + int len, max, i; + char *temp; + + /* Move to the last visible line of a possibly-multiple-line command. */ + _rl_move_vert (_rl_vis_botlin); + + /* Handle simple case first. What if there is only one answer? */ + if (matches[1] == 0) + { + temp = printable_part (matches[0]); + rl_crlf (); + print_filename (temp, matches[0]); + rl_crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + + /* There is more than one answer. Find out how many there are, + and find the maximum printed length of a single entry. */ + for (max = 0, i = 1; matches[i]; i++) + { + temp = printable_part (matches[i]); + len = fnwidth (temp); + + if (len > max) + max = len; + } + + len = i - 1; + + /* If the caller has defined a display hook, then call that now. */ + if (rl_completion_display_matches_hook) + { + (*rl_completion_display_matches_hook) (matches, len, max); + return; + } + + /* If there are many items, then ask the user if she really wants to + see them all. */ + if (len >= rl_completion_query_items) + { + rl_crlf (); + fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); + fflush (rl_outstream); + if (get_y_or_n (0) == 0) + { + rl_crlf (); + + rl_forced_update_display (); + rl_display_fixed = 1; + + return; + } + } + + rl_display_match_list (matches, len, max); + + rl_forced_update_display (); + rl_display_fixed = 1; +} + +static char * +make_quoted_replacement (match, mtype, qc) + char *match; + int mtype; + char *qc; /* Pointer to quoting character, if any */ +{ + int should_quote, do_replace; + char *replacement; + + /* If we are doing completion on quoted substrings, and any matches + contain any of the completer_word_break_characters, then auto- + matically prepend the substring with a quote character (just pick + the first one from the list of such) if it does not already begin + with a quote string. FIXME: Need to remove any such automatically + inserted quote character when it no longer is necessary, such as + if we change the string we are completing on and the new set of + matches don't require a quoted substring. */ + replacement = match; + + should_quote = match && rl_completer_quote_characters && + rl_filename_completion_desired && + rl_filename_quoting_desired; + + if (should_quote) + should_quote = should_quote && (!qc || !*qc || + (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); + + if (should_quote) + { + /* If there is a single match, see if we need to quote it. + This also checks whether the common prefix of several + matches needs to be quoted. */ + should_quote = rl_filename_quote_characters + ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0) + : 0; + + do_replace = should_quote ? mtype : NO_MATCH; + /* Quote the replacement, since we found an embedded + word break character in a potential match. */ + if (do_replace != NO_MATCH && rl_filename_quoting_function) + replacement = (*rl_filename_quoting_function) (match, do_replace, qc); + } + return (replacement); +} + +static void +insert_match (match, start, mtype, qc) + char *match; + int start, mtype; + char *qc; +{ + char *replacement; + char oqc; + + oqc = qc ? *qc : '\0'; + replacement = make_quoted_replacement (match, mtype, qc); + + /* Now insert the match. */ + if (replacement) + { + /* Don't double an opening quote character. */ + if (qc && *qc && start && rl_line_buffer[start - 1] == *qc && + replacement[0] == *qc) + start--; + /* If make_quoted_replacement changed the quoting character, remove + the opening quote and insert the (fully-quoted) replacement. */ + else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc && + replacement[0] != oqc) + start--; + _rl_replace_text (replacement, start, rl_point - 1); + if (replacement != match) + free (replacement); + } +} + +/* Append any necessary closing quote and a separator character to the + just-inserted match. If the user has specified that directories + should be marked by a trailing `/', append one of those instead. The + default trailing character is a space. Returns the number of characters + appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS + has them) and don't add a suffix for a symlink to a directory. A + nontrivial match is one that actually adds to the word being completed. + The variable rl_completion_mark_symlink_dirs controls this behavior + (it's initially set to the what the user has chosen, indicated by the + value of _rl_complete_mark_symlink_dirs, but may be modified by an + application's completion function). */ +static int +append_to_match (text, delimiter, quote_char, nontrivial_match) + char *text; + int delimiter, quote_char, nontrivial_match; +{ + char temp_string[4], *filename; + int temp_string_index, s; + struct stat finfo; + + temp_string_index = 0; + if (quote_char && rl_point && rl_completion_suppress_quote == 0 && + rl_line_buffer[rl_point - 1] != quote_char) + temp_string[temp_string_index++] = quote_char; + + if (delimiter) + temp_string[temp_string_index++] = delimiter; + else if (rl_completion_suppress_append == 0 && rl_completion_append_character) + temp_string[temp_string_index++] = rl_completion_append_character; + + temp_string[temp_string_index++] = '\0'; + + if (rl_filename_completion_desired) + { + filename = tilde_expand (text); + s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) + ? LSTAT (filename, &finfo) + : stat (filename, &finfo); + if (s == 0 && S_ISDIR (finfo.st_mode)) + { + if (_rl_complete_mark_directories) + { + /* This is clumsy. Avoid putting in a double slash if point + is at the end of the line and the previous character is a + slash. */ + if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') + ; + else if (rl_line_buffer[rl_point] != '/') + rl_insert_text ("/"); + } + } +#ifdef S_ISLNK + /* Don't add anything if the filename is a symlink and resolves to a + directory. */ + else if (s == 0 && S_ISLNK (finfo.st_mode) && + stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) + ; +#endif + else + { + if (rl_point == rl_end && temp_string_index) + rl_insert_text (temp_string); + } + free (filename); + } + else + { + if (rl_point == rl_end && temp_string_index) + rl_insert_text (temp_string); + } + + return (temp_string_index); +} + +static void +insert_all_matches (matches, point, qc) + char **matches; + int point; + char *qc; +{ + int i; + char *rp; + + rl_begin_undo_group (); + /* remove any opening quote character; make_quoted_replacement will add + it back. */ + if (qc && *qc && point && rl_line_buffer[point - 1] == *qc) + point--; + rl_delete_text (point, rl_point); + rl_point = point; + + if (matches[1]) + { + for (i = 1; matches[i]; i++) + { + rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc); + rl_insert_text (rp); + rl_insert_text (" "); + if (rp != matches[i]) + free (rp); + } + } + else + { + rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc); + rl_insert_text (rp); + rl_insert_text (" "); + if (rp != matches[0]) + free (rp); + } + rl_end_undo_group (); +} + +void +_rl_free_match_list (matches) + char **matches; +{ + register int i; + + if (matches == 0) + return; + + for (i = 0; matches[i]; i++) + free (matches[i]); + free (matches); +} + +/* Complete the word at or before point. + WHAT_TO_DO says what to do with the completion. + `?' means list the possible completions. + TAB means do standard completion. + `*' means insert all of the possible completions. + `!' means to do standard completion, and list all possible completions if + there is more than one. + `@' means to do standard completion, and list all possible completions if + there is more than one and partial completion is not possible. */ +int +rl_complete_internal (what_to_do) + int what_to_do; +{ + char **matches; + rl_compentry_func_t *our_func; + int start, end, delimiter, found_quote, i, nontrivial_lcd; + char *text, *saved_line_buffer; + char quote_char; + + RL_SETSTATE(RL_STATE_COMPLETING); + + set_completion_defaults (what_to_do); + + saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : rl_filename_completion_function; + /* We now look backwards for the start of a filename/variable word. */ + end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + if (rl_point) + /* This (possibly) changes rl_point. If it returns a non-zero char, + we know we have an open quote. */ + quote_char = _rl_find_completion_word (&found_quote, &delimiter); + + start = rl_point; + rl_point = end; + + text = rl_copy_text (start, end); + matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); + /* nontrivial_lcd is set if the common prefix adds something to the word + being completed. */ + nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; + free (text); + + if (matches == 0) + { + rl_ding (); + FREE (saved_line_buffer); + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + return (0); + } + + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + rl_filename_completion_function does this. */ + i = rl_filename_completion_desired; + + if (postprocess_matches (&matches, i) == 0) + { + rl_ding (); + FREE (saved_line_buffer); + completion_changed_buffer = 0; + RL_UNSETSTATE(RL_STATE_COMPLETING); + return (0); + } + + switch (what_to_do) + { + case TAB: + case '!': + case '@': + /* Insert the first match with proper quoting. */ + if (*matches[0]) + insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "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 '?': + display_matches (matches); + break; + + default: + fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do); + rl_ding (); + FREE (saved_line_buffer); + RL_UNSETSTATE(RL_STATE_COMPLETING); + return 1; + } + + _rl_free_match_list (matches); + + /* Check to see if the line has changed through all of this manipulation. */ + if (saved_line_buffer) + { + completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0; + free (saved_line_buffer); + } + + RL_UNSETSTATE(RL_STATE_COMPLETING); + return 0; +} + +/***************************************************************/ +/* */ +/* Application-callable completion match generator functions */ +/* */ +/***************************************************************/ + +/* Return an array of (char *) which is a list of completions for TEXT. + If there are no completions, return a NULL pointer. + The first entry in the returned array is the substitution for TEXT. + The remaining entries are the possible completions. + The array is terminated with a NULL pointer. + + ENTRY_FUNCTION is a function of two args, and returns a (char *). + The first argument is TEXT. + The second is a state argument; it should be zero on the first call, and + non-zero on subsequent calls. It returns a NULL pointer to the caller + when there are no more matches. + */ +char ** +rl_completion_matches (text, entry_function) + const char *text; + rl_compentry_func_t *entry_function; +{ + /* Number of slots in match_list. */ + int match_list_size; + + /* The list of matches. */ + char **match_list; + + /* Number of matches actually found. */ + int matches; + + /* Temporary string binder. */ + char *string; + + matches = 0; + match_list_size = 10; + match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); + match_list[1] = (char *)NULL; + + while (string = (*entry_function) (text, matches)) + { + if (matches + 1 == match_list_size) + match_list = (char **)xrealloc + (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); + + match_list[++matches] = string; + match_list[matches + 1] = (char *)NULL; + } + + /* If there were any matches, then look through them finding out the + lowest common denominator. That then becomes match_list[0]. */ + if (matches) + compute_lcd_of_matches (match_list, matches, text); + else /* There were no matches. */ + { + free (match_list); + match_list = (char **)NULL; + } + return (match_list); +} + +/* A completion function for usernames. + TEXT contains a partial username preceded by a random + character (usually `~'). */ +char * +rl_username_completion_function (text, state) + const char *text; + int state; +{ +#if defined (__WIN32__) || defined (__OPENNT) + return (char *)NULL; +#else /* !__WIN32__ && !__OPENNT) */ + static char *username = (char *)NULL; + static struct passwd *entry; + static int namelen, first_char, first_char_loc; + char *value; + + if (state == 0) + { + FREE (username); + + first_char = *text; + first_char_loc = first_char == '~'; + + username = savestring (&text[first_char_loc]); + namelen = strlen (username); + setpwent (); + } + + while (entry = getpwent ()) + { + /* Null usernames should result in all users as possible completions. */ + if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) + break; + } + + if (entry == 0) + { + endpwent (); + return ((char *)NULL); + } + else + { + value = (char *)xmalloc (2 + strlen (entry->pw_name)); + + *value = *text; + + strcpy (value + first_char_loc, entry->pw_name); + + if (first_char == '~') + rl_filename_completion_desired = 1; + + return (value); + } +#endif /* !__WIN32__ && !__OPENNT */ +} + +/* Okay, now we write the entry_function for filename completion. In the + general case. Note that completion in the shell is a little different + because of all the pathnames that must be followed when looking up the + completion for a command. */ +char * +rl_filename_completion_function (text, state) + const char *text; + int state; +{ + static DIR *directory = (DIR *)NULL; + static char *filename = (char *)NULL; + static char *dirname = (char *)NULL; + static char *users_dirname = (char *)NULL; + static int filename_len; + char *temp; + int dirlen; + struct dirent *entry; + + /* If we don't have any state, then do some initialization. */ + if (state == 0) + { + /* If we were interrupted before closing the directory or reading + all of its contents, close it. */ + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + FREE (dirname); + FREE (filename); + FREE (users_dirname); + + filename = savestring (text); + if (*text == 0) + text = "."; + dirname = savestring (text); + + temp = strrchr (dirname, '/'); + +#if defined (__MSDOS__) + /* special hack for //X/... */ + if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') + temp = strrchr (dirname + 3, '/'); +#endif + + if (temp) + { + strcpy (filename, ++temp); + *temp = '\0'; + } +#if defined (__MSDOS__) + /* searches from current directory on the drive */ + else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') + { + strcpy (filename, dirname + 2); + dirname[2] = '\0'; + } +#endif + else + { + dirname[0] = '.'; + dirname[1] = '\0'; + } + + /* We aren't done yet. We also support the "~user" syntax. */ + + /* Save the version of the directory that the user typed. */ + users_dirname = savestring (dirname); + + if (*dirname == '~') + { + temp = tilde_expand (dirname); + free (dirname); + dirname = temp; + } + + if (rl_directory_rewrite_hook) + (*rl_directory_rewrite_hook) (&dirname); + + if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname)) + { + free (users_dirname); + users_dirname = savestring (dirname); + } + + directory = opendir (dirname); + filename_len = strlen (filename); + + rl_filename_completion_desired = 1; + } + + /* At this point we should entertain the possibility of hacking wildcarded + filenames, like /usr/man/man/te. If the directory name + contains globbing characters, then build an array of directories, and + then map over that list while completing. */ + /* *** UNIMPLEMENTED *** */ + + /* Now that we have some state, we can read the directory. */ + + entry = (struct dirent *)NULL; + while (directory && (entry = readdir (directory))) + { + /* Special case for no filename. If the user has disabled the + `match-hidden-files' variable, skip filenames beginning with `.'. + All other entries except "." and ".." match. */ + if (filename_len == 0) + { + if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name)) + continue; + + if (entry->d_name[0] != '.' || + (entry->d_name[1] && + (entry->d_name[1] != '.' || entry->d_name[2]))) + break; + } + else + { + /* Otherwise, if these match up to the length of filename, then + it is a match. */ + if (_rl_completion_case_fold) + { + if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) && + (((int)D_NAMLEN (entry)) >= filename_len) && + (_rl_strnicmp (filename, entry->d_name, filename_len) == 0)) + break; + } + else + { + if ((entry->d_name[0] == filename[0]) && + (((int)D_NAMLEN (entry)) >= filename_len) && + (strncmp (filename, entry->d_name, filename_len) == 0)) + break; + } + } + } + + if (entry == 0) + { + if (directory) + { + closedir (directory); + directory = (DIR *)NULL; + } + if (dirname) + { + free (dirname); + dirname = (char *)NULL; + } + if (filename) + { + free (filename); + filename = (char *)NULL; + } + if (users_dirname) + { + free (users_dirname); + users_dirname = (char *)NULL; + } + + return (char *)NULL; + } + else + { + /* dirname && (strcmp (dirname, ".") != 0) */ + if (dirname && (dirname[0] != '.' || dirname[1])) + { + if (rl_complete_with_tilde_expansion && *users_dirname == '~') + { + dirlen = strlen (dirname); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); + strcpy (temp, dirname); + /* Canonicalization cuts off any final slash present. We + may need to add it back. */ + if (dirname[dirlen - 1] != '/') + { + temp[dirlen++] = '/'; + temp[dirlen] = '\0'; + } + } + else + { + dirlen = strlen (users_dirname); + temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); + strcpy (temp, users_dirname); + /* Make sure that temp has a trailing slash here. */ + if (users_dirname[dirlen - 1] != '/') + temp[dirlen++] = '/'; + } + + strcpy (temp + dirlen, entry->d_name); + } + else + temp = savestring (entry->d_name); + + return (temp); + } +} + +/* An initial implementation of a menu completion function a la tcsh. The + first time (if the last readline command was not rl_menu_complete), we + generate the list of matches. This code is very similar to the code in + rl_complete_internal -- there should be a way to combine the two. Then, + for each item in the list of matches, we insert the match in an undoable + fashion, with the appropriate character appended (this happens on the + second and subsequent consecutive calls to rl_menu_complete). When we + hit the end of the match list, we restore the original unmatched text, + ring the bell, and reset the counter to zero. */ +int +rl_menu_complete (count, ignore) + int count, ignore; +{ + rl_compentry_func_t *our_func; + int matching_filenames, found_quote; + + static char *orig_text; + static char **matches = (char **)0; + static int match_list_index = 0; + static int match_list_size = 0; + static int orig_start, orig_end; + static char quote_char; + static int delimiter; + + /* The first time through, we generate the list of matches and set things + up to insert them. */ + if (rl_last_func != rl_menu_complete) + { + /* Clean up from previous call, if any. */ + FREE (orig_text); + if (matches) + _rl_free_match_list (matches); + + match_list_index = match_list_size = 0; + matches = (char **)NULL; + + /* Only the completion entry function can change these. */ + set_completion_defaults ('%'); + + our_func = rl_completion_entry_function + ? rl_completion_entry_function + : rl_filename_completion_function; + + /* We now look backwards for the start of a filename/variable word. */ + orig_end = rl_point; + found_quote = delimiter = 0; + quote_char = '\0'; + + if (rl_point) + /* This (possibly) changes rl_point. If it returns a non-zero char, + we know we have an open quote. */ + quote_char = _rl_find_completion_word (&found_quote, &delimiter); + + orig_start = rl_point; + rl_point = orig_end; + + orig_text = rl_copy_text (orig_start, orig_end); + matches = gen_completion_matches (orig_text, orig_start, orig_end, + our_func, found_quote, quote_char); + + /* If we are matching filenames, the attempted completion function will + have set rl_filename_completion_desired to a non-zero value. The basic + rl_filename_completion_function does this. */ + matching_filenames = rl_filename_completion_desired; + + if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + FREE (orig_text); + orig_text = (char *)0; + completion_changed_buffer = 0; + return (0); + } + + for (match_list_size = 0; matches[match_list_size]; match_list_size++) + ; + /* matches[0] is lcd if match_list_size > 1, but the circular buffer + code below should take care of it. */ + } + + /* Now we have the list of matches. Replace the text between + rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with + matches[match_list_index], and add any necessary closing char. */ + + if (matches == 0 || match_list_size == 0) + { + rl_ding (); + FREE (matches); + matches = (char **)0; + completion_changed_buffer = 0; + return (0); + } + + match_list_index = (match_list_index + count) % match_list_size; + if (match_list_index < 0) + 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); +} diff --git a/lib/readline/doc/fdl.texi b/lib/readline/doc/fdl.texi deleted file mode 120000 index 68e5eb5..0000000 --- a/lib/readline/doc/fdl.texi +++ /dev/null @@ -1 +0,0 @@ -../../../doc/fdl.texi \ No newline at end of file diff --git a/lib/readline/doc/fdl.texi b/lib/readline/doc/fdl.texi new file mode 100644 index 0000000..47ead9f --- /dev/null +++ b/lib/readline/doc/fdl.texi @@ -0,0 +1,452 @@ + +@node GNU Free Documentation License +@appendixsec GNU Free Documentation License + +@cindex FDL, GNU Free Documentation License +@center Version 1.2, November 2002 + +@display +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +@sc{ascii} without markup, Texinfo input format, La@TeX{} input +format, @acronym{SGML} or @acronym{XML} using a publicly available +@acronym{DTD}, and standard-conforming simple @acronym{HTML}, +PostScript or @acronym{PDF} designed for human modification. Examples +of transparent image formats include @acronym{PNG}, @acronym{XCF} and +@acronym{JPG}. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, @acronym{SGML} or +@acronym{XML} for which the @acronym{DTD} and/or processing tools are +not generally available, and the machine-generated @acronym{HTML}, +PostScript or @acronym{PDF} produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. +@end enumerate + +@page +@appendixsubsec ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with...Texts.'' line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: + diff --git a/lib/readline/posixdir.h b/lib/readline/posixdir.h deleted file mode 120000 index 8b16384..0000000 --- a/lib/readline/posixdir.h +++ /dev/null @@ -1 +0,0 @@ -../../include/posixdir.h \ No newline at end of file diff --git a/lib/readline/posixdir.h b/lib/readline/posixdir.h new file mode 100644 index 0000000..91f6d96 --- /dev/null +++ b/lib/readline/posixdir.h @@ -0,0 +1,61 @@ +/* posixdir.h -- Posix directory reading includes and defines. */ + +/* Copyright (C) 1987,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 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* This file should be included instead of or . */ + +#if !defined (_POSIXDIR_H_) +#define _POSIXDIR_H_ + +#if defined (HAVE_DIRENT_H) +# include +# if defined (HAVE_STRUCT_DIRENT_D_NAMLEN) +# define D_NAMLEN(d) ((d)->d_namlen) +# else +# define D_NAMLEN(d) (strlen ((d)->d_name)) +# endif /* !HAVE_STRUCT_DIRENT_D_NAMLEN */ +#else +# if defined (HAVE_SYS_NDIR_H) +# include +# endif +# if defined (HAVE_SYS_DIR_H) +# include +# endif +# if defined (HAVE_NDIR_H) +# include +# endif +# if !defined (dirent) +# define dirent direct +# endif /* !dirent */ +# define D_NAMLEN(d) ((d)->d_namlen) +#endif /* !HAVE_DIRENT_H */ + +#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO) +# define d_fileno d_ino +#endif + +#if defined (_POSIX_SOURCE) && (!defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO)) +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +# define REAL_DIR_ENTRY(dp) 1 +#else +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +#endif /* _POSIX_SOURCE */ + +#endif /* !_POSIXDIR_H_ */ diff --git a/lib/readline/posixjmp.h b/lib/readline/posixjmp.h deleted file mode 120000 index b4d3ee7..0000000 --- a/lib/readline/posixjmp.h +++ /dev/null @@ -1 +0,0 @@ -../../include/posixjmp.h \ No newline at end of file diff --git a/lib/readline/posixjmp.h b/lib/readline/posixjmp.h new file mode 100644 index 0000000..b52aa00 --- /dev/null +++ b/lib/readline/posixjmp.h @@ -0,0 +1,40 @@ +/* posixjmp.h -- wrapper for setjmp.h with changes for POSIX systems. */ + +/* Copyright (C) 1987,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 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#ifndef _POSIXJMP_H_ +#define _POSIXJMP_H_ + +#include + +/* This *must* be included *after* config.h */ + +#if defined (HAVE_POSIX_SIGSETJMP) +# define procenv_t sigjmp_buf +# if !defined (__OPENNT) +# undef setjmp +# define setjmp(x) sigsetjmp((x), 1) +# undef longjmp +# define longjmp(x, n) siglongjmp((x), (n)) +# endif /* !__OPENNT */ +#else +# define procenv_t jmp_buf +#endif + +#endif /* _POSIXJMP_H_ */ diff --git a/lib/readline/posixstat.h b/lib/readline/posixstat.h deleted file mode 120000 index c6164b7..0000000 --- a/lib/readline/posixstat.h +++ /dev/null @@ -1 +0,0 @@ -../../include/posixstat.h \ No newline at end of file diff --git a/lib/readline/posixstat.h b/lib/readline/posixstat.h new file mode 100644 index 0000000..c93b528 --- /dev/null +++ b/lib/readline/posixstat.h @@ -0,0 +1,142 @@ +/* posixstat.h -- Posix stat(2) definitions for systems that + don't have them. */ + +/* Copyright (C) 1987,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 2, or (at your option) + any later version. + + Bash is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +/* This file should be included instead of . + It relies on the local sys/stat.h to work though. */ +#if !defined (_POSIXSTAT_H_) +#define _POSIXSTAT_H_ + +#include + +#if defined (STAT_MACROS_BROKEN) +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISREG +# undef S_ISLNK +#endif /* STAT_MACROS_BROKEN */ + +/* These are guaranteed to work only on isc386 */ +#if !defined (S_IFDIR) && !defined (S_ISDIR) +# define S_IFDIR 0040000 +#endif /* !S_IFDIR && !S_ISDIR */ +#if !defined (S_IFMT) +# define S_IFMT 0170000 +#endif /* !S_IFMT */ + +/* Posix 1003.1 5.6.1.1 file types */ + +/* Some Posix-wannabe systems define _S_IF* macros instead of S_IF*, but + do not provide the S_IS* macros that Posix requires. */ + +#if defined (_S_IFMT) && !defined (S_IFMT) +#define S_IFMT _S_IFMT +#endif +#if defined (_S_IFIFO) && !defined (S_IFIFO) +#define S_IFIFO _S_IFIFO +#endif +#if defined (_S_IFCHR) && !defined (S_IFCHR) +#define S_IFCHR _S_IFCHR +#endif +#if defined (_S_IFDIR) && !defined (S_IFDIR) +#define S_IFDIR _S_IFDIR +#endif +#if defined (_S_IFBLK) && !defined (S_IFBLK) +#define S_IFBLK _S_IFBLK +#endif +#if defined (_S_IFREG) && !defined (S_IFREG) +#define S_IFREG _S_IFREG +#endif +#if defined (_S_IFLNK) && !defined (S_IFLNK) +#define S_IFLNK _S_IFLNK +#endif +#if defined (_S_IFSOCK) && !defined (S_IFSOCK) +#define S_IFSOCK _S_IFSOCK +#endif + +/* Test for each symbol individually and define the ones necessary (some + systems claiming Posix compatibility define some but not all). */ + +#if defined (S_IFBLK) && !defined (S_ISBLK) +#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */ +#endif + +#if defined (S_IFCHR) && !defined (S_ISCHR) +#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */ +#endif + +#if defined (S_IFDIR) && !defined (S_ISDIR) +#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */ +#endif + +#if defined (S_IFREG) && !defined (S_ISREG) +#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */ +#endif + +#if defined (S_IFIFO) && !defined (S_ISFIFO) +#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */ +#endif + +#if defined (S_IFLNK) && !defined (S_ISLNK) +#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */ +#endif + +#if defined (S_IFSOCK) && !defined (S_ISSOCK) +#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */ +#endif + +/* + * POSIX 1003.1 5.6.1.2 File Modes + */ + +#if !defined (S_IRWXU) +# if !defined (S_IREAD) +# define S_IREAD 00400 +# define S_IWRITE 00200 +# define S_IEXEC 00100 +# endif /* S_IREAD */ + +# if !defined (S_IRUSR) +# define S_IRUSR S_IREAD /* read, owner */ +# define S_IWUSR S_IWRITE /* write, owner */ +# define S_IXUSR S_IEXEC /* execute, owner */ + +# define S_IRGRP (S_IREAD >> 3) /* read, group */ +# define S_IWGRP (S_IWRITE >> 3) /* write, group */ +# define S_IXGRP (S_IEXEC >> 3) /* execute, group */ + +# define S_IROTH (S_IREAD >> 6) /* read, other */ +# define S_IWOTH (S_IWRITE >> 6) /* write, other */ +# define S_IXOTH (S_IEXEC >> 6) /* execute, other */ +# endif /* !S_IRUSR */ + +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif /* !S_IRWXU */ + +/* These are non-standard, but are used in builtins.c$symbolic_umask() */ +#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH) +#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH) +#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) + +#endif /* _POSIXSTAT_H_ */ diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c deleted file mode 120000 index 439ceed..0000000 --- a/lib/readline/tilde.c +++ /dev/null @@ -1 +0,0 @@ -../tilde/tilde.c \ No newline at end of file diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c new file mode 100644 index 0000000..154f7f8 --- /dev/null +++ b/lib/readline/tilde.c @@ -0,0 +1,458 @@ +/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */ + +/* Copyright (C) 1988,1989 Free Software Foundation, Inc. + + This file is part of GNU 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 2, 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; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#if defined (HAVE_STRING_H) +# include +#else /* !HAVE_STRING_H */ +# include +#endif /* !HAVE_STRING_H */ + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif /* HAVE_STDLIB_H */ + +#include +#include + +#include "tilde.h" + +#if defined (TEST) || defined (STATIC_MALLOC) +static void *xmalloc (), *xrealloc (); +#else +# include "xmalloc.h" +#endif /* TEST || STATIC_MALLOC */ + +#if !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwuid PARAMS((uid_t)); +extern struct passwd *getpwnam PARAMS((const char *)); +#endif /* !HAVE_GETPW_DECLS */ + +#if !defined (savestring) +#define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x)) +#endif /* !savestring */ + +#if !defined (NULL) +# if defined (__STDC__) +# define NULL ((void *) 0) +# else +# define NULL 0x0 +# endif /* !__STDC__ */ +#endif /* !NULL */ + +/* If being compiled as part of bash, these will be satisfied from + variables.o. If being compiled as part of readline, they will + be satisfied from shell.o. */ +extern char *sh_get_home_dir PARAMS((void)); +extern char *sh_get_env_value PARAMS((const char *)); + +/* The default value of tilde_additional_prefixes. This is set to + whitespace preceding a tilde so that simple programs which do not + perform any word separation get desired behaviour. */ +static const char *default_prefixes[] = + { " ~", "\t~", (const char *)NULL }; + +/* The default value of tilde_additional_suffixes. This is set to + whitespace or newline so that simple programs which do not + perform any word separation get desired behaviour. */ +static const char *default_suffixes[] = + { " ", "\n", (const char *)NULL }; + +/* If non-null, this contains the address of a function that the application + wants called before trying the standard tilde expansions. The function + is called with the text sans tilde, and returns a malloc()'ed string + which is the expansion, or a NULL pointer if the expansion fails. */ +tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL; + +/* If non-null, this contains the address of a function to call if the + standard meaning for expanding a tilde fails. The function is called + with the text (sans tilde, as in "foo"), and returns a malloc()'ed string + which is the expansion, or a NULL pointer if there is no expansion. */ +tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL; + +/* When non-null, this is a NULL terminated array of strings which + are duplicates for a tilde prefix. Bash uses this to expand + `=~' and `:~'. */ +char **tilde_additional_prefixes = (char **)default_prefixes; + +/* When non-null, this is a NULL terminated array of strings which match + the end of a username, instead of just "/". Bash sets this to + `:' and `=~'. */ +char **tilde_additional_suffixes = (char **)default_suffixes; + +static int tilde_find_prefix PARAMS((const char *, int *)); +static int tilde_find_suffix PARAMS((const char *)); +static char *isolate_tilde_prefix PARAMS((const char *, int *)); +static char *glue_prefix_and_suffix PARAMS((char *, const char *, int)); + +/* Find the start of a tilde expansion in STRING, and return the index of + the tilde which starts the expansion. Place the length of the text + which identified this tilde starter in LEN, excluding the tilde itself. */ +static int +tilde_find_prefix (string, len) + const char *string; + int *len; +{ + register int i, j, string_len; + register char **prefixes; + + prefixes = tilde_additional_prefixes; + + string_len = strlen (string); + *len = 0; + + if (*string == '\0' || *string == '~') + return (0); + + if (prefixes) + { + for (i = 0; i < string_len; i++) + { + for (j = 0; prefixes[j]; j++) + { + if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0) + { + *len = strlen (prefixes[j]) - 1; + return (i + *len); + } + } + } + } + return (string_len); +} + +/* Find the end of a tilde expansion in STRING, and return the index of + the character which ends the tilde definition. */ +static int +tilde_find_suffix (string) + const char *string; +{ + register int i, j, string_len; + register char **suffixes; + + suffixes = tilde_additional_suffixes; + string_len = strlen (string); + + for (i = 0; i < string_len; i++) + { +#if defined (__MSDOS__) + if (string[i] == '/' || string[i] == '\\' /* || !string[i] */) +#else + if (string[i] == '/' /* || !string[i] */) +#endif + break; + + for (j = 0; suffixes && suffixes[j]; j++) + { + if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0) + return (i); + } + } + return (i); +} + +/* Return a new string which is the result of tilde expanding STRING. */ +char * +tilde_expand (string) + const char *string; +{ + char *result; + int result_size, result_index; + + result_index = result_size = 0; + if (result = strchr (string, '~')) + result = (char *)xmalloc (result_size = (strlen (string) + 16)); + else + result = (char *)xmalloc (result_size = (strlen (string) + 1)); + + /* Scan through STRING expanding tildes as we come to them. */ + while (1) + { + register int start, end; + char *tilde_word, *expansion; + int len; + + /* Make START point to the tilde which starts the expansion. */ + start = tilde_find_prefix (string, &len); + + /* Copy the skipped text into the result. */ + if ((result_index + start + 1) > result_size) + result = (char *)xrealloc (result, 1 + (result_size += (start + 20))); + + strncpy (result + result_index, string, start); + result_index += start; + + /* Advance STRING to the starting tilde. */ + string += start; + + /* Make END be the index of one after the last character of the + username. */ + end = tilde_find_suffix (string); + + /* If both START and END are zero, we are all done. */ + if (!start && !end) + break; + + /* Expand the entire tilde word, and copy it into RESULT. */ + tilde_word = (char *)xmalloc (1 + end); + strncpy (tilde_word, string, end); + tilde_word[end] = '\0'; + string += end; + + expansion = tilde_expand_word (tilde_word); + free (tilde_word); + + len = strlen (expansion); +#ifdef __CYGWIN__ + /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when + $HOME for `user' is /. On cygwin, // denotes a network drive. */ + if (len > 1 || *expansion != '/' || *string != '/') +#endif + { + if ((result_index + len + 1) > result_size) + result = (char *)xrealloc (result, 1 + (result_size += (len + 20))); + + strcpy (result + result_index, expansion); + result_index += len; + } + free (expansion); + } + + result[result_index] = '\0'; + + return (result); +} + +/* Take FNAME and return the tilde prefix we want expanded. If LENP is + non-null, the index of the end of the prefix into FNAME is returned in + the location it points to. */ +static char * +isolate_tilde_prefix (fname, lenp) + const char *fname; + int *lenp; +{ + char *ret; + int i; + + ret = (char *)xmalloc (strlen (fname)); +#if defined (__MSDOS__) + for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++) +#else + for (i = 1; fname[i] && fname[i] != '/'; i++) +#endif + ret[i - 1] = fname[i]; + ret[i - 1] = '\0'; + if (lenp) + *lenp = i; + return ret; +} + +/* Return a string that is PREFIX concatenated with SUFFIX starting at + SUFFIND. */ +static char * +glue_prefix_and_suffix (prefix, suffix, suffind) + char *prefix; + const char *suffix; + int suffind; +{ + char *ret; + int plen, slen; + + plen = (prefix && *prefix) ? strlen (prefix) : 0; + slen = strlen (suffix + suffind); + ret = (char *)xmalloc (plen + slen + 1); + if (plen) + strcpy (ret, prefix); + strcpy (ret + plen, suffix + suffind); + return ret; +} + +/* Do the work of tilde expansion on FILENAME. FILENAME starts with a + tilde. If there is no expansion, call tilde_expansion_failure_hook. + This always returns a newly-allocated string, never static storage. */ +char * +tilde_expand_word (filename) + const char *filename; +{ + char *dirname, *expansion, *username; + int user_len; + struct passwd *user_entry; + + if (filename == 0) + return ((char *)NULL); + + if (*filename != '~') + return (savestring (filename)); + + /* A leading `~/' or a bare `~' is *always* translated to the value of + $HOME or the home directory of the current user, regardless of any + preexpansion hook. */ + if (filename[1] == '\0' || filename[1] == '/') + { + /* Prefix $HOME to the rest of the string. */ + expansion = sh_get_env_value ("HOME"); + + /* If there is no HOME variable, look up the directory in + the password database. */ + if (expansion == 0) + expansion = sh_get_home_dir (); + + return (glue_prefix_and_suffix (expansion, filename, 1)); + } + + username = isolate_tilde_prefix (filename, &user_len); + + if (tilde_expansion_preexpansion_hook) + { + expansion = (*tilde_expansion_preexpansion_hook) (username); + if (expansion) + { + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (username); + free (expansion); + return (dirname); + } + } + + /* No preexpansion hook, or the preexpansion hook failed. Look in the + password database. */ + dirname = (char *)NULL; + user_entry = getpwnam (username); + if (user_entry == 0) + { + /* If the calling program has a special syntax for expanding tildes, + and we couldn't find a standard expansion, then let them try. */ + if (tilde_expansion_failure_hook) + { + expansion = (*tilde_expansion_failure_hook) (username); + if (expansion) + { + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (expansion); + } + } + free (username); + /* If we don't have a failure hook, or if the failure hook did not + expand the tilde, return a copy of what we were passed. */ + if (dirname == 0) + dirname = savestring (filename); + } + else + { + free (username); + dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); + } + + endpwent (); + return (dirname); +} + + +#if defined (TEST) +#undef NULL +#include + +main (argc, argv) + int argc; + char **argv; +{ + char *result, line[512]; + int done = 0; + + while (!done) + { + printf ("~expand: "); + fflush (stdout); + + if (!gets (line)) + strcpy (line, "done"); + + if ((strcmp (line, "done") == 0) || + (strcmp (line, "quit") == 0) || + (strcmp (line, "exit") == 0)) + { + done = 1; + break; + } + + result = tilde_expand (line); + printf (" --> %s\n", result); + free (result); + } + exit (0); +} + +static void memory_error_and_abort (); + +static void * +xmalloc (bytes) + size_t bytes; +{ + void *temp = (char *)malloc (bytes); + + if (!temp) + memory_error_and_abort (); + return (temp); +} + +static void * +xrealloc (pointer, bytes) + void *pointer; + int bytes; +{ + void *temp; + + if (!pointer) + temp = malloc (bytes); + else + temp = realloc (pointer, bytes); + + if (!temp) + memory_error_and_abort (); + + return (temp); +} + +static void +memory_error_and_abort () +{ + fprintf (stderr, "readline: out of virtual memory\n"); + abort (); +} + +/* + * Local variables: + * compile-command: "gcc -g -DTEST -o tilde tilde.c" + * end: + */ +#endif /* TEST */ diff --git a/lib/readline/tilde.h b/lib/readline/tilde.h deleted file mode 120000 index 6fea2ae..0000000 --- a/lib/readline/tilde.h +++ /dev/null @@ -1 +0,0 @@ -../tilde/tilde.h \ No newline at end of file diff --git a/lib/readline/tilde.h b/lib/readline/tilde.h new file mode 100644 index 0000000..f8182c9 --- /dev/null +++ b/lib/readline/tilde.h @@ -0,0 +1,78 @@ +/* tilde.h: Externally available variables and function in libtilde.a. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_TILDE_H_) +# define _TILDE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* A function can be defined using prototypes and compile on both ANSI C + and traditional C compilers with something like this: + extern char *func PARAMS((char *, char *, int)); */ + +#if !defined (PARAMS) +# if defined (__STDC__) || defined (__GNUC__) || defined (__cplusplus) +# define PARAMS(protos) protos +# else +# define PARAMS(protos) () +# endif +#endif + +typedef char *tilde_hook_func_t PARAMS((char *)); + +/* If non-null, this contains the address of a function that the application + wants called before trying the standard tilde expansions. The function + is called with the text sans tilde, and returns a malloc()'ed string + which is the expansion, or a NULL pointer if the expansion fails. */ +extern tilde_hook_func_t *tilde_expansion_preexpansion_hook; + +/* If non-null, this contains the address of a function to call if the + standard meaning for expanding a tilde fails. The function is called + with the text (sans tilde, as in "foo"), and returns a malloc()'ed string + which is the expansion, or a NULL pointer if there is no expansion. */ +extern tilde_hook_func_t *tilde_expansion_failure_hook; + +/* When non-null, this is a NULL terminated array of strings which + are duplicates for a tilde prefix. Bash uses this to expand + `=~' and `:~'. */ +extern char **tilde_additional_prefixes; + +/* When non-null, this is a NULL terminated array of strings which match + the end of a username, instead of just "/". Bash sets this to + `:' and `=~'. */ +extern char **tilde_additional_suffixes; + +/* Return a new string which is the result of tilde expanding STRING. */ +extern char *tilde_expand PARAMS((const char *)); + +/* Do the work of tilde expansion on FILENAME. FILENAME starts with a + tilde. If there is no expansion, call tilde_expansion_failure_hook. */ +extern char *tilde_expand_word PARAMS((const char *)); + +#ifdef __cplusplus +} +#endif + +#endif /* _TILDE_H_ */ diff --git a/parser-built b/parser-built index e69de29..3527227 100644 --- a/parser-built +++ b/parser-built @@ -0,0 +1,52 @@ +typedef 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; +} YYSTYPE; +#define IF 257 +#define THEN 258 +#define ELSE 259 +#define ELIF 260 +#define FI 261 +#define CASE 262 +#define ESAC 263 +#define FOR 264 +#define SELECT 265 +#define WHILE 266 +#define UNTIL 267 +#define DO 268 +#define DONE 269 +#define FUNCTION 270 +#define COND_START 271 +#define COND_END 272 +#define COND_ERROR 273 +#define IN 274 +#define BANG 275 +#define TIME 276 +#define TIMEOPT 277 +#define WORD 278 +#define ASSIGNMENT_WORD 279 +#define NUMBER 280 +#define ARITH_CMD 281 +#define ARITH_FOR_EXPRS 282 +#define COND_CMD 283 +#define AND_AND 284 +#define OR_OR 285 +#define GREATER_GREATER 286 +#define LESS_LESS 287 +#define LESS_AND 288 +#define LESS_LESS_LESS 289 +#define GREATER_AND 290 +#define SEMI_SEMI 291 +#define LESS_LESS_MINUS 292 +#define AND_GREATER 293 +#define LESS_GREATER 294 +#define GREATER_BAR 295 +#define yacc_EOF 296 + + +extern YYSTYPE yylval; diff --git a/po/Rules-builtins b/po/Rules-builtins index 602154a..57df81c 100644 --- a/po/Rules-builtins +++ b/po/Rules-builtins @@ -16,4 +16,4 @@ $(srcdir)/builtins.pot: $(MAKE) builtins.pot-update xdist: - update-po + $(MAKE) update-po diff --git a/po/en@boldquot.gmo b/po/en@boldquot.gmo index 7a35327c63e7e1b1ba2fffe4eb5dab40bed593ca..6a9c77ba25ca19e810fecf4cbdf2859e979a677f 100644 GIT binary patch delta 20884 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 ZC8inQYR|gZz|~6s>2FW`$UvD+{||Bcm#qK* delta 20749 zcmYk>1)NpI`^WLKgmf&+0?U$1=hCs%1(sN1=@RLX66uCZcdtlD3DVNtARwJ0f+&h8 zf`BwA<^S`&&-nX$UJmbhX6DS9Gc)I$3!Yz_C~i$6|BW;W=6D?E;(J~uoSMb+LKAx4 zoAN64y!s71FF!WGbT|ytV;m;Ob*QGhup~amq*$P#wJU`=h-0x7_Q6P8gPia8u8}EA z!EH>1*&12HBB%~OL|t$Zmc#8>1|MTE=5OqIAy^)xus-U%DOem2V`+SjMX*p4JHIuS z=K9{;K*saVV@Vn$YHA~{fErLcOpU!U9garb!F)`HCs70V77O8BEQ;xy*^I_u8sg5* z!I*(~DwgB=-U>3g@usUt+}tjl9Wzs26f0vr=PXQ1{0*kSJE#G^aB-p*c3vo|zBp>B zDq{(ZMGbfi`Zcn-WYoc0)E)1|tautr<2__ccsbs;6Z2tN;tHrKABe?p3u?-LL!BSi z(&DmMhWI0_fGeH9wq*XbCJ`U7>9CQrE2bp&qXsk`bK+u*!6R4zQ?&BD>R1-*;7C;c zShHBrP4z9TfLTAZ^ID*7oF>G`kL-SeU;7>_yeG#121SP3)tur+UmKH{;M z2all!@Bp<(GJRyve=O=fG7NRWEvU7=jhfkXJ?;GWu_V{`Mw8J~unRTPyDrZ2v0bn^ zs-yX+fu2P@erbByRMtTad<b z{#CJ)0*yHSAbW9?#zMqxu_R7M4dkdRe} zRwqv7A8Nb0DORDN7na4XE`ER-K#^gdmjydxS{#R3>jjt&_h1sdh{1T>l|OJM7;f#t zF%9*_Ff;nAkx50S1BPHIt`6nurc^ItF@zQT-{bCh*h$=MLqt`i0Zh#JT&%!V5=J6=Fd z^%GQi!qGOPxluP-0kd*_uLT)39E@6usV-iKT7r$J3x17Zcmp-CzfjM0$QT7n+Dw@lz~=-(xil8E5bM z78pf52lbd;zzUdQytQwN)rn_ddAu^7`PT^{6YOz{#frppF@IRbSKYH4T~?f27|C1@jg^Xf4TCgCHDM|Ky@??E8s<}gsGO=d!ioJChm%A zw;faC->3m5{ha4tnYv`u!Ay+7bEtu2SZ21u{KU(!AfCk{_zHbkV7YbJ!?_W4{u9&; zmj1%(hoknwA=LGftziDuFlL3laHeAx;?0DQlumn1z|~ z6jsMOs2PmhU~xa^Ud%vwyp8<5F^Jhk-AMOM)_xgk3H-m4(S>tuwhMMajc@~|z(?2| z-=QwtY>Ul6f7E7MiW=z8sDb3(Y6IzxD&KK<$k~m+woOL+;C>-kT&(>@M4 zP$Q1QJU9|{hpRC#)mVr)a+htUR#=C4F_yx6SP&z2+YHr1-T4so;eJey?@&{pZV%Vv z`d(u)dYl$uSv-wNFyUSsKq}Od)I%T6a$a(V?6awFj7+IFAGK6hT>K1c5*OWXOE3gA z14q%XJ4}3lgf&r9-2gR^4yYMfgqnd{F3x|@%6p-fUi!;v8eM0qHb&(s{fbhPfe!W z6|1P@oPk=)OQ`w`-`NH8VHx5|s0$844PXbVI>Z(&(X<^S1!AjDuc3dUhhT#1?SG=}3{RL2Q#TF1388S!lAV$49i7K`B# zOo}hCG6wx({a3||#2ryH?Dvz=8qYzk(Mr@3Jj6`+4z)z#x9skaHl-s_1DcDf z{{ahPrax?t#GnQ^5q)?LH4~}s*;lS8syqtSZYXMR9LB)!|0MVA0@0|onuJ=L)0h-* zVlupsn)<&mu&W=~k~GFh%0I+>I2ViKVbq;I$K06ePrHFqs68?O{Uyn)AyW{4!YY{j zp*?Q(P`i8@s(cA*27W;wMm(|sc0dihC#J+rSOE{Brv5D^$LPoQt!aQU#A6;a|C-vf z6lkr}Jh3UNfx6%{RQ&}kkD*Vkz9IUE=b;944OJiZ%m&gFH52nt{e0!h6F#^0HBd7; z;kn-$#8FU@f-4w-p)YK+l|kLvF!bR8=Rc_SzL(aa9}^KDL~Xj`sLdMxFPn)Ps2LcC zT8i1Oe7B#Bp2wG%4%7T?pVNG(xB==h?1EaNahL_SU{1VKq6=|>oqwqQUu!t8FSnJ*xLA)7Nei^G^Xi!k# zyylpScrNNftDKKeGf*~OP+*{b41E9hlhK_giEkCPF%9t~)NWpg;kXWU=f}~9$r1zw z*0K)fBJPWYaXuEp6IdEwU@0t|FevcYb;6>=^HBfj>762@wSDf4crPfhiRxhv%BNr` zZbS|A7;35$C9;{QhML+gr~z)ng!mV#{X5KnzQk7F0yPth(67ubGMe&yNf;4!K}~TS zX2l(-JG$abkksy=7?z;CBc{jsSP3_yp6|z~y;LrlElEApW7!7PZc?%!f8atVDJVn1 zebfMQCAT%LkD7rvEQdQ$FO;WP9-~s&Obo0Zn z% zhI$--bG}BsCxXLmK-o~Q<|3%4pa~YhC8z#?ljz_Xnj=m_he3+kOc6*X1g zy7Ejptlo!uQFV0ja@13C9Q7C`%V}#~1+x=3MYSJ<>USsV747A+_K~^#wsxH<(C+S! zn$pc!3tzj2)pOebhNCX{IjY0oumu**V@^bE+FvjX)91CNDvG*rOVkWbM!mw%_{r$U zVA6cHxf-G>#-QE@hp{d`M;}(rZ<}*0YBQe1g7^xxdGi#oHUAKO#M3bko<|MfC2Ei4 zF6f^B=47;4#-lE{54F~hP4!e5~V`qafm3)=~U;^<@NkeA)^tWKy8{gs42=)+;(k!^bt=)z57q1p6B=_ERJ+` zMa|rD)T{R!48=d3UP+77p*}(dG4T9%C8Mv_R@BpQ1NA+RSIYKAENbMRqRP*r1{_w} z-WzpMpXULnJN*K+nZI}C>BK&lBQAc6Ix!~7 zcJ)lu3uG;--2)frDQ5%dhFK_IihB1SMAq87jGCEem;{rR=lKsN6I$LX@;EDE1m#Uo zYd;9Jwo@<_uE7x8jr!c4MRoj}^9|-D4yj=Mlt&Gu4eBG;5A|l8Re|SUnOziUt$uPo zM{UMr741%&nK~?O68BhZ*f*M#YOo5$H1L%wN=l5oj z(GqNS6<1MH^un3Es=cBkQ0(e@(hje0tE zVw9f$r)2aBE?mvtXai6uY{TmK0QJ05;g3p7>tVdIfH6i zKh;qKnufaGMXbs7y|5Tt`}U~ke<5lr51|jg!+MyZmR+C=>dm$eli?4jf!slTwDQ!p z8R~-?$QCSyFR=pVuVXjR1q1*7znP4_dXG`>>T-3hgHfmx52G&d3^fzQW39dy>OHUt zRsYn*#p>CG`=e%X59+HIRNvZHMg1NaU!Uh+YjuDEt;reG01`K_JC8-(!3@;XaT&Gt zDI3}ziAA;Vh}w*6(T96b=edx*s3pBB~ zC+bc&qkg15LT$>os5{Ns)CSTWb)liC^24a}5;wB})S@`9KD>+S zFMkKg^Y;-Mb+8GwX3ql^JOv$XFN{Eq_#~=bqE7b0se@UFyPyU#0rgqFh?;?foo%LS zp!yw;n!z)u_K7~^M)mwRAkzTnr~rRQ9~S6hujU>YK|CF`%QvI$;4tdznV_pZ73r`P zaZ^-3(_DNJ^}kJ98%bC{yMwl< zJ6nnE@Gj~XQSJVAXLC^l{u$Llo&ok*?ScBtjzrz@Jk(FR9at1^qBdd3K>LbDqc(j< zKN&Tgj9QBAs9!F(Fb^glWK&)OHA7=jdtnjkP7a|qU6#Q%(1tjjcrohDS7?a+W%EPS z%xpv5V2Yt`iRzQl6iq@^96}$)A7*zHjhgxoP;0yZbtgZgE)YE2e#_NH%~TWAi|ljs z;X`MU5f=AG&D<8`MdbHhlF^ivU@5eD8ah8iJtn`Rc5~s8wuXH$G4U4E?%#{r3ujRS z%sR^6c%4x3F6TSUNgO@e2GA8N==tA3Mr(Q>^%JT17<=*5z!b#IQ5Wotn(B{HcfK6; z4fqjtM}MHc9g$=0F&lzf`}LRue?mRJ@yFRxhG059{{_kTuqvwISk!J^jT+b;)bIDm z@wQjSqUtxIUO*2~ujG^yY^my^_RkuzNZOZ$oCCD+=Hdj&9lnzI&?M95m=co(hnr3^Y7HZQ@N3}bHn%OkdZ3#=E_Dr|w zY%Wd7J_>ZgEi8=LXV?Ynqo#NvX2-p#c0Zz~Jbb3TfZj(9bRqh1EoxKWL%nK~%(8(s zKs_aMQ16SIellgq{Ov3@+fL|?dfvC9e$}2qop=+qNeji<9aY9E#GO!2%WBjTJV8x$ zs!#0acN>f)9)fCr67}ZvC!b^gViAj4lQF0ZokGn-x=-yhS`9T*eNfN;d`zfzs0&>{ zeciInwI3KQQJZug>gW7b`~d$%&0y_$f!~0BZxWfL6dXpq`OY9O2Jbm)q{Zgj)b+>I z#Jf@Dr<^Gk*c#VI)qje*;40M2?nhnl1!}LA_{`29j5YQA?<1p;CR}J%L%oQ`p=RV9 zYOO*S+4EiqHP9&3uJ3@lU?0@LCZaBQ+Qms0+orCAdXddXAO47e|Noa|iCwq_YJ~Gq z9o;}Z4cV94XbX2Y^8ZPUGv*@;J?)_6G%!fmJ}D74CUeR$(^lL1GcTr0cvBh55C6RBA-|Iw1pVb+tJ3WGW(fo+I zg9Kaca~h2$i3g(YXg%sF`5yJSW!`4Hyd~->`3QCXKJ?)m)Br1Nw}IEhjC%ejlhNa{ z0<|U&F*%mnVIP~SsQUh>H`qZefthyNN2CF2Aj?rRa~t&nE3nIEunYQ#H=qXe5LF+! zn}KkBuLl{X!rOov`Bhb5o;|kNx}v6ZJL*D*QJW~iUYp{2s8?_w)OlZ_PxbrEYN(IZ zc+>!nVIoYppXXn@I|Ui-))>@OPD9PWY1C3&Ma{rJm=R+R*o8ZymTrQJ_oCj6H&9EI z=%9T)OJGjoMyT@#p_U@wPCftL11)oIS`ETgMe5Y(FyP>e}s(Q?e9=0lsRo9 z9EQb+528+Zg84D$8GD}VIVYmtaEDQQDal!TA5=pPv?b~W7NKV1I_gH=Axq--YMrwm z5(`i#EJeM^enAcBH8#LX=WRx2p?3dwr~yS>u#W3uR^nc$7urnc0n`oLM?JP#F4`}r zMi}`2{{zWrcOOA*rWBWKNwT9J%c7{qrX}hQK103H4xk3`61Aog-&n_;P%|+J^*%X< zdft;?w(G=T5OLtp^Z$Y<9o9xY4Rzx4+9c(Q7ibdrqa%N|Bi@ZUsauSl0yX@fQ{vK` zTNZmz_94#3y0m}#zbi3gErHD#Sh`^j&mZYJqG=`!(3QZ@2=Ep^3Nq{*bABprh| zZv#n39A&l0KgN1kFz#Z-kXFUH$_r}SkZMvI?5?UabgUsQB9-T?Y1DN&0z zdM_*a`Q+P?e~zKFy%|@zQh4^)lq@G|O6d*qI(ic8)vKc!twQ|lqW>NB>5Df_;Fa=k zVKT~=QT7(olbVo!jlu4`aQuQ^Kch@XMdIstoj3{Q-AP?3`v7&s;1~D>W#{#vULfER z@v3t|MJlu5UeXkI!hP~7NI@hWzu`UFe@Kc?z7*~BlK$1z=cW8G`Bs!ilkZO5Lh>6( zMJeCu+NrPH@p(|vQ&ECKzQ2KEj^T~LozxAWZY}u@q-&&du7lq(jQW3%wVba9cm(Bx z@g?&1^Y)|O6f0f-ckx%3@2{myOJ!3Ez97$kfxrK(!xpadugUY4@sd+njO^PJHmHN5V|42NKq~l}K4R!2}PhELG+6L>L@rSE8K%*vciznPstx5zsPmil6)qYFG3%myMAcq6?Ns0 z$+vZVEuuaJ>6<{z^?hVkP%vI+xZ_XCGLXg**Qb+du3TTnaN53c9j7Fp$mJhVHzr!SoB9aqijW^ceid~s zP{$qTE6UFN=fYJe??>5e$`X*ir0q3gn}32e6rT9c387SmQC@(uP)v@uDSJpdL0p&k zp}W{Y$`+8i5yzsAhR*(!4W{h?Tt!MwU4lRhW+y(^KSR)j#*IlKG+cxwXvpW?t3y5s zevF?|ry~>TsLTIB`Ohlk_=>VU*pn2=ITNWnNxl=7KpncuUccqK#kH!IzUwif)kHtgDiu8?B|jB&P(F|RHzXbJ zQ?DOfI|7mYQJJ!{v~5jzi~K^oK>RWJzU0r4FH1fn`2%r3R!i^iN2Fsc=D_S+rH(5* zk0GQm(q77Qa<-1mn3q^bUDsCmZItIAPD*ms-doDE5?rS&8To%m`N&T~j##fbl^IA+ zDC|Ni>@LEOq`(nL{3Z3nTwI0HBb2?yzIYa6ND<@<#~rSo-v5tl`2!_=Ia6yMMm`_; z>Ez2$e;9QPC0~^CJJcU{=kasP>q{C=c`ni~b{zNNuf@}=nD4^k@92P7S} zs9Q?fN8FLNIwlY|#F3O0#`vyn9#y*IW7_Vd{3F`x7#rV@If|*Md=n_)XB@tAolhXYhq|}K z_31Ogybj8MCP{86ld9qH*ZsWWY^;-9YFcH&v2l$6cI zM_7`&jO2A}#HE3p{V|;Wrn)+n{7gI%3-j+H*24Xnn~I&}4`V?(ZAQM3I@8I-IpIEa zyNJ_}*O7%dJ07Qgvb#uQ%1)D?K*~V=0QI}c_aU$2G-(&9wioxRc2fUIPSsJ3CPVQ- zAhJK6QCFXA2htqsbu6JQm+MOLZBk;=0P5o?FX-AebgGSx2h@$BtkHkY9i)%@bk{JQ z8^}Rx?^UPa3CdPrd&+L&Hqyxdbo`fV8~LBIsg(8RyzaE!M7}F^U%9^3{9Dp^%JNgc zE2w~qJTDssJt$a68bVx-RDgU*(nxo5r?^6O)B9&rqN51Tb~Vk(UnLbGo=0j${vmCK zyZTwgOSnQBQn)KqA0=JB09K(+$2s!vyYib>v7P=(c%!6ZG`>ga;iu`a~&3PU9XF{(y1*-`5;5K)~w47Ad zour}e|iSCg+!Sz=7gc^{JBjAbz%^;1c`sOyZ`C|m2!P3oLa`AfUX3aUN2B+GV5c9JY6L4Jc3T&iB7Z z@bB>#`HQ5d6s&X&z9#NQn(yKuI@v_5qk`)&8D=KMQuY| z=vC02ild~@NtLKbN2)|#M;2!acR~#DJIbq)ey8k|8gWcyaJMi4^-0`0)hS!(@?X(* z74=<+Cy}D4(-9j#lJ~7^bd`cer0+>JD4WPh6O))oAB?hmPXGV_ diff --git a/po/en@boldquot.po b/po/en@boldquot.po index c1cd7a2..652c51b 100644 --- a/po/en@boldquot.po +++ b/po/en@boldquot.po @@ -1,7 +1,7 @@ # English translations for GNU bash package. -# Copyright (C) 2003 Free Software Foundation, Inc. +# Copyright (C) 2004 Free Software Foundation, Inc. # This file is distributed under the same license as the GNU bash package. -# Automatically generated, 2003. +# Automatically generated, 2004. # # All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation @@ -48,7 +48,7 @@ #: builtins.c:1362 builtins.c:1365 msgid "" msgstr "" -"Project-Id-Version: GNU bash 3.0-alpha\n" +"Project-Id-Version: GNU bash 3.0-rc1\n" "POT-Creation-Date: 2003-12-22 15:34-0500\n" "PO-Revision-Date: 2003-12-22 15:34-0500\n" "Last-Translator: Automatically generated\n" @@ -93,9 +93,9 @@ msgid "%s: missing colon separator" msgstr "%s: missing colon separator" #: builtins/alias.def:123 -#, fuzzy, c-format +#, c-format msgid "`%s': invalid alias name" -msgstr "‘%s’: invalid keymap name" +msgstr "‘%s’: invalid alias name" #: builtins/bind.def:194 #, c-format @@ -265,9 +265,9 @@ msgid "%s: not a shell builtin" msgstr "%s: not a shell builtin" #: builtins/common.c:486 -#, fuzzy, c-format +#, c-format msgid "%s: error retrieving current directory: %s: %s\n" -msgstr "%s: could not get current directory: %s: %s\n" +msgstr "%s: error retrieving current directory: %s: %s\n" #: builtins/common.c:553 builtins/common.c:555 #, c-format diff --git a/po/en@quot.gmo b/po/en@quot.gmo index 0b14df20d5761d44f189348b55cd7b38f2969b0a..62cf0807cb661d4b41814bb5af653910ad3f2acf 100644 GIT binary patch delta 20884 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 delta 20749 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 aUXGwKl~cQqZ?>yeouD~2c2VA>!~X$rmu^Y` diff --git a/po/en@quot.po b/po/en@quot.po index c256764..a560bf6 100644 --- a/po/en@quot.po +++ b/po/en@quot.po @@ -1,7 +1,7 @@ # English translations for GNU bash package. -# Copyright (C) 2003 Free Software Foundation, Inc. +# Copyright (C) 2004 Free Software Foundation, Inc. # This file is distributed under the same license as the GNU bash package. -# Automatically generated, 2003. +# Automatically generated, 2004. # # All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation @@ -45,7 +45,7 @@ #: builtins.c:1362 builtins.c:1365 msgid "" msgstr "" -"Project-Id-Version: GNU bash 3.0-alpha\n" +"Project-Id-Version: GNU bash 3.0-rc1\n" "POT-Creation-Date: 2003-12-22 15:34-0500\n" "PO-Revision-Date: 2003-12-22 15:34-0500\n" "Last-Translator: Automatically generated\n" @@ -90,9 +90,9 @@ msgid "%s: missing colon separator" msgstr "%s: missing colon separator" #: builtins/alias.def:123 -#, fuzzy, c-format +#, c-format msgid "`%s': invalid alias name" -msgstr "‘%s’: invalid keymap name" +msgstr "‘%s’: invalid alias name" #: builtins/bind.def:194 #, c-format @@ -262,9 +262,9 @@ msgid "%s: not a shell builtin" msgstr "%s: not a shell builtin" #: builtins/common.c:486 -#, fuzzy, c-format +#, c-format msgid "%s: error retrieving current directory: %s: %s\n" -msgstr "%s: could not get current directory: %s: %s\n" +msgstr "%s: error retrieving current directory: %s: %s\n" #: builtins/common.c:553 builtins/common.c:555 #, c-format diff --git a/subst.c b/subst.c index 011930b..fcc024b 100644 --- a/subst.c +++ b/subst.c @@ -138,6 +138,7 @@ extern char *this_command_name; extern struct fd_bitmap *current_fds_to_close; extern int wordexp_only; extern int expanding_redir; +extern int tempenv_assign_error; /* Non-zero means to allow unmatched globbed filenames to expand to a null file. */ @@ -699,9 +700,16 @@ add_one_character: for (t = 0; ret[t]; t++, j++) temp[j] = ret[t]; - temp[j++] = string[si]; + temp[j] = string[si]; + + if (string[si]) + { + j++; + i = si + 1; + } + else + i = si; - i = si + 1; if (free_ret) free (ret); continue; @@ -7343,6 +7351,7 @@ expand_word_list_internal (list, eflags) that the variable and environment assignments affect the shell's environment. */ assign_func = new_list ? assign_in_env : do_assignment; + tempenv_assign_error = 0; for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next) { @@ -7350,13 +7359,18 @@ expand_word_list_internal (list, eflags) tint = (*assign_func) (temp_list->word->word); /* Variable assignment errors in non-interactive shells running in Posix.2 mode cause the shell to exit. */ - if (tint == 0 && assign_func == do_assignment) + if (tint == 0) { - last_command_exit_value = EXECUTION_FAILURE; - if (interactive_shell == 0 && posixly_correct) - exp_jump_to_top_level (FORCE_EOF); + if (assign_func == do_assignment) + { + last_command_exit_value = EXECUTION_FAILURE; + if (interactive_shell == 0 && posixly_correct) + exp_jump_to_top_level (FORCE_EOF); + else + exp_jump_to_top_level (DISCARD); + } else - exp_jump_to_top_level (DISCARD); + tempenv_assign_error++; } } diff --git a/subst.c~ b/subst.c~ index 88d8724..f808537 100644 --- a/subst.c~ +++ b/subst.c~ @@ -689,6 +689,8 @@ add_one_character: 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; @@ -697,9 +699,16 @@ add_one_character: for (t = 0; ret[t]; t++, j++) temp[j] = ret[t]; - temp[j++] = string[si]; + temp[j] = string[si]; + + if (string[si]) + { + j++; + i = si + 1; + } + else + i = si; - i = si + 1; if (free_ret) free (ret); continue; diff --git a/support/mkconffiles b/support/mkconffiles old mode 100644 new mode 100755 diff --git a/support/mkversion.sh b/support/mkversion.sh old mode 100644 new mode 100755 diff --git a/support/rlvers.sh b/support/rlvers.sh old mode 100644 new mode 100755 diff --git a/tests/run-read b/tests/run-read index 35c94e4..45ab884 100644 --- a/tests/run-read +++ b/tests/run-read @@ -1,2 +1,4 @@ +echo "warning: different versions of wc put differing amounts of whitespace" >&2 +echo "warning: before their output. Please do not consider this an error." >&2 ${THIS_SH} ./read.tests > /tmp/xx 2>&1 diff /tmp/xx read.right && rm -f /tmp/xx diff --git a/variables.c b/variables.c index 5519550..dc876de 100644 --- a/variables.c +++ b/variables.c @@ -116,6 +116,10 @@ int variable_context = 0; for a single command. */ HASH_TABLE *temporary_env = (HASH_TABLE *)NULL; +/* Set to non-zero if an assignment error occurs while putting variables + into the temporary environment. */ +int tempenv_assign_error; + /* Some funky variables which are known about specially. Here is where "$*", "$1", and all the cruft is kept. */ char *dollar_vars[10]; diff --git a/variables.c~ b/variables.c~ index 592602d..b51c4b8 100644 --- a/variables.c~ +++ b/variables.c~ @@ -116,6 +116,10 @@ int variable_context = 0; for a single command. */ HASH_TABLE *temporary_env = (HASH_TABLE *)NULL; +/* Set to non-zero if an assignment error occurs while putting variables + into the temporary environment. */ +int tempenv_assign_errors; + /* Some funky variables which are known about specially. Here is where "$*", "$1", and all the cruft is kept. */ char *dollar_vars[10]; @@ -1663,8 +1667,9 @@ make_local_array_variable (name) ARRAY *array; var = make_local_variable (name); - if (var == 0) + if (var == 0 || array_p (var)) return var; + array = array_create (); FREE (value_cell(var)); @@ -2118,16 +2123,9 @@ assign_in_env (string) setifs (var); if (echo_command_at_execute) - { - /* The Korn shell prints the `+ ' in front of assignment statements, - so we do too. */ -#if 0 - fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value); - fflush (stderr); -#else - xtrace_print_assignment (name, value, 0, 1); -#endif - } + /* The Korn shell prints the `+ ' in front of assignment statements, + so we do too. */ + xtrace_print_assignment (name, value, 0, 1); free (name); return 1; diff --git a/y.tab.c b/y.tab.c index 142e163..bff19c4 100644 --- a/y.tab.c +++ b/y.tab.c @@ -1,50 +1,51 @@ -/* A Bison parser, made from /usr/homes/chet/src/bash/src/parse.y - by GNU bison 1.34. */ + +/* A Bison parser, made from /Users/chet/src/bash/src/parse.y + by GNU Bison version 1.28 */ #define YYBISON 1 /* Identify Bison output. */ -# define IF 257 -# define THEN 258 -# define ELSE 259 -# define ELIF 260 -# define FI 261 -# define CASE 262 -# define ESAC 263 -# define FOR 264 -# define SELECT 265 -# define WHILE 266 -# define UNTIL 267 -# define DO 268 -# define DONE 269 -# define FUNCTION 270 -# define COND_START 271 -# define COND_END 272 -# define COND_ERROR 273 -# define IN 274 -# define BANG 275 -# define TIME 276 -# define TIMEOPT 277 -# define WORD 278 -# define ASSIGNMENT_WORD 279 -# define NUMBER 280 -# define ARITH_CMD 281 -# define ARITH_FOR_EXPRS 282 -# define COND_CMD 283 -# define AND_AND 284 -# define OR_OR 285 -# define GREATER_GREATER 286 -# define LESS_LESS 287 -# define LESS_AND 288 -# define LESS_LESS_LESS 289 -# define GREATER_AND 290 -# define SEMI_SEMI 291 -# define LESS_LESS_MINUS 292 -# define AND_GREATER 293 -# define LESS_GREATER 294 -# define GREATER_BAR 295 -# define yacc_EOF 296 - -#line 21 "/usr/homes/chet/src/bash/src/parse.y" +#define IF 257 +#define THEN 258 +#define ELSE 259 +#define ELIF 260 +#define FI 261 +#define CASE 262 +#define ESAC 263 +#define FOR 264 +#define SELECT 265 +#define WHILE 266 +#define UNTIL 267 +#define DO 268 +#define DONE 269 +#define FUNCTION 270 +#define COND_START 271 +#define COND_END 272 +#define COND_ERROR 273 +#define IN 274 +#define BANG 275 +#define TIME 276 +#define TIMEOPT 277 +#define WORD 278 +#define ASSIGNMENT_WORD 279 +#define NUMBER 280 +#define ARITH_CMD 281 +#define ARITH_FOR_EXPRS 282 +#define COND_CMD 283 +#define AND_AND 284 +#define OR_OR 285 +#define GREATER_GREATER 286 +#define LESS_LESS 287 +#define LESS_AND 288 +#define LESS_LESS_LESS 289 +#define GREATER_AND 290 +#define SEMI_SEMI 291 +#define LESS_LESS_MINUS 292 +#define AND_GREATER 293 +#define LESS_GREATER 294 +#define GREATER_BAR 295 +#define yacc_EOF 296 + +#line 21 "/Users/chet/src/bash/src/parse.y" #include "config.h" @@ -67,6 +68,8 @@ #include "memalloc.h" +#include "bashintl.h" + #define NEED_STRFTIME_DECL /* used in externs.h */ #include "shell.h" @@ -311,10 +314,16 @@ static int arith_for_lineno; static int word_lineno[MAX_CASE_NEST]; static int word_top = -1; +/* If non-zero, it is the token that we want read_token to return + regardless of what text is (or isn't) present to be read. This + is reset by read_token. If token_to_read == WORD or + ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */ +static int token_to_read; +static WORD_DESC *word_desc_to_read; + static REDIRECTEE redir; -#line 290 "/usr/homes/chet/src/bash/src/parse.y" -#ifndef YYSTYPE +#line 299 "/Users/chet/src/bash/src/parse.y" typedef union { WORD_DESC *word; /* the word that we read. */ int number; /* the number that we read. */ @@ -323,454 +332,428 @@ typedef union { REDIRECT *redirect; ELEMENT element; PATTERN_LIST *pattern; -} yystype; -# define YYSTYPE yystype +} YYSTYPE; +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const #endif -#ifndef YYDEBUG -# define YYDEBUG 0 #endif -#define YYFINAL 301 +#define YYFINAL 302 #define YYFLAG -32768 #define YYNTBASE 54 -/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ #define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 90) -/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ -static const char yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 44, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 42, 2, - 52, 53, 2, 2, 2, 49, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 43, - 48, 2, 47, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 50, 46, 51, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 45 +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 44, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 42, 2, 52, + 53, 2, 2, 2, 49, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 43, 48, + 2, 47, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 50, 46, 51, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 45 }; -#if YYDEBUG -static const short yyprhs[] = -{ - 0, 0, 3, 5, 8, 10, 12, 15, 18, 21, - 25, 29, 32, 36, 39, 43, 46, 50, 53, 57, - 60, 64, 67, 71, 74, 78, 81, 85, 88, 92, - 95, 99, 102, 106, 109, 112, 116, 118, 120, 122, - 124, 127, 129, 132, 134, 136, 139, 141, 143, 145, - 151, 157, 159, 161, 163, 165, 167, 169, 171, 178, - 185, 193, 201, 212, 223, 233, 243, 251, 259, 265, - 271, 278, 285, 293, 301, 312, 323, 330, 338, 345, - 351, 358, 363, 365, 368, 372, 378, 386, 393, 397, - 399, 403, 408, 415, 421, 423, 426, 431, 436, 442, - 448, 451, 455, 457, 461, 464, 466, 469, 473, 477, - 481, 486, 491, 496, 501, 506, 508, 510, 512, 514, - 516, 518, 519, 522, 524, 527, 530, 535, 540, 544, - 548, 550, 552, 555, 558, 562, 566, 571, 573, 575 +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 3, 5, 8, 10, 12, 15, 18, 21, 25, + 29, 32, 36, 39, 43, 46, 50, 53, 57, 60, + 64, 67, 71, 74, 78, 81, 85, 88, 92, 95, + 99, 102, 106, 109, 112, 116, 118, 120, 122, 124, + 127, 129, 132, 134, 136, 139, 141, 143, 145, 151, + 157, 159, 161, 163, 165, 167, 169, 171, 178, 185, + 193, 201, 212, 223, 233, 243, 251, 259, 265, 271, + 278, 285, 293, 301, 312, 323, 330, 338, 345, 351, + 358, 363, 365, 368, 372, 378, 386, 393, 397, 399, + 403, 408, 415, 421, 423, 426, 431, 436, 442, 448, + 451, 455, 457, 461, 464, 466, 469, 473, 477, 481, + 486, 491, 496, 501, 506, 508, 510, 512, 514, 516, + 518, 519, 522, 524, 527, 530, 535, 540, 544, 548, + 550, 552, 555, 558, 562, 566, 569, 574, 576, 578 }; -static const short yyrhs[] = -{ - 85, 82, 0, 44, 0, 1, 44, 0, 45, 0, - 24, 0, 55, 24, 0, 47, 24, 0, 48, 24, - 0, 26, 47, 24, 0, 26, 48, 24, 0, 32, - 24, 0, 26, 32, 24, 0, 33, 24, 0, 26, - 33, 24, 0, 35, 24, 0, 26, 35, 24, 0, - 34, 26, 0, 26, 34, 26, 0, 36, 26, 0, - 26, 36, 26, 0, 34, 24, 0, 26, 34, 24, - 0, 36, 24, 0, 26, 36, 24, 0, 38, 24, - 0, 26, 38, 24, 0, 36, 49, 0, 26, 36, - 49, 0, 34, 49, 0, 26, 34, 49, 0, 39, - 24, 0, 26, 40, 24, 0, 40, 24, 0, 41, - 24, 0, 26, 41, 24, 0, 24, 0, 25, 0, - 56, 0, 56, 0, 58, 56, 0, 57, 0, 59, - 57, 0, 59, 0, 61, 0, 61, 58, 0, 66, - 0, 62, 0, 65, 0, 12, 79, 14, 79, 15, - 0, 13, 79, 14, 79, 15, 0, 64, 0, 69, - 0, 68, 0, 70, 0, 71, 0, 72, 0, 63, - 0, 10, 24, 84, 14, 79, 15, 0, 10, 24, - 84, 50, 79, 51, 0, 10, 24, 43, 84, 14, - 79, 15, 0, 10, 24, 43, 84, 50, 79, 51, - 0, 10, 24, 84, 20, 55, 83, 84, 14, 79, - 15, 0, 10, 24, 84, 20, 55, 83, 84, 50, - 79, 51, 0, 10, 24, 84, 20, 83, 84, 14, - 79, 15, 0, 10, 24, 84, 20, 83, 84, 50, - 79, 51, 0, 10, 28, 83, 84, 14, 79, 15, - 0, 10, 28, 83, 84, 50, 79, 51, 0, 10, - 28, 14, 79, 15, 0, 10, 28, 50, 79, 51, - 0, 11, 24, 84, 14, 78, 15, 0, 11, 24, - 84, 50, 78, 51, 0, 11, 24, 43, 84, 14, - 78, 15, 0, 11, 24, 43, 84, 50, 78, 51, - 0, 11, 24, 84, 20, 55, 83, 84, 14, 78, - 15, 0, 11, 24, 84, 20, 55, 83, 84, 50, - 78, 51, 0, 8, 24, 84, 20, 84, 9, 0, - 8, 24, 84, 20, 76, 84, 9, 0, 8, 24, - 84, 20, 74, 9, 0, 24, 52, 53, 84, 67, - 0, 16, 24, 52, 53, 84, 67, 0, 16, 24, - 84, 67, 0, 61, 0, 61, 58, 0, 52, 79, - 53, 0, 3, 79, 4, 79, 7, 0, 3, 79, - 4, 79, 5, 79, 7, 0, 3, 79, 4, 79, - 73, 7, 0, 50, 79, 51, 0, 27, 0, 17, - 29, 18, 0, 6, 79, 4, 79, 0, 6, 79, - 4, 79, 5, 79, 0, 6, 79, 4, 79, 73, - 0, 75, 0, 76, 75, 0, 84, 77, 53, 79, - 0, 84, 77, 53, 84, 0, 84, 52, 77, 53, - 79, 0, 84, 52, 77, 53, 84, 0, 75, 37, - 0, 76, 75, 37, 0, 24, 0, 77, 46, 24, - 0, 84, 80, 0, 78, 0, 84, 81, 0, 81, - 44, 84, 0, 81, 42, 84, 0, 81, 43, 84, - 0, 81, 30, 84, 81, 0, 81, 31, 84, 81, - 0, 81, 42, 84, 81, 0, 81, 43, 84, 81, - 0, 81, 44, 84, 81, 0, 87, 0, 44, 0, - 45, 0, 44, 0, 43, 0, 45, 0, 0, 84, - 44, 0, 86, 0, 86, 42, 0, 86, 43, 0, - 86, 30, 84, 86, 0, 86, 31, 84, 86, 0, - 86, 42, 86, 0, 86, 43, 86, 0, 87, 0, - 88, 0, 21, 88, 0, 89, 88, 0, 89, 21, - 88, 0, 21, 89, 88, 0, 88, 46, 84, 88, - 0, 60, 0, 22, 0, 22, 23, 0 + +static const short yyrhs[] = { 85, + 82, 0, 44, 0, 1, 44, 0, 45, 0, 24, + 0, 55, 24, 0, 47, 24, 0, 48, 24, 0, + 26, 47, 24, 0, 26, 48, 24, 0, 32, 24, + 0, 26, 32, 24, 0, 33, 24, 0, 26, 33, + 24, 0, 35, 24, 0, 26, 35, 24, 0, 34, + 26, 0, 26, 34, 26, 0, 36, 26, 0, 26, + 36, 26, 0, 34, 24, 0, 26, 34, 24, 0, + 36, 24, 0, 26, 36, 24, 0, 38, 24, 0, + 26, 38, 24, 0, 36, 49, 0, 26, 36, 49, + 0, 34, 49, 0, 26, 34, 49, 0, 39, 24, + 0, 26, 40, 24, 0, 40, 24, 0, 41, 24, + 0, 26, 41, 24, 0, 24, 0, 25, 0, 56, + 0, 56, 0, 58, 56, 0, 57, 0, 59, 57, + 0, 59, 0, 61, 0, 61, 58, 0, 66, 0, + 62, 0, 65, 0, 12, 79, 14, 79, 15, 0, + 13, 79, 14, 79, 15, 0, 64, 0, 69, 0, + 68, 0, 70, 0, 71, 0, 72, 0, 63, 0, + 10, 24, 84, 14, 79, 15, 0, 10, 24, 84, + 50, 79, 51, 0, 10, 24, 43, 84, 14, 79, + 15, 0, 10, 24, 43, 84, 50, 79, 51, 0, + 10, 24, 84, 20, 55, 83, 84, 14, 79, 15, + 0, 10, 24, 84, 20, 55, 83, 84, 50, 79, + 51, 0, 10, 24, 84, 20, 83, 84, 14, 79, + 15, 0, 10, 24, 84, 20, 83, 84, 50, 79, + 51, 0, 10, 28, 83, 84, 14, 79, 15, 0, + 10, 28, 83, 84, 50, 79, 51, 0, 10, 28, + 14, 79, 15, 0, 10, 28, 50, 79, 51, 0, + 11, 24, 84, 14, 78, 15, 0, 11, 24, 84, + 50, 78, 51, 0, 11, 24, 43, 84, 14, 78, + 15, 0, 11, 24, 43, 84, 50, 78, 51, 0, + 11, 24, 84, 20, 55, 83, 84, 14, 78, 15, + 0, 11, 24, 84, 20, 55, 83, 84, 50, 78, + 51, 0, 8, 24, 84, 20, 84, 9, 0, 8, + 24, 84, 20, 76, 84, 9, 0, 8, 24, 84, + 20, 74, 9, 0, 24, 52, 53, 84, 67, 0, + 16, 24, 52, 53, 84, 67, 0, 16, 24, 84, + 67, 0, 61, 0, 61, 58, 0, 52, 79, 53, + 0, 3, 79, 4, 79, 7, 0, 3, 79, 4, + 79, 5, 79, 7, 0, 3, 79, 4, 79, 73, + 7, 0, 50, 79, 51, 0, 27, 0, 17, 29, + 18, 0, 6, 79, 4, 79, 0, 6, 79, 4, + 79, 5, 79, 0, 6, 79, 4, 79, 73, 0, + 75, 0, 76, 75, 0, 84, 77, 53, 79, 0, + 84, 77, 53, 84, 0, 84, 52, 77, 53, 79, + 0, 84, 52, 77, 53, 84, 0, 75, 37, 0, + 76, 75, 37, 0, 24, 0, 77, 46, 24, 0, + 84, 80, 0, 78, 0, 84, 81, 0, 81, 44, + 84, 0, 81, 42, 84, 0, 81, 43, 84, 0, + 81, 30, 84, 81, 0, 81, 31, 84, 81, 0, + 81, 42, 84, 81, 0, 81, 43, 84, 81, 0, + 81, 44, 84, 81, 0, 87, 0, 44, 0, 45, + 0, 44, 0, 43, 0, 45, 0, 0, 84, 44, + 0, 86, 0, 86, 42, 0, 86, 43, 0, 86, + 30, 84, 86, 0, 86, 31, 84, 86, 0, 86, + 42, 86, 0, 86, 43, 86, 0, 87, 0, 88, + 0, 21, 88, 0, 89, 88, 0, 89, 21, 88, + 0, 21, 89, 88, 0, 89, 83, 0, 88, 46, + 84, 88, 0, 60, 0, 22, 0, 22, 23, 0 }; #endif -#if YYDEBUG -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const short yyrline[] = -{ - 0, 340, 349, 356, 371, 381, 383, 387, 392, 397, - 402, 407, 412, 417, 423, 429, 434, 439, 444, 449, - 454, 459, 464, 469, 474, 479, 486, 493, 498, 503, - 508, 513, 518, 523, 528, 533, 540, 542, 544, 548, - 552, 563, 565, 569, 571, 573, 589, 593, 595, 597, - 599, 601, 603, 605, 607, 609, 611, 613, 617, 622, - 627, 632, 637, 642, 647, 652, 659, 664, 669, 674, - 681, 686, 691, 696, 701, 706, 713, 718, 723, 730, - 733, 736, 741, 743, 774, 781, 783, 785, 790, 794, - 798, 802, 804, 806, 810, 811, 815, 817, 819, 821, - 825, 826, 830, 832, 841, 849, 850, 856, 857, 864, - 868, 870, 872, 879, 881, 883, 887, 888, 891, 892, - 893, 896, 897, 906, 912, 921, 929, 931, 933, 940, - 943, 947, 949, 954, 959, 964, 971, 974, 978, 980 +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 350, 359, 366, 381, 391, 393, 397, 402, 407, 412, + 417, 422, 427, 433, 439, 444, 449, 454, 459, 464, + 469, 474, 479, 484, 489, 496, 503, 508, 513, 518, + 523, 528, 533, 538, 543, 550, 552, 554, 558, 562, + 573, 575, 579, 581, 583, 599, 603, 605, 607, 609, + 611, 613, 615, 617, 619, 621, 623, 627, 632, 637, + 642, 647, 652, 657, 662, 669, 674, 679, 684, 691, + 696, 701, 706, 711, 716, 723, 728, 733, 740, 743, + 746, 751, 753, 784, 791, 793, 795, 800, 804, 808, + 812, 814, 816, 820, 821, 825, 827, 829, 831, 835, + 836, 840, 842, 851, 859, 860, 866, 867, 874, 878, + 880, 882, 889, 891, 893, 897, 898, 901, 903, 905, + 909, 910, 919, 925, 934, 942, 944, 946, 953, 956, + 960, 962, 967, 972, 977, 982, 1002, 1005, 1009, 1011 }; #endif -#if (YYDEBUG) || defined YYERROR_VERBOSE - -/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ -static const char *const yytname[] = -{ - "$", "error", "$undefined.", "IF", "THEN", "ELSE", "ELIF", "FI", "CASE", - "ESAC", "FOR", "SELECT", "WHILE", "UNTIL", "DO", "DONE", "FUNCTION", - "COND_START", "COND_END", "COND_ERROR", "IN", "BANG", "TIME", "TIMEOPT", - "WORD", "ASSIGNMENT_WORD", "NUMBER", "ARITH_CMD", "ARITH_FOR_EXPRS", - "COND_CMD", "AND_AND", "OR_OR", "GREATER_GREATER", "LESS_LESS", - "LESS_AND", "LESS_LESS_LESS", "GREATER_AND", "SEMI_SEMI", - "LESS_LESS_MINUS", "AND_GREATER", "LESS_GREATER", "GREATER_BAR", "'&'", - "';'", "'\\n'", "yacc_EOF", "'|'", "'>'", "'<'", "'-'", "'{'", "'}'", - "'('", "')'", "inputunit", "word_list", "redirection", - "simple_command_element", "redirection_list", "simple_command", - "command", "shell_command", "for_command", "arith_for_command", - "select_command", "case_command", "function_def", "function_body", - "subshell", "if_command", "group_command", "arith_command", - "cond_command", "elif_clause", "case_clause", "pattern_list", - "case_clause_sequence", "pattern", "list", "compound_list", "list0", - "list1", "simple_list_terminator", "list_terminator", "newline_list", - "simple_list", "simple_list1", "pipeline_command", "pipeline", - "timespec", 0 +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","IF","THEN", +"ELSE","ELIF","FI","CASE","ESAC","FOR","SELECT","WHILE","UNTIL","DO","DONE", +"FUNCTION","COND_START","COND_END","COND_ERROR","IN","BANG","TIME","TIMEOPT", +"WORD","ASSIGNMENT_WORD","NUMBER","ARITH_CMD","ARITH_FOR_EXPRS","COND_CMD","AND_AND", +"OR_OR","GREATER_GREATER","LESS_LESS","LESS_AND","LESS_LESS_LESS","GREATER_AND", +"SEMI_SEMI","LESS_LESS_MINUS","AND_GREATER","LESS_GREATER","GREATER_BAR","'&'", +"';'","'\\n'","yacc_EOF","'|'","'>'","'<'","'-'","'{'","'}'","'('","')'","inputunit", +"word_list","redirection","simple_command_element","redirection_list","simple_command", +"command","shell_command","for_command","arith_for_command","select_command", +"case_command","function_def","function_body","subshell","if_command","group_command", +"arith_command","cond_command","elif_clause","case_clause","pattern_list","case_clause_sequence", +"pattern","list","compound_list","list0","list1","simple_list_terminator","list_terminator", +"newline_list","simple_list","simple_list1","pipeline_command","pipeline","timespec", NULL }; #endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const short yyr1[] = -{ - 0, 54, 54, 54, 54, 55, 55, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 56, 56, 56, 56, 57, 57, 57, 58, - 58, 59, 59, 60, 60, 60, 60, 61, 61, 61, - 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, - 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, - 64, 64, 64, 64, 64, 64, 65, 65, 65, 66, - 66, 66, 67, 67, 68, 69, 69, 69, 70, 71, - 72, 73, 73, 73, 74, 74, 75, 75, 75, 75, - 76, 76, 77, 77, 78, 79, 79, 80, 80, 80, - 81, 81, 81, 81, 81, 81, 82, 82, 83, 83, - 83, 84, 84, 85, 85, 85, 86, 86, 86, 86, - 86, 87, 87, 87, 87, 87, 88, 88, 89, 89 +static const short yyr1[] = { 0, + 54, 54, 54, 54, 55, 55, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 57, 57, 57, 58, 58, + 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, + 62, 62, 62, 62, 62, 63, 63, 63, 63, 64, + 64, 64, 64, 64, 64, 65, 65, 65, 66, 66, + 66, 67, 67, 68, 69, 69, 69, 70, 71, 72, + 73, 73, 73, 74, 74, 75, 75, 75, 75, 76, + 76, 77, 77, 78, 79, 79, 80, 80, 80, 81, + 81, 81, 81, 81, 81, 82, 82, 83, 83, 83, + 84, 84, 85, 85, 85, 86, 86, 86, 86, 86, + 87, 87, 87, 87, 87, 87, 88, 88, 89, 89 }; -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const short yyr2[] = -{ - 0, 2, 1, 2, 1, 1, 2, 2, 2, 3, - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, - 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, - 3, 2, 3, 2, 2, 3, 1, 1, 1, 1, - 2, 1, 2, 1, 1, 2, 1, 1, 1, 5, - 5, 1, 1, 1, 1, 1, 1, 1, 6, 6, - 7, 7, 10, 10, 9, 9, 7, 7, 5, 5, - 6, 6, 7, 7, 10, 10, 6, 7, 6, 5, - 6, 4, 1, 2, 3, 5, 7, 6, 3, 1, - 3, 4, 6, 5, 1, 2, 4, 4, 5, 5, - 2, 3, 1, 3, 2, 1, 2, 3, 3, 3, - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, - 1, 0, 2, 1, 2, 2, 4, 4, 3, 3, - 1, 1, 2, 2, 3, 3, 4, 1, 1, 2 +static const short yyr2[] = { 0, + 2, 1, 2, 1, 1, 2, 2, 2, 3, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 2, 3, 1, 1, 1, 1, 2, + 1, 2, 1, 1, 2, 1, 1, 1, 5, 5, + 1, 1, 1, 1, 1, 1, 1, 6, 6, 7, + 7, 10, 10, 9, 9, 7, 7, 5, 5, 6, + 6, 7, 7, 10, 10, 6, 7, 6, 5, 6, + 4, 1, 2, 3, 5, 7, 6, 3, 1, 3, + 4, 6, 5, 1, 2, 4, 4, 5, 5, 2, + 3, 1, 3, 2, 1, 2, 3, 3, 3, 4, + 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, + 0, 2, 1, 2, 2, 4, 4, 3, 3, 1, + 1, 2, 2, 3, 3, 2, 4, 1, 1, 2 }; -/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE - doesn't specify something else to do. Zero means the default is an - error. */ -static const short yydefact[] = -{ - 0, 0, 121, 0, 0, 0, 121, 121, 0, 0, - 0, 138, 36, 37, 0, 89, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2, 4, 0, 0, 121, - 121, 38, 41, 43, 137, 44, 47, 57, 51, 48, - 46, 53, 52, 54, 55, 56, 0, 123, 130, 131, - 0, 3, 105, 0, 0, 121, 121, 0, 121, 0, - 0, 121, 0, 132, 0, 139, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 11, 13, 21, - 17, 29, 15, 23, 19, 27, 25, 31, 33, 34, - 7, 8, 0, 0, 36, 42, 39, 45, 116, 117, - 1, 121, 121, 124, 125, 121, 0, 133, 121, 122, - 104, 106, 115, 0, 121, 0, 121, 119, 118, 120, - 121, 121, 121, 0, 121, 121, 0, 0, 90, 135, - 121, 12, 14, 22, 18, 30, 16, 24, 20, 28, - 26, 32, 35, 9, 10, 88, 84, 40, 0, 0, - 128, 129, 0, 134, 0, 121, 121, 121, 121, 121, - 121, 0, 121, 0, 121, 0, 0, 0, 0, 121, - 0, 121, 0, 0, 121, 82, 81, 0, 126, 127, - 0, 0, 136, 121, 121, 85, 0, 0, 0, 108, - 109, 107, 0, 94, 121, 0, 121, 121, 0, 5, - 0, 121, 0, 68, 69, 121, 121, 121, 121, 0, - 0, 0, 0, 49, 50, 0, 83, 79, 0, 0, - 87, 110, 111, 112, 113, 114, 78, 100, 95, 0, - 76, 102, 0, 0, 0, 0, 58, 6, 121, 0, - 59, 0, 0, 0, 0, 70, 0, 121, 71, 80, - 86, 121, 121, 121, 121, 101, 77, 0, 0, 121, - 60, 61, 0, 121, 121, 66, 67, 72, 73, 0, - 91, 0, 0, 0, 121, 103, 96, 97, 121, 121, - 0, 0, 121, 121, 121, 93, 98, 99, 0, 0, - 64, 65, 0, 0, 92, 62, 63, 74, 75, 0, - 0, 0 +static const short yydefact[] = { 0, + 0, 121, 0, 0, 0, 121, 121, 0, 0, 0, + 139, 36, 37, 0, 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 4, 0, 0, 121, 121, + 38, 41, 43, 138, 44, 47, 57, 51, 48, 46, + 53, 52, 54, 55, 56, 0, 123, 130, 131, 0, + 3, 105, 0, 0, 121, 121, 0, 121, 0, 0, + 121, 0, 132, 0, 140, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 13, 21, 17, + 29, 15, 23, 19, 27, 25, 31, 33, 34, 7, + 8, 0, 0, 36, 42, 39, 45, 116, 117, 1, + 121, 121, 124, 125, 121, 0, 119, 118, 120, 136, + 133, 121, 122, 104, 106, 115, 0, 121, 0, 121, + 121, 121, 121, 0, 121, 121, 0, 0, 90, 135, + 121, 12, 14, 22, 18, 30, 16, 24, 20, 28, + 26, 32, 35, 9, 10, 88, 84, 40, 0, 0, + 128, 129, 0, 134, 0, 121, 121, 121, 121, 121, + 121, 0, 121, 0, 121, 0, 0, 0, 0, 121, + 0, 121, 0, 0, 121, 82, 81, 0, 126, 127, + 0, 0, 137, 121, 121, 85, 0, 0, 0, 108, + 109, 107, 0, 94, 121, 0, 121, 121, 0, 5, + 0, 121, 0, 68, 69, 121, 121, 121, 121, 0, + 0, 0, 0, 49, 50, 0, 83, 79, 0, 0, + 87, 110, 111, 112, 113, 114, 78, 100, 95, 0, + 76, 102, 0, 0, 0, 0, 58, 6, 121, 0, + 59, 0, 0, 0, 0, 70, 0, 121, 71, 80, + 86, 121, 121, 121, 121, 101, 77, 0, 0, 121, + 60, 61, 0, 121, 121, 66, 67, 72, 73, 0, + 91, 0, 0, 0, 121, 103, 96, 97, 121, 121, + 0, 0, 121, 121, 121, 93, 98, 99, 0, 0, + 64, 65, 0, 0, 92, 62, 63, 74, 75, 0, + 0, 0 }; -static const short yydefgoto[] = -{ - 299, 200, 31, 32, 97, 33, 34, 35, 36, 37, - 38, 39, 40, 176, 41, 42, 43, 44, 45, 186, - 192, 193, 194, 233, 52, 53, 110, 111, 100, 121, - 54, 46, 150, 112, 49, 50 +static const short yydefgoto[] = { 300, + 201, 31, 32, 97, 33, 34, 35, 36, 37, 38, + 39, 40, 177, 41, 42, 43, 44, 45, 187, 193, + 194, 195, 234, 52, 53, 114, 115, 100, 110, 54, + 46, 151, 116, 49, 50 }; -static const short yypact[] = -{ - 273, -24,-32768, -2, 11, 6,-32768,-32768, 12, 9, - 402, 41, 10,-32768, 552,-32768, 46, 52, -5, 58, - 64, 68, 102, 117, 135,-32768,-32768, 146, 149,-32768, - -32768,-32768,-32768, 169,-32768, 202,-32768,-32768,-32768,-32768, - -32768,-32768,-32768,-32768,-32768,-32768, -33, 42,-32768, 91, - 445,-32768,-32768, 142, 316,-32768, 133, 72, 136, 172, - 174, 97, 171, 91, 531,-32768, 139, 173, 182, 99, - 188, 138, 189, 190, 191, 194, 195,-32768,-32768,-32768, - -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, - -32768,-32768, 145, 168,-32768,-32768,-32768, 202,-32768,-32768, - -32768,-32768,-32768, 359, 359,-32768, 531, 91,-32768,-32768, - -32768, 249,-32768, -12,-32768, 13,-32768,-32768,-32768,-32768, - -32768,-32768,-32768, 57,-32768,-32768, 170, 39,-32768, 91, - -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, - -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 316, 316, - 28, 28, 488, 91, 74,-32768,-32768,-32768,-32768,-32768, - -32768, 90,-32768, 220,-32768, 183, 178, 110, 113,-32768, - 198,-32768, 209, 215,-32768, 202,-32768, 39,-32768,-32768, - 359, 359, 91,-32768,-32768,-32768, 224, 316, 316, 316, - 316, 316, 230, 196,-32768, 16,-32768,-32768, 231,-32768, - 258,-32768, 197,-32768,-32768,-32768,-32768,-32768,-32768, 236, - 316, 258, 201,-32768,-32768, 39, 202,-32768, 247, 255, - -32768,-32768,-32768, 66, 66, 66,-32768,-32768, 223, 17, - -32768,-32768, 237, 92, 251, 211,-32768,-32768,-32768, 121, - -32768, 252, 218, 256, 219,-32768, 249,-32768,-32768,-32768, - -32768,-32768,-32768,-32768,-32768,-32768,-32768, 115, 253,-32768, - -32768,-32768, 122,-32768,-32768,-32768,-32768,-32768,-32768, 125, - 106, 316, 316, 316,-32768,-32768,-32768, 316,-32768,-32768, - 260, 245,-32768,-32768,-32768,-32768,-32768, 316, 272, 259, - -32768,-32768, 289, 264,-32768,-32768,-32768,-32768,-32768, 288, - 322,-32768 +static const short yypact[] = { 274, + -23,-32768, 5, 55, 10,-32768,-32768, 21, 31, 446, + 32, 19,-32768, 553,-32768, 56, 72, -12, 89, -11, + 92, 102, 111, 113,-32768,-32768, 117, 124,-32768,-32768, +-32768,-32768, 183,-32768, 202,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768, -13, 134,-32768, 52, 317, +-32768,-32768, 148, 360,-32768, 115, 22, 120, 154, 173, + 114, 155, 52, 532,-32768, 140, 180, 181, 101, 182, + 112, 186, 188, 189, 190, 205,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, 193, 195,-32768,-32768,-32768, 202,-32768,-32768,-32768, +-32768,-32768, 403, 403,-32768, 532,-32768,-32768,-32768,-32768, + 52,-32768,-32768,-32768, 221,-32768, -9,-32768, 42,-32768, +-32768,-32768,-32768, 61,-32768,-32768, 200, 41,-32768, 52, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 360, 360, + 152, 152, 489, 52, 192,-32768,-32768,-32768,-32768,-32768, +-32768, 26,-32768, 127,-32768, 218, 194, 34, 73,-32768, + 215,-32768, 242, 245,-32768, 202,-32768, 41,-32768,-32768, + 403, 403, 52,-32768,-32768,-32768, 254, 360, 360, 360, + 360, 360, 253, 229,-32768, -2,-32768,-32768, 252,-32768, + 151,-32768, 217,-32768,-32768,-32768,-32768,-32768,-32768, 255, + 360, 151, 220,-32768,-32768, 41, 202,-32768, 265, 272, +-32768,-32768,-32768, 159, 159, 159,-32768,-32768, 241, 17, +-32768,-32768, 256, 36, 266, 232,-32768,-32768,-32768, 74, +-32768, 273, 238, 277, 243,-32768, 221,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768, 116, 269,-32768, +-32768,-32768, 90,-32768,-32768,-32768,-32768,-32768,-32768, 95, + 197, 360, 360, 360,-32768,-32768,-32768, 360,-32768,-32768, + 282, 251,-32768,-32768,-32768,-32768,-32768, 360, 288, 260, +-32768,-32768, 289, 280,-32768,-32768,-32768,-32768,-32768, 305, + 316,-32768 }; -static const short yypgoto[] = -{ - -32768, 160, -32, 283, 156,-32768,-32768, -122,-32768,-32768, - -32768,-32768,-32768, -167,-32768,-32768,-32768,-32768,-32768, 65, - -32768, 140,-32768, 104, -162, -6,-32768, -173,-32768, -157, - -27,-32768, 4, 2, 3, 329 +static const short yypgoto[] = {-32768, + 146, -33, 290, 156,-32768,-32768, -119,-32768,-32768,-32768, +-32768,-32768, -153,-32768,-32768,-32768,-32768,-32768, 64,-32768, + 141,-32768, 104, -162, -6,-32768, -172,-32768, -52, -28, +-32768, 6, 4, -7, 329 }; -#define YYLAST 600 - - -static const short yytable[] = -{ - 59, 60, 48, 96, 47, 175, 201, 209, 160, 212, - 217, 98, 99, 63, 221, 222, 223, 224, 225, 79, - 51, 80, 55, 92, 93, 230, 256, 162, 113, 115, - 58, 123, 109, 163, 127, 56, 61, 246, 62, 57, - 231, 231, 2, 238, 81, 243, 244, 3, 249, 4, - 5, 6, 7, 107, 247, 175, 9, 109, 101, 102, - 109, 109, 66, 164, 65, 147, 15, 129, 232, 232, - 77, 169, 101, 102, 148, 149, 78, 170, 152, 183, - 184, 185, 82, 109, 103, 104, 116, 161, 83, 29, - 84, 30, 86, 175, 167, 168, 155, 156, 223, 224, - 225, 109, 154, 177, 196, 48, 48, 171, 151, 153, - 165, 284, 184, 85, 166, 117, 118, 119, 172, 173, - 292, 293, 120, 133, 205, 134, 87, 207, 187, 188, - 189, 190, 191, 195, 109, 263, 278, 105, 258, 282, - 197, 88, 210, 96, 210, 259, 108, 215, 135, 126, - 48, 48, 178, 179, 109, 182, 198, 109, 202, 89, - 206, 258, 137, 208, 138, 109, 109, 229, 274, 109, - 90, 264, 279, 91, 239, 283, 114, 218, 219, 122, - 210, 210, 48, 48, 147, 151, 124, 139, 125, 128, - 234, 235, 130, 94, 13, 14, 145, 131, 203, 241, - 242, 16, 17, 18, 19, 20, 132, 21, 22, 23, - 24, 262, 136, 140, 141, 142, 27, 28, 143, 144, - 269, 146, 199, 174, 213, 271, 272, 273, 14, 204, - 214, 220, 277, 227, 16, 17, 18, 19, 20, 226, - 21, 22, 23, 24, 199, 270, 236, 287, 240, 27, - 28, 245, 248, 276, 250, 210, 210, 280, 281, 251, - 255, 231, 261, 117, 118, 119, 260, 265, 286, 266, - 268, 267, 288, 289, 1, 290, 2, 275, 294, 155, - 156, 3, 237, 4, 5, 6, 7, 295, 300, 8, - 9, 157, 158, 159, 10, 11, 291, 12, 13, 14, - 15, 117, 118, 119, 297, 16, 17, 18, 19, 20, - 296, 21, 22, 23, 24, 298, 95, 25, 26, 2, - 27, 28, 301, 29, 3, 30, 4, 5, 6, 7, - 211, 216, 8, 9, 228, 285, 257, 10, 11, 64, - 12, 13, 14, 15, 0, 0, 0, 0, 16, 17, - 18, 19, 20, 0, 21, 22, 23, 24, 0, 0, - 109, 0, 2, 27, 28, 0, 29, 3, 30, 4, - 5, 6, 7, 0, 0, 8, 9, 0, 0, 0, - 10, 11, 0, 12, 13, 14, 15, 0, 0, 0, - 0, 16, 17, 18, 19, 20, 0, 21, 22, 23, - 24, 0, 0, 0, 0, 2, 27, 28, 0, 29, - 3, 30, 4, 5, 6, 7, 0, 0, 8, 9, - 0, 0, 0, 0, 11, 0, 12, 13, 14, 15, - 0, 0, 0, 0, 16, 17, 18, 19, 20, 0, - 21, 22, 23, 24, 0, 0, 0, 0, 2, 27, - 28, 0, 29, 3, 30, 4, 5, 6, 7, 0, - 0, 8, 9, 0, 0, 0, 106, 0, 0, 12, - 13, 14, 15, 0, 0, 0, 0, 16, 17, 18, - 19, 20, 0, 21, 22, 23, 24, 0, 0, 0, - 0, 2, 27, 28, 0, 29, 3, 30, 4, 5, - 6, 7, 0, 0, 8, 9, 0, 0, 0, 0, - 0, 0, 12, 13, 14, 15, 0, 0, 0, 0, - 16, 17, 18, 19, 20, 0, 21, 22, 23, 24, - 0, 0, 109, 0, 2, 27, 28, 0, 29, 3, - 30, 4, 5, 6, 7, 0, 0, 8, 9, 0, - 0, 0, 0, 0, 0, 12, 13, 14, 15, 0, - 0, 0, 0, 16, 17, 18, 19, 20, 0, 21, - 22, 23, 24, 0, 0, 0, 0, 0, 27, 28, - 0, 29, 0, 30, 67, 68, 69, 70, 71, 0, - 72, 0, 73, 74, 0, 0, 0, 0, 0, 75, - 76 +#define YYLAST 601 + + +static const short yytable[] = { 59, + 60, 96, 63, 48, 122, 47, 231, 210, 176, 213, + 161, 79, 83, 80, 84, 222, 223, 224, 225, 226, + 51, 232, 92, 93, 218, 257, 117, 119, 55, 124, + 98, 99, 128, 58, 113, 120, 81, 85, 247, 197, + 232, 113, 111, 2, 61, 244, 245, 206, 3, 233, + 4, 5, 6, 7, 65, 163, 130, 9, 176, 62, + 113, 164, 250, 148, 107, 108, 109, 15, 233, 113, + 66, 121, 149, 150, 170, 198, 153, 113, 56, 77, + 171, 259, 57, 207, 113, 113, 208, 264, 260, 162, + 29, 165, 30, 168, 169, 78, 176, 105, 154, 224, + 225, 226, 178, 279, 113, 155, 48, 48, 283, 152, + 172, 202, 82, 166, 167, 86, 113, 113, 173, 174, + 293, 294, 209, 265, 134, 87, 135, 188, 189, 190, + 191, 192, 196, 113, 88, 138, 89, 139, 113, 280, + 90, 211, 96, 211, 284, 183, 216, 91, 239, 136, + 200, 112, 48, 48, 179, 180, 199, 118, 203, 248, + 140, 259, 123, 101, 102, 127, 230, 125, 275, 107, + 108, 109, 129, 240, 238, 103, 104, 219, 220, 211, + 211, 101, 102, 148, 48, 48, 126, 152, 156, 157, + 235, 236, 131, 107, 108, 109, 184, 185, 186, 242, + 243, 285, 185, 132, 133, 137, 94, 13, 14, 141, + 263, 142, 143, 144, 16, 17, 18, 19, 20, 270, + 21, 22, 23, 24, 272, 273, 274, 14, 145, 27, + 28, 278, 204, 16, 17, 18, 19, 20, 200, 21, + 22, 23, 24, 146, 205, 271, 288, 147, 27, 28, + 156, 157, 175, 277, 211, 211, 214, 281, 282, 215, + 221, 227, 158, 159, 160, 228, 237, 241, 287, 246, + 249, 251, 289, 290, 1, 252, 2, 256, 295, 232, + 261, 3, 262, 4, 5, 6, 7, 266, 267, 8, + 9, 268, 276, 269, 10, 11, 291, 12, 13, 14, + 15, 292, 296, 298, 301, 16, 17, 18, 19, 20, + 297, 21, 22, 23, 24, 302, 212, 25, 26, 2, + 27, 28, 95, 29, 3, 30, 4, 5, 6, 7, + 299, 217, 8, 9, 286, 229, 258, 106, 64, 0, + 12, 13, 14, 15, 0, 0, 0, 0, 16, 17, + 18, 19, 20, 0, 21, 22, 23, 24, 0, 107, + 108, 109, 2, 27, 28, 0, 29, 3, 30, 4, + 5, 6, 7, 0, 0, 8, 9, 0, 0, 0, + 10, 11, 0, 12, 13, 14, 15, 0, 0, 0, + 0, 16, 17, 18, 19, 20, 0, 21, 22, 23, + 24, 0, 0, 113, 0, 2, 27, 28, 0, 29, + 3, 30, 4, 5, 6, 7, 0, 0, 8, 9, + 0, 0, 0, 10, 11, 0, 12, 13, 14, 15, + 0, 0, 0, 0, 16, 17, 18, 19, 20, 0, + 21, 22, 23, 24, 0, 0, 0, 0, 2, 27, + 28, 0, 29, 3, 30, 4, 5, 6, 7, 0, + 0, 8, 9, 0, 0, 0, 0, 11, 0, 12, + 13, 14, 15, 0, 0, 0, 0, 16, 17, 18, + 19, 20, 0, 21, 22, 23, 24, 0, 0, 0, + 0, 2, 27, 28, 0, 29, 3, 30, 4, 5, + 6, 7, 0, 0, 8, 9, 0, 0, 0, 0, + 0, 0, 12, 13, 14, 15, 0, 0, 0, 0, + 16, 17, 18, 19, 20, 0, 21, 22, 23, 24, + 0, 0, 113, 0, 2, 27, 28, 0, 29, 3, + 30, 4, 5, 6, 7, 0, 0, 8, 9, 0, + 0, 0, 0, 0, 0, 12, 13, 14, 15, 0, + 0, 0, 0, 16, 17, 18, 19, 20, 0, 21, + 22, 23, 24, 0, 0, 0, 0, 0, 27, 28, + 0, 29, 0, 30, 67, 68, 69, 70, 71, 0, + 72, 0, 73, 74, 0, 0, 0, 0, 0, 75, + 76 }; -static const short yycheck[] = -{ - 6, 7, 0, 35, 0, 127, 163, 169, 20, 171, - 177, 44, 45, 10, 187, 188, 189, 190, 191, 24, - 44, 26, 24, 29, 30, 9, 9, 14, 55, 56, - 24, 58, 44, 20, 61, 24, 24, 210, 29, 28, - 24, 24, 3, 200, 49, 207, 208, 8, 215, 10, - 11, 12, 13, 50, 211, 177, 17, 44, 30, 31, - 44, 44, 52, 50, 23, 97, 27, 64, 52, 52, - 24, 14, 30, 31, 101, 102, 24, 20, 105, 5, - 6, 7, 24, 44, 42, 43, 14, 114, 24, 50, - 26, 52, 24, 215, 121, 122, 30, 31, 271, 272, - 273, 44, 108, 130, 14, 103, 104, 50, 104, 106, - 116, 5, 6, 49, 120, 43, 44, 45, 124, 125, - 282, 283, 50, 24, 14, 26, 24, 14, 155, 156, - 157, 158, 159, 160, 44, 14, 14, 46, 46, 14, - 50, 24, 169, 175, 171, 53, 4, 174, 49, 52, - 148, 149, 148, 149, 44, 152, 162, 44, 164, 24, - 50, 46, 24, 50, 26, 44, 44, 194, 53, 44, - 24, 50, 50, 24, 201, 50, 43, 183, 184, 43, - 207, 208, 180, 181, 216, 181, 14, 49, 14, 18, - 196, 197, 53, 24, 25, 26, 51, 24, 15, 205, - 206, 32, 33, 34, 35, 36, 24, 38, 39, 40, - 41, 238, 24, 24, 24, 24, 47, 48, 24, 24, - 247, 53, 24, 53, 15, 252, 253, 254, 26, 51, - 15, 7, 259, 37, 32, 33, 34, 35, 36, 9, - 38, 39, 40, 41, 24, 251, 15, 274, 51, 47, - 48, 15, 51, 259, 7, 282, 283, 263, 264, 4, - 37, 24, 51, 43, 44, 45, 15, 15, 274, 51, - 51, 15, 278, 279, 1, 15, 3, 24, 284, 30, - 31, 8, 24, 10, 11, 12, 13, 15, 0, 16, - 17, 42, 43, 44, 21, 22, 51, 24, 25, 26, - 27, 43, 44, 45, 15, 32, 33, 34, 35, 36, - 51, 38, 39, 40, 41, 51, 33, 44, 45, 3, - 47, 48, 0, 50, 8, 52, 10, 11, 12, 13, - 170, 175, 16, 17, 194, 270, 232, 21, 22, 10, - 24, 25, 26, 27, -1, -1, -1, -1, 32, 33, - 34, 35, 36, -1, 38, 39, 40, 41, -1, -1, - 44, -1, 3, 47, 48, -1, 50, 8, 52, 10, - 11, 12, 13, -1, -1, 16, 17, -1, -1, -1, - 21, 22, -1, 24, 25, 26, 27, -1, -1, -1, - -1, 32, 33, 34, 35, 36, -1, 38, 39, 40, - 41, -1, -1, -1, -1, 3, 47, 48, -1, 50, - 8, 52, 10, 11, 12, 13, -1, -1, 16, 17, - -1, -1, -1, -1, 22, -1, 24, 25, 26, 27, - -1, -1, -1, -1, 32, 33, 34, 35, 36, -1, - 38, 39, 40, 41, -1, -1, -1, -1, 3, 47, - 48, -1, 50, 8, 52, 10, 11, 12, 13, -1, - -1, 16, 17, -1, -1, -1, 21, -1, -1, 24, - 25, 26, 27, -1, -1, -1, -1, 32, 33, 34, - 35, 36, -1, 38, 39, 40, 41, -1, -1, -1, - -1, 3, 47, 48, -1, 50, 8, 52, 10, 11, - 12, 13, -1, -1, 16, 17, -1, -1, -1, -1, - -1, -1, 24, 25, 26, 27, -1, -1, -1, -1, - 32, 33, 34, 35, 36, -1, 38, 39, 40, 41, - -1, -1, 44, -1, 3, 47, 48, -1, 50, 8, - 52, 10, 11, 12, 13, -1, -1, 16, 17, -1, - -1, -1, -1, -1, -1, 24, 25, 26, 27, -1, - -1, -1, -1, 32, 33, 34, 35, 36, -1, 38, - 39, 40, 41, -1, -1, -1, -1, -1, 47, 48, - -1, 50, -1, 52, 32, 33, 34, 35, 36, -1, - 38, -1, 40, 41, -1, -1, -1, -1, -1, 47, - 48 +static const short yycheck[] = { 6, + 7, 35, 10, 0, 57, 0, 9, 170, 128, 172, + 20, 24, 24, 26, 26, 188, 189, 190, 191, 192, + 44, 24, 29, 30, 178, 9, 55, 56, 24, 58, + 44, 45, 61, 24, 44, 14, 49, 49, 211, 14, + 24, 44, 50, 3, 24, 208, 209, 14, 8, 52, + 10, 11, 12, 13, 23, 14, 64, 17, 178, 29, + 44, 20, 216, 97, 43, 44, 45, 27, 52, 44, + 52, 50, 101, 102, 14, 50, 105, 44, 24, 24, + 20, 46, 28, 50, 44, 44, 14, 14, 53, 118, + 50, 50, 52, 122, 123, 24, 216, 46, 106, 272, + 273, 274, 131, 14, 44, 112, 103, 104, 14, 104, + 50, 164, 24, 120, 121, 24, 44, 44, 125, 126, + 283, 284, 50, 50, 24, 24, 26, 156, 157, 158, + 159, 160, 161, 44, 24, 24, 24, 26, 44, 50, + 24, 170, 176, 172, 50, 153, 175, 24, 201, 49, + 24, 4, 149, 150, 149, 150, 163, 43, 165, 212, + 49, 46, 43, 30, 31, 52, 195, 14, 53, 43, + 44, 45, 18, 202, 24, 42, 43, 184, 185, 208, + 209, 30, 31, 217, 181, 182, 14, 182, 30, 31, + 197, 198, 53, 43, 44, 45, 5, 6, 7, 206, + 207, 5, 6, 24, 24, 24, 24, 25, 26, 24, + 239, 24, 24, 24, 32, 33, 34, 35, 36, 248, + 38, 39, 40, 41, 253, 254, 255, 26, 24, 47, + 48, 260, 15, 32, 33, 34, 35, 36, 24, 38, + 39, 40, 41, 51, 51, 252, 275, 53, 47, 48, + 30, 31, 53, 260, 283, 284, 15, 264, 265, 15, + 7, 9, 42, 43, 44, 37, 15, 51, 275, 15, + 51, 7, 279, 280, 1, 4, 3, 37, 285, 24, + 15, 8, 51, 10, 11, 12, 13, 15, 51, 16, + 17, 15, 24, 51, 21, 22, 15, 24, 25, 26, + 27, 51, 15, 15, 0, 32, 33, 34, 35, 36, + 51, 38, 39, 40, 41, 0, 171, 44, 45, 3, + 47, 48, 33, 50, 8, 52, 10, 11, 12, 13, + 51, 176, 16, 17, 271, 195, 233, 21, 10, -1, + 24, 25, 26, 27, -1, -1, -1, -1, 32, 33, + 34, 35, 36, -1, 38, 39, 40, 41, -1, 43, + 44, 45, 3, 47, 48, -1, 50, 8, 52, 10, + 11, 12, 13, -1, -1, 16, 17, -1, -1, -1, + 21, 22, -1, 24, 25, 26, 27, -1, -1, -1, + -1, 32, 33, 34, 35, 36, -1, 38, 39, 40, + 41, -1, -1, 44, -1, 3, 47, 48, -1, 50, + 8, 52, 10, 11, 12, 13, -1, -1, 16, 17, + -1, -1, -1, 21, 22, -1, 24, 25, 26, 27, + -1, -1, -1, -1, 32, 33, 34, 35, 36, -1, + 38, 39, 40, 41, -1, -1, -1, -1, 3, 47, + 48, -1, 50, 8, 52, 10, 11, 12, 13, -1, + -1, 16, 17, -1, -1, -1, -1, 22, -1, 24, + 25, 26, 27, -1, -1, -1, -1, 32, 33, 34, + 35, 36, -1, 38, 39, 40, 41, -1, -1, -1, + -1, 3, 47, 48, -1, 50, 8, 52, 10, 11, + 12, 13, -1, -1, 16, 17, -1, -1, -1, -1, + -1, -1, 24, 25, 26, 27, -1, -1, -1, -1, + 32, 33, 34, 35, 36, -1, 38, 39, 40, 41, + -1, -1, 44, -1, 3, 47, 48, -1, 50, 8, + 52, 10, 11, 12, 13, -1, -1, 16, 17, -1, + -1, -1, -1, -1, -1, 24, 25, 26, 27, -1, + -1, -1, -1, 32, 33, 34, 35, 36, -1, 38, + 39, 40, 41, -1, -1, -1, -1, -1, 47, 48, + -1, 50, -1, 52, 32, 33, 34, 35, 36, -1, + 38, -1, 40, 41, -1, -1, -1, -1, -1, 47, + 48 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/local/share/bison/bison.simple" +#line 3 "/usr/share/bison.simple" +/* This file comes from bison-1.28. */ /* Skeleton output parser for bison, - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software - Foundation, Inc. + Copyright (C) 1984, 1989, 1990 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 @@ -792,109 +775,63 @@ static const short yycheck[] = This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ -/* This is the parser code that is written into each bison parser when - the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free -# endif - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - short yyss; - YYSTYPE yyvs; -# if YYLSP_NEEDED - YYLTYPE yyls; -# endif -}; +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# if YYLSP_NEEDED -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAX) -# else -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAX) -# endif - -/* Relocate the TYPE STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Type, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - yymemcpy ((char *) yyptr, (char *) (Stack), \ - yysize * (YYSIZE_T) sizeof (Type)); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ - - -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include #endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ #endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc #endif +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 @@ -902,188 +839,131 @@ union yyalloc #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ +#define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ + { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ - { \ - yyerror ("syntax error: cannot back up"); \ - YYERROR; \ - } \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). +#ifndef YYPURE - When YYLLOC_DEFAULT is run, CURRENT is set the location of the - first token. By default, to implement support for ranges, extend - its range to the last symbol. */ +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ #endif +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif -/* YYLEX -- calling `yylex' with the right arguments. */ +/* YYINITDEPTH indicates the initial size of the parser's stacks */ -#if YYPURE -# if YYLSP_NEEDED -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval, &yylloc) -# endif -# else /* !YYLSP_NEEDED */ -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval) -# endif -# endif /* !YYLSP_NEEDED */ -#else /* !YYPURE */ -# define YYLEX yylex () -#endif /* !YYPURE */ - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -#endif /* !YYDEBUG */ - -/* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -# define YYINITDEPTH 200 +#define YYINITDEPTH 200 #endif -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 -# undef YYMAXDEPTH +#undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 +#define YYMAXDEPTH 10000 #endif -#if ! defined (yyoverflow) && ! defined (yymemcpy) -# if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -# define yymemcpy __builtin_memcpy -# else /* not GNU C or C++ */ +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void -# if defined (__STDC__) || defined (__cplusplus) -yymemcpy (char *yyto, const char *yyfrom, YYSIZE_T yycount) -# else -yymemcpy (yyto, yyfrom, yycount) - char *yyto; - const char *yyfrom; - YYSIZE_T yycount; -# endif +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; { - register const char *yyf = yyfrom; - register char *yyt = yyto; - register YYSIZE_T yyi = yycount; + register char *f = from; + register char *t = to; + register int i = count; - while (yyi-- != 0) - *yyt++ = *yyf++; + while (i-- > 0) + *t++ = *f++; } -# endif -#endif -#ifdef YYERROR_VERBOSE +#else /* __cplusplus */ -# ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) -yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif -{ - register const char *yys = yystr; - - while (*yys++ != '\0') - continue; - - return yys - yystr - 1; -} -# endif -# endif - -# ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -# if defined (__STDC__) || defined (__cplusplus) -yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) { - register char *yyd = yydest; - register const char *yys = yysrc; + register char *t = to; + register char *f = from; + register int i = count; - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; + while (i-- > 0) + *t++ = *f++; } -# endif -# endif + +#endif #endif -#line 319 "/usr/local/share/bison/bison.simple" - +#line 217 "/usr/share/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. @@ -1092,121 +972,76 @@ yystpcpy (yydest, yysrc) to the proper pointer type. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -# define YYPARSE_PARAM_DECL -# else -# define YYPARSE_PARAM_ARG YYPARSE_PARAM -# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -# endif -#else /* !YYPARSE_PARAM */ -# define YYPARSE_PARAM_ARG -# define YYPARSE_PARAM_DECL -#endif /* !YYPARSE_PARAM */ +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ -# ifdef YYPARSE_PARAM +#ifdef YYPARSE_PARAM int yyparse (void *); -# else +#else int yyparse (void); -# endif #endif - -/* YY_DECL_VARIABLES -- depending whether we use a pure parser, - variables are global, or local to YYPARSE. */ - -#define YY_DECL_NON_LSP_VARIABLES \ -/* The lookahead symbol. */ \ -int yychar; \ - \ -/* The semantic value of the lookahead symbol. */ \ -YYSTYPE yylval; \ - \ -/* Number of parse errors so far. */ \ -int yynerrs; - -#if YYLSP_NEEDED -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES \ - \ -/* Location data for the lookahead symbol. */ \ -YYLTYPE yylloc; -#else -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES #endif - -/* If nonreentrant, generate the variables here. */ - -#if !YYPURE -YY_DECL_VARIABLES -#endif /* !YYPURE */ - int -yyparse (YYPARSE_PARAM_ARG) +yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { - /* If reentrant, generate the variables here. */ -#if YYPURE - YY_DECL_VARIABLES -#endif /* !YYPURE */ - register int yystate; register int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ - int yychar1 = 0; - - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; register short *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ -#if YYLSP_NEEDED - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; -#endif -#if YYLSP_NEEDED -# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else -# define YYPOPSTACK (yyvsp--, yyssp--) +#define YYPOPSTACK (yyvsp--, yyssp--) #endif - YYSIZE_T yystacksize = YYINITDEPTH; - + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; -#if YYLSP_NEEDED - YYLTYPE yyloc; +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif #endif - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + int yylen; - YYDPRINTF ((stderr, "Starting parse\n")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif yystate = 0; yyerrstatus = 0; @@ -1218,106 +1053,110 @@ yyparse (YYPARSE_PARAM_ARG) so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss; + yyssp = yyss - 1; yyvsp = yyvs; -#if YYLSP_NEEDED +#ifdef YYLSP_NEEDED yylsp = yyls; #endif - goto yysetstate; -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ - yyssp++; +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: - yysetstate: - *yyssp = yystate; + *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + int size = yyssp - yyss + 1; #ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. */ -# if YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - yyls = yyls1; -# else - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); -# endif - yyss = yyss1; - yyvs = yyvs1; - } + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) - goto yyoverflowlab; + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; - - { - short *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (short, yyss); - YYSTACK_RELOCATE (YYSTYPE, yyvs); -# if YYLSP_NEEDED - YYSTACK_RELOCATE (YYLTYPE, yyls); -# endif -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif #endif /* no yyoverflow */ - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; -#if YYLSP_NEEDED - yylsp = yyls + yysize - 1; + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; #endif - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: + yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ @@ -1336,7 +1175,10 @@ yybackup: if (yychar == YYEMPTY) { - YYDPRINTF ((stderr, "Reading a token: ")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif yychar = YYLEX; } @@ -1347,25 +1189,25 @@ yybackup: yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ - YYDPRINTF ((stderr, "Now at end of input.\n")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif } else { - yychar1 = YYTRANSLATE (yychar); + yychar1 = YYTRANSLATE(yychar); -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables - which are defined only if `YYDEBUG' is set. */ +#if YYDEBUG != 0 if (yydebug) { - YYFPRINTF (stderr, "Next token is %d (%s", - yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise - meaning of a token, for further debugging info. */ -# ifdef YYPRINT + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT YYPRINT (stderr, yychar, yylval); -# endif - YYFPRINTF (stderr, ")\n"); +#endif + fprintf (stderr, ")\n"); } #endif } @@ -1397,82 +1239,60 @@ yybackup: YYACCEPT; /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %d (%s), ", - yychar, yytname[yychar1])); + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; -#if YYLSP_NEEDED +#ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ +/* Do the default action for the current state. */ yydefault: + yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; - goto yyreduce; - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ +/* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: - /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to the semantic value of - the lookahead token. This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - -#if YYLSP_NEEDED - /* Similarly for the default location. Let the user run additional - commands if for instance locations are ranges. */ - yyloc = yylsp[1-yylen]; - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); -#endif - -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables which - are defined only if `YYDEBUG' is set. */ +#if YYDEBUG != 0 if (yydebug) { - int yyi; + int i; - YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif + switch (yyn) { case 1: -#line 341 "/usr/homes/chet/src/bash/src/parse.y" +#line 351 "/Users/chet/src/bash/src/parse.y" { /* Case of regular command. Discard the error safety net,and return the command just parsed. */ @@ -1480,19 +1300,19 @@ case 1: eof_encountered = 0; /* discard_parser_constructs (0); */ YYACCEPT; - } - break; + ; + break;} case 2: -#line 350 "/usr/homes/chet/src/bash/src/parse.y" +#line 360 "/Users/chet/src/bash/src/parse.y" { /* Case of regular command, but not a very interesting one. Return a NULL command. */ global_command = (COMMAND *)NULL; YYACCEPT; - } - break; + ; + break;} case 3: -#line 357 "/usr/homes/chet/src/bash/src/parse.y" +#line 367 "/Users/chet/src/bash/src/parse.y" { /* Error during parsing. Return NULL command. */ global_command = (COMMAND *)NULL; @@ -1506,255 +1326,255 @@ case 3: { YYABORT; } - } - break; + ; + break;} case 4: -#line 372 "/usr/homes/chet/src/bash/src/parse.y" +#line 382 "/Users/chet/src/bash/src/parse.y" { /* Case of EOF seen by itself. Do ignoreeof or not. */ global_command = (COMMAND *)NULL; handle_eof_input_unit (); YYACCEPT; - } - break; + ; + break;} case 5: -#line 382 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); } - break; +#line 392 "/Users/chet/src/bash/src/parse.y" +{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; + break;} case 6: -#line 384 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); } - break; +#line 394 "/Users/chet/src/bash/src/parse.y" +{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-1].word_list); ; + break;} case 7: -#line 388 "/usr/homes/chet/src/bash/src/parse.y" +#line 398 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (1, r_output_direction, redir); - } - break; + ; + break;} case 8: -#line 393 "/usr/homes/chet/src/bash/src/parse.y" +#line 403 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_input_direction, redir); - } - break; + ; + break;} case 9: -#line 398 "/usr/homes/chet/src/bash/src/parse.y" +#line 408 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_output_direction, redir); - } - break; + ; + break;} case 10: -#line 403 "/usr/homes/chet/src/bash/src/parse.y" +#line 413 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_input_direction, redir); - } - break; + ; + break;} case 11: -#line 408 "/usr/homes/chet/src/bash/src/parse.y" +#line 418 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (1, r_appending_to, redir); - } - break; + ; + break;} case 12: -#line 413 "/usr/homes/chet/src/bash/src/parse.y" +#line 423 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_appending_to, redir); - } - break; + ; + break;} case 13: -#line 418 "/usr/homes/chet/src/bash/src/parse.y" +#line 428 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_reading_until, redir); redir_stack[need_here_doc++] = yyval.redirect; - } - break; + ; + break;} case 14: -#line 424 "/usr/homes/chet/src/bash/src/parse.y" +#line 434 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_reading_until, redir); redir_stack[need_here_doc++] = yyval.redirect; - } - break; + ; + break;} case 15: -#line 430 "/usr/homes/chet/src/bash/src/parse.y" +#line 440 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_reading_string, redir); - } - break; + ; + break;} case 16: -#line 435 "/usr/homes/chet/src/bash/src/parse.y" +#line 445 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_reading_string, redir); - } - break; + ; + break;} case 17: -#line 440 "/usr/homes/chet/src/bash/src/parse.y" +#line 450 "/Users/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; yyval.redirect = make_redirection (0, r_duplicating_input, redir); - } - break; + ; + break;} case 18: -#line 445 "/usr/homes/chet/src/bash/src/parse.y" +#line 455 "/Users/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input, redir); - } - break; + ; + break;} case 19: -#line 450 "/usr/homes/chet/src/bash/src/parse.y" +#line 460 "/Users/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; yyval.redirect = make_redirection (1, r_duplicating_output, redir); - } - break; + ; + break;} case 20: -#line 455 "/usr/homes/chet/src/bash/src/parse.y" +#line 465 "/Users/chet/src/bash/src/parse.y" { redir.dest = yyvsp[0].number; yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output, redir); - } - break; + ; + break;} case 21: -#line 460 "/usr/homes/chet/src/bash/src/parse.y" +#line 470 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_duplicating_input_word, redir); - } - break; + ; + break;} case 22: -#line 465 "/usr/homes/chet/src/bash/src/parse.y" +#line 475 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_input_word, redir); - } - break; + ; + break;} case 23: -#line 470 "/usr/homes/chet/src/bash/src/parse.y" +#line 480 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (1, r_duplicating_output_word, redir); - } - break; + ; + break;} case 24: -#line 475 "/usr/homes/chet/src/bash/src/parse.y" +#line 485 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_duplicating_output_word, redir); - } - break; + ; + break;} case 25: -#line 480 "/usr/homes/chet/src/bash/src/parse.y" +#line 490 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_deblank_reading_until, redir); redir_stack[need_here_doc++] = yyval.redirect; - } - break; + ; + break;} case 26: -#line 487 "/usr/homes/chet/src/bash/src/parse.y" +#line 497 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_deblank_reading_until, redir); redir_stack[need_here_doc++] = yyval.redirect; - } - break; + ; + break;} case 27: -#line 494 "/usr/homes/chet/src/bash/src/parse.y" +#line 504 "/Users/chet/src/bash/src/parse.y" { redir.dest = 0; yyval.redirect = make_redirection (1, r_close_this, redir); - } - break; + ; + break;} case 28: -#line 499 "/usr/homes/chet/src/bash/src/parse.y" +#line 509 "/Users/chet/src/bash/src/parse.y" { redir.dest = 0; yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir); - } - break; + ; + break;} case 29: -#line 504 "/usr/homes/chet/src/bash/src/parse.y" +#line 514 "/Users/chet/src/bash/src/parse.y" { redir.dest = 0; yyval.redirect = make_redirection (0, r_close_this, redir); - } - break; + ; + break;} case 30: -#line 509 "/usr/homes/chet/src/bash/src/parse.y" +#line 519 "/Users/chet/src/bash/src/parse.y" { redir.dest = 0; yyval.redirect = make_redirection (yyvsp[-2].number, r_close_this, redir); - } - break; + ; + break;} case 31: -#line 514 "/usr/homes/chet/src/bash/src/parse.y" +#line 524 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (1, r_err_and_out, redir); - } - break; + ; + break;} case 32: -#line 519 "/usr/homes/chet/src/bash/src/parse.y" +#line 529 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_input_output, redir); - } - break; + ; + break;} case 33: -#line 524 "/usr/homes/chet/src/bash/src/parse.y" +#line 534 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (0, r_input_output, redir); - } - break; + ; + break;} case 34: -#line 529 "/usr/homes/chet/src/bash/src/parse.y" +#line 539 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (1, r_output_force, redir); - } - break; + ; + break;} case 35: -#line 534 "/usr/homes/chet/src/bash/src/parse.y" +#line 544 "/Users/chet/src/bash/src/parse.y" { redir.filename = yyvsp[0].word; yyval.redirect = make_redirection (yyvsp[-2].number, r_output_force, redir); - } - break; + ; + break;} case 36: -#line 541 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; } - break; +#line 551 "/Users/chet/src/bash/src/parse.y" +{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; + break;} case 37: -#line 543 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; } - break; +#line 553 "/Users/chet/src/bash/src/parse.y" +{ yyval.element.word = yyvsp[0].word; yyval.element.redirect = 0; ; + break;} case 38: -#line 545 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; } - break; +#line 555 "/Users/chet/src/bash/src/parse.y" +{ yyval.element.redirect = yyvsp[0].redirect; yyval.element.word = 0; ; + break;} case 39: -#line 549 "/usr/homes/chet/src/bash/src/parse.y" +#line 559 "/Users/chet/src/bash/src/parse.y" { yyval.redirect = yyvsp[0].redirect; - } - break; + ; + break;} case 40: -#line 553 "/usr/homes/chet/src/bash/src/parse.y" +#line 563 "/Users/chet/src/bash/src/parse.y" { register REDIRECT *t; @@ -1762,26 +1582,26 @@ case 40: ; t->next = yyvsp[0].redirect; yyval.redirect = yyvsp[-1].redirect; - } - break; + ; + break;} case 41: -#line 564 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); } - break; +#line 574 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_simple_command (yyvsp[0].element, (COMMAND *)NULL); ; + break;} case 42: -#line 566 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); } - break; +#line 576 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_simple_command (yyvsp[0].element, yyvsp[-1].command); ; + break;} case 43: -#line 570 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = clean_simple_command (yyvsp[0].command); } - break; +#line 580 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = clean_simple_command (yyvsp[0].command); ; + break;} case 44: -#line 572 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 582 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 45: -#line 574 "/usr/homes/chet/src/bash/src/parse.y" +#line 584 "/Users/chet/src/bash/src/parse.y" { COMMAND *tc; @@ -1796,221 +1616,221 @@ case 45: else tc->redirects = yyvsp[0].redirect; yyval.command = yyvsp[-1].command; - } - break; + ; + break;} case 46: -#line 590 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 600 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 47: -#line 594 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 604 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 48: -#line 596 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 606 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 49: -#line 598 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); } - break; +#line 608 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_while_command (yyvsp[-3].command, yyvsp[-1].command); ; + break;} case 50: -#line 600 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); } - break; +#line 610 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_until_command (yyvsp[-3].command, yyvsp[-1].command); ; + break;} case 51: -#line 602 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 612 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 52: -#line 604 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 614 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 53: -#line 606 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 616 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 54: -#line 608 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 618 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 55: -#line 610 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 620 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 56: -#line 612 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 622 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 57: -#line 614 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 624 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 58: -#line 618 "/usr/homes/chet/src/bash/src/parse.y" +#line 628 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 59: -#line 623 "/usr/homes/chet/src/bash/src/parse.y" +#line 633 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 60: -#line 628 "/usr/homes/chet/src/bash/src/parse.y" +#line 638 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 61: -#line 633 "/usr/homes/chet/src/bash/src/parse.y" +#line 643 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 62: -#line 638 "/usr/homes/chet/src/bash/src/parse.y" +#line 648 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 63: -#line 643 "/usr/homes/chet/src/bash/src/parse.y" +#line 653 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 64: -#line 648 "/usr/homes/chet/src/bash/src/parse.y" +#line 658 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 65: -#line 653 "/usr/homes/chet/src/bash/src/parse.y" +#line 663 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_for_command (yyvsp[-7].word, (WORD_LIST *)NULL, yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 66: -#line 660 "/usr/homes/chet/src/bash/src/parse.y" +#line 670 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); if (word_top > 0) word_top--; - } - break; + ; + break;} case 67: -#line 665 "/usr/homes/chet/src/bash/src/parse.y" +#line 675 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_arith_for_command (yyvsp[-5].word_list, yyvsp[-1].command, arith_for_lineno); if (word_top > 0) word_top--; - } - break; + ; + break;} case 68: -#line 670 "/usr/homes/chet/src/bash/src/parse.y" +#line 680 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); if (word_top > 0) word_top--; - } - break; + ; + break;} case 69: -#line 675 "/usr/homes/chet/src/bash/src/parse.y" +#line 685 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_arith_for_command (yyvsp[-3].word_list, yyvsp[-1].command, arith_for_lineno); if (word_top > 0) word_top--; - } - break; + ; + break;} case 70: -#line 682 "/usr/homes/chet/src/bash/src/parse.y" +#line 692 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 71: -#line 687 "/usr/homes/chet/src/bash/src/parse.y" +#line 697 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-4].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 72: -#line 692 "/usr/homes/chet/src/bash/src/parse.y" +#line 702 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 73: -#line 697 "/usr/homes/chet/src/bash/src/parse.y" +#line 707 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-5].word, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 74: -#line 702 "/usr/homes/chet/src/bash/src/parse.y" +#line 712 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 75: -#line 707 "/usr/homes/chet/src/bash/src/parse.y" +#line 717 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_select_command (yyvsp[-8].word, REVERSE_LIST (yyvsp[-5].word_list, WORD_LIST *), yyvsp[-1].command, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 76: -#line 714 "/usr/homes/chet/src/bash/src/parse.y" +#line 724 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, (PATTERN_LIST *)NULL, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 77: -#line 719 "/usr/homes/chet/src/bash/src/parse.y" +#line 729 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-5].word, yyvsp[-2].pattern, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 78: -#line 724 "/usr/homes/chet/src/bash/src/parse.y" +#line 734 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_case_command (yyvsp[-4].word, yyvsp[-1].pattern, word_lineno[word_top]); if (word_top > 0) word_top--; - } - break; + ; + break;} case 79: -#line 731 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); } - break; +#line 741 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; + break;} case 80: -#line 734 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); } - break; +#line 744 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_function_def (yyvsp[-4].word, yyvsp[0].command, function_dstart, function_bstart); ; + break;} case 81: -#line 737 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); } - break; +#line 747 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_function_def (yyvsp[-2].word, yyvsp[0].command, function_dstart, function_bstart); ; + break;} case 82: -#line 742 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 752 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 83: -#line 744 "/usr/homes/chet/src/bash/src/parse.y" +#line 754 "/Users/chet/src/bash/src/parse.y" { COMMAND *tc; @@ -2038,145 +1858,157 @@ case 83: else tc->redirects = yyvsp[0].redirect; yyval.command = yyvsp[-1].command; - } - break; + ; + break;} case 84: -#line 775 "/usr/homes/chet/src/bash/src/parse.y" +#line 785 "/Users/chet/src/bash/src/parse.y" { yyval.command = make_subshell_command (yyvsp[-1].command); yyval.command->flags |= CMD_WANT_SUBSHELL; - } - break; + ; + break;} case 85: -#line 782 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); } - break; +#line 792 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, (COMMAND *)NULL); ; + break;} case 86: -#line 784 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); } - break; +#line 794 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-5].command, yyvsp[-3].command, yyvsp[-1].command); ; + break;} case 87: -#line 786 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); } - break; +#line 796 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[-1].command); ; + break;} case 88: -#line 791 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_group_command (yyvsp[-1].command); } - break; +#line 801 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_group_command (yyvsp[-1].command); ; + break;} case 89: -#line 795 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_arith_command (yyvsp[0].word_list); } - break; +#line 805 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_arith_command (yyvsp[0].word_list); ; + break;} case 90: -#line 799 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[-1].command; } - break; +#line 809 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[-1].command; ; + break;} case 91: -#line 803 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); } - break; +#line 813 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-2].command, yyvsp[0].command, (COMMAND *)NULL); ; + break;} case 92: -#line 805 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); } - break; +#line 815 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-4].command, yyvsp[-2].command, yyvsp[0].command); ; + break;} case 93: -#line 807 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); } - break; +#line 817 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = make_if_command (yyvsp[-3].command, yyvsp[-1].command, yyvsp[0].command); ; + break;} case 95: -#line 812 "/usr/homes/chet/src/bash/src/parse.y" -{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; } - break; +#line 822 "/Users/chet/src/bash/src/parse.y" +{ yyvsp[0].pattern->next = yyvsp[-1].pattern; yyval.pattern = yyvsp[0].pattern; ; + break;} case 96: -#line 816 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); } - break; +#line 826 "/Users/chet/src/bash/src/parse.y" +{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; + break;} case 97: -#line 818 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); } - break; +#line 828 "/Users/chet/src/bash/src/parse.y" +{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; + break;} case 98: -#line 820 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); } - break; +#line 830 "/Users/chet/src/bash/src/parse.y" +{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, yyvsp[0].command); ; + break;} case 99: -#line 822 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); } - break; +#line 832 "/Users/chet/src/bash/src/parse.y" +{ yyval.pattern = make_pattern_list (yyvsp[-2].word_list, (COMMAND *)NULL); ; + break;} case 101: -#line 827 "/usr/homes/chet/src/bash/src/parse.y" -{ yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; } - break; +#line 837 "/Users/chet/src/bash/src/parse.y" +{ yyvsp[-1].pattern->next = yyvsp[-2].pattern; yyval.pattern = yyvsp[-1].pattern; ; + break;} case 102: -#line 831 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); } - break; +#line 841 "/Users/chet/src/bash/src/parse.y" +{ yyval.word_list = make_word_list (yyvsp[0].word, (WORD_LIST *)NULL); ; + break;} case 103: -#line 833 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); } - break; +#line 843 "/Users/chet/src/bash/src/parse.y" +{ yyval.word_list = make_word_list (yyvsp[0].word, yyvsp[-2].word_list); ; + break;} case 104: -#line 842 "/usr/homes/chet/src/bash/src/parse.y" +#line 852 "/Users/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; if (need_here_doc) gather_here_documents (); - } - break; + ; + break;} case 106: -#line 851 "/usr/homes/chet/src/bash/src/parse.y" +#line 861 "/Users/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; - } - break; + ; + break;} case 108: -#line 858 "/usr/homes/chet/src/bash/src/parse.y" +#line 868 "/Users/chet/src/bash/src/parse.y" { if (yyvsp[-2].command->type == cm_connection) yyval.command = connect_async_list (yyvsp[-2].command, (COMMAND *)NULL, '&'); else yyval.command = command_connect (yyvsp[-2].command, (COMMAND *)NULL, '&'); - } - break; + ; + break;} case 110: -#line 869 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); } - break; +#line 879 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; + break;} case 111: -#line 871 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); } - break; +#line 881 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; + break;} case 112: -#line 873 "/usr/homes/chet/src/bash/src/parse.y" +#line 883 "/Users/chet/src/bash/src/parse.y" { if (yyvsp[-3].command->type == cm_connection) yyval.command = connect_async_list (yyvsp[-3].command, yyvsp[0].command, '&'); else yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '&'); - } - break; + ; + break;} case 113: -#line 880 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); } - break; +#line 890 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; + break;} case 114: -#line 882 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); } - break; +#line 892 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, ';'); ; + break;} case 115: -#line 884 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 894 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} +case 118: +#line 902 "/Users/chet/src/bash/src/parse.y" +{ yyval.number = '\n'; ; + break;} +case 119: +#line 904 "/Users/chet/src/bash/src/parse.y" +{ yyval.number = ';'; ; + break;} +case 120: +#line 906 "/Users/chet/src/bash/src/parse.y" +{ yyval.number = yacc_EOF; ; + break;} case 123: -#line 907 "/usr/homes/chet/src/bash/src/parse.y" +#line 920 "/Users/chet/src/bash/src/parse.y" { yyval.command = yyvsp[0].command; if (need_here_doc) gather_here_documents (); - } - break; + ; + break;} case 124: -#line 913 "/usr/homes/chet/src/bash/src/parse.y" +#line 926 "/Users/chet/src/bash/src/parse.y" { if (yyvsp[-1].command->type == cm_connection) yyval.command = connect_async_list (yyvsp[-1].command, (COMMAND *)NULL, '&'); @@ -2184,119 +2016,152 @@ case 124: yyval.command = command_connect (yyvsp[-1].command, (COMMAND *)NULL, '&'); if (need_here_doc) gather_here_documents (); - } - break; + ; + break;} case 125: -#line 922 "/usr/homes/chet/src/bash/src/parse.y" +#line 935 "/Users/chet/src/bash/src/parse.y" { yyval.command = yyvsp[-1].command; if (need_here_doc) gather_here_documents (); - } - break; + ; + break;} case 126: -#line 930 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); } - break; +#line 943 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, AND_AND); ; + break;} case 127: -#line 932 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); } - break; +#line 945 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, OR_OR); ; + break;} case 128: -#line 934 "/usr/homes/chet/src/bash/src/parse.y" +#line 947 "/Users/chet/src/bash/src/parse.y" { if (yyvsp[-2].command->type == cm_connection) yyval.command = connect_async_list (yyvsp[-2].command, yyvsp[0].command, '&'); else yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, '&'); - } - break; + ; + break;} case 129: -#line 941 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); } - break; +#line 954 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-2].command, yyvsp[0].command, ';'); ; + break;} case 130: -#line 944 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 957 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 131: -#line 948 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 961 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 132: -#line 950 "/usr/homes/chet/src/bash/src/parse.y" +#line 963 "/Users/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= CMD_INVERT_RETURN; yyval.command = yyvsp[0].command; - } - break; + ; + break;} case 133: -#line 955 "/usr/homes/chet/src/bash/src/parse.y" +#line 968 "/Users/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number; yyval.command = yyvsp[0].command; - } - break; + ; + break;} case 134: -#line 960 "/usr/homes/chet/src/bash/src/parse.y" +#line 973 "/Users/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-2].number|CMD_INVERT_RETURN; yyval.command = yyvsp[0].command; - } - break; + ; + break;} case 135: -#line 965 "/usr/homes/chet/src/bash/src/parse.y" +#line 978 "/Users/chet/src/bash/src/parse.y" { yyvsp[0].command->flags |= yyvsp[-1].number|CMD_INVERT_RETURN; yyval.command = yyvsp[0].command; - } - break; + ; + break;} case 136: -#line 973 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); } - break; +#line 983 "/Users/chet/src/bash/src/parse.y" +{ + 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; + yyval.command = make_simple_command (x, (COMMAND *)NULL); + yyval.command->flags |= yyvsp[-1].number; + /* XXX - let's cheat and push a newline back */ + if (yyvsp[0].number == '\n') + token_to_read = '\n'; + ; + break;} case 137: -#line 975 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.command = yyvsp[0].command; } - break; +#line 1004 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = command_connect (yyvsp[-3].command, yyvsp[0].command, '|'); ; + break;} case 138: -#line 979 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.number = CMD_TIME_PIPELINE; } - break; +#line 1006 "/Users/chet/src/bash/src/parse.y" +{ yyval.command = yyvsp[0].command; ; + break;} case 139: -#line 981 "/usr/homes/chet/src/bash/src/parse.y" -{ yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; } - break; +#line 1010 "/Users/chet/src/bash/src/parse.y" +{ yyval.number = CMD_TIME_PIPELINE; ; + break;} +case 140: +#line 1012 "/Users/chet/src/bash/src/parse.y" +{ yyval.number = CMD_TIME_PIPELINE|CMD_TIME_POSIX; ; + break;} } - -#line 705 "/usr/local/share/bison/bison.simple" - + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/share/bison.simple" yyvsp -= yylen; yyssp -= yylen; -#if YYLSP_NEEDED +#ifdef YYLSP_NEEDED yylsp -= yylen; #endif -#if YYDEBUG +#if YYDEBUG != 0 if (yydebug) { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; -#if YYLSP_NEEDED - *++yylsp = yyloc; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } #endif - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ yyn = yyr1[yyn]; @@ -2308,13 +2173,10 @@ case 139: goto yynewstate; +yyerrlab: /* here on detecting error */ -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ { ++yynerrs; @@ -2323,121 +2185,102 @@ yyerrlab: if (yyn > YYFLAG && yyn < YYLAST) { - YYSIZE_T yysize = 0; - char *yymsg; - int yyx, yycount; - - yycount = 0; - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) - if (yycheck[yyx + yyn] == yyx) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("parse error, unexpected ") + 1; - yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) { - char *yyp = yystpcpy (yymsg, "parse error, unexpected "); - yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + strcpy(msg, "parse error"); - if (yycount < 5) + if (count < 5) { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) - if (yycheck[yyx + yyn] == yyx) + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); - yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; } } - yyerror (yymsg); - YYSTACK_FREE (yymsg); + yyerror(msg); + free(msg); } else - yyerror ("parse error; also virtual memory exhausted"); + yyerror ("parse error; also virtual memory exceeded"); } else -#endif /* defined (YYERROR_VERBOSE) */ - yyerror ("parse error"); +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); } - goto yyerrlab1; + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ -/*--------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action | -`--------------------------------------------------*/ -yyerrlab1: if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ + /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; - YYDPRINTF ((stderr, "Discarding token %d (%s).\n", - yychar, yytname[yychar1])); + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + yychar = YYEMPTY; } - /* Else will try to reuse lookahead token after shifting the error - token. */ + /* Else will try to reuse lookahead token + after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; +yyerrdefault: /* current state does not do anything special for the error token. */ -/*-------------------------------------------------------------------. -| yyerrdefault -- current state does not do anything special for the | -| error token. | -`-------------------------------------------------------------------*/ -yyerrdefault: #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ - - /* If its default is to accept any token, ok. Otherwise pop it. */ - yyn = yydefact[yystate]; - if (yyn) - goto yydefault; + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; #endif +yyerrpop: /* pop the current state because it cannot handle the error token */ -/*---------------------------------------------------------------. -| yyerrpop -- pop the current state because it cannot handle the | -| error token | -`---------------------------------------------------------------*/ -yyerrpop: - if (yyssp == yyss) - YYABORT; + if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; -#if YYLSP_NEEDED +#ifdef YYLSP_NEEDED yylsp--; #endif -#if YYDEBUG +#if YYDEBUG != 0 if (yydebug) { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "Error: state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); } #endif -/*--------------. -| yyerrhandle. | -`--------------*/ yyerrhandle: + yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; @@ -2460,47 +2303,44 @@ yyerrhandle: if (yyn == YYFINAL) YYACCEPT; - YYDPRINTF ((stderr, "Shifting error token, ")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif *++yyvsp = yylval; -#if YYLSP_NEEDED +#ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -/*---------------------------------------------. -| yyoverflowab -- parser overflow comes here. | -`---------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); - yyresult = 2; - /* Fall through. */ - -yyreturn: -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); #endif - return yyresult; + } + return 1; } -#line 983 "/usr/homes/chet/src/bash/src/parse.y" +#line 1014 "/Users/chet/src/bash/src/parse.y" /* Possible states for the parser that require it to do special things. */ @@ -2517,6 +2357,7 @@ yyreturn: #define PST_ARITHFOR 0x0400 /* parsing an arithmetic for command */ #define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */ #define PST_CMDTOKEN 0x1000 /* command token OK - unused */ +#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */ /* Initial size to allocate for tokens, and the amount to grow them by. */ @@ -2546,13 +2387,6 @@ static int token_before_that; /* The token read prior to token_before_that. */ static int two_tokens_ago; -/* 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; - /* The current parser state. */ static int parser_state; @@ -4219,7 +4053,7 @@ parse_matched_pair (qc, open, close, lenp, flags) if (ch == EOF) { free (ret); - parser_error (start_lineno, "unexpected EOF while looking for matching `%c'", close); + parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close); EOF_Reached = 1; /* XXX */ return (&matched_pair_error); } @@ -4504,16 +4338,16 @@ cond_error () char *etext; if (EOF_Reached && cond_token != COND_ERROR) /* [[ */ - parser_error (cond_lineno, "unexpected EOF while looking for `]]'"); + 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); + 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"); + parser_error (cond_lineno, _("syntax error in conditional expression")); } } @@ -4591,11 +4425,11 @@ cond_term () dispose_cond_node (term); /* ( */ if (etext = error_token_from_token (cond_token)) { - parser_error (lineno, "unexpected token `%s', expected `)'", etext); + parser_error (lineno, _("unexpected token `%s', expected `)'"), etext); free (etext); } else - parser_error (lineno, "expected `)'"); + parser_error (lineno, _("expected `)'")); COND_RETURN_ERROR (); } term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL); @@ -4623,11 +4457,11 @@ cond_term () dispose_word (op); if (etext = error_token_from_token (tok)) { - parser_error (line_number, "unexpected argument `%s' to conditional unary operator", etext); + 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"); + parser_error (line_number, _("unexpected argument to conditional unary operator")); COND_RETURN_ERROR (); } @@ -4664,11 +4498,11 @@ cond_term () { if (etext = error_token_from_token (tok)) { - parser_error (line_number, "unexpected token `%s', conditional binary operator expected", etext); + parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext); free (etext); } else - parser_error (line_number, "conditional binary operator expected"); + parser_error (line_number, _("conditional binary operator expected")); dispose_cond_node (tleft); COND_RETURN_ERROR (); } @@ -4684,11 +4518,11 @@ cond_term () { if (etext = error_token_from_token (tok)) { - parser_error (line_number, "unexpected argument `%s' to conditional binary operator", etext); + 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"); + parser_error (line_number, _("unexpected argument to conditional binary operator")); dispose_cond_node (tleft); dispose_word (op); COND_RETURN_ERROR (); @@ -4699,14 +4533,14 @@ cond_term () else { if (tok < 256) - parser_error (line_number, "unexpected token `%c' in conditional command", tok); + 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); + 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); + parser_error (line_number, _("unexpected token %d in conditional command"), tok); COND_RETURN_ERROR (); } return (term); @@ -4737,7 +4571,7 @@ token_is_assignment (t, i) c = t[i]; c1 = t[i+1]; t[i] = '='; t[i+1] = '\0'; - r = assignment (t); + r = assignment (t, (parser_state & PST_COMPASSIGN) != 0); t[i] = c; t[i+1] = c1; return r; } @@ -5130,11 +4964,11 @@ got_token: /* 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)) + 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)) + if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0) the_word->flags |= W_NOSPLIT; } @@ -5506,7 +5340,11 @@ decode_prompt_string (string) else if (c == 'A') n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm); - timebuf[sizeof(timebuf) - 1] = '\0'; + if (n == 0) + timebuf[0] = '\0'; + else + timebuf[sizeof(timebuf) - 1] = '\0'; + temp = savestring (timebuf); goto add_string; @@ -5531,7 +5369,11 @@ decode_prompt_string (string) n = strftime (timebuf, sizeof (timebuf), timefmt, tm); free (timefmt); - timebuf[sizeof(timebuf) - 1] = '\0'; + 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 @@ -5566,7 +5408,7 @@ decode_prompt_string (string) case 'W': { /* Use the value of PWD because it is much more efficient. */ - char t_string[PATH_MAX]; + char t_string[PATH_MAX], *t; int tlen; temp = get_string_value ("PWD"); @@ -5590,7 +5432,8 @@ decode_prompt_string (string) #define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0) #define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0) - if (c == 'W') + /* Abbreviate \W as ~ if $PWD == $HOME */ + if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, temp) == 0)) { if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0) { @@ -5893,7 +5736,7 @@ report_syntax_error (message) parser's complaining about by looking at current_token. */ if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token))) { - parser_error (line_number, "syntax error near unexpected token `%s'", msg); + parser_error (line_number, _("syntax error near unexpected token `%s'"), msg); free (msg); if (interactive == 0) @@ -5911,7 +5754,7 @@ report_syntax_error (message) msg = error_token_from_text (); if (msg) { - parser_error (line_number, "syntax error near `%s'", msg); + parser_error (line_number, _("syntax error near `%s'"), msg); free (msg); } @@ -5921,7 +5764,7 @@ report_syntax_error (message) } else { - msg = EOF_Reached ? "syntax error: unexpected end of file" : "syntax error"; + 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 @@ -5983,7 +5826,7 @@ handle_eof_input_unit () { if (eof_encountered < eof_encountered_limit) { - fprintf (stderr, "Use \"%s\" to leave the shell.\n", + fprintf (stderr, _("Use \"%s\" to leave the shell.\n"), login_shell ? "logout" : "exit"); eof_encountered++; /* Reset the parsing state. */ @@ -6020,8 +5863,9 @@ 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, whom) +parse_string_to_word_list (s, flags, whom) char *s; + int flags; const char *whom; { WORD_LIST *wl; @@ -6053,6 +5897,10 @@ parse_string_to_word_list (s, whom) with_input_from_string (s, whom); wl = (WORD_LIST *)NULL; + + if (flags & 1) + parser_state |= PST_COMPASSIGN; + while ((tok = read_token (READ)) != yacc_EOF) { if (tok == '\n' && *bash_input.location.string == '\0') @@ -6090,6 +5938,9 @@ parse_string_to_word_list (s, whom) current_command_line_count = orig_line_count; shell_input_line_terminator = orig_input_terminator; + if (flags & 1) + parser_state &= ~PST_COMPASSIGN; + if (wl == &parse_string_error) { last_command_exit_value = EXECUTION_FAILURE; @@ -6120,15 +5971,21 @@ parse_compound_assignment (retlenp) token_buffer_size = 0; wl = (WORD_LIST *)NULL; /* ( */ + parser_state |= PST_COMPASSIGN; + while ((tok = read_token (READ)) != ')') { if (tok == '\n') /* Allow newlines in compound assignments */ - continue; + { + 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 `)'"); + parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'")); else yyerror ((char *)NULL); /* does the right thing */ if (wl) @@ -6143,6 +6000,8 @@ parse_compound_assignment (retlenp) token = saved_token; token_buffer_size = orig_token_size; + parser_state &= ~PST_COMPASSIGN; + if (wl == &parse_string_error) { last_command_exit_value = EXECUTION_FAILURE; diff --git a/y.tab.h b/y.tab.h index 565b039..3527227 100644 --- a/y.tab.h +++ b/y.tab.h @@ -1,7 +1,3 @@ -#ifndef BISON_Y_TAB_H -# define BISON_Y_TAB_H - -#ifndef YYSTYPE typedef union { WORD_DESC *word; /* the word that we read. */ int number; /* the number that we read. */ @@ -10,51 +6,47 @@ typedef union { REDIRECT *redirect; ELEMENT element; PATTERN_LIST *pattern; -} yystype; -# define YYSTYPE yystype -#endif -# define IF 257 -# define THEN 258 -# define ELSE 259 -# define ELIF 260 -# define FI 261 -# define CASE 262 -# define ESAC 263 -# define FOR 264 -# define SELECT 265 -# define WHILE 266 -# define UNTIL 267 -# define DO 268 -# define DONE 269 -# define FUNCTION 270 -# define COND_START 271 -# define COND_END 272 -# define COND_ERROR 273 -# define IN 274 -# define BANG 275 -# define TIME 276 -# define TIMEOPT 277 -# define WORD 278 -# define ASSIGNMENT_WORD 279 -# define NUMBER 280 -# define ARITH_CMD 281 -# define ARITH_FOR_EXPRS 282 -# define COND_CMD 283 -# define AND_AND 284 -# define OR_OR 285 -# define GREATER_GREATER 286 -# define LESS_LESS 287 -# define LESS_AND 288 -# define LESS_LESS_LESS 289 -# define GREATER_AND 290 -# define SEMI_SEMI 291 -# define LESS_LESS_MINUS 292 -# define AND_GREATER 293 -# define LESS_GREATER 294 -# define GREATER_BAR 295 -# define yacc_EOF 296 +} YYSTYPE; +#define IF 257 +#define THEN 258 +#define ELSE 259 +#define ELIF 260 +#define FI 261 +#define CASE 262 +#define ESAC 263 +#define FOR 264 +#define SELECT 265 +#define WHILE 266 +#define UNTIL 267 +#define DO 268 +#define DONE 269 +#define FUNCTION 270 +#define COND_START 271 +#define COND_END 272 +#define COND_ERROR 273 +#define IN 274 +#define BANG 275 +#define TIME 276 +#define TIMEOPT 277 +#define WORD 278 +#define ASSIGNMENT_WORD 279 +#define NUMBER 280 +#define ARITH_CMD 281 +#define ARITH_FOR_EXPRS 282 +#define COND_CMD 283 +#define AND_AND 284 +#define OR_OR 285 +#define GREATER_GREATER 286 +#define LESS_LESS 287 +#define LESS_AND 288 +#define LESS_LESS_LESS 289 +#define GREATER_AND 290 +#define SEMI_SEMI 291 +#define LESS_LESS_MINUS 292 +#define AND_GREATER 293 +#define LESS_GREATER 294 +#define GREATER_BAR 295 +#define yacc_EOF 296 extern YYSTYPE yylval; - -#endif /* not BISON_Y_TAB_H */ -- 2.7.4