From: Chet Ramey Date: Fri, 9 Dec 2011 01:06:56 +0000 (-0500) Subject: commit bash-20090319 snapshot X-Git-Tag: bash-4.3-alpha~235 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c302751c7b9cc559f6d517c7b2ce701a89b8a2da;p=thirdparty%2Fbash.git commit bash-20090319 snapshot --- diff --git a/CHANGES b/CHANGES index 3d71f176b..8724a13bb 100644 --- a/CHANGES +++ b/CHANGES @@ -601,7 +601,7 @@ bb. The command assigned to a key sequence with `bind -x' now sets two new and cursor position by modifying READLINE_LINE_BUFFER and READLINE_POINT, respectively. -cc. There is a new >>& redirection operator, which appends the standard output +cc. There is a new &>> redirection operator, which appends the standard output and standard error to the named file. dd. The parser now understands `|&' as a synonym for `2>&1 |', which redirects diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 7c9ef07d4..ef585c996 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -7710,6 +7710,14 @@ parse.y {.,lib/readline}/doc/fdl.texi - updated to FDL version 1.3 + 3/11 + ---- +parse.y + - when using the |& construct with a simple command preceding it, add + the implicit redirection to the simple command's redirection list, + since the redirections associated with the command struct are never + executed. Fixes bug reported by Matt Zyzik + 3/14 ---- execute_cmd.c @@ -7770,3 +7778,55 @@ subst.c expand_word_internal if $IFS is NULL, just like expand_word_unsplit. It is now virtually identical to expand_word_unsplit. Rest of fix for problems reported by Stephane Chazleas + + 3/20 + ---- +trap.c + - in _run_trap_internal, don't pass SEVAL_RESETLINE as flag to + parse_and_execute if running the ERR trap (further modification + of change from 1/12) + +execute_cmd.c + - in execute_simple_command, set line_number to line_number_for_err_trap + before calling run_error_trap. Part of fix for bug reported by + Brian J. Murrell + - change other places calling run_error_trap() to set and use + line_number_for_err_trap + + 3/21 + ---- +builtins/fc.def + - Even though command substitution through parse_and_execute turns + off remember_on_history, command substitution in a shell when + set -o history has been enabled (interactive or not) should use it + in the last_hist calculation as if it were on. Same calculation + in fc_gethnum and fc_builtin. Fixes bug reported by + + +sig.c + - change termsig_sighandler to terminate immediately if it gets called + twice with the same signal before termsig_handler gets called. This + fixes the `looping on SIGSEGV' phenomenon reported by Linux users. + +parse.y + - in read_secondary_line, don't try to add NULL lines to the history + list. Report and patch from Lubomir Rintel + + 3/22 + ---- +sig.c + - Augment change from 3/21 with explicit check for signals we *don't* + want this to happen for. Patch from Lubomir Rintel + + 3/28 + ---- +array.c + - in array_reference, return NULL immediately if the desired index + is larger than the maximum + - add cache of last array referenced and last array element referenced; + use in array_reference to optimize case of sequential access; + invalidated where necessary in other functions + - array_rshift needs to set max_index to 0 if the array was empty + before shifting in the new element 0 + - array_shift needs to use element_index(a->head->prev) to set the + max_index, not a simple decrement, to deal with sparse arrays diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 315c43c7f..cb5349717 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -7710,6 +7710,14 @@ parse.y {.,lib/readline}/doc/fdl.texi - updated to FDL version 1.3 + 3/11 + ---- +parse.y + - when using the |& construct with a simple command preceding it, add + the implicit redirection to the simple command's redirection list, + since the redirections associated with the command struct are never + executed. Fixes bug reported by Matt Zyzik + 3/14 ---- execute_cmd.c @@ -7764,9 +7772,59 @@ subst.c - param_expand now checks for Q_PATQUOTE and treats it identically to Q_DOUBLE_QUOTES when expanding $* - expand_word_unsplit now sets W_NOSPLIT in the flags of the word it - passes to expand_word_internal + passes to expand_word_internal if $IFS is NULL - expand_word_leave_quoted now sets expand_no_split_dollar_start and the W_NOSPLIT bit in the word flags before calling - expand_word_internal, just like expand_word_unsplit. It is now - virtually identical to expand_word_unsplit. Rest of fix for + expand_word_internal if $IFS is NULL, just like expand_word_unsplit. + It is now virtually identical to expand_word_unsplit. Rest of fix for problems reported by Stephane Chazleas + + 3/20 + ---- +trap.c + - in _run_trap_internal, don't pass SEVAL_RESETLINE as flag to + parse_and_execute if running the ERR trap (further modification + of change from 1/12) + +execute_cmd.c + - in execute_simple_command, set line_number to line_number_for_err_trap + before calling run_error_trap. Part of fix for bug reported by + Brian J. Murrell + - change other places calling run_error_trap() to set and use + line_number_for_err_trap + + 3/21 + ---- +builtins/fc.def + - Even though command substitution through parse_and_execute turns + off remember_on_history, command substitution in a shell when + set -o history has been enabled (interactive or not) should use it + in the last_hist calculation as if it were on. Same calculation + in fc_gethnum and fc_builtin. Fixes bug reported by + + +sig.c + - change termsig_sighandler to terminate immediately if it gets called + twice with the same signal before termsig_handler gets called. This + fixes the `looping on SIGSEGV' phenomenon reported by Linux users. + +parse.y + - in read_secondary_line, don't try to add NULL lines to the history + list. Report and patch from Lubomir Rintel + + 3/22 + ---- +sig.c + - Augment change from 3/21 with explicit check for signals we *don't* + want this to happen for. Patch from Lubomir Rintel + + 3/28 + ---- +array.c + - in array_reference, return NULL immediately if the desired index + is larger than the maximum + - add cache of last array referenced and last array element referenced; + use in array_reference to optimize case of sequential access; + invalidated where necessary in other functions + - array_rshift needs to set max_index to 0 if the array was empty + before shifting in the new element 0 diff --git a/MANIFEST b/MANIFEST index 37276297a..a724e3510 100644 --- a/MANIFEST +++ b/MANIFEST @@ -859,6 +859,7 @@ tests/history.tests f tests/history.right f tests/history.list f 444 tests/history1.sub f +tests/history2.sub f tests/ifs.tests f tests/ifs.right f tests/ifs-posix.tests f @@ -1035,6 +1036,7 @@ tests/trap.right f tests/trap1.sub f 755 tests/trap2.sub f 755 tests/trap2a.sub f 755 +tests/trap3.sub f tests/type.tests f tests/type.right f tests/type1.sub f diff --git a/MANIFEST~ b/MANIFEST~ index d83d286c8..0e6ceb60a 100644 --- a/MANIFEST~ +++ b/MANIFEST~ @@ -798,9 +798,11 @@ tests/dbg-support3.sub f tests/dollar-at-star f tests/dollar-at1.sub f tests/dollar-at2.sub f +tests/dollar-at3.sub f tests/dollar-star1.sub f tests/dollar-star2.sub f tests/dollar-star3.sub f +tests/dollar-star4.sub f tests/dollar.right f tests/dstack.tests f tests/dstack.right f @@ -857,6 +859,7 @@ tests/history.tests f tests/history.right f tests/history.list f 444 tests/history1.sub f +tests/history2.sub f tests/ifs.tests f tests/ifs.right f tests/ifs-posix.tests f diff --git a/array.c b/array.c index a8c7766e1..27fe17083 100644 --- a/array.c +++ b/array.c @@ -55,6 +55,31 @@ static char *array_to_string_internal __P((ARRAY_ELEMENT *, ARRAY_ELEMENT *, char *, int)); +static ARRAY *lastarray = 0; +static ARRAY_ELEMENT *lastref = 0; + +#define IS_LASTREF(a) ((a) == lastarray) + +#define INVALIDATE_LASTREF(a) \ +do { \ + if ((a) == lastarray) { \ + lastarray = 0; \ + lastref = 0; \ + } \ +} while (0) + +#define SET_LASTREF(a, e) \ +do { \ + lastarray = (a); \ + lastref = (e); \ +} while (0) + +#define UNSET_LASTREF() \ +do { \ + lastarray = 0; \ + lastref = 0; \ +} while (0) + ARRAY * array_create() { @@ -87,6 +112,7 @@ ARRAY *a; a->head->next = a->head->prev = a->head; a->max_index = -1; a->num_elements = 0; + INVALIDATE_LASTREF(a); } void @@ -185,6 +211,7 @@ int n, flags; if (a == 0 || array_empty(a) || n <= 0) return ((ARRAY_ELEMENT *)NULL); + INVALIDATE_LASTREF(a); for (i = 0, ret = ae = element_forw(a->head); ae != a->head && i < n; ae = element_forw(ae), i++) ; if (ae == a->head) { @@ -214,7 +241,7 @@ int n, flags; element_index(ae) -= n; /* renumber retained indices */ a->num_elements -= n; /* modify bookkeeping information */ - a->max_index -= n; + a->max_index = element_index(a->head->prev); if (flags & AS_DISPOSE) { for (ae = ret; ae; ) { @@ -251,8 +278,10 @@ char *s; new = array_create_element(0, s); ADD_BEFORE(ae, new); a->num_elements++; - if (array_num_elements(a) == 1) /* array was empty */ + if (array_num_elements(a) == 1) { /* array was empty */ + a->max_index = 0; return 1; + } } /* @@ -263,6 +292,7 @@ char *s; a->max_index = element_index(a->head->prev); + INVALIDATE_LASTREF(a); return (a->num_elements); } @@ -594,6 +624,7 @@ char *v; ADD_BEFORE(a->head, new); a->max_index = i; a->num_elements++; + SET_LASTREF(a, new); return(0); } /* @@ -607,13 +638,16 @@ char *v; array_dispose_element(new); free(element_value(ae)); ae->value = v ? savestring(v) : (char *)NULL; + SET_LASTREF(a, ae); return(0); } else if (element_index(ae) > i) { ADD_BEFORE(ae, new); a->num_elements++; + SET_LASTREF(a, new); return(0); } } + INVALIDATE_LASTREF(a); return (-1); /* problem */ } @@ -637,6 +671,7 @@ arrayind_t i; a->num_elements--; if (i == array_max_index(a)) a->max_index = element_index(ae->prev); + INVALIDATE_LASTREF(a); return(ae); } return((ARRAY_ELEMENT *) NULL); @@ -654,9 +689,19 @@ arrayind_t i; if (a == 0 || array_empty(a)) return((char *) NULL); - for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) - if (element_index(ae) == i) + if (i > array_max_index(a)) + return((char *)NULL); + /* Keep roving pointer into array to optimize sequential access */ + if (lastref && IS_LASTREF(a)) + ae = (i >= element_index(lastref)) ? lastref : element_forw(a->head); + else + ae = element_forw(a->head); + for ( ; ae != a->head; ae = element_forw(ae)) + if (element_index(ae) == i) { + SET_LASTREF(a, ae); return(element_value(ae)); + } + UNSET_LASTREF(); return((char *) NULL); } diff --git a/array.c~ b/array.c~ new file mode 100644 index 000000000..27fe17083 --- /dev/null +++ b/array.c~ @@ -0,0 +1,1130 @@ +/* + * array.c - functions to create, destroy, access, and manipulate arrays + * of strings. + * + * Arrays are sparse doubly-linked lists. An element's index is stored + * with it. + * + * Chet Ramey + * chet@ins.cwru.edu + */ + +/* Copyright (C) 1997-2009 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + +#include "config.h" + +#if defined (ARRAY_VARS) + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include +#include "bashansi.h" + +#include "shell.h" +#include "array.h" +#include "builtins/common.h" + +#define ADD_BEFORE(ae, new) \ + do { \ + ae->prev->next = new; \ + new->prev = ae->prev; \ + ae->prev = new; \ + new->next = ae; \ + } while(0) + +static char *array_to_string_internal __P((ARRAY_ELEMENT *, ARRAY_ELEMENT *, char *, int)); + +static ARRAY *lastarray = 0; +static ARRAY_ELEMENT *lastref = 0; + +#define IS_LASTREF(a) ((a) == lastarray) + +#define INVALIDATE_LASTREF(a) \ +do { \ + if ((a) == lastarray) { \ + lastarray = 0; \ + lastref = 0; \ + } \ +} while (0) + +#define SET_LASTREF(a, e) \ +do { \ + lastarray = (a); \ + lastref = (e); \ +} while (0) + +#define UNSET_LASTREF() \ +do { \ + lastarray = 0; \ + lastref = 0; \ +} while (0) + +ARRAY * +array_create() +{ + ARRAY *r; + ARRAY_ELEMENT *head; + + r =(ARRAY *)xmalloc(sizeof(ARRAY)); + r->type = array_indexed; + r->max_index = -1; + r->num_elements = 0; + head = array_create_element(-1, (char *)NULL); /* dummy head */ + head->prev = head->next = head; + r->head = head; + return(r); +} + +void +array_flush (a) +ARRAY *a; +{ + register ARRAY_ELEMENT *r, *r1; + + if (a == 0) + return; + for (r = element_forw(a->head); r != a->head; ) { + r1 = element_forw(r); + array_dispose_element(r); + r = r1; + } + a->head->next = a->head->prev = a->head; + a->max_index = -1; + a->num_elements = 0; + INVALIDATE_LASTREF(a); +} + +void +array_dispose(a) +ARRAY *a; +{ + if (a == 0) + return; + array_flush (a); + array_dispose_element(a->head); + free(a); +} + +ARRAY * +array_copy(a) +ARRAY *a; +{ + ARRAY *a1; + ARRAY_ELEMENT *ae, *new; + + if (a == 0) + return((ARRAY *) NULL); + a1 = array_create(); + a1->type = a->type; + a1->max_index = a->max_index; + a1->num_elements = a->num_elements; + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) { + new = array_create_element(element_index(ae), element_value(ae)); + ADD_BEFORE(a1->head, new); + } + return(a1); +} + +/* + * Make and return a new array composed of the elements in array A from + * S to E, inclusive. + */ +ARRAY * +array_slice(array, s, e) +ARRAY *array; +ARRAY_ELEMENT *s, *e; +{ + ARRAY *a; + ARRAY_ELEMENT *p, *n; + int i; + arrayind_t mi; + + a = array_create (); + a->type = array->type; + + for (mi = 0, p = s, i = 0; p != e; p = element_forw(p), i++) { + n = array_create_element (element_index(p), element_value(p)); + ADD_BEFORE(a->head, n); + mi = element_index(n); + } + a->num_elements = i; + a->max_index = mi; + return a; +} + +/* + * Walk the array, calling FUNC once for each element, with the array + * element as the argument. + */ +void +array_walk(a, func, udata) +ARRAY *a; +sh_ae_map_func_t *func; +void *udata; +{ + register ARRAY_ELEMENT *ae; + + if (a == 0 || array_empty(a)) + return; + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) + if ((*func)(ae, udata) < 0) + return; +} + +/* + * Shift the array A N elements to the left. Delete the first N elements + * and subtract N from the indices of the remaining elements. If FLAGS + * does not include AS_DISPOSE, this returns a singly-linked null-terminated + * list of elements so the caller can dispose of the chain. If FLAGS + * includes AS_DISPOSE, this function disposes of the shifted-out elements + * and returns NULL. + */ +ARRAY_ELEMENT * +array_shift(a, n, flags) +ARRAY *a; +int n, flags; +{ + register ARRAY_ELEMENT *ae, *ret; + register int i; + + if (a == 0 || array_empty(a) || n <= 0) + return ((ARRAY_ELEMENT *)NULL); + + INVALIDATE_LASTREF(a); + for (i = 0, ret = ae = element_forw(a->head); ae != a->head && i < n; ae = element_forw(ae), i++) + ; + if (ae == a->head) { + /* Easy case; shifting out all of the elements */ + if (flags & AS_DISPOSE) { + array_flush (a); + return ((ARRAY_ELEMENT *)NULL); + } + for (ae = ret; element_forw(ae) != a->head; ae = element_forw(ae)) + ; + element_forw(ae) = (ARRAY_ELEMENT *)NULL; + a->head->next = a->head->prev = a->head; + a->max_index = -1; + a->num_elements = 0; + return ret; + } + /* + * ae now points to the list of elements we want to retain. + * ret points to the list we want to either destroy or return. + */ + ae->prev->next = (ARRAY_ELEMENT *)NULL; /* null-terminate RET */ + + a->head->next = ae; /* slice RET out of the array */ + ae->prev = a->head; + + for ( ; ae != a->head; ae = element_forw(ae)) + element_index(ae) -= n; /* renumber retained indices */ + + a->num_elements -= n; /* modify bookkeeping information */ + a->max_index = element_index(a->head->prev); + + if (flags & AS_DISPOSE) { + for (ae = ret; ae; ) { + ret = element_forw(ae); + array_dispose_element(ae); + ae = ret; + } + return ((ARRAY_ELEMENT *)NULL); + } + + return ret; +} + +/* + * Shift array A right N indices. If S is non-null, it becomes the value of + * the new element 0. Returns the number of elements in the array after the + * shift. + */ +int +array_rshift (a, n, s) +ARRAY *a; +int n; +char *s; +{ + register ARRAY_ELEMENT *ae, *new; + + if (a == 0 || (array_empty(a) && s == 0)) + return 0; + else if (n <= 0) + return (a->num_elements); + + ae = element_forw(a->head); + if (s) { + new = array_create_element(0, s); + ADD_BEFORE(ae, new); + a->num_elements++; + if (array_num_elements(a) == 1) { /* array was empty */ + a->max_index = 0; + return 1; + } + } + + /* + * Renumber all elements in the array except the one we just added. + */ + for ( ; ae != a->head; ae = element_forw(ae)) + element_index(ae) += n; + + a->max_index = element_index(a->head->prev); + + INVALIDATE_LASTREF(a); + return (a->num_elements); +} + +ARRAY_ELEMENT * +array_unshift_element(a) +ARRAY *a; +{ + return (array_shift (a, 1, 0)); +} + +int +array_shift_element(a, v) +ARRAY *a; +char *v; +{ + return (array_rshift (a, 1, v)); +} + +ARRAY * +array_quote(array) +ARRAY *array; +{ + ARRAY_ELEMENT *a; + char *t; + + if (array == 0 || array_head(array) == 0 || array_empty(array)) + return (ARRAY *)NULL; + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) { + t = quote_string (a->value); + FREE(a->value); + a->value = t; + } + return array; +} + +ARRAY * +array_quote_escapes(array) +ARRAY *array; +{ + ARRAY_ELEMENT *a; + char *t; + + if (array == 0 || array_head(array) == 0 || array_empty(array)) + return (ARRAY *)NULL; + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) { + t = quote_escapes (a->value); + FREE(a->value); + a->value = t; + } + return array; +} + +ARRAY * +array_dequote(array) +ARRAY *array; +{ + ARRAY_ELEMENT *a; + char *t; + + if (array == 0 || array_head(array) == 0 || array_empty(array)) + return (ARRAY *)NULL; + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) { + t = dequote_string (a->value); + FREE(a->value); + a->value = t; + } + return array; +} + +ARRAY * +array_dequote_escapes(array) +ARRAY *array; +{ + ARRAY_ELEMENT *a; + char *t; + + if (array == 0 || array_head(array) == 0 || array_empty(array)) + return (ARRAY *)NULL; + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) { + t = dequote_escapes (a->value); + FREE(a->value); + a->value = t; + } + return array; +} + +ARRAY * +array_remove_quoted_nulls(array) +ARRAY *array; +{ + ARRAY_ELEMENT *a; + char *t; + + if (array == 0 || array_head(array) == 0 || array_empty(array)) + return (ARRAY *)NULL; + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) + a->value = remove_quoted_nulls (a->value); + return array; +} + +/* + * Return a string whose elements are the members of array A beginning at + * index START and spanning NELEM members. Null elements are counted. + * Since arrays are sparse, unset array elements are not counted. + */ +char * +array_subrange (a, start, nelem, starsub, quoted) +ARRAY *a; +arrayind_t start, nelem; +int starsub, quoted; +{ + ARRAY *a2; + ARRAY_ELEMENT *h, *p; + arrayind_t i; + char *ifs, *sifs, *t; + int slen; + + p = a ? array_head (a) : 0; + if (p == 0 || array_empty (a) || start > array_max_index(a)) + return ((char *)NULL); + + /* + * Find element with index START. If START corresponds to an unset + * element (arrays can be sparse), use the first element whose index + * is >= START. If START is < 0, we count START indices back from + * the end of A (not elements, even with sparse arrays -- START is an + * index). + */ + for (p = element_forw(p); p != array_head(a) && start > element_index(p); p = element_forw(p)) + ; + + if (p == a->head) + return ((char *)NULL); + + /* Starting at P, take NELEM elements, inclusive. */ + for (i = 0, h = p; p != a->head && i < nelem; i++, p = element_forw(p)) + ; + + a2 = array_slice(a, h, p); + + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) + array_quote(a2); + else + array_quote_escapes(a2); + + if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) { + /* ${array[*]} */ + array_remove_quoted_nulls (a2); + sifs = ifs_firstchar ((int *)NULL); + t = array_to_string (a2, sifs, 0); + free (sifs); + } else if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) { + /* ${array[@]} */ + sifs = ifs_firstchar (&slen); + ifs = getifs (); + if (ifs == 0 || *ifs == 0) { + if (slen < 2) + sifs = xrealloc(sifs, 2); + sifs[0] = ' '; + sifs[1] = '\0'; + } + t = array_to_string (a2, sifs, 0); + free (sifs); + } else + t = array_to_string (a2, " ", 0); + array_dispose(a2); + + return t; +} + +char * +array_patsub (a, pat, rep, mflags) +ARRAY *a; +char *pat, *rep; +int mflags; +{ + ARRAY *a2; + ARRAY_ELEMENT *e; + char *t, *sifs, *ifs; + int slen; + + if (a == 0 || array_head(a) == 0 || array_empty(a)) + return ((char *)NULL); + + a2 = array_copy(a); + for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) { + t = pat_subst(element_value(e), pat, rep, mflags); + FREE(element_value(e)); + e->value = t; + } + + if (mflags & MATCH_QUOTED) + array_quote(a2); + else + array_quote_escapes(a2); + + if (mflags & MATCH_STARSUB) { + array_remove_quoted_nulls (a2); + sifs = ifs_firstchar((int *)NULL); + t = array_to_string (a2, sifs, 0); + free(sifs); + } else if (mflags & MATCH_QUOTED) { + /* ${array[@]} */ + sifs = ifs_firstchar (&slen); + ifs = getifs (); + if (ifs == 0 || *ifs == 0) { + if (slen < 2) + sifs = xrealloc (sifs, 2); + sifs[0] = ' '; + sifs[1] = '\0'; + } + t = array_to_string (a2, sifs, 0); + free(sifs); + } else + t = array_to_string (a2, " ", 0); + array_dispose (a2); + + return t; +} + +char * +array_modcase (a, pat, modop, mflags) +ARRAY *a; +char *pat; +int modop; +int mflags; +{ + ARRAY *a2; + ARRAY_ELEMENT *e; + char *t, *sifs, *ifs; + int slen; + + if (a == 0 || array_head(a) == 0 || array_empty(a)) + return ((char *)NULL); + + a2 = array_copy(a); + for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) { + t = sh_modcase(element_value(e), pat, modop); + FREE(element_value(e)); + e->value = t; + } + + if (mflags & MATCH_QUOTED) + array_quote(a2); + else + array_quote_escapes(a2); + + if (mflags & MATCH_STARSUB) { + array_remove_quoted_nulls (a2); + sifs = ifs_firstchar((int *)NULL); + t = array_to_string (a2, sifs, 0); + free(sifs); + } else if (mflags & MATCH_QUOTED) { + /* ${array[@]} */ + sifs = ifs_firstchar (&slen); + ifs = getifs (); + if (ifs == 0 || *ifs == 0) { + if (slen < 2) + sifs = xrealloc (sifs, 2); + sifs[0] = ' '; + sifs[1] = '\0'; + } + t = array_to_string (a2, sifs, 0); + free(sifs); + } else + t = array_to_string (a2, " ", 0); + array_dispose (a2); + + return t; +} +/* + * Allocate and return a new array element with index INDEX and value + * VALUE. + */ +ARRAY_ELEMENT * +array_create_element(indx, value) +arrayind_t indx; +char *value; +{ + ARRAY_ELEMENT *r; + + r = (ARRAY_ELEMENT *)xmalloc(sizeof(ARRAY_ELEMENT)); + r->ind = indx; + r->value = value ? savestring(value) : (char *)NULL; + r->next = r->prev = (ARRAY_ELEMENT *) NULL; + return(r); +} + +#ifdef INCLUDE_UNUSED +ARRAY_ELEMENT * +array_copy_element(ae) +ARRAY_ELEMENT *ae; +{ + return(ae ? array_create_element(element_index(ae), element_value(ae)) + : (ARRAY_ELEMENT *) NULL); +} +#endif + +void +array_dispose_element(ae) +ARRAY_ELEMENT *ae; +{ + if (ae) { + FREE(ae->value); + free(ae); + } +} + +/* + * Add a new element with index I and value V to array A (a[i] = v). + */ +int +array_insert(a, i, v) +ARRAY *a; +arrayind_t i; +char *v; +{ + register ARRAY_ELEMENT *new, *ae; + + if (a == 0) + return(-1); + new = array_create_element(i, v); + if (i > array_max_index(a)) { + /* + * Hook onto the end. This also works for an empty array. + * Fast path for the common case of allocating arrays + * sequentially. + */ + ADD_BEFORE(a->head, new); + a->max_index = i; + a->num_elements++; + SET_LASTREF(a, new); + return(0); + } + /* + * Otherwise we search for the spot to insert it. + */ + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) { + if (element_index(ae) == i) { + /* + * Replacing an existing element. + */ + array_dispose_element(new); + free(element_value(ae)); + ae->value = v ? savestring(v) : (char *)NULL; + SET_LASTREF(a, ae); + return(0); + } else if (element_index(ae) > i) { + ADD_BEFORE(ae, new); + a->num_elements++; + SET_LASTREF(a, new); + return(0); + } + } + INVALIDATE_LASTREF(a); + return (-1); /* problem */ +} + +/* + * Delete the element with index I from array A and return it so the + * caller can dispose of it. + */ +ARRAY_ELEMENT * +array_remove(a, i) +ARRAY *a; +arrayind_t i; +{ + register ARRAY_ELEMENT *ae; + + if (a == 0 || array_empty(a)) + return((ARRAY_ELEMENT *) NULL); + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) + if (element_index(ae) == i) { + ae->next->prev = ae->prev; + ae->prev->next = ae->next; + a->num_elements--; + if (i == array_max_index(a)) + a->max_index = element_index(ae->prev); + INVALIDATE_LASTREF(a); + return(ae); + } + return((ARRAY_ELEMENT *) NULL); +} + +/* + * Return the value of a[i]. + */ +char * +array_reference(a, i) +ARRAY *a; +arrayind_t i; +{ + register ARRAY_ELEMENT *ae; + + if (a == 0 || array_empty(a)) + return((char *) NULL); + if (i > array_max_index(a)) + return((char *)NULL); + /* Keep roving pointer into array to optimize sequential access */ + if (lastref && IS_LASTREF(a)) + ae = (i >= element_index(lastref)) ? lastref : element_forw(a->head); + else + ae = element_forw(a->head); + for ( ; ae != a->head; ae = element_forw(ae)) + if (element_index(ae) == i) { + SET_LASTREF(a, ae); + return(element_value(ae)); + } + UNSET_LASTREF(); + return((char *) NULL); +} + +/* Convenience routines for the shell to translate to and from the form used + by the rest of the code. */ + +WORD_LIST * +array_to_word_list(a) +ARRAY *a; +{ + WORD_LIST *list; + ARRAY_ELEMENT *ae; + + if (a == 0 || array_empty(a)) + return((WORD_LIST *)NULL); + list = (WORD_LIST *)NULL; + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) + list = make_word_list (make_bare_word(element_value(ae)), list); + return (REVERSE_LIST(list, WORD_LIST *)); +} + +ARRAY * +array_from_word_list (list) +WORD_LIST *list; +{ + ARRAY *a; + + if (list == 0) + return((ARRAY *)NULL); + a = array_create(); + return (array_assign_list (a, list)); +} + +WORD_LIST * +array_keys_to_word_list(a) +ARRAY *a; +{ + WORD_LIST *list; + ARRAY_ELEMENT *ae; + char *t; + + if (a == 0 || array_empty(a)) + return((WORD_LIST *)NULL); + list = (WORD_LIST *)NULL; + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) { + t = itos(element_index(ae)); + list = make_word_list (make_bare_word(t), list); + free(t); + } + return (REVERSE_LIST(list, WORD_LIST *)); +} + +ARRAY * +array_assign_list (array, list) +ARRAY *array; +WORD_LIST *list; +{ + register WORD_LIST *l; + register arrayind_t i; + + for (l = list, i = 0; l; l = l->next, i++) + array_insert(array, i, l->word->word); + return array; +} + +char ** +array_to_argv (a) +ARRAY *a; +{ + char **ret, *t; + int i; + ARRAY_ELEMENT *ae; + + if (a == 0 || array_empty(a)) + return ((char **)NULL); + ret = strvec_create (array_num_elements (a) + 1); + i = 0; + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) { + t = element_value (ae); + ret[i++] = t ? savestring (t) : (char *)NULL; + } + ret[i] = (char *)NULL; + return (ret); +} + +/* + * Return a string that is the concatenation of the elements in A from START + * to END, separated by SEP. + */ +static char * +array_to_string_internal (start, end, sep, quoted) +ARRAY_ELEMENT *start, *end; +char *sep; +int quoted; +{ + char *result, *t; + ARRAY_ELEMENT *ae; + int slen, rsize, rlen, reg; + + if (start == end) /* XXX - should not happen */ + return ((char *)NULL); + + slen = strlen(sep); + result = NULL; + for (rsize = rlen = 0, ae = start; ae != end; ae = element_forw(ae)) { + if (rsize == 0) + result = (char *)xmalloc (rsize = 64); + if (element_value(ae)) { + t = quoted ? quote_string(element_value(ae)) : element_value(ae); + reg = strlen(t); + RESIZE_MALLOCED_BUFFER (result, rlen, (reg + slen + 2), + rsize, rsize); + strcpy(result + rlen, t); + rlen += reg; + if (quoted && t) + free(t); + /* + * Add a separator only after non-null elements. + */ + if (element_forw(ae) != end) { + strcpy(result + rlen, sep); + rlen += slen; + } + } + } + if (result) + result[rlen] = '\0'; /* XXX */ + return(result); +} + +char * +array_to_assign (a, quoted) +ARRAY *a; +int quoted; +{ + char *result, *valstr, *is; + char indstr[INT_STRLEN_BOUND(intmax_t) + 1]; + ARRAY_ELEMENT *ae; + int rsize, rlen, elen; + + if (a == 0 || array_empty (a)) + return((char *)NULL); + + result = (char *)xmalloc (rsize = 128); + result[0] = '('; + rlen = 1; + + for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) { + is = inttostr (element_index(ae), indstr, sizeof(indstr)); + valstr = element_value (ae) ? sh_double_quote (element_value(ae)) + : (char *)NULL; + elen = STRLEN (is) + 8 + STRLEN (valstr); + RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize); + + result[rlen++] = '['; + strcpy (result + rlen, is); + rlen += STRLEN (is); + result[rlen++] = ']'; + result[rlen++] = '='; + if (valstr) { + strcpy (result + rlen, valstr); + rlen += STRLEN (valstr); + } + + if (element_forw(ae) != a->head) + result[rlen++] = ' '; + + FREE (valstr); + } + RESIZE_MALLOCED_BUFFER (result, rlen, 1, rsize, 8); + result[rlen++] = ')'; + result[rlen] = '\0'; + if (quoted) { + /* This is not as efficient as it could be... */ + valstr = sh_single_quote (result); + free (result); + result = valstr; + } + return(result); +} + +char * +array_to_string (a, sep, quoted) +ARRAY *a; +char *sep; +int quoted; +{ + if (a == 0) + return((char *)NULL); + if (array_empty(a)) + return(savestring("")); + return (array_to_string_internal (element_forw(a->head), a->head, sep, quoted)); +} + +#if defined (INCLUDE_UNUSED) || defined (TEST_ARRAY) +/* + * Return an array consisting of elements in S, separated by SEP + */ +ARRAY * +array_from_string(s, sep) +char *s, *sep; +{ + ARRAY *a; + WORD_LIST *w; + + if (s == 0) + return((ARRAY *)NULL); + w = list_string (s, sep, 0); + if (w == 0) + return((ARRAY *)NULL); + a = array_from_word_list (w); + return (a); +} +#endif + +#if defined (TEST_ARRAY) +/* + * To make a running version, compile -DTEST_ARRAY and link with: + * xmalloc.o syntax.o lib/malloc/libmalloc.a lib/sh/libsh.a + */ +int interrupt_immediately = 0; + +int +signal_is_trapped(s) +int s; +{ + return 0; +} + +void +fatal_error(const char *s, ...) +{ + fprintf(stderr, "array_test: fatal memory error\n"); + abort(); +} + +void +programming_error(const char *s, ...) +{ + fprintf(stderr, "array_test: fatal programming error\n"); + abort(); +} + +WORD_DESC * +make_bare_word (s) +const char *s; +{ + WORD_DESC *w; + + w = (WORD_DESC *)xmalloc(sizeof(WORD_DESC)); + w->word = s ? savestring(s) : savestring (""); + w->flags = 0; + return w; +} + +WORD_LIST * +make_word_list(x, l) +WORD_DESC *x; +WORD_LIST *l; +{ + WORD_LIST *w; + + w = (WORD_LIST *)xmalloc(sizeof(WORD_LIST)); + w->word = x; + w->next = l; + return w; +} + +WORD_LIST * +list_string(s, t, i) +char *s, *t; +int i; +{ + char *r, *a; + WORD_LIST *wl; + + if (s == 0) + return (WORD_LIST *)NULL; + r = savestring(s); + wl = (WORD_LIST *)NULL; + a = strtok(r, t); + while (a) { + wl = make_word_list (make_bare_word(a), wl); + a = strtok((char *)NULL, t); + } + return (REVERSE_LIST (wl, WORD_LIST *)); +} + +GENERIC_LIST * +list_reverse (list) +GENERIC_LIST *list; +{ + register GENERIC_LIST *next, *prev; + + for (prev = 0; list; ) { + next = list->next; + list->next = prev; + prev = list; + list = next; + } + return prev; +} + +char * +pat_subst(s, t, u, i) +char *s, *t, *u; +int i; +{ + return ((char *)NULL); +} + +char * +quote_string(s) +char *s; +{ + return savestring(s); +} + +print_element(ae) +ARRAY_ELEMENT *ae; +{ + char lbuf[INT_STRLEN_BOUND (intmax_t) + 1]; + + printf("array[%s] = %s\n", + inttostr (element_index(ae), lbuf, sizeof (lbuf)), + element_value(ae)); +} + +print_array(a) +ARRAY *a; +{ + printf("\n"); + array_walk(a, print_element, (void *)NULL); +} + +main() +{ + ARRAY *a, *new_a, *copy_of_a; + ARRAY_ELEMENT *ae, *aew; + char *s; + + a = array_create(); + array_insert(a, 1, "one"); + array_insert(a, 7, "seven"); + array_insert(a, 4, "four"); + array_insert(a, 1029, "one thousand twenty-nine"); + array_insert(a, 12, "twelve"); + array_insert(a, 42, "forty-two"); + print_array(a); + s = array_to_string (a, " ", 0); + printf("s = %s\n", s); + copy_of_a = array_from_string(s, " "); + printf("copy_of_a:"); + print_array(copy_of_a); + array_dispose(copy_of_a); + printf("\n"); + free(s); + ae = array_remove(a, 4); + array_dispose_element(ae); + ae = array_remove(a, 1029); + array_dispose_element(ae); + array_insert(a, 16, "sixteen"); + print_array(a); + s = array_to_string (a, " ", 0); + printf("s = %s\n", s); + copy_of_a = array_from_string(s, " "); + printf("copy_of_a:"); + print_array(copy_of_a); + array_dispose(copy_of_a); + printf("\n"); + free(s); + array_insert(a, 2, "two"); + array_insert(a, 1029, "new one thousand twenty-nine"); + array_insert(a, 0, "zero"); + array_insert(a, 134, ""); + print_array(a); + s = array_to_string (a, ":", 0); + printf("s = %s\n", s); + copy_of_a = array_from_string(s, ":"); + printf("copy_of_a:"); + print_array(copy_of_a); + array_dispose(copy_of_a); + printf("\n"); + free(s); + new_a = array_copy(a); + print_array(new_a); + s = array_to_string (new_a, ":", 0); + printf("s = %s\n", s); + copy_of_a = array_from_string(s, ":"); + free(s); + printf("copy_of_a:"); + print_array(copy_of_a); + array_shift(copy_of_a, 2, AS_DISPOSE); + printf("copy_of_a shifted by two:"); + print_array(copy_of_a); + ae = array_shift(copy_of_a, 2, 0); + printf("copy_of_a shifted by two:"); + print_array(copy_of_a); + for ( ; ae; ) { + aew = element_forw(ae); + array_dispose_element(ae); + ae = aew; + } + array_rshift(copy_of_a, 1, (char *)0); + printf("copy_of_a rshift by 1:"); + print_array(copy_of_a); + array_rshift(copy_of_a, 2, "new element zero"); + printf("copy_of_a rshift again by 2 with new element zero:"); + print_array(copy_of_a); + s = array_to_assign(copy_of_a, 0); + printf("copy_of_a=%s\n", s); + free(s); + ae = array_shift(copy_of_a, array_num_elements(copy_of_a), 0); + for ( ; ae; ) { + aew = element_forw(ae); + array_dispose_element(ae); + ae = aew; + } + array_dispose(copy_of_a); + printf("\n"); + array_dispose(a); + array_dispose(new_a); +} + +#endif /* TEST_ARRAY */ +#endif /* ARRAY_VARS */ diff --git a/array.h b/array.h index 1080fc980..fb4f789f3 100644 --- a/array.h +++ b/array.h @@ -31,7 +31,8 @@ enum atype {array_indexed, array_assoc}; typedef struct array { enum atype type; - arrayind_t max_index, num_elements; + arrayind_t max_index; + int num_elements; struct array_element *head; } ARRAY; diff --git a/array.h~ b/array.h~ new file mode 100644 index 000000000..1080fc980 --- /dev/null +++ b/array.h~ @@ -0,0 +1,118 @@ +/* array.h -- definitions for the interface exported by array.c that allows + the rest of the shell to manipulate array variables. */ + +/* Copyright (C) 1997-2009 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bash is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bash. If not, see . +*/ + + +#ifndef _ARRAY_H_ +#define _ARRAY_H_ + +#include "stdc.h" + +typedef intmax_t arrayind_t; + +enum atype {array_indexed, array_assoc}; + +typedef struct array { + enum atype type; + arrayind_t max_index, num_elements; + struct array_element *head; +} ARRAY; + +typedef struct array_element { + arrayind_t ind; + char *value; + struct array_element *next, *prev; +} ARRAY_ELEMENT; + +typedef int sh_ae_map_func_t __P((ARRAY_ELEMENT *, void *)); + +/* Basic operations on entire arrays */ +extern ARRAY *array_create __P((void)); +extern void array_flush __P((ARRAY *)); +extern void array_dispose __P((ARRAY *)); +extern ARRAY *array_copy __P((ARRAY *)); +extern ARRAY *array_slice __P((ARRAY *, ARRAY_ELEMENT *, ARRAY_ELEMENT *)); +extern void array_walk __P((ARRAY *, sh_ae_map_func_t *, void *)); + +extern ARRAY_ELEMENT *array_shift __P((ARRAY *, int, int)); +extern int array_rshift __P((ARRAY *, int, char *)); +extern ARRAY_ELEMENT *array_unshift_element __P((ARRAY *)); +extern int array_shift_element __P((ARRAY *, char *)); + +extern ARRAY *array_quote __P((ARRAY *)); +extern ARRAY *array_quote_escapes __P((ARRAY *)); +extern ARRAY *array_dequote __P((ARRAY *)); +extern ARRAY *array_dequote_escapes __P((ARRAY *)); +extern ARRAY *array_remove_quoted_nulls __P((ARRAY *)); + +extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int)); +extern char *array_patsub __P((ARRAY *, char *, char *, int)); +extern char *array_modcase __P((ARRAY *, char *, int, int)); + +/* Basic operations on array elements. */ +extern ARRAY_ELEMENT *array_create_element __P((arrayind_t, char *)); +extern ARRAY_ELEMENT *array_copy_element __P((ARRAY_ELEMENT *)); +extern void array_dispose_element __P((ARRAY_ELEMENT *)); + +extern int array_insert __P((ARRAY *, arrayind_t, char *)); +extern ARRAY_ELEMENT *array_remove __P((ARRAY *, arrayind_t)); +extern char *array_reference __P((ARRAY *, arrayind_t)); + +/* Converting to and from arrays */ +extern WORD_LIST *array_to_word_list __P((ARRAY *)); +extern ARRAY *array_from_word_list __P((WORD_LIST *)); +extern WORD_LIST *array_keys_to_word_list __P((ARRAY *)); + +extern ARRAY *array_assign_list __P((ARRAY *, WORD_LIST *)); + +extern char **array_to_argv __P((ARRAY *)); + +extern char *array_to_assign __P((ARRAY *, int)); +extern char *array_to_string __P((ARRAY *, char *, int)); +extern ARRAY *array_from_string __P((char *, char *)); + +/* Flags for array_shift */ +#define AS_DISPOSE 0x01 + +#define array_num_elements(a) ((a)->num_elements) +#define array_max_index(a) ((a)->max_index) +#define array_head(a) ((a)->head) +#define array_empty(a) ((a)->num_elements == 0) + +#define element_value(ae) ((ae)->value) +#define element_index(ae) ((ae)->ind) +#define element_forw(ae) ((ae)->next) +#define element_back(ae) ((ae)->prev) + +/* Convenience */ +#define array_push(a,v) \ + do { array_rshift ((a), 1, (v)); } while (0) +#define array_pop(a) \ + do { array_dispose_element (array_shift ((a), 1, 0)); } while (0) + +#define GET_ARRAY_FROM_VAR(n, v, a) \ + do { \ + (v) = find_variable (n); \ + (a) = ((v) && array_p ((v))) ? array_cell (v) : (ARRAY *)0; \ + } while (0) + +#define ALL_ELEMENT_SUB(c) ((c) == '@' || (c) == '*') + +#endif /* _ARRAY_H_ */ diff --git a/builtins/fc.def b/builtins/fc.def index 22425d704..a378d9de0 100644 --- a/builtins/fc.def +++ b/builtins/fc.def @@ -88,6 +88,7 @@ extern int errno; extern int current_command_line_count; extern int literal_history; extern int posixly_correct; +extern int subshell_environment, interactive_shell; extern int unlink __P((const char *)); @@ -172,7 +173,7 @@ fc_builtin (list) register int i; register char *sep; int numbering, reverse, listing, execute; - int histbeg, histend, last_hist, retval, opt; + int histbeg, histend, last_hist, retval, opt, rh; FILE *stream; REPL *rlist, *rl; char *ename, *command, *newcom, *fcedit; @@ -275,6 +276,8 @@ fc_builtin (list) fprintf (stderr, "%s\n", command); fc_replhist (command); /* replace `fc -s' with command */ + /* Posix says that the re-executed commands should be entered into the + history. */ return (parse_and_execute (command, "fc", SEVAL_NOHIST)); } @@ -293,7 +296,12 @@ fc_builtin (list) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. */ - last_hist = i - remember_on_history - hist_last_line_added; + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were on. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + last_hist = i - rh - hist_last_line_added; if (list) { @@ -456,7 +464,7 @@ fc_gethnum (command, hlist) char *command; HIST_ENTRY **hlist; { - int sign, n, clen; + int sign, n, clen, rh; register int i, j; register char *s; @@ -472,7 +480,12 @@ fc_gethnum (command, hlist) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. This needs to agree with the calculation of last_hist in fc_builtin above. */ - i -= remember_on_history + hist_last_line_added; + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were on. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + i -= rh + hist_last_line_added; /* No specification defaults to most recent command. */ if (command == NULL) diff --git a/builtins/fc.def.save b/builtins/fc.def.save new file mode 100644 index 000000000..b00e2ccae --- /dev/null +++ b/builtins/fc.def.save @@ -0,0 +1,669 @@ +This file is fc.def, from which is created fc.c. +It implements the builtin "fc" in Bash. + +Copyright (C) 1987-2009 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Bash. If not, see . + +$PRODUCES fc.c + +$BUILTIN fc +$FUNCTION fc_builtin +$DEPENDS_ON HISTORY +$SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command] +Display or execute commands from the history list. + +fc is used to list or edit and re-execute commands from the history list. +FIRST and LAST can be numbers specifying the range, or FIRST can be a +string, which means the most recent command beginning with that +string. + +Options: + -e ENAME select which editor to use. Default is FCEDIT, then EDITOR, + then vi + -l list lines instead of editing + -n omit line numbers when listing + -r reverse the order of the lines (newest listed first) + +With the `fc -s [pat=rep ...] [command]' format, COMMAND is +re-executed after the substitution OLD=NEW is performed. + +A useful alias to use with this is r='fc -s', so that typing `r cc' +runs the last command beginning with `cc' and typing `r' re-executes +the last command. + +Exit Status: +Returns success or status of executed command; non-zero if an error occurs. +$END + +#include + +#if defined (HISTORY) +#ifndef _MINIX +# include +#endif +#include "../bashtypes.h" +#include "posixstat.h" +#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include +#include + +#include "../bashansi.h" +#include "../bashintl.h" +#include + +#include "../shell.h" +#include "../builtins.h" +#include "../flags.h" +#include "../bashhist.h" +#include "maxpath.h" +#include +#include "bashgetopt.h" +#include "common.h" + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int current_command_line_count; +extern int literal_history; +extern int posixly_correct; +extern int subshell_environment, interactive_shell; + +extern int unlink __P((const char *)); + +extern FILE *sh_mktmpfp __P((char *, int, char **)); + +/* **************************************************************** */ +/* */ +/* The K*rn shell style fc command (Fix Command) */ +/* */ +/* **************************************************************** */ + +/* fc builtin command (fix command) for Bash for those who + like K*rn-style history better than csh-style. + + fc [-e ename] [-nlr] [first] [last] + + FIRST and LAST can be numbers specifying the range, or FIRST can be + a string, which means the most recent command beginning with that + string. + + -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR, + then the editor which corresponds to the current readline editing + mode, then vi. + + -l means list lines instead of editing. + -n means no line numbers listed. + -r means reverse the order of the lines (making it newest listed first). + + fc -e - [pat=rep ...] [command] + fc -s [pat=rep ...] [command] + + Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's. +*/ + +/* Data structure describing a list of global replacements to perform. */ +typedef struct repl { + struct repl *next; + char *pat; + char *rep; +} REPL; + +/* Accessors for HIST_ENTRY lists that are called HLIST. */ +#define histline(i) (hlist[(i)]->line) +#define histdata(i) (hlist[(i)]->data) + +#define FREE_RLIST() \ + do { \ + for (rl = rlist; rl; ) { \ + REPL *r; \ + r = rl->next; \ + if (rl->pat) \ + free (rl->pat); \ + if (rl->rep) \ + free (rl->rep); \ + free (rl); \ + rl = r; \ + } \ + } while (0) + +static char *fc_dosubs __P((char *, REPL *)); +static char *fc_gethist __P((char *, HIST_ENTRY **)); +static int fc_gethnum __P((char *, HIST_ENTRY **)); +static int fc_number __P((WORD_LIST *)); +static void fc_replhist __P((char *)); +#ifdef INCLUDE_UNUSED +static char *fc_readline __P((FILE *)); +static void fc_addhist __P((char *)); +#endif + +/* String to execute on a file that we want to edit. */ +#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}" +#if defined (STRICT_POSIX) +# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}" +#else +# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}" +#endif + +int +fc_builtin (list) + WORD_LIST *list; +{ + register int i; + register char *sep; + int numbering, reverse, listing, execute; + int histbeg, histend, last_hist, retval, opt, rh; + FILE *stream; + REPL *rlist, *rl; + char *ename, *command, *newcom, *fcedit; + HIST_ENTRY **hlist; + char *fn; + + numbering = 1; + reverse = listing = execute = 0; + ename = (char *)NULL; + + /* Parse out the options and set which of the two forms we're in. */ + reset_internal_getopt (); + lcurrent = list; /* XXX */ + while (fc_number (loptend = lcurrent) == 0 && + (opt = internal_getopt (list, ":e:lnrs")) != -1) + { + switch (opt) + { + case 'n': + numbering = 0; + break; + + case 'l': + listing = 1; + break; + + case 'r': + reverse = 1; + break; + + case 's': + execute = 1; + break; + + case 'e': + ename = list_optarg; + break; + + default: + builtin_usage (); + return (EX_USAGE); + } + } + + list = loptend; + + if (ename && (*ename == '-') && (ename[1] == '\0')) + execute = 1; + + /* The "execute" form of the command (re-run, with possible string + substitutions). */ + if (execute) + { + rlist = (REPL *)NULL; + while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL)) + { + *sep++ = '\0'; + rl = (REPL *)xmalloc (sizeof (REPL)); + rl->next = (REPL *)NULL; + rl->pat = savestring (list->word->word); + rl->rep = savestring (sep); + + if (rlist == NULL) + rlist = rl; + else + { + rl->next = rlist; + rlist = rl; + } + list = list->next; + } + + /* If we have a list of substitutions to do, then reverse it + to get the replacements in the proper order. */ + + rlist = REVERSE_LIST (rlist, REPL *); + + hlist = history_list (); + + /* If we still have something in list, it is a command spec. + Otherwise, we use the most recent command in time. */ + command = fc_gethist (list ? list->word->word : (char *)NULL, hlist); + + if (command == NULL) + { + builtin_error (_("no command found")); + if (rlist) + FREE_RLIST (); + + return (EXECUTION_FAILURE); + } + + if (rlist) + { + newcom = fc_dosubs (command, rlist); + free (command); + FREE_RLIST (); + command = newcom; + } + + fprintf (stderr, "%s\n", command); + fc_replhist (command); /* replace `fc -s' with command */ + /* Posix says that the re-executed commands should be entered into the + history. */ + return (parse_and_execute (command, "fc", SEVAL_NOHIST)); + } + + /* This is the second form of the command (the list-or-edit-and-rerun + form). */ + hlist = history_list (); + if (hlist == 0) + return (EXECUTION_SUCCESS); + for (i = 0; hlist[i]; i++); + + /* With the Bash implementation of history, the current command line + ("fc blah..." and so on) is already part of the history list by + the time we get to this point. This just skips over that command + and makes the last command that this deals with be the last command + the user entered before the fc. We need to check whether the + line was actually added (HISTIGNORE may have caused it to not be), + so we check hist_last_line_added. */ + + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + last_hist = i - rh - hist_last_line_added; +itrace("fc: last_hist = %d i = %d rh = %d hist_last_line_added = %d", last_hist, i, rh, hist_last_line_added); +itrace("fc: enable_history_list = %d subshell_environment = %d interactive_shell = %d", enable_history_list, subshell_environment, interactive_shell); + + if (list) + { + histbeg = fc_gethnum (list->word->word, hlist); + list = list->next; + + if (list) + histend = fc_gethnum (list->word->word, hlist); + else + histend = listing ? last_hist : histbeg; + } + else + { + /* The default for listing is the last 16 history items. */ + if (listing) + { + histend = last_hist; + histbeg = histend - 16 + 1; /* +1 because loop below uses >= */ + if (histbeg < 0) + histbeg = 0; + } + else + /* For editing, it is the last history command. */ + histbeg = histend = last_hist; + } + +itrace("fc: histbeg = %d histend = %d", histbeg, histend); + + /* "When not listing, the fc command that caused the editing shall not be + entered into the history list." */ + if (listing == 0 && hist_last_line_added) + { + bash_delete_last_history (); + /* If we're editing a single command -- the last command in the + history -- and we just removed the dummy command added by + edit_and_execute_command (), we need to check whether or not we + just removed the last command in the history and need to back + the pointer up. remember_on_history is off because we're running + in parse_and_execute(). */ + if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0) + last_hist = histbeg = --histend; + } + + /* We print error messages for line specifications out of range. */ + if ((histbeg < 0) || (histend < 0)) + { + sh_erange ((char *)NULL, _("history specification")); + return (EXECUTION_FAILURE); + } + + if (histend < histbeg) + { + i = histend; + histend = histbeg; + histbeg = i; + + reverse = 1; + } + + if (listing) + stream = stdout; + else + { + numbering = 0; + stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn); + if (stream == 0) + { + builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno)); + FREE (fn); + return (EXECUTION_FAILURE); + } + } + + for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++) + { + QUIT; + if (numbering) + fprintf (stream, "%d", i + history_base); + if (listing) + { + if (posixly_correct) + fputs ("\t", stream); + else + fprintf (stream, "\t%c", histdata (i) ? '*' : ' '); + } + fprintf (stream, "%s\n", histline (i)); + } + + if (listing) + return (sh_chkwrite (EXECUTION_SUCCESS)); + + fflush (stream); + if (ferror (stream)) + { + sh_wrerror (); + fclose (stream); + return (EXECUTION_FAILURE); + } + fclose (stream); + + /* Now edit the file of commands. */ + if (ename) + { + command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2); + sprintf (command, "%s %s", ename, fn); + } + else + { + fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND; + command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn)); + sprintf (command, "%s %s", fcedit, fn); + } + retval = parse_and_execute (command, "fc", SEVAL_NOHIST); + if (retval != EXECUTION_SUCCESS) + { + unlink (fn); + free (fn); + return (EXECUTION_FAILURE); + } + + /* Make sure parse_and_execute doesn't turn this off, even though a + call to parse_and_execute farther up the function call stack (e.g., + if this is called by vi_edit_and_execute_command) may have already + called bash_history_disable. */ + remember_on_history = 1; + + /* Turn on the `v' flag while fc_execute_file runs so the commands + will be echoed as they are read by the parser. */ + begin_unwind_frame ("fc builtin"); + add_unwind_protect ((Function *)xfree, fn); + add_unwind_protect (unlink, fn); + unwind_protect_int (echo_input_at_read); + echo_input_at_read = 1; + + retval = fc_execute_file (fn); + + run_unwind_frame ("fc builtin"); + + return (retval); +} + +/* Return 1 if LIST->word->word is a legal number for fc's use. */ +static int +fc_number (list) + WORD_LIST *list; +{ + char *s; + + if (list == 0) + return 0; + s = list->word->word; + if (*s == '-') + s++; + return (legal_number (s, (intmax_t *)NULL)); +} + +/* Return an absolute index into HLIST which corresponds to COMMAND. If + COMMAND is a number, then it was specified in relative terms. If it + is a string, then it is the start of a command line present in HLIST. */ +static int +fc_gethnum (command, hlist) + char *command; + HIST_ENTRY **hlist; +{ + int sign, n, clen, rh; + register int i, j; + register char *s; + + sign = 1; + /* Count history elements. */ + for (i = 0; hlist[i]; i++); + + /* With the Bash implementation of history, the current command line + ("fc blah..." and so on) is already part of the history list by + the time we get to this point. This just skips over that command + and makes the last command that this deals with be the last command + the user entered before the fc. We need to check whether the + line was actually added (HISTIGNORE may have caused it to not be), + so we check hist_last_line_added. This needs to agree with the + calculation of last_hist in fc_builtin above. */ + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + i -= rh + hist_last_line_added; + + /* No specification defaults to most recent command. */ + if (command == NULL) + return (i); + + /* Otherwise, there is a specification. It can be a number relative to + the current position, or an absolute history number. */ + s = command; + + /* Handle possible leading minus sign. */ + if (s && (*s == '-')) + { + sign = -1; + s++; + } + + if (s && DIGIT(*s)) + { + n = atoi (s); + n *= sign; + + /* If the value is negative or zero, then it is an offset from + the current history item. */ + if (n < 0) + { + n += i + 1; + return (n < 0 ? 0 : n); + } + else if (n == 0) + return (i); + else + { + n -= history_base; + return (i < n ? i : n); + } + } + + clen = strlen (command); + for (j = i; j >= 0; j--) + { + if (STREQN (command, histline (j), clen)) + return (j); + } + return (-1); +} + +/* Locate the most recent history line which begins with + COMMAND in HLIST, and return a malloc()'ed copy of it. */ +static char * +fc_gethist (command, hlist) + char *command; + HIST_ENTRY **hlist; +{ + int i; + + if (hlist == 0) + return ((char *)NULL); + + i = fc_gethnum (command, hlist); + + if (i >= 0) + return (savestring (histline (i))); + else + return ((char *)NULL); +} + +#ifdef INCLUDE_UNUSED +/* Read the edited history lines from STREAM and return them + one at a time. This can read unlimited length lines. The + caller should free the storage. */ +static char * +fc_readline (stream) + FILE *stream; +{ + register int c; + int line_len = 0, lindex = 0; + char *line = (char *)NULL; + + while ((c = getc (stream)) != EOF) + { + if ((lindex + 2) >= line_len) + line = (char *)xrealloc (line, (line_len += 128)); + + if (c == '\n') + { + line[lindex++] = '\n'; + line[lindex++] = '\0'; + return (line); + } + else + line[lindex++] = c; + } + + if (!lindex) + { + if (line) + free (line); + + return ((char *)NULL); + } + + if (lindex + 2 >= line_len) + line = (char *)xrealloc (line, lindex + 3); + + line[lindex++] = '\n'; /* Finish with newline if none in file */ + line[lindex++] = '\0'; + return (line); +} +#endif + +/* Perform the SUBS on COMMAND. + SUBS is a list of substitutions, and COMMAND is a simple string. + Return a pointer to a malloc'ed string which contains the substituted + command. */ +static char * +fc_dosubs (command, subs) + char *command; + REPL *subs; +{ + register char *new, *t; + register REPL *r; + + for (new = savestring (command), r = subs; r; r = r->next) + { + t = strsub (new, r->pat, r->rep, 1); + free (new); + new = t; + } + return (new); +} + +/* Use `command' to replace the last entry in the history list, which, + by this time, is `fc blah...'. The intent is that the new command + become the history entry, and that `fc' should never appear in the + history list. This way you can do `r' to your heart's content. */ +static void +fc_replhist (command) + char *command; +{ + int n; + + if (command == 0 || *command == '\0') + return; + + n = strlen (command); + if (command[n - 1] == '\n') + command[n - 1] = '\0'; + + if (command && *command) + { + bash_delete_last_history (); + maybe_add_history (command); /* Obeys HISTCONTROL setting. */ + } +} + +#ifdef INCLUDE_UNUSED +/* Add LINE to the history, after removing a single trailing newline. */ +static void +fc_addhist (line) + char *line; +{ + register int n; + + if (line == 0 || *line == 0) + return; + + n = strlen (line); + + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + if (line && *line) + maybe_add_history (line); /* Obeys HISTCONTROL setting. */ +} +#endif + +#endif /* HISTORY */ diff --git a/builtins/fc.def~ b/builtins/fc.def~ new file mode 100644 index 000000000..d8c8c23a8 --- /dev/null +++ b/builtins/fc.def~ @@ -0,0 +1,665 @@ +This file is fc.def, from which is created fc.c. +It implements the builtin "fc" in Bash. + +Copyright (C) 1987-2009 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Bash is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Bash. If not, see . + +$PRODUCES fc.c + +$BUILTIN fc +$FUNCTION fc_builtin +$DEPENDS_ON HISTORY +$SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command] +Display or execute commands from the history list. + +fc is used to list or edit and re-execute commands from the history list. +FIRST and LAST can be numbers specifying the range, or FIRST can be a +string, which means the most recent command beginning with that +string. + +Options: + -e ENAME select which editor to use. Default is FCEDIT, then EDITOR, + then vi + -l list lines instead of editing + -n omit line numbers when listing + -r reverse the order of the lines (newest listed first) + +With the `fc -s [pat=rep ...] [command]' format, COMMAND is +re-executed after the substitution OLD=NEW is performed. + +A useful alias to use with this is r='fc -s', so that typing `r cc' +runs the last command beginning with `cc' and typing `r' re-executes +the last command. + +Exit Status: +Returns success or status of executed command; non-zero if an error occurs. +$END + +#include + +#if defined (HISTORY) +#ifndef _MINIX +# include +#endif +#include "../bashtypes.h" +#include "posixstat.h" +#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H) +# include +#endif + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include +#include + +#include "../bashansi.h" +#include "../bashintl.h" +#include + +#include "../shell.h" +#include "../builtins.h" +#include "../flags.h" +#include "../bashhist.h" +#include "maxpath.h" +#include +#include "bashgetopt.h" +#include "common.h" + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int current_command_line_count; +extern int literal_history; +extern int posixly_correct; +extern int subshell_environment, interactive_shell; + +extern int unlink __P((const char *)); + +extern FILE *sh_mktmpfp __P((char *, int, char **)); + +/* **************************************************************** */ +/* */ +/* The K*rn shell style fc command (Fix Command) */ +/* */ +/* **************************************************************** */ + +/* fc builtin command (fix command) for Bash for those who + like K*rn-style history better than csh-style. + + fc [-e ename] [-nlr] [first] [last] + + FIRST and LAST can be numbers specifying the range, or FIRST can be + a string, which means the most recent command beginning with that + string. + + -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR, + then the editor which corresponds to the current readline editing + mode, then vi. + + -l means list lines instead of editing. + -n means no line numbers listed. + -r means reverse the order of the lines (making it newest listed first). + + fc -e - [pat=rep ...] [command] + fc -s [pat=rep ...] [command] + + Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's. +*/ + +/* Data structure describing a list of global replacements to perform. */ +typedef struct repl { + struct repl *next; + char *pat; + char *rep; +} REPL; + +/* Accessors for HIST_ENTRY lists that are called HLIST. */ +#define histline(i) (hlist[(i)]->line) +#define histdata(i) (hlist[(i)]->data) + +#define FREE_RLIST() \ + do { \ + for (rl = rlist; rl; ) { \ + REPL *r; \ + r = rl->next; \ + if (rl->pat) \ + free (rl->pat); \ + if (rl->rep) \ + free (rl->rep); \ + free (rl); \ + rl = r; \ + } \ + } while (0) + +static char *fc_dosubs __P((char *, REPL *)); +static char *fc_gethist __P((char *, HIST_ENTRY **)); +static int fc_gethnum __P((char *, HIST_ENTRY **)); +static int fc_number __P((WORD_LIST *)); +static void fc_replhist __P((char *)); +#ifdef INCLUDE_UNUSED +static char *fc_readline __P((FILE *)); +static void fc_addhist __P((char *)); +#endif + +/* String to execute on a file that we want to edit. */ +#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}" +#if defined (STRICT_POSIX) +# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}" +#else +# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}" +#endif + +int +fc_builtin (list) + WORD_LIST *list; +{ + register int i; + register char *sep; + int numbering, reverse, listing, execute; + int histbeg, histend, last_hist, retval, opt, rh; + FILE *stream; + REPL *rlist, *rl; + char *ename, *command, *newcom, *fcedit; + HIST_ENTRY **hlist; + char *fn; + + numbering = 1; + reverse = listing = execute = 0; + ename = (char *)NULL; + + /* Parse out the options and set which of the two forms we're in. */ + reset_internal_getopt (); + lcurrent = list; /* XXX */ + while (fc_number (loptend = lcurrent) == 0 && + (opt = internal_getopt (list, ":e:lnrs")) != -1) + { + switch (opt) + { + case 'n': + numbering = 0; + break; + + case 'l': + listing = 1; + break; + + case 'r': + reverse = 1; + break; + + case 's': + execute = 1; + break; + + case 'e': + ename = list_optarg; + break; + + default: + builtin_usage (); + return (EX_USAGE); + } + } + + list = loptend; + + if (ename && (*ename == '-') && (ename[1] == '\0')) + execute = 1; + + /* The "execute" form of the command (re-run, with possible string + substitutions). */ + if (execute) + { + rlist = (REPL *)NULL; + while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL)) + { + *sep++ = '\0'; + rl = (REPL *)xmalloc (sizeof (REPL)); + rl->next = (REPL *)NULL; + rl->pat = savestring (list->word->word); + rl->rep = savestring (sep); + + if (rlist == NULL) + rlist = rl; + else + { + rl->next = rlist; + rlist = rl; + } + list = list->next; + } + + /* If we have a list of substitutions to do, then reverse it + to get the replacements in the proper order. */ + + rlist = REVERSE_LIST (rlist, REPL *); + + hlist = history_list (); + + /* If we still have something in list, it is a command spec. + Otherwise, we use the most recent command in time. */ + command = fc_gethist (list ? list->word->word : (char *)NULL, hlist); + + if (command == NULL) + { + builtin_error (_("no command found")); + if (rlist) + FREE_RLIST (); + + return (EXECUTION_FAILURE); + } + + if (rlist) + { + newcom = fc_dosubs (command, rlist); + free (command); + FREE_RLIST (); + command = newcom; + } + + fprintf (stderr, "%s\n", command); + fc_replhist (command); /* replace `fc -s' with command */ + /* Posix says that the re-executed commands should be entered into the + history. */ + return (parse_and_execute (command, "fc", SEVAL_NOHIST)); + } + + /* This is the second form of the command (the list-or-edit-and-rerun + form). */ + hlist = history_list (); + if (hlist == 0) + return (EXECUTION_SUCCESS); + for (i = 0; hlist[i]; i++); + + /* With the Bash implementation of history, the current command line + ("fc blah..." and so on) is already part of the history list by + the time we get to this point. This just skips over that command + and makes the last command that this deals with be the last command + the user entered before the fc. We need to check whether the + line was actually added (HISTIGNORE may have caused it to not be), + so we check hist_last_line_added. */ + + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + last_hist = i - rh - hist_last_line_added; + + if (list) + { + histbeg = fc_gethnum (list->word->word, hlist); + list = list->next; + + if (list) + histend = fc_gethnum (list->word->word, hlist); + else + histend = listing ? last_hist : histbeg; + } + else + { + /* The default for listing is the last 16 history items. */ + if (listing) + { + histend = last_hist; + histbeg = histend - 16 + 1; /* +1 because loop below uses >= */ + if (histbeg < 0) + histbeg = 0; + } + else + /* For editing, it is the last history command. */ + histbeg = histend = last_hist; + } + + /* "When not listing, the fc command that caused the editing shall not be + entered into the history list." */ + if (listing == 0 && hist_last_line_added) + { + bash_delete_last_history (); + /* If we're editing a single command -- the last command in the + history -- and we just removed the dummy command added by + edit_and_execute_command (), we need to check whether or not we + just removed the last command in the history and need to back + the pointer up. remember_on_history is off because we're running + in parse_and_execute(). */ + if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0) + last_hist = histbeg = --histend; + } + + /* We print error messages for line specifications out of range. */ + if ((histbeg < 0) || (histend < 0)) + { + sh_erange ((char *)NULL, _("history specification")); + return (EXECUTION_FAILURE); + } + + if (histend < histbeg) + { + i = histend; + histend = histbeg; + histbeg = i; + + reverse = 1; + } + + if (listing) + stream = stdout; + else + { + numbering = 0; + stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn); + if (stream == 0) + { + builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno)); + FREE (fn); + return (EXECUTION_FAILURE); + } + } + + for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++) + { + QUIT; + if (numbering) + fprintf (stream, "%d", i + history_base); + if (listing) + { + if (posixly_correct) + fputs ("\t", stream); + else + fprintf (stream, "\t%c", histdata (i) ? '*' : ' '); + } + fprintf (stream, "%s\n", histline (i)); + } + + if (listing) + return (sh_chkwrite (EXECUTION_SUCCESS)); + + fflush (stream); + if (ferror (stream)) + { + sh_wrerror (); + fclose (stream); + return (EXECUTION_FAILURE); + } + fclose (stream); + + /* Now edit the file of commands. */ + if (ename) + { + command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2); + sprintf (command, "%s %s", ename, fn); + } + else + { + fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND; + command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn)); + sprintf (command, "%s %s", fcedit, fn); + } + retval = parse_and_execute (command, "fc", SEVAL_NOHIST); + if (retval != EXECUTION_SUCCESS) + { + unlink (fn); + free (fn); + return (EXECUTION_FAILURE); + } + + /* Make sure parse_and_execute doesn't turn this off, even though a + call to parse_and_execute farther up the function call stack (e.g., + if this is called by vi_edit_and_execute_command) may have already + called bash_history_disable. */ + remember_on_history = 1; + + /* Turn on the `v' flag while fc_execute_file runs so the commands + will be echoed as they are read by the parser. */ + begin_unwind_frame ("fc builtin"); + add_unwind_protect ((Function *)xfree, fn); + add_unwind_protect (unlink, fn); + unwind_protect_int (echo_input_at_read); + echo_input_at_read = 1; + + retval = fc_execute_file (fn); + + run_unwind_frame ("fc builtin"); + + return (retval); +} + +/* Return 1 if LIST->word->word is a legal number for fc's use. */ +static int +fc_number (list) + WORD_LIST *list; +{ + char *s; + + if (list == 0) + return 0; + s = list->word->word; + if (*s == '-') + s++; + return (legal_number (s, (intmax_t *)NULL)); +} + +/* Return an absolute index into HLIST which corresponds to COMMAND. If + COMMAND is a number, then it was specified in relative terms. If it + is a string, then it is the start of a command line present in HLIST. */ +static int +fc_gethnum (command, hlist) + char *command; + HIST_ENTRY **hlist; +{ + int sign, n, clen, rh; + register int i, j; + register char *s; + + sign = 1; + /* Count history elements. */ + for (i = 0; hlist[i]; i++); + + /* With the Bash implementation of history, the current command line + ("fc blah..." and so on) is already part of the history list by + the time we get to this point. This just skips over that command + and makes the last command that this deals with be the last command + the user entered before the fc. We need to check whether the + line was actually added (HISTIGNORE may have caused it to not be), + so we check hist_last_line_added. This needs to agree with the + calculation of last_hist in fc_builtin above. */ + /* Even though command substitution through parse_and_execute turns off + remember_on_history, command substitution in a shell when set -o history + has been enabled (interactive or not) should use it in the last_hist + calculation as if it were. */ + rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list); + i -= rh + hist_last_line_added; + + /* No specification defaults to most recent command. */ + if (command == NULL) + return (i); + + /* Otherwise, there is a specification. It can be a number relative to + the current position, or an absolute history number. */ + s = command; + + /* Handle possible leading minus sign. */ + if (s && (*s == '-')) + { + sign = -1; + s++; + } + + if (s && DIGIT(*s)) + { + n = atoi (s); + n *= sign; + + /* If the value is negative or zero, then it is an offset from + the current history item. */ + if (n < 0) + { + n += i + 1; + return (n < 0 ? 0 : n); + } + else if (n == 0) + return (i); + else + { + n -= history_base; + return (i < n ? i : n); + } + } + + clen = strlen (command); + for (j = i; j >= 0; j--) + { + if (STREQN (command, histline (j), clen)) + return (j); + } + return (-1); +} + +/* Locate the most recent history line which begins with + COMMAND in HLIST, and return a malloc()'ed copy of it. */ +static char * +fc_gethist (command, hlist) + char *command; + HIST_ENTRY **hlist; +{ + int i; + + if (hlist == 0) + return ((char *)NULL); + + i = fc_gethnum (command, hlist); + + if (i >= 0) + return (savestring (histline (i))); + else + return ((char *)NULL); +} + +#ifdef INCLUDE_UNUSED +/* Read the edited history lines from STREAM and return them + one at a time. This can read unlimited length lines. The + caller should free the storage. */ +static char * +fc_readline (stream) + FILE *stream; +{ + register int c; + int line_len = 0, lindex = 0; + char *line = (char *)NULL; + + while ((c = getc (stream)) != EOF) + { + if ((lindex + 2) >= line_len) + line = (char *)xrealloc (line, (line_len += 128)); + + if (c == '\n') + { + line[lindex++] = '\n'; + line[lindex++] = '\0'; + return (line); + } + else + line[lindex++] = c; + } + + if (!lindex) + { + if (line) + free (line); + + return ((char *)NULL); + } + + if (lindex + 2 >= line_len) + line = (char *)xrealloc (line, lindex + 3); + + line[lindex++] = '\n'; /* Finish with newline if none in file */ + line[lindex++] = '\0'; + return (line); +} +#endif + +/* Perform the SUBS on COMMAND. + SUBS is a list of substitutions, and COMMAND is a simple string. + Return a pointer to a malloc'ed string which contains the substituted + command. */ +static char * +fc_dosubs (command, subs) + char *command; + REPL *subs; +{ + register char *new, *t; + register REPL *r; + + for (new = savestring (command), r = subs; r; r = r->next) + { + t = strsub (new, r->pat, r->rep, 1); + free (new); + new = t; + } + return (new); +} + +/* Use `command' to replace the last entry in the history list, which, + by this time, is `fc blah...'. The intent is that the new command + become the history entry, and that `fc' should never appear in the + history list. This way you can do `r' to your heart's content. */ +static void +fc_replhist (command) + char *command; +{ + int n; + + if (command == 0 || *command == '\0') + return; + + n = strlen (command); + if (command[n - 1] == '\n') + command[n - 1] = '\0'; + + if (command && *command) + { + bash_delete_last_history (); + maybe_add_history (command); /* Obeys HISTCONTROL setting. */ + } +} + +#ifdef INCLUDE_UNUSED +/* Add LINE to the history, after removing a single trailing newline. */ +static void +fc_addhist (line) + char *line; +{ + register int n; + + if (line == 0 || *line == 0) + return; + + n = strlen (line); + + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + if (line && *line) + maybe_add_history (line); /* Obeys HISTCONTROL setting. */ +} +#endif + +#endif /* HISTORY */ diff --git a/ddd1 b/ddd1 index bf5f5d199..7674dc451 100644 --- a/ddd1 +++ b/ddd1 @@ -1,205 +1,118 @@ -*** ../bash-4.0-patched/parse.y 2009-03-08 21:24:47.000000000 -0400 ---- parse.y 2009-03-14 20:24:51.000000000 -0400 +*** array.c 2009-03-29 17:21:09.000000000 -0400 +--- array.c.save3 2009-03-28 18:16:49.000000000 -0400 *************** -*** 260,263 **** ---- 260,266 ---- - int current_token; +*** 56,59 **** +--- 56,84 ---- + static char *array_to_string_internal __P((ARRAY_ELEMENT *, ARRAY_ELEMENT *, char *, int)); -+ /* The current parser state. */ -+ int parser_state; ++ static ARRAY *lastarray = 0; ++ static ARRAY_ELEMENT *lastref = 0; + - /* Variables to manage the task of reading here documents, because we need to - defer the reading until after a complete command has been collected. */ -*************** -*** 284,290 **** - static int arith_for_lineno; - -- /* The current parser state. */ -- static int parser_state; -- - /* The last read token, or NULL. read_token () uses this for context - checking. */ ---- 287,290 ---- -*************** -*** 1123,1127 **** - REDIRECT *r; - -! tc = $1; - rd.dest = 1; - r = make_redirection (2, r_duplicating_output, rd); ---- 1123,1127 ---- - REDIRECT *r; - -! tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1; - rd.dest = 1; - r = make_redirection (2, r_duplicating_output, rd); -*************** -*** 2397,2401 **** - - #define command_token_position(token) \ -! (((token) == ASSIGNMENT_WORD) || \ - ((token) != SEMI_SEMI && (token) != SEMI_AND && (token) != SEMI_SEMI_AND && reserved_word_acceptable(token))) - ---- 2397,2401 ---- - - #define command_token_position(token) \ -! (((token) == ASSIGNMENT_WORD) || (parser_state&PST_REDIRLIST) || \ - ((token) != SEMI_SEMI && (token) != SEMI_AND && (token) != SEMI_SEMI_AND && reserved_word_acceptable(token))) - ++ #define IS_LASTREF(a) ((a) == lastarray) ++ ++ #define INVALIDATE_LASTREF(a) \ ++ do { \ ++ if ((a) == lastarray) { \ ++ lastarray = 0; \ ++ lastref = 0; \ ++ } \ ++ } while (0) ++ ++ #define SET_LASTREF(a, e) \ ++ do { \ ++ lastarray = (a); \ ++ lastref = (e); \ ++ } while (0) ++ ++ #define UNSET_LASTREF() \ ++ do { \ ++ lastarray = 0; \ ++ lastref = 0; \ ++ } while (0) ++ + ARRAY * + array_create() *************** -*** 2968,2972 **** - int retind, retsize, rflags; - -! /* itrace("parse_matched_pair: open = %c close = %c flags = %d", open, close, flags); */ - count = 1; - tflags = 0; ---- 2968,2972 ---- - int retind, retsize, rflags; +*** 88,91 **** +--- 113,117 ---- + a->max_index = -1; + a->num_elements = 0; ++ INVALIDATE_LASTREF(a); + } -! /*itrace("parse_matched_pair: open = %c close = %c flags = %d", open, close, flags); */ - count = 1; - tflags = 0; *************** -*** 3263,3266 **** ---- 3263,3283 ---- - prompt_again (); +*** 186,189 **** +--- 212,216 ---- + return ((ARRAY_ELEMENT *)NULL); -+ /* XXX -- possibly allow here doc to be delimited by ending right -+ paren. */ -+ if ((tflags & LEX_INHEREDOC) && ch == close && count == 1) -+ { -+ int tind; -+ /*itrace("parse_comsub: in here doc, ch == close, retind - firstind = %d hdlen = %d retind = %d", retind-lex_firstind, hdlen, retind);*/ -+ tind = lex_firstind; -+ while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t') -+ tind++; -+ if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen)) -+ { -+ tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC); -+ /*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/ -+ lex_firstind = -1; -+ } -+ } -+ - /* Don't bother counting parens or doing anything else if in a comment */ - if (tflags & (LEX_INCOMMENT|LEX_INHEREDOC)) ++ INVALIDATE_LASTREF(a); + for (i = 0, ret = ae = element_forw(a->head); ae != a->head && i < n; ae = element_forw(ae), i++) + ; *************** -*** 3271,3275 **** ---- 3288,3295 ---- - - if ((tflags & LEX_INCOMMENT) && ch == '\n') -+ { -+ /*itrace("parse_comsub:%d: lex_incomment -> 0 ch = `%c'", line_number, ch);*/ - tflags &= ~LEX_INCOMMENT; -+ } +*** 264,267 **** +--- 291,295 ---- + a->max_index = element_index(a->head->prev); - continue; -*************** -*** 3365,3369 **** - RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64); - ret[retind++] = peekc; -! /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch); */ - tflags |= LEX_RESWDOK; - lex_rwlen = 0; ---- 3385,3389 ---- - RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64); - ret[retind++] = peekc; -! /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/ - tflags |= LEX_RESWDOK; - lex_rwlen = 0; -*************** -*** 3373,3378 **** - { - shell_ungetc (peekc); -- tflags |= LEX_RESWDOK; - /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/ - lex_rwlen = 0; - continue; ---- 3393,3398 ---- - { - shell_ungetc (peekc); - /*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/ -+ tflags |= LEX_RESWDOK; - lex_rwlen = 0; - continue; -*************** -*** 3404,3413 **** - { - tflags |= LEX_INCASE; -! /*itrace("parse_comsub:%d: found `case', lex_incase -> 1", line_number);*/ - } - else if (STREQN (ret + retind - 4, "esac", 4)) - { - tflags &= ~LEX_INCASE; -! /*itrace("parse_comsub:%d: found `esac', lex_incase -> 0", line_number);*/ - } - tflags &= ~LEX_RESWDOK; ---- 3424,3433 ---- - { - tflags |= LEX_INCASE; -! /*itrace("parse_comsub:%d: found `case', lex_incase -> 1 lex_reswdok -> 0", line_number);*/ ++ INVALIDATE_LASTREF(a); + return (a->num_elements); } - else if (STREQN (ret + retind - 4, "esac", 4)) - { - tflags &= ~LEX_INCASE; -! /*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 0", line_number);*/ - } - tflags &= ~LEX_RESWDOK; *************** -*** 3432,3435 **** ---- 3452,3456 ---- +*** 595,598 **** +--- 623,627 ---- + a->max_index = i; + a->num_elements++; ++ SET_LASTREF(a, new); + return(0); } - -+ /* Might be the start of a here-doc delimiter */ - if MBTEST((tflags & LEX_INCOMMENT) == 0 && (tflags & LEX_CKCASE) && ch == '<') - { *************** -*** 3488,3492 **** ---- 3509,3516 ---- +*** 608,618 **** +--- 637,650 ---- + free(element_value(ae)); + ae->value = v ? savestring(v) : (char *)NULL; ++ SET_LASTREF(a, ae); + return(0); + } else if (element_index(ae) > i) { + ADD_BEFORE(ae, new); + a->num_elements++; ++ SET_LASTREF(a, new); + return(0); + } + } ++ INVALIDATE_LASTREF(a); + return (-1); /* problem */ } - else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && (tflags & LEX_INCASE) == 0 && ch == open) /* nested begin */ -+ { - count++; -+ /*itrace("parse_comsub:%d: found open: count = %d", line_number, count);*/ -+ } - - /* Add this character. */ -*************** -*** 5232,5236 **** - if (interactive && EOF_Reached) - EOF_Reached = 0; -! last_command_exit_value = EX_USAGE; - return; - } ---- 5256,5260 ---- - if (interactive && EOF_Reached) - EOF_Reached = 0; -! last_command_exit_value = EX_BADUSAGE; - return; - } *************** -*** 5247,5251 **** - print_offending_line (); - -! last_command_exit_value = EX_USAGE; - return; - } ---- 5271,5275 ---- - print_offending_line (); - -! last_command_exit_value = EX_BADUSAGE; - return; - } +*** 638,641 **** +--- 670,674 ---- + if (i == array_max_index(a)) + a->max_index = element_index(ae->prev); ++ INVALIDATE_LASTREF(a); + return(ae); + } *************** -*** 5278,5282 **** - } - -! last_command_exit_value = EX_USAGE; +*** 655,661 **** + if (a == 0 || array_empty(a)) + return((char *) NULL); +! for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) +! if (element_index(ae) == i) + return(element_value(ae)); + return((char *) NULL); } - ---- 5302,5306 ---- - } - -! last_command_exit_value = EX_BADUSAGE; +--- 688,704 ---- + if (a == 0 || array_empty(a)) + return((char *) NULL); +! if (i > array_max_index(a)) +! return ((char *)NULL); +! /* Keep roving pointer into array to optimize sequential access */ +! if (lastref && IS_LASTREF(a)) +! ae = (i >= element_index(lastref)) ? lastref : element_forw(a->head); +! else +! ae = element_forw(a->head); +! for ( ; ae != a->head; ae = element_forw(ae)) +! if (element_index(ae) == i) { +! SET_LASTREF(a, ae); + return(element_value(ae)); ++ } ++ UNSET_LASTREF(); + return((char *) NULL); } - diff --git a/doc/bash.pdf b/doc/bash.pdf index 563daf148..e7da49017 100644 Binary files a/doc/bash.pdf and b/doc/bash.pdf differ diff --git a/doc/bashref.aux b/doc/bashref.aux index 2648c6296..9d4dfbafc 100644 --- a/doc/bashref.aux +++ b/doc/bashref.aux @@ -1,378 +1,378 @@ @xrdef{Introduction-title}{Introduction} -@xrdef{Introduction-pg}{1} @xrdef{Introduction-snt}{Chapter@tie 1} @xrdef{What is Bash?-title}{What is Bash?} -@xrdef{What is Bash?-pg}{1} @xrdef{What is Bash?-snt}{Section@tie 1.1} @xrdef{What is a shell?-title}{What is a shell?} -@xrdef{What is a shell?-pg}{1} @xrdef{What is a shell?-snt}{Section@tie 1.2} +@xrdef{Introduction-pg}{1} +@xrdef{What is Bash?-pg}{1} +@xrdef{What is a shell?-pg}{1} @xrdef{Definitions-title}{Definitions} -@xrdef{Definitions-pg}{3} @xrdef{Definitions-snt}{Chapter@tie 2} +@xrdef{Definitions-pg}{3} @xrdef{Basic Shell Features-title}{Basic Shell Features} -@xrdef{Basic Shell Features-pg}{5} @xrdef{Basic Shell Features-snt}{Chapter@tie 3} @xrdef{Shell Syntax-title}{Shell Syntax} -@xrdef{Shell Syntax-pg}{5} @xrdef{Shell Syntax-snt}{Section@tie 3.1} @xrdef{Shell Operation-title}{Shell Operation} -@xrdef{Shell Operation-pg}{5} @xrdef{Shell Operation-snt}{Section@tie 3.1.1} @xrdef{Quoting-title}{Quoting} -@xrdef{Quoting-pg}{6} @xrdef{Quoting-snt}{Section@tie 3.1.2} +@xrdef{Basic Shell Features-pg}{5} +@xrdef{Shell Syntax-pg}{5} +@xrdef{Shell Operation-pg}{5} @xrdef{Escape Character-title}{Escape Character} -@xrdef{Escape Character-pg}{6} @xrdef{Escape Character-snt}{Section@tie 3.1.2.1} @xrdef{Single Quotes-title}{Single Quotes} -@xrdef{Single Quotes-pg}{6} @xrdef{Single Quotes-snt}{Section@tie 3.1.2.2} @xrdef{Double Quotes-title}{Double Quotes} -@xrdef{Double Quotes-pg}{6} @xrdef{Double Quotes-snt}{Section@tie 3.1.2.3} @xrdef{ANSI-C Quoting-title}{ANSI-C Quoting} -@xrdef{ANSI-C Quoting-pg}{6} @xrdef{ANSI-C Quoting-snt}{Section@tie 3.1.2.4} +@xrdef{Quoting-pg}{6} +@xrdef{Escape Character-pg}{6} +@xrdef{Single Quotes-pg}{6} +@xrdef{Double Quotes-pg}{6} +@xrdef{ANSI-C Quoting-pg}{6} @xrdef{Locale Translation-title}{Locale-Specific Translation} -@xrdef{Locale Translation-pg}{7} @xrdef{Locale Translation-snt}{Section@tie 3.1.2.5} @xrdef{Comments-title}{Comments} -@xrdef{Comments-pg}{7} @xrdef{Comments-snt}{Section@tie 3.1.3} @xrdef{Shell Commands-title}{Shell Commands} -@xrdef{Shell Commands-pg}{8} @xrdef{Shell Commands-snt}{Section@tie 3.2} @xrdef{Simple Commands-title}{Simple Commands} -@xrdef{Simple Commands-pg}{8} @xrdef{Simple Commands-snt}{Section@tie 3.2.1} +@xrdef{Locale Translation-pg}{7} +@xrdef{Comments-pg}{7} +@xrdef{Shell Commands-pg}{7} @xrdef{Pipelines-title}{Pipelines} -@xrdef{Pipelines-pg}{8} @xrdef{Pipelines-snt}{Section@tie 3.2.2} @xrdef{Lists-title}{Lists of Commands} -@xrdef{Lists-pg}{9} @xrdef{Lists-snt}{Section@tie 3.2.3} +@xrdef{Simple Commands-pg}{8} +@xrdef{Pipelines-pg}{8} +@xrdef{Lists-pg}{8} @xrdef{Compound Commands-title}{Compound Commands} -@xrdef{Compound Commands-pg}{9} @xrdef{Compound Commands-snt}{Section@tie 3.2.4} @xrdef{Looping Constructs-title}{Looping Constructs} -@xrdef{Looping Constructs-pg}{10} @xrdef{Looping Constructs-snt}{Section@tie 3.2.4.1} +@xrdef{Compound Commands-pg}{9} +@xrdef{Looping Constructs-pg}{9} @xrdef{Conditional Constructs-title}{Conditional Constructs} -@xrdef{Conditional Constructs-pg}{10} @xrdef{Conditional Constructs-snt}{Section@tie 3.2.4.2} +@xrdef{Conditional Constructs-pg}{10} @xrdef{Command Grouping-title}{Grouping Commands} -@xrdef{Command Grouping-pg}{13} @xrdef{Command Grouping-snt}{Section@tie 3.2.4.3} @xrdef{Coprocesses-title}{Coprocesses} -@xrdef{Coprocesses-pg}{14} @xrdef{Coprocesses-snt}{Section@tie 3.2.5} +@xrdef{Command Grouping-pg}{13} +@xrdef{Coprocesses-pg}{13} @xrdef{Shell Functions-title}{Shell Functions} -@xrdef{Shell Functions-pg}{14} @xrdef{Shell Functions-snt}{Section@tie 3.3} +@xrdef{Shell Functions-pg}{14} @xrdef{Shell Parameters-title}{Shell Parameters} -@xrdef{Shell Parameters-pg}{16} @xrdef{Shell Parameters-snt}{Section@tie 3.4} +@xrdef{Shell Parameters-pg}{15} @xrdef{Positional Parameters-title}{Positional Parameters} -@xrdef{Positional Parameters-pg}{16} @xrdef{Positional Parameters-snt}{Section@tie 3.4.1} @xrdef{Special Parameters-title}{Special Parameters} -@xrdef{Special Parameters-pg}{17} @xrdef{Special Parameters-snt}{Section@tie 3.4.2} +@xrdef{Positional Parameters-pg}{16} +@xrdef{Special Parameters-pg}{16} @xrdef{Shell Expansions-title}{Shell Expansions} -@xrdef{Shell Expansions-pg}{17} @xrdef{Shell Expansions-snt}{Section@tie 3.5} @xrdef{Brace Expansion-title}{Brace Expansion} -@xrdef{Brace Expansion-pg}{18} @xrdef{Brace Expansion-snt}{Section@tie 3.5.1} +@xrdef{Shell Expansions-pg}{17} @xrdef{Tilde Expansion-title}{Tilde Expansion} -@xrdef{Tilde Expansion-pg}{19} @xrdef{Tilde Expansion-snt}{Section@tie 3.5.2} +@xrdef{Brace Expansion-pg}{18} +@xrdef{Tilde Expansion-pg}{18} @xrdef{Shell Parameter Expansion-title}{Shell Parameter Expansion} -@xrdef{Shell Parameter Expansion-pg}{20} @xrdef{Shell Parameter Expansion-snt}{Section@tie 3.5.3} +@xrdef{Shell Parameter Expansion-pg}{19} @xrdef{Command Substitution-title}{Command Substitution} -@xrdef{Command Substitution-pg}{23} @xrdef{Command Substitution-snt}{Section@tie 3.5.4} @xrdef{Arithmetic Expansion-title}{Arithmetic Expansion} -@xrdef{Arithmetic Expansion-pg}{23} @xrdef{Arithmetic Expansion-snt}{Section@tie 3.5.5} +@xrdef{Command Substitution-pg}{22} @xrdef{Process Substitution-title}{Process Substitution} -@xrdef{Process Substitution-pg}{23} @xrdef{Process Substitution-snt}{Section@tie 3.5.6} @xrdef{Word Splitting-title}{Word Splitting} -@xrdef{Word Splitting-pg}{24} @xrdef{Word Splitting-snt}{Section@tie 3.5.7} @xrdef{Filename Expansion-title}{Filename Expansion} -@xrdef{Filename Expansion-pg}{24} @xrdef{Filename Expansion-snt}{Section@tie 3.5.8} +@xrdef{Arithmetic Expansion-pg}{23} +@xrdef{Process Substitution-pg}{23} +@xrdef{Word Splitting-pg}{23} @xrdef{Pattern Matching-title}{Pattern Matching} -@xrdef{Pattern Matching-pg}{25} @xrdef{Pattern Matching-snt}{Section@tie 3.5.8.1} +@xrdef{Filename Expansion-pg}{24} +@xrdef{Pattern Matching-pg}{24} @xrdef{Quote Removal-title}{Quote Removal} -@xrdef{Quote Removal-pg}{26} @xrdef{Quote Removal-snt}{Section@tie 3.5.9} @xrdef{Redirections-title}{Redirections} -@xrdef{Redirections-pg}{26} @xrdef{Redirections-snt}{Section@tie 3.6} +@xrdef{Quote Removal-pg}{25} +@xrdef{Redirections-pg}{25} @xrdef{Executing Commands-title}{Executing Commands} -@xrdef{Executing Commands-pg}{30} @xrdef{Executing Commands-snt}{Section@tie 3.7} @xrdef{Simple Command Expansion-title}{Simple Command Expansion} -@xrdef{Simple Command Expansion-pg}{30} @xrdef{Simple Command Expansion-snt}{Section@tie 3.7.1} @xrdef{Command Search and Execution-title}{Command Search and Execution} -@xrdef{Command Search and Execution-pg}{30} @xrdef{Command Search and Execution-snt}{Section@tie 3.7.2} +@xrdef{Executing Commands-pg}{29} +@xrdef{Simple Command Expansion-pg}{29} +@xrdef{Command Search and Execution-pg}{29} @xrdef{Command Execution Environment-title}{Command Execution Environment} -@xrdef{Command Execution Environment-pg}{31} @xrdef{Command Execution Environment-snt}{Section@tie 3.7.3} +@xrdef{Command Execution Environment-pg}{30} @xrdef{Environment-title}{Environment} -@xrdef{Environment-pg}{32} @xrdef{Environment-snt}{Section@tie 3.7.4} @xrdef{Exit Status-title}{Exit Status} -@xrdef{Exit Status-pg}{33} @xrdef{Exit Status-snt}{Section@tie 3.7.5} +@xrdef{Environment-pg}{31} +@xrdef{Exit Status-pg}{31} @xrdef{Signals-title}{Signals} -@xrdef{Signals-pg}{33} @xrdef{Signals-snt}{Section@tie 3.7.6} @xrdef{Shell Scripts-title}{Shell Scripts} -@xrdef{Shell Scripts-pg}{34} @xrdef{Shell Scripts-snt}{Section@tie 3.8} +@xrdef{Signals-pg}{32} +@xrdef{Shell Scripts-pg}{33} @xrdef{Shell Builtin Commands-title}{Shell Builtin Commands} -@xrdef{Shell Builtin Commands-pg}{35} @xrdef{Shell Builtin Commands-snt}{Chapter@tie 4} @xrdef{Bourne Shell Builtins-title}{Bourne Shell Builtins} -@xrdef{Bourne Shell Builtins-pg}{35} @xrdef{Bourne Shell Builtins-snt}{Section@tie 4.1} +@xrdef{Shell Builtin Commands-pg}{35} +@xrdef{Bourne Shell Builtins-pg}{35} @xrdef{Bash Builtins-title}{Bash Builtin Commands} -@xrdef{Bash Builtins-pg}{41} @xrdef{Bash Builtins-snt}{Section@tie 4.2} +@xrdef{Bash Builtins-pg}{41} @xrdef{Modifying Shell Behavior-title}{Modifying Shell Behavior} -@xrdef{Modifying Shell Behavior-pg}{51} @xrdef{Modifying Shell Behavior-snt}{Section@tie 4.3} @xrdef{The Set Builtin-title}{The Set Builtin} -@xrdef{The Set Builtin-pg}{51} @xrdef{The Set Builtin-snt}{Section@tie 4.3.1} +@xrdef{Modifying Shell Behavior-pg}{51} +@xrdef{The Set Builtin-pg}{51} @xrdef{The Shopt Builtin-title}{The Shopt Builtin} -@xrdef{The Shopt Builtin-pg}{55} @xrdef{The Shopt Builtin-snt}{Section@tie 4.3.2} +@xrdef{The Shopt Builtin-pg}{55} @xrdef{Special Builtins-title}{Special Builtins} -@xrdef{Special Builtins-pg}{59} @xrdef{Special Builtins-snt}{Section@tie 4.4} +@xrdef{Special Builtins-pg}{59} @xrdef{Shell Variables-title}{Shell Variables} -@xrdef{Shell Variables-pg}{61} @xrdef{Shell Variables-snt}{Chapter@tie 5} @xrdef{Bourne Shell Variables-title}{Bourne Shell Variables} -@xrdef{Bourne Shell Variables-pg}{61} @xrdef{Bourne Shell Variables-snt}{Section@tie 5.1} @xrdef{Bash Variables-title}{Bash Variables} -@xrdef{Bash Variables-pg}{61} @xrdef{Bash Variables-snt}{Section@tie 5.2} +@xrdef{Shell Variables-pg}{61} +@xrdef{Bourne Shell Variables-pg}{61} +@xrdef{Bash Variables-pg}{61} @xrdef{Bash Features-title}{Bash Features} -@xrdef{Bash Features-pg}{71} @xrdef{Bash Features-snt}{Chapter@tie 6} @xrdef{Invoking Bash-title}{Invoking Bash} -@xrdef{Invoking Bash-pg}{71} @xrdef{Invoking Bash-snt}{Section@tie 6.1} +@xrdef{Bash Features-pg}{71} +@xrdef{Invoking Bash-pg}{71} @xrdef{Bash Startup Files-title}{Bash Startup Files} -@xrdef{Bash Startup Files-pg}{73} @xrdef{Bash Startup Files-snt}{Section@tie 6.2} +@xrdef{Bash Startup Files-pg}{73} @xrdef{Interactive Shells-title}{Interactive Shells} -@xrdef{Interactive Shells-pg}{75} @xrdef{Interactive Shells-snt}{Section@tie 6.3} @xrdef{What is an Interactive Shell?-title}{What is an Interactive Shell?} -@xrdef{What is an Interactive Shell?-pg}{75} @xrdef{What is an Interactive Shell?-snt}{Section@tie 6.3.1} +@xrdef{Interactive Shells-pg}{74} @xrdef{Is this Shell Interactive?-title}{Is this Shell Interactive?} -@xrdef{Is this Shell Interactive?-pg}{75} @xrdef{Is this Shell Interactive?-snt}{Section@tie 6.3.2} @xrdef{Interactive Shell Behavior-title}{Interactive Shell Behavior} -@xrdef{Interactive Shell Behavior-pg}{75} @xrdef{Interactive Shell Behavior-snt}{Section@tie 6.3.3} +@xrdef{What is an Interactive Shell?-pg}{75} +@xrdef{Is this Shell Interactive?-pg}{75} +@xrdef{Interactive Shell Behavior-pg}{75} @xrdef{Bash Conditional Expressions-title}{Bash Conditional Expressions} -@xrdef{Bash Conditional Expressions-pg}{77} @xrdef{Bash Conditional Expressions-snt}{Section@tie 6.4} +@xrdef{Bash Conditional Expressions-pg}{76} @xrdef{Shell Arithmetic-title}{Shell Arithmetic} -@xrdef{Shell Arithmetic-pg}{78} @xrdef{Shell Arithmetic-snt}{Section@tie 6.5} +@xrdef{Shell Arithmetic-pg}{78} @xrdef{Aliases-title}{Aliases} -@xrdef{Aliases-pg}{79} @xrdef{Aliases-snt}{Section@tie 6.6} +@xrdef{Aliases-pg}{79} @xrdef{Arrays-title}{Arrays} -@xrdef{Arrays-pg}{80} @xrdef{Arrays-snt}{Section@tie 6.7} +@xrdef{Arrays-pg}{80} @xrdef{The Directory Stack-title}{The Directory Stack} -@xrdef{The Directory Stack-pg}{81} @xrdef{The Directory Stack-snt}{Section@tie 6.8} @xrdef{Directory Stack Builtins-title}{Directory Stack Builtins} -@xrdef{Directory Stack Builtins-pg}{82} @xrdef{Directory Stack Builtins-snt}{Section@tie 6.8.1} +@xrdef{The Directory Stack-pg}{81} +@xrdef{Directory Stack Builtins-pg}{81} @xrdef{Printing a Prompt-title}{Controlling the Prompt} -@xrdef{Printing a Prompt-pg}{83} @xrdef{Printing a Prompt-snt}{Section@tie 6.9} +@xrdef{Printing a Prompt-pg}{82} @xrdef{The Restricted Shell-title}{The Restricted Shell} -@xrdef{The Restricted Shell-pg}{84} @xrdef{The Restricted Shell-snt}{Section@tie 6.10} @xrdef{Bash POSIX Mode-title}{Bash POSIX Mode} -@xrdef{Bash POSIX Mode-pg}{85} @xrdef{Bash POSIX Mode-snt}{Section@tie 6.11} +@xrdef{The Restricted Shell-pg}{84} +@xrdef{Bash POSIX Mode-pg}{84} @xrdef{Job Control-title}{Job Control} -@xrdef{Job Control-pg}{89} @xrdef{Job Control-snt}{Chapter@tie 7} @xrdef{Job Control Basics-title}{Job Control Basics} -@xrdef{Job Control Basics-pg}{89} @xrdef{Job Control Basics-snt}{Section@tie 7.1} +@xrdef{Job Control-pg}{87} +@xrdef{Job Control Basics-pg}{87} @xrdef{Job Control Builtins-title}{Job Control Builtins} -@xrdef{Job Control Builtins-pg}{90} @xrdef{Job Control Builtins-snt}{Section@tie 7.2} +@xrdef{Job Control Builtins-pg}{88} @xrdef{Job Control Variables-title}{Job Control Variables} -@xrdef{Job Control Variables-pg}{92} @xrdef{Job Control Variables-snt}{Section@tie 7.3} +@xrdef{Job Control Variables-pg}{90} @xrdef{Command Line Editing-title}{Command Line Editing} -@xrdef{Command Line Editing-pg}{93} @xrdef{Command Line Editing-snt}{Chapter@tie 8} @xrdef{Introduction and Notation-title}{Introduction to Line Editing} -@xrdef{Introduction and Notation-pg}{93} @xrdef{Introduction and Notation-snt}{Section@tie 8.1} @xrdef{Readline Interaction-title}{Readline Interaction} -@xrdef{Readline Interaction-pg}{93} @xrdef{Readline Interaction-snt}{Section@tie 8.2} @xrdef{Readline Bare Essentials-title}{Readline Bare Essentials} -@xrdef{Readline Bare Essentials-pg}{94} @xrdef{Readline Bare Essentials-snt}{Section@tie 8.2.1} +@xrdef{Command Line Editing-pg}{91} +@xrdef{Introduction and Notation-pg}{91} +@xrdef{Readline Interaction-pg}{91} @xrdef{Readline Movement Commands-title}{Readline Movement Commands} -@xrdef{Readline Movement Commands-pg}{94} @xrdef{Readline Movement Commands-snt}{Section@tie 8.2.2} @xrdef{Readline Killing Commands-title}{Readline Killing Commands} -@xrdef{Readline Killing Commands-pg}{95} @xrdef{Readline Killing Commands-snt}{Section@tie 8.2.3} +@xrdef{Readline Bare Essentials-pg}{92} +@xrdef{Readline Movement Commands-pg}{92} @xrdef{Readline Arguments-title}{Readline Arguments} -@xrdef{Readline Arguments-pg}{95} @xrdef{Readline Arguments-snt}{Section@tie 8.2.4} @xrdef{Searching-title}{Searching for Commands in the History} -@xrdef{Searching-pg}{96} @xrdef{Searching-snt}{Section@tie 8.2.5} +@xrdef{Readline Killing Commands-pg}{93} +@xrdef{Readline Arguments-pg}{93} +@xrdef{Searching-pg}{93} @xrdef{Readline Init File-title}{Readline Init File} -@xrdef{Readline Init File-pg}{96} @xrdef{Readline Init File-snt}{Section@tie 8.3} @xrdef{Readline Init File Syntax-title}{Readline Init File Syntax} -@xrdef{Readline Init File Syntax-pg}{96} @xrdef{Readline Init File Syntax-snt}{Section@tie 8.3.1} +@xrdef{Readline Init File-pg}{94} +@xrdef{Readline Init File Syntax-pg}{94} @xrdef{Conditional Init Constructs-title}{Conditional Init Constructs} -@xrdef{Conditional Init Constructs-pg}{102} @xrdef{Conditional Init Constructs-snt}{Section@tie 8.3.2} @xrdef{Sample Init File-title}{Sample Init File} -@xrdef{Sample Init File-pg}{103} @xrdef{Sample Init File-snt}{Section@tie 8.3.3} +@xrdef{Conditional Init Constructs-pg}{100} +@xrdef{Sample Init File-pg}{100} @xrdef{Bindable Readline Commands-title}{Bindable Readline Commands} -@xrdef{Bindable Readline Commands-pg}{106} @xrdef{Bindable Readline Commands-snt}{Section@tie 8.4} @xrdef{Commands For Moving-title}{Commands For Moving} -@xrdef{Commands For Moving-pg}{106} @xrdef{Commands For Moving-snt}{Section@tie 8.4.1} @xrdef{Commands For History-title}{Commands For Manipulating The History} -@xrdef{Commands For History-pg}{107} @xrdef{Commands For History-snt}{Section@tie 8.4.2} +@xrdef{Bindable Readline Commands-pg}{103} +@xrdef{Commands For Moving-pg}{103} +@xrdef{Commands For History-pg}{104} @xrdef{Commands For Text-title}{Commands For Changing Text} -@xrdef{Commands For Text-pg}{108} @xrdef{Commands For Text-snt}{Section@tie 8.4.3} +@xrdef{Commands For Text-pg}{105} @xrdef{Commands For Killing-title}{Killing And Yanking} -@xrdef{Commands For Killing-pg}{109} @xrdef{Commands For Killing-snt}{Section@tie 8.4.4} +@xrdef{Commands For Killing-pg}{106} @xrdef{Numeric Arguments-title}{Specifying Numeric Arguments} -@xrdef{Numeric Arguments-pg}{110} @xrdef{Numeric Arguments-snt}{Section@tie 8.4.5} @xrdef{Commands For Completion-title}{Letting Readline Type For You} -@xrdef{Commands For Completion-pg}{110} @xrdef{Commands For Completion-snt}{Section@tie 8.4.6} +@xrdef{Numeric Arguments-pg}{107} +@xrdef{Commands For Completion-pg}{107} @xrdef{Keyboard Macros-title}{Keyboard Macros} -@xrdef{Keyboard Macros-pg}{112} @xrdef{Keyboard Macros-snt}{Section@tie 8.4.7} @xrdef{Miscellaneous Commands-title}{Some Miscellaneous Commands} -@xrdef{Miscellaneous Commands-pg}{112} @xrdef{Miscellaneous Commands-snt}{Section@tie 8.4.8} +@xrdef{Keyboard Macros-pg}{109} +@xrdef{Miscellaneous Commands-pg}{109} @xrdef{Readline vi Mode-title}{Readline vi Mode} -@xrdef{Readline vi Mode-pg}{114} @xrdef{Readline vi Mode-snt}{Section@tie 8.5} @xrdef{Programmable Completion-title}{Programmable Completion} -@xrdef{Programmable Completion-pg}{115} @xrdef{Programmable Completion-snt}{Section@tie 8.6} +@xrdef{Readline vi Mode-pg}{111} +@xrdef{Programmable Completion-pg}{112} @xrdef{Programmable Completion Builtins-title}{Programmable Completion Builtins} -@xrdef{Programmable Completion Builtins-pg}{116} @xrdef{Programmable Completion Builtins-snt}{Section@tie 8.7} +@xrdef{Programmable Completion Builtins-pg}{113} @xrdef{Using History Interactively-title}{Using History Interactively} -@xrdef{Using History Interactively-pg}{121} @xrdef{Using History Interactively-snt}{Chapter@tie 9} @xrdef{Bash History Facilities-title}{Bash History Facilities} -@xrdef{Bash History Facilities-pg}{121} @xrdef{Bash History Facilities-snt}{Section@tie 9.1} @xrdef{Bash History Builtins-title}{Bash History Builtins} -@xrdef{Bash History Builtins-pg}{121} @xrdef{Bash History Builtins-snt}{Section@tie 9.2} +@xrdef{Using History Interactively-pg}{119} +@xrdef{Bash History Facilities-pg}{119} +@xrdef{Bash History Builtins-pg}{119} @xrdef{History Interaction-title}{History Expansion} -@xrdef{History Interaction-pg}{123} @xrdef{History Interaction-snt}{Section@tie 9.3} @xrdef{Event Designators-title}{Event Designators} -@xrdef{Event Designators-pg}{124} @xrdef{Event Designators-snt}{Section@tie 9.3.1} +@xrdef{History Interaction-pg}{121} +@xrdef{Event Designators-pg}{121} @xrdef{Word Designators-title}{Word Designators} -@xrdef{Word Designators-pg}{124} @xrdef{Word Designators-snt}{Section@tie 9.3.2} +@xrdef{Word Designators-pg}{122} @xrdef{Modifiers-title}{Modifiers} -@xrdef{Modifiers-pg}{125} @xrdef{Modifiers-snt}{Section@tie 9.3.3} +@xrdef{Modifiers-pg}{123} @xrdef{Installing Bash-title}{Installing Bash} -@xrdef{Installing Bash-pg}{127} @xrdef{Installing Bash-snt}{Chapter@tie 10} @xrdef{Basic Installation-title}{Basic Installation} -@xrdef{Basic Installation-pg}{127} @xrdef{Basic Installation-snt}{Section@tie 10.1} @xrdef{Compilers and Options-title}{Compilers and Options} -@xrdef{Compilers and Options-pg}{128} @xrdef{Compilers and Options-snt}{Section@tie 10.2} +@xrdef{Installing Bash-pg}{125} +@xrdef{Basic Installation-pg}{125} @xrdef{Compiling For Multiple Architectures-title}{Compiling For Multiple Architectures} -@xrdef{Compiling For Multiple Architectures-pg}{128} @xrdef{Compiling For Multiple Architectures-snt}{Section@tie 10.3} @xrdef{Installation Names-title}{Installation Names} -@xrdef{Installation Names-pg}{128} @xrdef{Installation Names-snt}{Section@tie 10.4} @xrdef{Specifying the System Type-title}{Specifying the System Type} -@xrdef{Specifying the System Type-pg}{129} @xrdef{Specifying the System Type-snt}{Section@tie 10.5} +@xrdef{Compilers and Options-pg}{126} +@xrdef{Compiling For Multiple Architectures-pg}{126} +@xrdef{Installation Names-pg}{126} +@xrdef{Specifying the System Type-pg}{126} @xrdef{Sharing Defaults-title}{Sharing Defaults} -@xrdef{Sharing Defaults-pg}{129} @xrdef{Sharing Defaults-snt}{Section@tie 10.6} @xrdef{Operation Controls-title}{Operation Controls} -@xrdef{Operation Controls-pg}{129} @xrdef{Operation Controls-snt}{Section@tie 10.7} @xrdef{Optional Features-title}{Optional Features} -@xrdef{Optional Features-pg}{129} @xrdef{Optional Features-snt}{Section@tie 10.8} +@xrdef{Sharing Defaults-pg}{127} +@xrdef{Operation Controls-pg}{127} +@xrdef{Optional Features-pg}{127} @xrdef{Reporting Bugs-title}{Reporting Bugs} -@xrdef{Reporting Bugs-pg}{135} @xrdef{Reporting Bugs-snt}{Appendix@tie @char65{}} +@xrdef{Reporting Bugs-pg}{133} @xrdef{Major Differences From The Bourne Shell-title}{Major Differences From The Bourne Shell} -@xrdef{Major Differences From The Bourne Shell-pg}{137} @xrdef{Major Differences From The Bourne Shell-snt}{Appendix@tie @char66{}} +@xrdef{Major Differences From The Bourne Shell-pg}{135} @xrdef{GNU Free Documentation License-title}{GNU Free Documentation License} -@xrdef{GNU Free Documentation License-pg}{143} @xrdef{GNU Free Documentation License-snt}{Appendix@tie @char67{}} +@xrdef{GNU Free Documentation License-pg}{141} @xrdef{Indexes-title}{Indexes} -@xrdef{Indexes-pg}{151} @xrdef{Indexes-snt}{Appendix@tie @char68{}} @xrdef{Builtin Index-title}{Index of Shell Builtin Commands} -@xrdef{Builtin Index-pg}{151} @xrdef{Builtin Index-snt}{Section@tie @char68.1} +@xrdef{Indexes-pg}{149} +@xrdef{Builtin Index-pg}{149} @xrdef{Reserved Word Index-title}{Index of Shell Reserved Words} -@xrdef{Reserved Word Index-pg}{152} @xrdef{Reserved Word Index-snt}{Section@tie @char68.2} @xrdef{Variable Index-title}{Parameter and Variable Index} -@xrdef{Variable Index-pg}{152} @xrdef{Variable Index-snt}{Section@tie @char68.3} +@xrdef{Reserved Word Index-pg}{150} +@xrdef{Variable Index-pg}{150} @xrdef{Function Index-title}{Function Index} -@xrdef{Function Index-pg}{154} @xrdef{Function Index-snt}{Section@tie @char68.4} +@xrdef{Function Index-pg}{152} @xrdef{Concept Index-title}{Concept Index} -@xrdef{Concept Index-pg}{156} @xrdef{Concept Index-snt}{Section@tie @char68.5} +@xrdef{Concept Index-pg}{154} diff --git a/doc/bashref.bt b/doc/bashref.bt index 6f948903e..0a2cb0000 100644 --- a/doc/bashref.bt +++ b/doc/bashref.bt @@ -6,7 +6,7 @@ \entry{eval}{36}{\code {eval}} \entry{exec}{36}{\code {exec}} \entry{exit}{36}{\code {exit}} -\entry{export}{37}{\code {export}} +\entry{export}{36}{\code {export}} \entry{getopts}{37}{\code {getopts}} \entry{hash}{37}{\code {hash}} \entry{pwd}{38}{\code {pwd}} @@ -42,18 +42,18 @@ \entry{unalias}{50}{\code {unalias}} \entry{set}{51}{\code {set}} \entry{shopt}{55}{\code {shopt}} -\entry{dirs}{82}{\code {dirs}} +\entry{dirs}{81}{\code {dirs}} \entry{popd}{82}{\code {popd}} \entry{pushd}{82}{\code {pushd}} -\entry{bg}{90}{\code {bg}} -\entry{fg}{90}{\code {fg}} -\entry{jobs}{90}{\code {jobs}} -\entry{kill}{91}{\code {kill}} -\entry{wait}{91}{\code {wait}} -\entry{disown}{91}{\code {disown}} -\entry{suspend}{91}{\code {suspend}} -\entry{compgen}{116}{\code {compgen}} -\entry{complete}{117}{\code {complete}} -\entry{compopt}{120}{\code {compopt}} -\entry{fc}{122}{\code {fc}} -\entry{history}{122}{\code {history}} +\entry{bg}{88}{\code {bg}} +\entry{fg}{88}{\code {fg}} +\entry{jobs}{88}{\code {jobs}} +\entry{kill}{89}{\code {kill}} +\entry{wait}{89}{\code {wait}} +\entry{disown}{89}{\code {disown}} +\entry{suspend}{89}{\code {suspend}} +\entry{compgen}{113}{\code {compgen}} +\entry{complete}{114}{\code {complete}} +\entry{compopt}{116}{\code {compopt}} +\entry{fc}{119}{\code {fc}} +\entry{history}{120}{\code {history}} diff --git a/doc/bashref.bts b/doc/bashref.bts index 455fa1016..38ed0baa5 100644 --- a/doc/bashref.bts +++ b/doc/bashref.bts @@ -7,7 +7,7 @@ \initial {A} \entry {\code {alias}}{41} \initial {B} -\entry {\code {bg}}{90} +\entry {\code {bg}}{88} \entry {\code {bind}}{41} \entry {\code {break}}{35} \entry {\code {builtin}}{43} @@ -15,34 +15,34 @@ \entry {\code {caller}}{43} \entry {\code {cd}}{36} \entry {\code {command}}{43} -\entry {\code {compgen}}{116} -\entry {\code {complete}}{117} -\entry {\code {compopt}}{120} +\entry {\code {compgen}}{113} +\entry {\code {complete}}{114} +\entry {\code {compopt}}{116} \entry {\code {continue}}{36} \initial {D} \entry {\code {declare}}{43} -\entry {\code {dirs}}{82} -\entry {\code {disown}}{91} +\entry {\code {dirs}}{81} +\entry {\code {disown}}{89} \initial {E} \entry {\code {echo}}{44} \entry {\code {enable}}{45} \entry {\code {eval}}{36} \entry {\code {exec}}{36} \entry {\code {exit}}{36} -\entry {\code {export}}{37} +\entry {\code {export}}{36} \initial {F} -\entry {\code {fc}}{122} -\entry {\code {fg}}{90} +\entry {\code {fc}}{119} +\entry {\code {fg}}{88} \initial {G} \entry {\code {getopts}}{37} \initial {H} \entry {\code {hash}}{37} \entry {\code {help}}{46} -\entry {\code {history}}{122} +\entry {\code {history}}{120} \initial {J} -\entry {\code {jobs}}{90} +\entry {\code {jobs}}{88} \initial {K} -\entry {\code {kill}}{91} +\entry {\code {kill}}{89} \initial {L} \entry {\code {let}}{46} \entry {\code {local}}{46} @@ -64,7 +64,7 @@ \entry {\code {shift}}{38} \entry {\code {shopt}}{55} \entry {\code {source}}{49} -\entry {\code {suspend}}{91} +\entry {\code {suspend}}{89} \initial {T} \entry {\code {test}}{39} \entry {\code {times}}{40} @@ -77,4 +77,4 @@ \entry {\code {unalias}}{50} \entry {\code {unset}}{41} \initial {W} -\entry {\code {wait}}{91} +\entry {\code {wait}}{89} diff --git a/doc/bashref.cp b/doc/bashref.cp index 6fba4c4ed..a509e9581 100644 --- a/doc/bashref.cp +++ b/doc/bashref.cp @@ -26,58 +26,58 @@ \entry{native languages}{7}{native languages} \entry{translation, native languages}{7}{translation, native languages} \entry{comments, shell}{7}{comments, shell} -\entry{commands, shell}{8}{commands, shell} +\entry{commands, shell}{7}{commands, shell} \entry{commands, simple}{8}{commands, simple} \entry{pipeline}{8}{pipeline} \entry{commands, pipelines}{8}{commands, pipelines} \entry{command timing}{8}{command timing} -\entry{commands, lists}{9}{commands, lists} +\entry{commands, lists}{8}{commands, lists} \entry{commands, compound}{9}{commands, compound} -\entry{commands, looping}{10}{commands, looping} +\entry{commands, looping}{9}{commands, looping} \entry{commands, conditional}{10}{commands, conditional} \entry{commands, grouping}{13}{commands, grouping} -\entry{coprocess}{14}{coprocess} +\entry{coprocess}{13}{coprocess} \entry{shell function}{14}{shell function} \entry{functions, shell}{14}{functions, shell} -\entry{parameters}{16}{parameters} -\entry{variable, shell}{16}{variable, shell} -\entry{shell variable}{16}{shell variable} +\entry{parameters}{15}{parameters} +\entry{variable, shell}{15}{variable, shell} +\entry{shell variable}{15}{shell variable} \entry{parameters, positional}{16}{parameters, positional} -\entry{parameters, special}{17}{parameters, special} +\entry{parameters, special}{16}{parameters, special} \entry{expansion}{17}{expansion} \entry{brace expansion}{18}{brace expansion} \entry{expansion, brace}{18}{expansion, brace} -\entry{tilde expansion}{19}{tilde expansion} -\entry{expansion, tilde}{19}{expansion, tilde} -\entry{parameter expansion}{20}{parameter expansion} -\entry{expansion, parameter}{20}{expansion, parameter} -\entry{command substitution}{23}{command substitution} +\entry{tilde expansion}{18}{tilde expansion} +\entry{expansion, tilde}{18}{expansion, tilde} +\entry{parameter expansion}{19}{parameter expansion} +\entry{expansion, parameter}{19}{expansion, parameter} +\entry{command substitution}{22}{command substitution} \entry{expansion, arithmetic}{23}{expansion, arithmetic} \entry{arithmetic expansion}{23}{arithmetic expansion} \entry{process substitution}{23}{process substitution} -\entry{word splitting}{24}{word splitting} +\entry{word splitting}{23}{word splitting} \entry{expansion, filename}{24}{expansion, filename} \entry{expansion, pathname}{24}{expansion, pathname} \entry{filename expansion}{24}{filename expansion} \entry{pathname expansion}{24}{pathname expansion} -\entry{pattern matching}{25}{pattern matching} -\entry{matching, pattern}{25}{matching, pattern} -\entry{redirection}{26}{redirection} -\entry{command expansion}{30}{command expansion} -\entry{command execution}{30}{command execution} -\entry{command search}{30}{command search} -\entry{execution environment}{31}{execution environment} -\entry{environment}{32}{environment} -\entry{exit status}{33}{exit status} -\entry{signal handling}{33}{signal handling} -\entry{shell script}{34}{shell script} +\entry{pattern matching}{24}{pattern matching} +\entry{matching, pattern}{24}{matching, pattern} +\entry{redirection}{25}{redirection} +\entry{command expansion}{29}{command expansion} +\entry{command execution}{29}{command execution} +\entry{command search}{29}{command search} +\entry{execution environment}{30}{execution environment} +\entry{environment}{31}{environment} +\entry{exit status}{31}{exit status} +\entry{signal handling}{32}{signal handling} +\entry{shell script}{33}{shell script} \entry{special builtin}{59}{special builtin} \entry{login shell}{73}{login shell} \entry{interactive shell}{73}{interactive shell} \entry{startup files}{73}{startup files} -\entry{interactive shell}{75}{interactive shell} -\entry{shell, interactive}{75}{shell, interactive} -\entry{expressions, conditional}{77}{expressions, conditional} +\entry{interactive shell}{74}{interactive shell} +\entry{shell, interactive}{74}{shell, interactive} +\entry{expressions, conditional}{76}{expressions, conditional} \entry{arithmetic, shell}{78}{arithmetic, shell} \entry{shell arithmetic}{78}{shell arithmetic} \entry{expressions, arithmetic}{78}{expressions, arithmetic} @@ -86,33 +86,33 @@ \entry{alias expansion}{79}{alias expansion} \entry{arrays}{80}{arrays} \entry{directory stack}{81}{directory stack} -\entry{prompting}{83}{prompting} +\entry{prompting}{82}{prompting} \entry{restricted shell}{84}{restricted shell} -\entry{POSIX Mode}{85}{POSIX Mode} -\entry{job control}{89}{job control} -\entry{foreground}{89}{foreground} -\entry{background}{89}{background} -\entry{suspending jobs}{89}{suspending jobs} -\entry{Readline, how to use}{92}{Readline, how to use} -\entry{interaction, readline}{93}{interaction, readline} -\entry{notation, readline}{94}{notation, readline} -\entry{command editing}{94}{command editing} -\entry{editing command lines}{94}{editing command lines} -\entry{killing text}{95}{killing text} -\entry{yanking text}{95}{yanking text} -\entry{kill ring}{95}{kill ring} -\entry{initialization file, readline}{96}{initialization file, readline} -\entry{variables, readline}{97}{variables, readline} -\entry{programmable completion}{115}{programmable completion} -\entry{completion builtins}{116}{completion builtins} -\entry{History, how to use}{120}{History, how to use} -\entry{command history}{121}{command history} -\entry{history list}{121}{history list} -\entry{history builtins}{121}{history builtins} -\entry{history expansion}{123}{history expansion} -\entry{event designators}{124}{event designators} -\entry{history events}{124}{history events} -\entry{installation}{127}{installation} -\entry{configuration}{127}{configuration} -\entry{Bash installation}{127}{Bash installation} -\entry{Bash configuration}{127}{Bash configuration} +\entry{POSIX Mode}{84}{POSIX Mode} +\entry{job control}{87}{job control} +\entry{foreground}{87}{foreground} +\entry{background}{87}{background} +\entry{suspending jobs}{87}{suspending jobs} +\entry{Readline, how to use}{90}{Readline, how to use} +\entry{interaction, readline}{91}{interaction, readline} +\entry{notation, readline}{92}{notation, readline} +\entry{command editing}{92}{command editing} +\entry{editing command lines}{92}{editing command lines} +\entry{killing text}{93}{killing text} +\entry{yanking text}{93}{yanking text} +\entry{kill ring}{93}{kill ring} +\entry{initialization file, readline}{94}{initialization file, readline} +\entry{variables, readline}{95}{variables, readline} +\entry{programmable completion}{112}{programmable completion} +\entry{completion builtins}{113}{completion builtins} +\entry{History, how to use}{117}{History, how to use} +\entry{command history}{119}{command history} +\entry{history list}{119}{history list} +\entry{history builtins}{119}{history builtins} +\entry{history expansion}{121}{history expansion} +\entry{event designators}{121}{event designators} +\entry{history events}{121}{history events} +\entry{installation}{125}{installation} +\entry{configuration}{125}{configuration} +\entry{Bash installation}{125}{Bash installation} +\entry{Bash configuration}{125}{Bash configuration} diff --git a/doc/bashref.cps b/doc/bashref.cps index c0737e066..912b5073a 100644 --- a/doc/bashref.cps +++ b/doc/bashref.cps @@ -5,132 +5,132 @@ \entry {arithmetic, shell}{78} \entry {arrays}{80} \initial {B} -\entry {background}{89} -\entry {Bash configuration}{127} -\entry {Bash installation}{127} +\entry {background}{87} +\entry {Bash configuration}{125} +\entry {Bash installation}{125} \entry {Bourne shell}{5} \entry {brace expansion}{18} \entry {builtin}{3} \initial {C} -\entry {command editing}{94} -\entry {command execution}{30} -\entry {command expansion}{30} -\entry {command history}{121} -\entry {command search}{30} -\entry {command substitution}{23} +\entry {command editing}{92} +\entry {command execution}{29} +\entry {command expansion}{29} +\entry {command history}{119} +\entry {command search}{29} +\entry {command substitution}{22} \entry {command timing}{8} \entry {commands, compound}{9} \entry {commands, conditional}{10} \entry {commands, grouping}{13} -\entry {commands, lists}{9} -\entry {commands, looping}{10} +\entry {commands, lists}{8} +\entry {commands, looping}{9} \entry {commands, pipelines}{8} -\entry {commands, shell}{8} +\entry {commands, shell}{7} \entry {commands, simple}{8} \entry {comments, shell}{7} -\entry {completion builtins}{116} -\entry {configuration}{127} +\entry {completion builtins}{113} +\entry {configuration}{125} \entry {control operator}{3} -\entry {coprocess}{14} +\entry {coprocess}{13} \initial {D} \entry {directory stack}{81} \initial {E} -\entry {editing command lines}{94} -\entry {environment}{32} +\entry {editing command lines}{92} +\entry {environment}{31} \entry {evaluation, arithmetic}{78} -\entry {event designators}{124} -\entry {execution environment}{31} -\entry {exit status}{3, 33} +\entry {event designators}{121} +\entry {execution environment}{30} +\entry {exit status}{3, 31} \entry {expansion}{17} \entry {expansion, arithmetic}{23} \entry {expansion, brace}{18} \entry {expansion, filename}{24} -\entry {expansion, parameter}{20} +\entry {expansion, parameter}{19} \entry {expansion, pathname}{24} -\entry {expansion, tilde}{19} +\entry {expansion, tilde}{18} \entry {expressions, arithmetic}{78} -\entry {expressions, conditional}{77} +\entry {expressions, conditional}{76} \initial {F} \entry {field}{3} \entry {filename}{3} \entry {filename expansion}{24} -\entry {foreground}{89} +\entry {foreground}{87} \entry {functions, shell}{14} \initial {H} -\entry {history builtins}{121} -\entry {history events}{124} -\entry {history expansion}{123} -\entry {history list}{121} -\entry {History, how to use}{120} +\entry {history builtins}{119} +\entry {history events}{121} +\entry {history expansion}{121} +\entry {history list}{119} +\entry {History, how to use}{117} \initial {I} \entry {identifier}{3} -\entry {initialization file, readline}{96} -\entry {installation}{127} -\entry {interaction, readline}{93} -\entry {interactive shell}{73, 75} +\entry {initialization file, readline}{94} +\entry {installation}{125} +\entry {interaction, readline}{91} +\entry {interactive shell}{73, 74} \entry {internationalization}{7} \initial {J} \entry {job}{3} -\entry {job control}{3, 89} +\entry {job control}{3, 87} \initial {K} -\entry {kill ring}{95} -\entry {killing text}{95} +\entry {kill ring}{93} +\entry {killing text}{93} \initial {L} \entry {localization}{7} \entry {login shell}{73} \initial {M} -\entry {matching, pattern}{25} +\entry {matching, pattern}{24} \entry {metacharacter}{3} \initial {N} \entry {name}{3} \entry {native languages}{7} -\entry {notation, readline}{94} +\entry {notation, readline}{92} \initial {O} \entry {operator, shell}{3} \initial {P} -\entry {parameter expansion}{20} -\entry {parameters}{16} +\entry {parameter expansion}{19} +\entry {parameters}{15} \entry {parameters, positional}{16} -\entry {parameters, special}{17} +\entry {parameters, special}{16} \entry {pathname expansion}{24} -\entry {pattern matching}{25} +\entry {pattern matching}{24} \entry {pipeline}{8} \entry {POSIX}{3} -\entry {POSIX Mode}{85} +\entry {POSIX Mode}{84} \entry {process group}{3} \entry {process group ID}{3} \entry {process substitution}{23} -\entry {programmable completion}{115} -\entry {prompting}{83} +\entry {programmable completion}{112} +\entry {prompting}{82} \initial {Q} \entry {quoting}{6} \entry {quoting, ANSI}{6} \initial {R} -\entry {Readline, how to use}{92} -\entry {redirection}{26} +\entry {Readline, how to use}{90} +\entry {redirection}{25} \entry {reserved word}{3} \entry {restricted shell}{84} \entry {return status}{4} \initial {S} \entry {shell arithmetic}{78} \entry {shell function}{14} -\entry {shell script}{34} -\entry {shell variable}{16} -\entry {shell, interactive}{75} +\entry {shell script}{33} +\entry {shell variable}{15} +\entry {shell, interactive}{74} \entry {signal}{4} -\entry {signal handling}{33} +\entry {signal handling}{32} \entry {special builtin}{4, 59} \entry {startup files}{73} -\entry {suspending jobs}{89} +\entry {suspending jobs}{87} \initial {T} -\entry {tilde expansion}{19} +\entry {tilde expansion}{18} \entry {token}{4} \entry {translation, native languages}{7} \initial {V} -\entry {variable, shell}{16} -\entry {variables, readline}{97} +\entry {variable, shell}{15} +\entry {variables, readline}{95} \initial {W} \entry {word}{4} -\entry {word splitting}{24} +\entry {word splitting}{23} \initial {Y} -\entry {yanking text}{95} +\entry {yanking text}{93} diff --git a/doc/bashref.dvi b/doc/bashref.dvi index a9e463967..e267efc6b 100644 Binary files a/doc/bashref.dvi and b/doc/bashref.dvi differ diff --git a/doc/bashref.fn b/doc/bashref.fn index bb1f5c04c..46f46e5c2 100644 --- a/doc/bashref.fn +++ b/doc/bashref.fn @@ -1,101 +1,101 @@ -\entry{beginning-of-line (C-a)}{106}{\code {beginning-of-line (C-a)}} -\entry{end-of-line (C-e)}{106}{\code {end-of-line (C-e)}} -\entry{forward-char (C-f)}{106}{\code {forward-char (C-f)}} -\entry{backward-char (C-b)}{106}{\code {backward-char (C-b)}} -\entry{forward-word (M-f)}{106}{\code {forward-word (M-f)}} -\entry{backward-word (M-b)}{106}{\code {backward-word (M-b)}} -\entry{shell-forward-word ()}{106}{\code {shell-forward-word ()}} -\entry{shell-backward-word ()}{106}{\code {shell-backward-word ()}} -\entry{clear-screen (C-l)}{106}{\code {clear-screen (C-l)}} -\entry{redraw-current-line ()}{107}{\code {redraw-current-line ()}} -\entry{accept-line (Newline or Return)}{107}{\code {accept-line (Newline or Return)}} -\entry{previous-history (C-p)}{107}{\code {previous-history (C-p)}} -\entry{next-history (C-n)}{107}{\code {next-history (C-n)}} -\entry{beginning-of-history (M-<)}{107}{\code {beginning-of-history (M-<)}} -\entry{end-of-history (M->)}{107}{\code {end-of-history (M->)}} -\entry{reverse-search-history (C-r)}{107}{\code {reverse-search-history (C-r)}} -\entry{forward-search-history (C-s)}{107}{\code {forward-search-history (C-s)}} -\entry{non-incremental-reverse-search-history (M-p)}{107}{\code {non-incremental-reverse-search-history (M-p)}} -\entry{non-incremental-forward-search-history (M-n)}{107}{\code {non-incremental-forward-search-history (M-n)}} -\entry{history-search-forward ()}{107}{\code {history-search-forward ()}} -\entry{history-search-backward ()}{107}{\code {history-search-backward ()}} -\entry{yank-nth-arg (M-C-y)}{107}{\code {yank-nth-arg (M-C-y)}} -\entry{yank-last-arg (M-. or M-_)}{108}{\code {yank-last-arg (M-. or M-_)}} -\entry{delete-char (C-d)}{108}{\code {delete-char (C-d)}} -\entry{backward-delete-char (Rubout)}{108}{\code {backward-delete-char (Rubout)}} -\entry{forward-backward-delete-char ()}{108}{\code {forward-backward-delete-char ()}} -\entry{quoted-insert (C-q or C-v)}{108}{\code {quoted-insert (C-q or C-v)}} -\entry{self-insert (a, b, A, 1, !, ...{})}{108}{\code {self-insert (a, b, A, 1, !, \dots {})}} -\entry{transpose-chars (C-t)}{108}{\code {transpose-chars (C-t)}} -\entry{transpose-words (M-t)}{108}{\code {transpose-words (M-t)}} -\entry{upcase-word (M-u)}{108}{\code {upcase-word (M-u)}} -\entry{downcase-word (M-l)}{108}{\code {downcase-word (M-l)}} -\entry{capitalize-word (M-c)}{109}{\code {capitalize-word (M-c)}} -\entry{overwrite-mode ()}{109}{\code {overwrite-mode ()}} -\entry{kill-line (C-k)}{109}{\code {kill-line (C-k)}} -\entry{backward-kill-line (C-x Rubout)}{109}{\code {backward-kill-line (C-x Rubout)}} -\entry{unix-line-discard (C-u)}{109}{\code {unix-line-discard (C-u)}} -\entry{kill-whole-line ()}{109}{\code {kill-whole-line ()}} -\entry{kill-word (M-d)}{109}{\code {kill-word (M-d)}} -\entry{backward-kill-word (M-DEL)}{109}{\code {backward-kill-word (M-\key {DEL})}} -\entry{shell-kill-word ()}{109}{\code {shell-kill-word ()}} -\entry{backward-kill-word ()}{109}{\code {backward-kill-word ()}} -\entry{unix-word-rubout (C-w)}{109}{\code {unix-word-rubout (C-w)}} -\entry{unix-filename-rubout ()}{109}{\code {unix-filename-rubout ()}} -\entry{delete-horizontal-space ()}{110}{\code {delete-horizontal-space ()}} -\entry{kill-region ()}{110}{\code {kill-region ()}} -\entry{copy-region-as-kill ()}{110}{\code {copy-region-as-kill ()}} -\entry{copy-backward-word ()}{110}{\code {copy-backward-word ()}} -\entry{copy-forward-word ()}{110}{\code {copy-forward-word ()}} -\entry{yank (C-y)}{110}{\code {yank (C-y)}} -\entry{yank-pop (M-y)}{110}{\code {yank-pop (M-y)}} -\entry{digit-argument (M-0, M-1, ...{} M--)}{110}{\code {digit-argument (\kbd {M-0}, \kbd {M-1}, \dots {} \kbd {M--})}} -\entry{universal-argument ()}{110}{\code {universal-argument ()}} -\entry{complete (TAB)}{110}{\code {complete (\key {TAB})}} -\entry{possible-completions (M-?)}{111}{\code {possible-completions (M-?)}} -\entry{insert-completions (M-*)}{111}{\code {insert-completions (M-*)}} -\entry{menu-complete ()}{111}{\code {menu-complete ()}} -\entry{delete-char-or-list ()}{111}{\code {delete-char-or-list ()}} -\entry{complete-filename (M-/)}{111}{\code {complete-filename (M-/)}} -\entry{possible-filename-completions (C-x /)}{111}{\code {possible-filename-completions (C-x /)}} -\entry{complete-username (M-~)}{111}{\code {complete-username (M-~)}} -\entry{possible-username-completions (C-x ~)}{111}{\code {possible-username-completions (C-x ~)}} -\entry{complete-variable (M-$)}{111}{\code {complete-variable (M-$)}} -\entry{possible-variable-completions (C-x $)}{111}{\code {possible-variable-completions (C-x $)}} -\entry{complete-hostname (M-@)}{111}{\code {complete-hostname (M-@)}} -\entry{possible-hostname-completions (C-x @)}{111}{\code {possible-hostname-completions (C-x @)}} -\entry{complete-command (M-!)}{111}{\code {complete-command (M-!)}} -\entry{possible-command-completions (C-x !)}{112}{\code {possible-command-completions (C-x !)}} -\entry{dynamic-complete-history (M-TAB)}{112}{\code {dynamic-complete-history (M-\key {TAB})}} -\entry{dabbrev-expand ()}{112}{\code {dabbrev-expand ()}} -\entry{complete-into-braces (M-{\tt \char 123})}{112}{\code {complete-into-braces (M-{\tt \char 123})}} -\entry{start-kbd-macro (C-x ()}{112}{\code {start-kbd-macro (C-x ()}} -\entry{end-kbd-macro (C-x ))}{112}{\code {end-kbd-macro (C-x ))}} -\entry{call-last-kbd-macro (C-x e)}{112}{\code {call-last-kbd-macro (C-x e)}} -\entry{re-read-init-file (C-x C-r)}{112}{\code {re-read-init-file (C-x C-r)}} -\entry{abort (C-g)}{112}{\code {abort (C-g)}} -\entry{do-uppercase-version (M-a, M-b, M-x, ...{})}{112}{\code {do-uppercase-version (M-a, M-b, M-\var {x}, \dots {})}} -\entry{prefix-meta (ESC)}{112}{\code {prefix-meta (\key {ESC})}} -\entry{undo (C-_ or C-x C-u)}{112}{\code {undo (C-_ or C-x C-u)}} -\entry{revert-line (M-r)}{113}{\code {revert-line (M-r)}} -\entry{tilde-expand (M-&)}{113}{\code {tilde-expand (M-&)}} -\entry{set-mark (C-@)}{113}{\code {set-mark (C-@)}} -\entry{exchange-point-and-mark (C-x C-x)}{113}{\code {exchange-point-and-mark (C-x C-x)}} -\entry{character-search (C-])}{113}{\code {character-search (C-])}} -\entry{character-search-backward (M-C-])}{113}{\code {character-search-backward (M-C-])}} -\entry{insert-comment (M-#)}{113}{\code {insert-comment (M-#)}} -\entry{dump-functions ()}{113}{\code {dump-functions ()}} -\entry{dump-variables ()}{113}{\code {dump-variables ()}} -\entry{dump-macros ()}{113}{\code {dump-macros ()}} -\entry{glob-complete-word (M-g)}{113}{\code {glob-complete-word (M-g)}} -\entry{glob-expand-word (C-x *)}{114}{\code {glob-expand-word (C-x *)}} -\entry{glob-list-expansions (C-x g)}{114}{\code {glob-list-expansions (C-x g)}} -\entry{display-shell-version (C-x C-v)}{114}{\code {display-shell-version (C-x C-v)}} -\entry{shell-expand-line (M-C-e)}{114}{\code {shell-expand-line (M-C-e)}} -\entry{history-expand-line (M-^)}{114}{\code {history-expand-line (M-^)}} -\entry{magic-space ()}{114}{\code {magic-space ()}} -\entry{alias-expand-line ()}{114}{\code {alias-expand-line ()}} -\entry{history-and-alias-expand-line ()}{114}{\code {history-and-alias-expand-line ()}} -\entry{insert-last-argument (M-. or M-_)}{114}{\code {insert-last-argument (M-. or M-_)}} -\entry{operate-and-get-next (C-o)}{114}{\code {operate-and-get-next (C-o)}} -\entry{edit-and-execute-command (C-xC-e)}{114}{\code {edit-and-execute-command (C-xC-e)}} +\entry{beginning-of-line (C-a)}{103}{\code {beginning-of-line (C-a)}} +\entry{end-of-line (C-e)}{103}{\code {end-of-line (C-e)}} +\entry{forward-char (C-f)}{103}{\code {forward-char (C-f)}} +\entry{backward-char (C-b)}{103}{\code {backward-char (C-b)}} +\entry{forward-word (M-f)}{103}{\code {forward-word (M-f)}} +\entry{backward-word (M-b)}{103}{\code {backward-word (M-b)}} +\entry{shell-forward-word ()}{103}{\code {shell-forward-word ()}} +\entry{shell-backward-word ()}{103}{\code {shell-backward-word ()}} +\entry{clear-screen (C-l)}{103}{\code {clear-screen (C-l)}} +\entry{redraw-current-line ()}{103}{\code {redraw-current-line ()}} +\entry{accept-line (Newline or Return)}{104}{\code {accept-line (Newline or Return)}} +\entry{previous-history (C-p)}{104}{\code {previous-history (C-p)}} +\entry{next-history (C-n)}{104}{\code {next-history (C-n)}} +\entry{beginning-of-history (M-<)}{104}{\code {beginning-of-history (M-<)}} +\entry{end-of-history (M->)}{104}{\code {end-of-history (M->)}} +\entry{reverse-search-history (C-r)}{104}{\code {reverse-search-history (C-r)}} +\entry{forward-search-history (C-s)}{104}{\code {forward-search-history (C-s)}} +\entry{non-incremental-reverse-search-history (M-p)}{104}{\code {non-incremental-reverse-search-history (M-p)}} +\entry{non-incremental-forward-search-history (M-n)}{104}{\code {non-incremental-forward-search-history (M-n)}} +\entry{history-search-forward ()}{104}{\code {history-search-forward ()}} +\entry{history-search-backward ()}{104}{\code {history-search-backward ()}} +\entry{yank-nth-arg (M-C-y)}{104}{\code {yank-nth-arg (M-C-y)}} +\entry{yank-last-arg (M-. or M-_)}{105}{\code {yank-last-arg (M-. or M-_)}} +\entry{delete-char (C-d)}{105}{\code {delete-char (C-d)}} +\entry{backward-delete-char (Rubout)}{105}{\code {backward-delete-char (Rubout)}} +\entry{forward-backward-delete-char ()}{105}{\code {forward-backward-delete-char ()}} +\entry{quoted-insert (C-q or C-v)}{105}{\code {quoted-insert (C-q or C-v)}} +\entry{self-insert (a, b, A, 1, !, ...{})}{105}{\code {self-insert (a, b, A, 1, !, \dots {})}} +\entry{transpose-chars (C-t)}{105}{\code {transpose-chars (C-t)}} +\entry{transpose-words (M-t)}{105}{\code {transpose-words (M-t)}} +\entry{upcase-word (M-u)}{105}{\code {upcase-word (M-u)}} +\entry{downcase-word (M-l)}{105}{\code {downcase-word (M-l)}} +\entry{capitalize-word (M-c)}{106}{\code {capitalize-word (M-c)}} +\entry{overwrite-mode ()}{106}{\code {overwrite-mode ()}} +\entry{kill-line (C-k)}{106}{\code {kill-line (C-k)}} +\entry{backward-kill-line (C-x Rubout)}{106}{\code {backward-kill-line (C-x Rubout)}} +\entry{unix-line-discard (C-u)}{106}{\code {unix-line-discard (C-u)}} +\entry{kill-whole-line ()}{106}{\code {kill-whole-line ()}} +\entry{kill-word (M-d)}{106}{\code {kill-word (M-d)}} +\entry{backward-kill-word (M-DEL)}{106}{\code {backward-kill-word (M-\key {DEL})}} +\entry{shell-kill-word ()}{106}{\code {shell-kill-word ()}} +\entry{backward-kill-word ()}{106}{\code {backward-kill-word ()}} +\entry{unix-word-rubout (C-w)}{106}{\code {unix-word-rubout (C-w)}} +\entry{unix-filename-rubout ()}{106}{\code {unix-filename-rubout ()}} +\entry{delete-horizontal-space ()}{106}{\code {delete-horizontal-space ()}} +\entry{kill-region ()}{107}{\code {kill-region ()}} +\entry{copy-region-as-kill ()}{107}{\code {copy-region-as-kill ()}} +\entry{copy-backward-word ()}{107}{\code {copy-backward-word ()}} +\entry{copy-forward-word ()}{107}{\code {copy-forward-word ()}} +\entry{yank (C-y)}{107}{\code {yank (C-y)}} +\entry{yank-pop (M-y)}{107}{\code {yank-pop (M-y)}} +\entry{digit-argument (M-0, M-1, ...{} M--)}{107}{\code {digit-argument (\kbd {M-0}, \kbd {M-1}, \dots {} \kbd {M--})}} +\entry{universal-argument ()}{107}{\code {universal-argument ()}} +\entry{complete (TAB)}{107}{\code {complete (\key {TAB})}} +\entry{possible-completions (M-?)}{107}{\code {possible-completions (M-?)}} +\entry{insert-completions (M-*)}{108}{\code {insert-completions (M-*)}} +\entry{menu-complete ()}{108}{\code {menu-complete ()}} +\entry{delete-char-or-list ()}{108}{\code {delete-char-or-list ()}} +\entry{complete-filename (M-/)}{108}{\code {complete-filename (M-/)}} +\entry{possible-filename-completions (C-x /)}{108}{\code {possible-filename-completions (C-x /)}} +\entry{complete-username (M-~)}{108}{\code {complete-username (M-~)}} +\entry{possible-username-completions (C-x ~)}{108}{\code {possible-username-completions (C-x ~)}} +\entry{complete-variable (M-$)}{108}{\code {complete-variable (M-$)}} +\entry{possible-variable-completions (C-x $)}{108}{\code {possible-variable-completions (C-x $)}} +\entry{complete-hostname (M-@)}{108}{\code {complete-hostname (M-@)}} +\entry{possible-hostname-completions (C-x @)}{108}{\code {possible-hostname-completions (C-x @)}} +\entry{complete-command (M-!)}{108}{\code {complete-command (M-!)}} +\entry{possible-command-completions (C-x !)}{108}{\code {possible-command-completions (C-x !)}} +\entry{dynamic-complete-history (M-TAB)}{109}{\code {dynamic-complete-history (M-\key {TAB})}} +\entry{dabbrev-expand ()}{109}{\code {dabbrev-expand ()}} +\entry{complete-into-braces (M-{\tt \char 123})}{109}{\code {complete-into-braces (M-{\tt \char 123})}} +\entry{start-kbd-macro (C-x ()}{109}{\code {start-kbd-macro (C-x ()}} +\entry{end-kbd-macro (C-x ))}{109}{\code {end-kbd-macro (C-x ))}} +\entry{call-last-kbd-macro (C-x e)}{109}{\code {call-last-kbd-macro (C-x e)}} +\entry{re-read-init-file (C-x C-r)}{109}{\code {re-read-init-file (C-x C-r)}} +\entry{abort (C-g)}{109}{\code {abort (C-g)}} +\entry{do-uppercase-version (M-a, M-b, M-x, ...{})}{109}{\code {do-uppercase-version (M-a, M-b, M-\var {x}, \dots {})}} +\entry{prefix-meta (ESC)}{109}{\code {prefix-meta (\key {ESC})}} +\entry{undo (C-_ or C-x C-u)}{109}{\code {undo (C-_ or C-x C-u)}} +\entry{revert-line (M-r)}{109}{\code {revert-line (M-r)}} +\entry{tilde-expand (M-&)}{109}{\code {tilde-expand (M-&)}} +\entry{set-mark (C-@)}{110}{\code {set-mark (C-@)}} +\entry{exchange-point-and-mark (C-x C-x)}{110}{\code {exchange-point-and-mark (C-x C-x)}} +\entry{character-search (C-])}{110}{\code {character-search (C-])}} +\entry{character-search-backward (M-C-])}{110}{\code {character-search-backward (M-C-])}} +\entry{insert-comment (M-#)}{110}{\code {insert-comment (M-#)}} +\entry{dump-functions ()}{110}{\code {dump-functions ()}} +\entry{dump-variables ()}{110}{\code {dump-variables ()}} +\entry{dump-macros ()}{110}{\code {dump-macros ()}} +\entry{glob-complete-word (M-g)}{110}{\code {glob-complete-word (M-g)}} +\entry{glob-expand-word (C-x *)}{110}{\code {glob-expand-word (C-x *)}} +\entry{glob-list-expansions (C-x g)}{111}{\code {glob-list-expansions (C-x g)}} +\entry{display-shell-version (C-x C-v)}{111}{\code {display-shell-version (C-x C-v)}} +\entry{shell-expand-line (M-C-e)}{111}{\code {shell-expand-line (M-C-e)}} +\entry{history-expand-line (M-^)}{111}{\code {history-expand-line (M-^)}} +\entry{magic-space ()}{111}{\code {magic-space ()}} +\entry{alias-expand-line ()}{111}{\code {alias-expand-line ()}} +\entry{history-and-alias-expand-line ()}{111}{\code {history-and-alias-expand-line ()}} +\entry{insert-last-argument (M-. or M-_)}{111}{\code {insert-last-argument (M-. or M-_)}} +\entry{operate-and-get-next (C-o)}{111}{\code {operate-and-get-next (C-o)}} +\entry{edit-and-execute-command (C-xC-e)}{111}{\code {edit-and-execute-command (C-xC-e)}} diff --git a/doc/bashref.fns b/doc/bashref.fns index 863455b7b..5f5597089 100644 --- a/doc/bashref.fns +++ b/doc/bashref.fns @@ -1,121 +1,121 @@ \initial {A} -\entry {\code {abort (C-g)}}{112} -\entry {\code {accept-line (Newline or Return)}}{107} -\entry {\code {alias-expand-line ()}}{114} +\entry {\code {abort (C-g)}}{109} +\entry {\code {accept-line (Newline or Return)}}{104} +\entry {\code {alias-expand-line ()}}{111} \initial {B} -\entry {\code {backward-char (C-b)}}{106} -\entry {\code {backward-delete-char (Rubout)}}{108} -\entry {\code {backward-kill-line (C-x Rubout)}}{109} -\entry {\code {backward-kill-word ()}}{109} -\entry {\code {backward-kill-word (M-\key {DEL})}}{109} -\entry {\code {backward-word (M-b)}}{106} -\entry {\code {beginning-of-history (M-<)}}{107} -\entry {\code {beginning-of-line (C-a)}}{106} +\entry {\code {backward-char (C-b)}}{103} +\entry {\code {backward-delete-char (Rubout)}}{105} +\entry {\code {backward-kill-line (C-x Rubout)}}{106} +\entry {\code {backward-kill-word ()}}{106} +\entry {\code {backward-kill-word (M-\key {DEL})}}{106} +\entry {\code {backward-word (M-b)}}{103} +\entry {\code {beginning-of-history (M-<)}}{104} +\entry {\code {beginning-of-line (C-a)}}{103} \initial {C} -\entry {\code {call-last-kbd-macro (C-x e)}}{112} -\entry {\code {capitalize-word (M-c)}}{109} -\entry {\code {character-search (C-])}}{113} -\entry {\code {character-search-backward (M-C-])}}{113} -\entry {\code {clear-screen (C-l)}}{106} -\entry {\code {complete (\key {TAB})}}{110} -\entry {\code {complete-command (M-!)}}{111} -\entry {\code {complete-filename (M-/)}}{111} -\entry {\code {complete-hostname (M-@)}}{111} -\entry {\code {complete-into-braces (M-{\tt \char 123})}}{112} -\entry {\code {complete-username (M-~)}}{111} -\entry {\code {complete-variable (M-$)}}{111} -\entry {\code {copy-backward-word ()}}{110} -\entry {\code {copy-forward-word ()}}{110} -\entry {\code {copy-region-as-kill ()}}{110} +\entry {\code {call-last-kbd-macro (C-x e)}}{109} +\entry {\code {capitalize-word (M-c)}}{106} +\entry {\code {character-search (C-])}}{110} +\entry {\code {character-search-backward (M-C-])}}{110} +\entry {\code {clear-screen (C-l)}}{103} +\entry {\code {complete (\key {TAB})}}{107} +\entry {\code {complete-command (M-!)}}{108} +\entry {\code {complete-filename (M-/)}}{108} +\entry {\code {complete-hostname (M-@)}}{108} +\entry {\code {complete-into-braces (M-{\tt \char 123})}}{109} +\entry {\code {complete-username (M-~)}}{108} +\entry {\code {complete-variable (M-$)}}{108} +\entry {\code {copy-backward-word ()}}{107} +\entry {\code {copy-forward-word ()}}{107} +\entry {\code {copy-region-as-kill ()}}{107} \initial {D} -\entry {\code {dabbrev-expand ()}}{112} -\entry {\code {delete-char (C-d)}}{108} -\entry {\code {delete-char-or-list ()}}{111} -\entry {\code {delete-horizontal-space ()}}{110} -\entry {\code {digit-argument (\kbd {M-0}, \kbd {M-1}, \dots {} \kbd {M--})}}{110} -\entry {\code {display-shell-version (C-x C-v)}}{114} -\entry {\code {do-uppercase-version (M-a, M-b, M-\var {x}, \dots {})}}{112} -\entry {\code {downcase-word (M-l)}}{108} -\entry {\code {dump-functions ()}}{113} -\entry {\code {dump-macros ()}}{113} -\entry {\code {dump-variables ()}}{113} -\entry {\code {dynamic-complete-history (M-\key {TAB})}}{112} +\entry {\code {dabbrev-expand ()}}{109} +\entry {\code {delete-char (C-d)}}{105} +\entry {\code {delete-char-or-list ()}}{108} +\entry {\code {delete-horizontal-space ()}}{106} +\entry {\code {digit-argument (\kbd {M-0}, \kbd {M-1}, \dots {} \kbd {M--})}}{107} +\entry {\code {display-shell-version (C-x C-v)}}{111} +\entry {\code {do-uppercase-version (M-a, M-b, M-\var {x}, \dots {})}}{109} +\entry {\code {downcase-word (M-l)}}{105} +\entry {\code {dump-functions ()}}{110} +\entry {\code {dump-macros ()}}{110} +\entry {\code {dump-variables ()}}{110} +\entry {\code {dynamic-complete-history (M-\key {TAB})}}{109} \initial {E} -\entry {\code {edit-and-execute-command (C-xC-e)}}{114} -\entry {\code {end-kbd-macro (C-x ))}}{112} -\entry {\code {end-of-history (M->)}}{107} -\entry {\code {end-of-line (C-e)}}{106} -\entry {\code {exchange-point-and-mark (C-x C-x)}}{113} +\entry {\code {edit-and-execute-command (C-xC-e)}}{111} +\entry {\code {end-kbd-macro (C-x ))}}{109} +\entry {\code {end-of-history (M->)}}{104} +\entry {\code {end-of-line (C-e)}}{103} +\entry {\code {exchange-point-and-mark (C-x C-x)}}{110} \initial {F} -\entry {\code {forward-backward-delete-char ()}}{108} -\entry {\code {forward-char (C-f)}}{106} -\entry {\code {forward-search-history (C-s)}}{107} -\entry {\code {forward-word (M-f)}}{106} +\entry {\code {forward-backward-delete-char ()}}{105} +\entry {\code {forward-char (C-f)}}{103} +\entry {\code {forward-search-history (C-s)}}{104} +\entry {\code {forward-word (M-f)}}{103} \initial {G} -\entry {\code {glob-complete-word (M-g)}}{113} -\entry {\code {glob-expand-word (C-x *)}}{114} -\entry {\code {glob-list-expansions (C-x g)}}{114} +\entry {\code {glob-complete-word (M-g)}}{110} +\entry {\code {glob-expand-word (C-x *)}}{110} +\entry {\code {glob-list-expansions (C-x g)}}{111} \initial {H} -\entry {\code {history-and-alias-expand-line ()}}{114} -\entry {\code {history-expand-line (M-^)}}{114} -\entry {\code {history-search-backward ()}}{107} -\entry {\code {history-search-forward ()}}{107} +\entry {\code {history-and-alias-expand-line ()}}{111} +\entry {\code {history-expand-line (M-^)}}{111} +\entry {\code {history-search-backward ()}}{104} +\entry {\code {history-search-forward ()}}{104} \initial {I} -\entry {\code {insert-comment (M-#)}}{113} -\entry {\code {insert-completions (M-*)}}{111} -\entry {\code {insert-last-argument (M-. or M-_)}}{114} +\entry {\code {insert-comment (M-#)}}{110} +\entry {\code {insert-completions (M-*)}}{108} +\entry {\code {insert-last-argument (M-. or M-_)}}{111} \initial {K} -\entry {\code {kill-line (C-k)}}{109} -\entry {\code {kill-region ()}}{110} -\entry {\code {kill-whole-line ()}}{109} -\entry {\code {kill-word (M-d)}}{109} +\entry {\code {kill-line (C-k)}}{106} +\entry {\code {kill-region ()}}{107} +\entry {\code {kill-whole-line ()}}{106} +\entry {\code {kill-word (M-d)}}{106} \initial {M} -\entry {\code {magic-space ()}}{114} -\entry {\code {menu-complete ()}}{111} +\entry {\code {magic-space ()}}{111} +\entry {\code {menu-complete ()}}{108} \initial {N} -\entry {\code {next-history (C-n)}}{107} -\entry {\code {non-incremental-forward-search-history (M-n)}}{107} -\entry {\code {non-incremental-reverse-search-history (M-p)}}{107} +\entry {\code {next-history (C-n)}}{104} +\entry {\code {non-incremental-forward-search-history (M-n)}}{104} +\entry {\code {non-incremental-reverse-search-history (M-p)}}{104} \initial {O} -\entry {\code {operate-and-get-next (C-o)}}{114} -\entry {\code {overwrite-mode ()}}{109} +\entry {\code {operate-and-get-next (C-o)}}{111} +\entry {\code {overwrite-mode ()}}{106} \initial {P} -\entry {\code {possible-command-completions (C-x !)}}{112} -\entry {\code {possible-completions (M-?)}}{111} -\entry {\code {possible-filename-completions (C-x /)}}{111} -\entry {\code {possible-hostname-completions (C-x @)}}{111} -\entry {\code {possible-username-completions (C-x ~)}}{111} -\entry {\code {possible-variable-completions (C-x $)}}{111} -\entry {\code {prefix-meta (\key {ESC})}}{112} -\entry {\code {previous-history (C-p)}}{107} +\entry {\code {possible-command-completions (C-x !)}}{108} +\entry {\code {possible-completions (M-?)}}{107} +\entry {\code {possible-filename-completions (C-x /)}}{108} +\entry {\code {possible-hostname-completions (C-x @)}}{108} +\entry {\code {possible-username-completions (C-x ~)}}{108} +\entry {\code {possible-variable-completions (C-x $)}}{108} +\entry {\code {prefix-meta (\key {ESC})}}{109} +\entry {\code {previous-history (C-p)}}{104} \initial {Q} -\entry {\code {quoted-insert (C-q or C-v)}}{108} +\entry {\code {quoted-insert (C-q or C-v)}}{105} \initial {R} -\entry {\code {re-read-init-file (C-x C-r)}}{112} -\entry {\code {redraw-current-line ()}}{107} -\entry {\code {reverse-search-history (C-r)}}{107} -\entry {\code {revert-line (M-r)}}{113} +\entry {\code {re-read-init-file (C-x C-r)}}{109} +\entry {\code {redraw-current-line ()}}{103} +\entry {\code {reverse-search-history (C-r)}}{104} +\entry {\code {revert-line (M-r)}}{109} \initial {S} -\entry {\code {self-insert (a, b, A, 1, !, \dots {})}}{108} -\entry {\code {set-mark (C-@)}}{113} -\entry {\code {shell-backward-word ()}}{106} -\entry {\code {shell-expand-line (M-C-e)}}{114} -\entry {\code {shell-forward-word ()}}{106} -\entry {\code {shell-kill-word ()}}{109} -\entry {\code {start-kbd-macro (C-x ()}}{112} +\entry {\code {self-insert (a, b, A, 1, !, \dots {})}}{105} +\entry {\code {set-mark (C-@)}}{110} +\entry {\code {shell-backward-word ()}}{103} +\entry {\code {shell-expand-line (M-C-e)}}{111} +\entry {\code {shell-forward-word ()}}{103} +\entry {\code {shell-kill-word ()}}{106} +\entry {\code {start-kbd-macro (C-x ()}}{109} \initial {T} -\entry {\code {tilde-expand (M-&)}}{113} -\entry {\code {transpose-chars (C-t)}}{108} -\entry {\code {transpose-words (M-t)}}{108} +\entry {\code {tilde-expand (M-&)}}{109} +\entry {\code {transpose-chars (C-t)}}{105} +\entry {\code {transpose-words (M-t)}}{105} \initial {U} -\entry {\code {undo (C-_ or C-x C-u)}}{112} -\entry {\code {universal-argument ()}}{110} -\entry {\code {unix-filename-rubout ()}}{109} -\entry {\code {unix-line-discard (C-u)}}{109} -\entry {\code {unix-word-rubout (C-w)}}{109} -\entry {\code {upcase-word (M-u)}}{108} +\entry {\code {undo (C-_ or C-x C-u)}}{109} +\entry {\code {universal-argument ()}}{107} +\entry {\code {unix-filename-rubout ()}}{106} +\entry {\code {unix-line-discard (C-u)}}{106} +\entry {\code {unix-word-rubout (C-w)}}{106} +\entry {\code {upcase-word (M-u)}}{105} \initial {Y} -\entry {\code {yank (C-y)}}{110} -\entry {\code {yank-last-arg (M-. or M-_)}}{108} -\entry {\code {yank-nth-arg (M-C-y)}}{107} -\entry {\code {yank-pop (M-y)}}{110} +\entry {\code {yank (C-y)}}{107} +\entry {\code {yank-last-arg (M-. or M-_)}}{105} +\entry {\code {yank-nth-arg (M-C-y)}}{104} +\entry {\code {yank-pop (M-y)}}{107} diff --git a/doc/bashref.html b/doc/bashref.html index b47efcad2..2b849bdf2 100644 --- a/doc/bashref.html +++ b/doc/bashref.html @@ -1,6 +1,6 @@ - + + + +