commit bash-20040819 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 13:35:21 -05:00
parent de3341d16e
commit 40b074c61d
15 changed files with 1674 additions and 554 deletions
+34
View File
@@ -9900,3 +9900,37 @@ lib/readline/vi_mode
command) to have the right behavior at EOL -- handle case where vi
mode backs up at the end of the line
8/18
----
array.c
- check for an empty array in array_rshift before shifting elements
and adjusting max_index
- check for null array in array_subrange
jobs.c
- fix raw_job_exit_status to not ignore exit status of the last
process in the pipeline when `set -o pipefail' is enabled
8/19
----
lib/readline/mbutil.c
- make sure _rl_find_next_mbchar_internal has a valid multibyte
character before it checks whether or not it's a zero-width
wide character and adjusts point accordingly
8/24
----
bashline.c
- new function, bash_directory_expansion, duplicates the expansions
performed on the directory name by rl_filename_completion_function
- call bash_directory_expansion in command_word_completion_function
if we decide we're doing tilde expansion (and any other
canonicalization) on the directory name being completed
8/25
----
configure.in
- use new-style AC_CHECK_HEADER to check for sys/ptem.h (which requires
sys/stream.h). The correct checks are in the code, but autoconf
complains if sys/stream.h is not included, rather than simply
checking for the header's presence
+20 -1
View File
@@ -9897,4 +9897,23 @@ builtins/fg_bg.def
lib/readline/vi_mode
- fix _rl_vi_change_mbchar_case (multibyte-char version of `~'
command) to have the right behavior at EOL
command) to have the right behavior at EOL -- handle case where vi
mode backs up at the end of the line
8/18
----
array.c
- check for an empty array in array_rshift before shifting elements
and adjusting max_index
- check for null array in array_subrange
jobs.c
- fix raw_job_exit_status to not ignore exit status of the last
process in the pipeline when `set -o pipefail' is enabled
8/19
----
lib/readline/mbutil.c
- make sure _rl_find_next_mbchar_internal has a valid multibyte
character before it checks whether or not it's a zero-width
wide character and adjusts point accordingly
+11 -9
View File
@@ -107,7 +107,7 @@ ARRAY *a;
ARRAY *a1;
ARRAY_ELEMENT *ae, *new;
if (!a)
if (a == 0)
return((ARRAY *) NULL);
a1 = array_create();
a1->type = a->type;
@@ -243,9 +243,9 @@ char *s;
{
register ARRAY_ELEMENT *ae, *new;
if (a == 0)
if (a == 0 || (array_empty(a) && s == 0))
return 0;
if (n <= 0)
else if (n <= 0)
return (a->num_elements);
ae = element_forw(a->head);
@@ -253,6 +253,8 @@ char *s;
new = array_create_element(0, s);
ADD_BEFORE(ae, new);
a->num_elements++;
if (array_num_elements(a) == 1) /* array was empty */
return 1;
}
a->max_index += n;
@@ -288,7 +290,7 @@ ARRAY *array;
ARRAY_ELEMENT *a;
char *t;
if (array == 0 || array->head == 0 || array_empty (array))
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);
@@ -313,7 +315,7 @@ int starsub, quoted;
arrayind_t i;
char *ifs, sep[2];
p = array_head (a);
p = a ? array_head (a) : 0;
if (p == 0 || array_empty (a) || start > array_max_index(a))
return ((char *)NULL);
@@ -354,10 +356,10 @@ int mflags;
ARRAY_ELEMENT *e;
char *t, *ifs, sifs[2];
if (array_head (a) == 0 || array_empty (a))
if (a == 0 || array_head(a) == 0 || array_empty(a))
return ((char *)NULL);
a2 = array_copy (a);
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));
@@ -427,7 +429,7 @@ char *v;
{
register ARRAY_ELEMENT *new, *ae;
if (!a)
if (a == 0)
return(-1);
new = array_create_element(i, v);
if (i > array_max_index(a)) {
@@ -473,7 +475,7 @@ arrayind_t i;
{
register ARRAY_ELEMENT *ae;
if (!a || array_empty(a))
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) {
+934
View File
@@ -0,0 +1,934 @@
/*
* 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-2004 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#include "config.h"
#if defined (ARRAY_VARS)
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#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));
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;
}
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);
}
#ifdef INCLUDE_UNUSED
/*
* 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 (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(ae);
}
a->num_elements = i;
a->max_index = mi;
return a;
}
#endif
/*
* 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);
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 -= n;
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)
return 0;
else if (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 */
return 1;
}
a->max_index += n;
/*
* Renumber all elements in the array except the one we just added.
*/
for ( ; ae != a->head; ae = element_forw(ae))
element_index(ae) += n;
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;
}
/*
* 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_ELEMENT *h, *p;
arrayind_t i;
char *ifs, sep[2];
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))
;
if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
ifs = getifs();
sep[0] = ifs ? *ifs : '\0';
} else
sep[0] = ' ';
sep[1] = '\0';
return (array_to_string_internal (h, p, sep, quoted));
}
char *
array_patsub (a, pat, rep, mflags)
ARRAY *a;
char *pat, *rep;
int mflags;
{
ARRAY *a2;
ARRAY_ELEMENT *e;
char *t, *ifs, sifs[2];
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);
if (mflags & MATCH_STARSUB) {
ifs = getifs();
sifs[0] = ifs ? *ifs : '\0';
sifs[1] = '\0';
t = array_to_string (a2, sifs, 0);
} 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++;
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;
return(0);
} else if (element_index(ae) > i) {
ADD_BEFORE(ae, new);
a->num_elements++;
return(0);
}
}
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);
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);
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);
}
/* 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 all the elements in A,
* 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 (indstr) + 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 */
+48 -3
View File
@@ -1,5 +1,5 @@
@%:@! /bin/sh
@%:@ From configure.in for Bash 3.0, version 3.167, from autoconf version AC_ACVERSION.
@%:@ From configure.in for Bash 3.0, version 3.168, from autoconf version AC_ACVERSION.
@%:@ Guess values for system-dependent variables and create Makefiles.
@%:@ Generated by GNU Autoconf 2.57 for bash 3.0-release.
@%:@
@@ -9622,8 +9622,7 @@ done
for ac_header in sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \
for ac_header in sys/pte.h sys/stream.h sys/select.h sys/file.h \
sys/resource.h sys/param.h sys/socket.h sys/stat.h \
sys/time.h sys/times.h sys/types.h sys/wait.h
do
@@ -9910,6 +9909,52 @@ fi
done
echo "$as_me:$LINENO: checking for sys/ptem.h" >&5
echo $ECHO_N "checking for sys/ptem.h... $ECHO_C" >&6
if test "${ac_cv_header_sys_ptem_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#if HAVE_SYS_STREAM_H
# include <sys/stream.h>
#endif
@%:@include <sys/ptem.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_header_sys_ptem_h=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_header_sys_ptem_h=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_header_sys_ptem_h" >&5
echo "${ECHO_T}$ac_cv_header_sys_ptem_h" >&6
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo "$as_me:$LINENO: checking for working alloca.h" >&5
+86 -86
View File
@@ -15,96 +15,96 @@
'configure.in'
],
{
'm4_include' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'AC_FUNC_STRERROR_R' => 1,
'AC_FUNC_FORK' => 1,
'AC_C_VOLATILE' => 1,
'AC_FUNC_STRCOLL' => 1,
'AC_FUNC_MKTIME' => 1,
'AC_HEADER_TIME' => 1,
'AC_STRUCT_TIMEZONE' => 1,
'AC_FUNC_REALLOC' => 1,
'AC_TYPE_MODE_T' => 1,
'AM_GNU_GETTEXT' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_FUNC_UTIME_NULL' => 1,
'AC_FUNC_STRFTIME' => 1,
'AC_CHECK_LIB' => 1,
'AC_PROG_INSTALL' => 1,
'AC_HEADER_MAJOR' => 1,
'AC_REPLACE_FNMATCH' => 1,
'include' => 1,
'AC_INIT' => 1,
'AC_FUNC_ERROR_AT_LINE' => 1,
'AC_PROG_CPP' => 1,
'AC_PROG_LIBTOOL' => 1,
'AC_PATH_X' => 1,
'AC_DECL_SYS_SIGLIST' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_STRUCT_ST_BLOCKS' => 1,
'AC_FUNC_CLOSEDIR_VOID' => 1,
'AC_TYPE_SIZE_T' => 1,
'AC_FUNC_FSEEKO' => 1,
'm4_pattern_forbid' => 1,
'AC_FUNC_SETPGRP' => 1,
'm4_pattern_allow' => 1,
'AC_FUNC_STAT' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_HEADER_STDC' => 1,
'AC_FUNC_STRTOD' => 1,
'AC_CHECK_MEMBERS' => 1,
'AC_PROG_CXX' => 1,
'AC_FUNC_MMAP' => 1,
'AC_TYPE_SIGNAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_C_CONST' => 1,
'AC_CHECK_TYPES' => 1,
'AC_FUNC_CHOWN' => 1,
'AC_FUNC_GETMNTENT' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_CONDITIONAL' => 1,
'AC_FUNC_MBRTOWC' => 1,
'AC_HEADER_SYS_WAIT' => 1,
'AC_C_INLINE' => 1,
'AC_PROG_MAKE_SET' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'AC_FUNC_GETPGRP' => 1,
'AH_OUTPUT' => 1,
'AC_PROG_AWK' => 1,
'AC_FUNC_VPRINTF' => 1,
'AC_FUNC_MEMCMP' => 1,
'AC_FUNC_SELECT_ARGTYPES' => 1,
'AC_HEADER_STAT' => 1,
'AC_PROG_LN_S' => 1,
'AC_PROG_CC' => 1,
'AC_STRUCT_TM' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AC_SUBST' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_TYPE_PID_T' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AC_PROG_GCC_TRADITIONAL' => 1,
'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
'AC_CHECK_HEADERS' => 1,
'AC_FUNC_OBSTACK' => 1,
'AC_CHECK_FUNCS' => 1,
'AC_HEADER_DIRENT' => 1,
'AC_FUNC_LSTAT' => 1,
'AC_PROG_LEX' => 1,
'AC_PROG_YACC' => 1,
'AC_TYPE_OFF_T' => 1,
'AC_PROG_RANLIB' => 1,
'AC_CONFIG_FILES' => 1,
'AC_FUNC_GETLOADAVG' => 1,
'AC_FUNC_ALLOCA' => 1,
'AC_FUNC_STRNLEN' => 1,
'AC_TYPE_UID_T' => 1,
'AC_LIBSOURCE' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'AC_C_CONST' => 1,
'AC_PROG_RANLIB' => 1,
'AC_FUNC_CHOWN' => 1,
'AC_FUNC_MBRTOWC' => 1,
'AC_CANONICAL_HOST' => 1,
'm4_pattern_forbid' => 1,
'AC_HEADER_SYS_WAIT' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_FUNC_SETPGRP' => 1,
'AC_REPLACE_FNMATCH' => 1,
'AC_FUNC_STAT' => 1,
'AC_FUNC_STRERROR_R' => 1,
'AC_HEADER_STDC' => 1,
'AC_FUNC_WAIT3' => 1,
'AC_FUNC_CLOSEDIR_VOID' => 1,
'AM_GNU_GETTEXT' => 1,
'AC_FUNC_OBSTACK' => 1,
'AC_FUNC_REALLOC' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_CONFIG_FILES' => 1,
'AC_FUNC_MKTIME' => 1,
'm4_pattern_allow' => 1,
'AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK' => 1,
'AC_INIT' => 1,
'AC_FUNC_VPRINTF' => 1,
'AC_PROG_LIBTOOL' => 1,
'AC_STRUCT_ST_BLOCKS' => 1,
'AC_PATH_X' => 1,
'AC_LIBSOURCE' => 1,
'AC_FUNC_MALLOC' => 1,
'AC_FUNC_STRNLEN' => 1,
'AC_FUNC_ERROR_AT_LINE' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AC_HEADER_DIRENT' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_STRUCT_TIMEZONE' => 1,
'AC_PROG_CC' => 1,
'AC_FUNC_GETGROUPS' => 1,
'AC_FUNC_SETVBUF_REVERSED' => 1
'AC_FUNC_FORK' => 1,
'AC_TYPE_PID_T' => 1,
'AC_PROG_MAKE_SET' => 1,
'AC_HEADER_TIME' => 1,
'AC_FUNC_UTIME_NULL' => 1,
'AC_FUNC_MEMCMP' => 1,
'AC_HEADER_MAJOR' => 1,
'AC_PROG_CPP' => 1,
'AC_FUNC_SETVBUF_REVERSED' => 1,
'include' => 1,
'AC_FUNC_FSEEKO' => 1,
'AC_HEADER_STAT' => 1,
'AC_C_INLINE' => 1,
'AC_FUNC_GETMNTENT' => 1,
'AM_CONDITIONAL' => 1,
'AC_STRUCT_TM' => 1,
'AC_FUNC_LSTAT' => 1,
'AC_DECL_SYS_SIGLIST' => 1,
'AC_SUBST' => 1,
'AC_FUNC_ALLOCA' => 1,
'AC_FUNC_STRFTIME' => 1,
'AC_FUNC_GETLOADAVG' => 1,
'AC_PROG_YACC' => 1,
'AC_TYPE_SIGNAL' => 1,
'AC_FUNC_MMAP' => 1,
'AC_PROG_INSTALL' => 1,
'AH_OUTPUT' => 1,
'AC_FUNC_SELECT_ARGTYPES' => 1,
'AC_FUNC_STRTOD' => 1,
'AC_PROG_GCC_TRADITIONAL' => 1,
'AC_FUNC_GETPGRP' => 1,
'AC_CHECK_TYPES' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_FUNC_STRCOLL' => 1,
'AC_CHECK_FUNCS' => 1,
'AC_PROG_AWK' => 1,
'AC_CHECK_MEMBERS' => 1,
'AC_PROG_LEX' => 1,
'AC_C_VOLATILE' => 1,
'AC_TYPE_MODE_T' => 1,
'AC_TYPE_OFF_T' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AC_PROG_LN_S' => 1,
'AC_TYPE_SIZE_T' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_PROG_CXX' => 1,
'AC_CHECK_HEADERS' => 1,
'm4_include' => 1,
'AC_CHECK_LIB' => 1
}
], 'Request' )
);
+436 -438
View File
File diff suppressed because it is too large Load Diff
+31 -1
View File
@@ -100,6 +100,7 @@ static int history_and_alias_expand_line __P((int, int));
#endif
/* Helper functions for Readline. */
static int bash_directory_expansion __P((char **));
static int bash_directory_completion_hook __P((char **));
static int filename_completion_ignore __P((char **));
static int bash_push_line __P((void));
@@ -1406,10 +1407,18 @@ command_word_completion_function (hint_text, state)
filename. */
if (*hint_text == '~')
{
int l, tl, vl;
int l, tl, vl, dl;
char *rd;
vl = strlen (val);
tl = strlen (hint_text);
#if 0
l = vl - hint_len; /* # of chars added */
#else
rd = savestring (filename_hint);
bash_directory_expansion (&rd);
dl = strlen (rd);
l = vl - dl; /* # of chars added */
#endif
temp = (char *)xmalloc (l + 2 + tl);
strcpy (temp, hint_text);
strcpy (temp + tl, val + vl - l);
@@ -2187,6 +2196,27 @@ bash_ignore_everything (names)
return 0;
}
/* Simulate the expansions that will be performed by
rl_filename_completion_function. This must be called with the address of
a pointer to malloc'd memory. */
static int
bash_directory_expansion (dirname)
char **dirname;
{
char *d;
d = savestring (*dirname);
if (rl_directory_rewrite_hook)
(*rl_directory_rewrite_hook) (&d);
if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
{
free (*dirname);
*dirname = d;
}
}
/* Handle symbolic link references and other directory name
expansions while hacking completion. */
static int
Vendored
+48 -3
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in for Bash 3.0, version 3.167, from autoconf version AC_ACVERSION.
# From configure.in for Bash 3.0, version 3.168, from autoconf version AC_ACVERSION.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.57 for bash 3.0-release.
#
@@ -9622,8 +9622,7 @@ done
for ac_header in sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \
for ac_header in sys/pte.h sys/stream.h sys/select.h sys/file.h \
sys/resource.h sys/param.h sys/socket.h sys/stat.h \
sys/time.h sys/times.h sys/types.h sys/wait.h
do
@@ -9910,6 +9909,52 @@ fi
done
echo "$as_me:$LINENO: checking for sys/ptem.h" >&5
echo $ECHO_N "checking for sys/ptem.h... $ECHO_C" >&6
if test "${ac_cv_header_sys_ptem_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#if HAVE_SYS_STREAM_H
# include <sys/stream.h>
#endif
#include <sys/ptem.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_header_sys_ptem_h=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_header_sys_ptem_h=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $ac_cv_header_sys_ptem_h" >&5
echo "${ECHO_T}$ac_cv_header_sys_ptem_h" >&6
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo "$as_me:$LINENO: checking for working alloca.h" >&5
+10 -2
View File
@@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script.
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
AC_REVISION([for Bash 3.0, version 3.167, from autoconf version] AC_ACVERSION)dnl
AC_REVISION([for Bash 3.0, version 3.168, from autoconf version] AC_ACVERSION)dnl
define(bashvers, 3.0)
define(relstatus, release)
@@ -574,11 +574,19 @@ BASH_HEADER_INTTYPES
AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
memory.h locale.h termcap.h termio.h termios.h dlfcn.h \
stddef.h stdint.h netdb.h grp.h strings.h regex.h)
AC_CHECK_HEADERS(sys/ptem.h sys/pte.h sys/stream.h sys/select.h sys/file.h \
AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h \
sys/resource.h sys/param.h sys/socket.h sys/stat.h \
sys/time.h sys/times.h sys/types.h sys/wait.h)
AC_CHECK_HEADERS(netinet/in.h arpa/inet.h)
dnl sys/ptem.h requires definitions from sys/stream.h on systems where it
dnl exists
AC_CHECK_HEADER(sys/ptem.h, , ,[[
#if HAVE_SYS_STREAM_H
# include <sys/stream.h>
#endif
]])
dnl special checks for libc functions
AC_FUNC_ALLOCA
AC_FUNC_GETPGRP
+1 -1
View File
@@ -8232,7 +8232,7 @@ command, and before the first command executes in a shell function (see
.SM
.B SHELL GRAMMAR
above).
Refer to the description of the \fBextglob\fP option to the
Refer to the description of the \fBextdebug\fP option to the
\fBshopt\fP builtin for details of its effect on the \fBDEBUG\fP trap.
If a
.I sigspec
+5 -5
View File
@@ -6,7 +6,7 @@
.\" Case Western Reserve University
.\" chet@po.CWRU.Edu
.\"
.\" Last Change: Sat Jun 26 14:26:44 EDT 2004
.\" Last Change: Mon Aug 16 23:07:25 EDT 2004
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
@@ -5872,8 +5872,8 @@ is supplied, the name and value of the alias is printed.
\fBAlias\fP returns true unless a \fIname\fP is given for which
no alias has been defined.
.TP
\fBbg\fP [\fIjobspec\fP]
Resume the suspended job \fIjobspec\fP in the background, as if it
\fBbg\fP [\fIjobspec\fP ...]
Resume each suspended job \fIjobspec\fP in the background, as if it
had been started with
.BR & .
If \fIjobspec\fP is not present, the shell's notion of the
@@ -5881,8 +5881,8 @@ If \fIjobspec\fP is not present, the shell's notion of the
.B bg
.I jobspec
returns 0 unless run when job control is disabled or, when run with
job control enabled, if \fIjobspec\fP was not found or started without
job control.
job control enabled, if the last \fIjobspec\fP was not found or was
started without job control.
.TP
\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
.PD 0
+7 -2
View File
@@ -1778,8 +1778,13 @@ raw_job_exit_status (job)
if (pipefail_opt)
{
fail = 0;
for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
if (p->status != EXECUTION_SUCCESS) fail = p->status;
p = jobs[job]->pipe;
do
{
if (p->status != EXECUTION_SUCCESS) fail = p->status;
p = p->next;
}
while (p != jobs[job]->pipe);
return fail;
}
+2 -2
View File
@@ -126,11 +126,11 @@ _rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
if (find_non_zero)
{
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
while (wcwidth (wc) == 0)
while (tmp > 0 && wcwidth (wc) == 0)
{
point += tmp;
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
if (tmp == (size_t)(0) || tmp == (size_t)(-1) || tmp == (size_t)(-2))
if (MB_NULLWCH (tmp) || MB_INVALIDCH (tmp))
break;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR