mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 18:30:49 +02:00
commit bash-20070111 snapshot
This commit is contained in:
@@ -14183,3 +14183,99 @@ lib/intl/Makefile.in
|
||||
lib/builtins/Makefile
|
||||
- fixes to build LIBINTL_H if necessary, dependency on this for
|
||||
mkbuiltins.o prevented `make -j 6' from working correctly
|
||||
|
||||
1/8
|
||||
---
|
||||
subst.c
|
||||
- new function, fifos_pending(), returns the count of FIFOs in
|
||||
fifo_list (process substitution)
|
||||
|
||||
subst.h
|
||||
- extern declaration for fifos_pending()
|
||||
|
||||
execute_cmd.c
|
||||
- in execute_simple_command, if CMD_NO_FORK is set before we call
|
||||
execute_disk_command, make sure there are no FIFOs in the expanded
|
||||
words (from process substitution) and turn off CMD_NO_FORK if there
|
||||
are, so they can get unlinked when the command finishes
|
||||
|
||||
1/10
|
||||
----
|
||||
subst.c
|
||||
- read_comsub now takes a flags parameter and returns appropriate W_*
|
||||
flags in it
|
||||
- command_substitute now returns a WORD_DESC *, with the string it used
|
||||
to return as the `word' and `flags' filled in appropriately
|
||||
|
||||
subst.h
|
||||
- changed extern declaration for command_substitute
|
||||
|
||||
{pcomplete,subst}.c
|
||||
- changed callers of command_substitute appropriately
|
||||
|
||||
subst.c
|
||||
- string_extract_verbatim now takes an additional int flags argument;
|
||||
changed callers
|
||||
|
||||
1/11
|
||||
----
|
||||
support/texi2html
|
||||
- fix problem that caused index links to not be generated if the first
|
||||
index node had a name different than the node name
|
||||
|
||||
doc/bashref.texi
|
||||
- encapsulated all indexes into a single `Indexes' appendix; works
|
||||
around bug fixed in texi2html
|
||||
|
||||
1/12
|
||||
----
|
||||
subst.c
|
||||
- add call to sv_histtimefmt in initialize_variables so HISTTIMEFORMAT
|
||||
rom the environment is honored. Fix from Ark Submedes (heh)
|
||||
<archimerged@gmail.com>
|
||||
|
||||
lib/readline/histfile.c
|
||||
- make sure that the first character following the history comment
|
||||
character at the beginning of a line is a digit before interpreting
|
||||
it as a timestamp for the previous line
|
||||
|
||||
doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi
|
||||
- added detail to make it clear exactly how history timestamps are
|
||||
saved to and read from the history file
|
||||
|
||||
subst.c
|
||||
- change quote_escapes to add CTLESC before spaces if IFS is null,
|
||||
just in case we have to split on literal spaces later on (e.g., in
|
||||
case of unquoted $@). Corresponding changes to dequote_escapes.
|
||||
Fixes a couple of problems reported by Brett Stahlman
|
||||
<brettstahlman@comcast.net>
|
||||
|
||||
1/14
|
||||
----
|
||||
subst.c
|
||||
- make same change to read_comsub to add CTLESC before ' ' if $IFS is
|
||||
null, since we will split on literal spaces later
|
||||
|
||||
1/15
|
||||
----
|
||||
array.c
|
||||
- new function, array_quote_escapes (ARRAY *a), calls quote_escapes
|
||||
on each element of the array in the same way array_quote calls
|
||||
quote_string
|
||||
- call array_quote_escapes if match is not quoted in array_patsub
|
||||
- array_slice is now used, so remove the #ifdef INCLUDE_UNUSED define
|
||||
- change structure of array_subrange to call array_slice to create a
|
||||
new array with the desired subset of elements, then call array_quote
|
||||
or array_quote_escapes as necessary, like array_patsub. Convert to
|
||||
a string by calling array_to_string on the sliced-out array
|
||||
|
||||
array.h
|
||||
- new extern declaration for array_quote_escapes
|
||||
|
||||
subst.c
|
||||
- since array_patsub now calls quote_escapes as necessary, callers
|
||||
don't need to call it after array_patsub returns. Fixes first bug
|
||||
reported by Brett Stahlman <brettstahlman@comcast.net>
|
||||
- since array_subrange now calls quote_escapes as necessary, callers
|
||||
don't need to call it after array_patsub returns. Same fix as
|
||||
for array_patsub
|
||||
|
||||
+99
-1
@@ -14171,5 +14171,103 @@ doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi
|
||||
|
||||
[many files]
|
||||
- changes to make variables and function parameters `const' for better
|
||||
text sharing
|
||||
text sharing. Changes originally from Andreas Mohr
|
||||
<andi@rhlx01.fht-esslingen.de>
|
||||
|
||||
1/4/2007
|
||||
--------
|
||||
lib/intl/Makefile.in
|
||||
- use cmp before copying libgnuintl.h to libintl.h -- maybe save a few
|
||||
rebuilds
|
||||
|
||||
lib/builtins/Makefile
|
||||
- fixes to build LIBINTL_H if necessary, dependency on this for
|
||||
mkbuiltins.o prevented `make -j 6' from working correctly
|
||||
|
||||
1/8
|
||||
---
|
||||
subst.c
|
||||
- new function, fifos_pending(), returns the count of FIFOs in
|
||||
fifo_list (process substitution)
|
||||
|
||||
subst.h
|
||||
- extern declaration for fifos_pending()
|
||||
|
||||
execute_cmd.c
|
||||
- in execute_simple_command, if CMD_NO_FORK is set before we call
|
||||
execute_disk_command, make sure there are no FIFOs in the expanded
|
||||
words (from process substitution) and turn off CMD_NO_FORK if there
|
||||
are, so they can get unlinked when the command finishes
|
||||
|
||||
1/10
|
||||
----
|
||||
subst.c
|
||||
- read_comsub now takes a flags parameter and returns appropriate W_*
|
||||
flags in it
|
||||
- command_substitute now returns a WORD_DESC *, with the string it used
|
||||
to return as the `word' and `flags' filled in appropriately
|
||||
|
||||
subst.h
|
||||
- changed extern declaration for command_substitute
|
||||
|
||||
{pcomplete,subst}.c
|
||||
- changed callers of command_substitute appropriately
|
||||
|
||||
subst.c
|
||||
- string_extract_verbatim now takes an additional int flags argument;
|
||||
changed callers
|
||||
|
||||
1/11
|
||||
----
|
||||
support/texi2html
|
||||
- fix problem that caused index links to not be generated if the first
|
||||
index node had a name different than the node name
|
||||
|
||||
doc/bashref.texi
|
||||
- encapsulated all indexes into a single `Indexes' appendix; works
|
||||
around bug fixed in texi2html
|
||||
|
||||
1/12
|
||||
----
|
||||
subst.c
|
||||
- add call to sv_histtimefmt in initialize_variables so HISTTIMEFORMAT
|
||||
rom the environment is honored. Fix from Ark Submedes (heh)
|
||||
<archimerged@gmail.com>
|
||||
|
||||
lib/readline/histfile.c
|
||||
- make sure that the first character following the history comment
|
||||
character at the beginning of a line is a digit before interpreting
|
||||
it as a timestamp for the previous line
|
||||
|
||||
doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi
|
||||
- added detail to make it clear exactly how history timestamps are
|
||||
saved to and read from the history file
|
||||
|
||||
subst.c
|
||||
- change quote_escapes to add CTLESC before spaces if IFS is null,
|
||||
just in case we have to split on literal spaces later on (e.g., in
|
||||
case of unquoted $@). Corresponding changes to dequote_escapes.
|
||||
Fixes a couple of problems reported by Brett Stahlman
|
||||
<brettstahlman@comcast.net>
|
||||
|
||||
1/14
|
||||
----
|
||||
subst.c
|
||||
- make same change to read_comsub to add CTLESC before ' ' if $IFS is
|
||||
null, since we will split on literal spaces later
|
||||
|
||||
1/15
|
||||
----
|
||||
array.c
|
||||
- new function, array_quote_escapes (ARRAY *a), calls quote_escapes
|
||||
on each element of the array in the same way array_quote calls
|
||||
quote_string
|
||||
- call array_quote_escapes if match is not quoted in array_patsub
|
||||
|
||||
array.h
|
||||
- new extern declaration for array_quote_escapes
|
||||
|
||||
subst.c
|
||||
- since array_patsub now calls quote_escapes as necessary, callers
|
||||
don't need to call it after array_patsub returns. Fixes first bug
|
||||
reported by Brett Stahlman <brettstahlman@comcast.net>
|
||||
|
||||
@@ -120,7 +120,6 @@ ARRAY *a;
|
||||
return(a1);
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/*
|
||||
* Make and return a new array composed of the elements in array A from
|
||||
* S to E, inclusive.
|
||||
@@ -141,13 +140,12 @@ ARRAY_ELEMENT *s, *e;
|
||||
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);
|
||||
mi = element_index(n);
|
||||
}
|
||||
a->num_elements = i;
|
||||
a->max_index = mi;
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Walk the array, calling FUNC once for each element, with the array
|
||||
@@ -300,6 +298,23 @@ ARRAY *array;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string whose elements are the members of array A beginning at
|
||||
* index START and spanning NELEM members. Null elements are counted.
|
||||
@@ -311,9 +326,10 @@ ARRAY *a;
|
||||
arrayind_t start, nelem;
|
||||
int starsub, quoted;
|
||||
{
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *h, *p;
|
||||
arrayind_t i;
|
||||
char *ifs, sep[2];
|
||||
char *ifs, sep[2], *t;
|
||||
|
||||
p = a ? array_head (a) : 0;
|
||||
if (p == 0 || array_empty (a) || start > array_max_index(a))
|
||||
@@ -336,6 +352,13 @@ int starsub, quoted;
|
||||
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))) {
|
||||
ifs = getifs();
|
||||
sep[0] = ifs ? *ifs : '\0';
|
||||
@@ -343,7 +366,10 @@ int starsub, quoted;
|
||||
sep[0] = ' ';
|
||||
sep[1] = '\0';
|
||||
|
||||
return (array_to_string_internal (h, p, sep, quoted));
|
||||
t = array_to_string (a2, sep, 0);
|
||||
array_dispose(a2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *
|
||||
@@ -367,7 +393,9 @@ int mflags;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
array_quote (a2);
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
if (mflags & MATCH_STARSUB) {
|
||||
ifs = getifs();
|
||||
sifs[0] = ifs ? *ifs : '\0';
|
||||
|
||||
@@ -0,0 +1,960 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(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);
|
||||
|
||||
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 || (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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, sep[2], *t;
|
||||
|
||||
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 (mflags & MATCH_QUOTED)
|
||||
array_quote (a2);
|
||||
else
|
||||
array_quote_escapes (a2);
|
||||
|
||||
if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
|
||||
ifs = getifs();
|
||||
sep[0] = ifs ? *ifs : '\0';
|
||||
} else
|
||||
sep[0] = ' ';
|
||||
sep[1] = '\0';
|
||||
|
||||
t = array_to_string (a2, sep, 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, *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);
|
||||
else
|
||||
array_quote_escapes (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 */
|
||||
@@ -55,6 +55,7 @@ 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 char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
|
||||
extern char *array_patsub __P((ARRAY *, char *, char *, int));
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/* array.h -- definitions for the interface exported by array.c that allows
|
||||
the rest of the shell to manipulate array variables. */
|
||||
|
||||
/* Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#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 char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
|
||||
extern char *array_patsub __P((ARRAY *, char *, char *, 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_ */
|
||||
@@ -55,7 +55,7 @@
|
||||
*/
|
||||
|
||||
/* The character which is used to separate arguments. */
|
||||
int brace_arg_separator = ',';
|
||||
static const int brace_arg_separator = ',';
|
||||
|
||||
#if defined (__P)
|
||||
static int brace_gobbler __P((char *, size_t, int *, int));
|
||||
|
||||
@@ -88,6 +88,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define W_HASQUOTEDNULL 0x040000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x080000 /* word should be treated as if double-quoted */
|
||||
#define W_NOPROCSUB 0x100000 /* don't perform process substitution */
|
||||
#define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
|
||||
@@ -908,7 +908,9 @@ D1) Why does bash run a different version of `command' than
|
||||
On many systems, `which' is actually a csh script that assumes
|
||||
you're running csh. In tcsh, `which' and its cousin `where'
|
||||
are builtins. On other Unix systems, `which' is a perl script
|
||||
that uses the PATH environment variable.
|
||||
that uses the PATH environment variable. Many Linux distributions
|
||||
use GNU `which', which is a C program that can understand shell
|
||||
aliases.
|
||||
|
||||
The csh script version reads the csh startup files from your
|
||||
home directory and uses those to determine which `command' will
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
# This Makefile is for the Bash/documentation directory -*- text -*-.
|
||||
#
|
||||
# Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
PACKAGE = bash
|
||||
VERSION = 3.2-maint
|
||||
|
||||
PACKAGE_BUGREPORT = bug-bash@gnu.org
|
||||
PACKAGE_NAME = bash
|
||||
PACKAGE_STRING = bash 3.2-maint
|
||||
PACKAGE_VERSION = 3.2-maint
|
||||
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
RM = rm -f
|
||||
|
||||
topdir = /Users/chet/src/bash/src
|
||||
srcdir = /Users/chet/src/bash/src/doc
|
||||
VPATH = .:/Users/chet/src/bash/src/doc
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
|
||||
infodir = ${prefix}/share/info
|
||||
|
||||
# set this to a directory name to have the HTML files installed
|
||||
htmldir = ${docdir}
|
||||
|
||||
# Support an alternate destination root directory for package building
|
||||
DESTDIR =
|
||||
|
||||
mandir = ${prefix}/share/man
|
||||
manpfx = man
|
||||
|
||||
man1ext = .1
|
||||
man1dir = $(mandir)/$(manpfx)1
|
||||
man3ext = .3
|
||||
man3dir = $(mandir)/$(manpfx)3
|
||||
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
BUILD_DIR = /usr/local/build/chet/bash/bash-current
|
||||
|
||||
SUPPORT_SRCDIR = $(topdir)/support
|
||||
|
||||
# bad style
|
||||
RL_LIBDIR = $(topdir)/lib/readline
|
||||
|
||||
# unused
|
||||
TEXINDEX = texindex
|
||||
TEX = tex
|
||||
|
||||
MAKEINFO = makeinfo
|
||||
TEXI2DVI = ${SUPPORT_SRCDIR}/texi2dvi
|
||||
TEXI2HTML = ${SUPPORT_SRCDIR}/texi2html
|
||||
MAN2HTML = ${BUILD_DIR}/support/man2html
|
||||
HTMLPOST = ${srcdir}/htmlpost.sh
|
||||
INFOPOST = ${srcdir}/infopost.sh
|
||||
QUIETPS = #set this to -q to shut up dvips
|
||||
PAPERSIZE = letter # change to a4 for A4-size paper
|
||||
PSDPI = 600 # could be 300 if you like
|
||||
DVIPS = dvips -D ${PSDPI} $(QUIETPS) -t ${PAPERSIZE} -o $@ # tricky
|
||||
|
||||
TEXINPUTDIR = $(RL_LIBDIR)/doc
|
||||
SET_TEXINPUTS = TEXINPUTS=.:$(TEXINPUTDIR):$$TEXINPUTS
|
||||
|
||||
# These tools might not be available; they're not required
|
||||
DVIPDF = dvipdfm -o $@ -p ${PAPERSIZE}
|
||||
PSPDF = gs -sPAPERSIZE=${PAPERSIZE} -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -sOutputFile=$@
|
||||
|
||||
MKDIRS = ${SUPPORT_SRCDIR}/mkdirs
|
||||
|
||||
# This should be a program that converts troff to an ascii-readable format
|
||||
NROFF = groff -Tascii
|
||||
|
||||
# This should be a program that converts troff to postscript
|
||||
GROFF = groff
|
||||
|
||||
HSUSER = $(RL_LIBDIR)/doc/hsuser.texi
|
||||
RLUSER = $(RL_LIBDIR)/doc/rluser.texi
|
||||
|
||||
BASHREF_FILES = $(srcdir)/bashref.texi $(srcdir)/version.texi
|
||||
|
||||
.SUFFIXES: .0 .1 .3 .ms .ps .txt .dvi .html .pdf
|
||||
|
||||
.1.ps:
|
||||
$(RM) $@
|
||||
-${GROFF} -man $< > $@
|
||||
|
||||
.1.0:
|
||||
$(RM) $@
|
||||
-${NROFF} -man $< > $@
|
||||
|
||||
.1.html:
|
||||
$(RM) $@
|
||||
-${MAN2HTML} $< | ${HTMLPOST} > $@
|
||||
|
||||
.ms.ps:
|
||||
$(RM) $@
|
||||
-${GROFF} -ms $< > $@
|
||||
|
||||
.ms.txt:
|
||||
$(RM) $@
|
||||
-${NROFF} -ms $< > $@
|
||||
|
||||
.3.ps:
|
||||
$(RM) $@
|
||||
-${GROFF} -man $< > $@
|
||||
|
||||
.3.0:
|
||||
$(RM) $@
|
||||
-${NROFF} -man $< > $@
|
||||
|
||||
.3.html:
|
||||
$(RM) $@
|
||||
-${MAN2HTML} $< > $@
|
||||
|
||||
.ps.pdf:
|
||||
$(RM) $@
|
||||
-${PSPDF} $<
|
||||
|
||||
.dvi.pdf:
|
||||
$(RM) $@
|
||||
-${DVIPDF} $<
|
||||
|
||||
.dvi.ps:
|
||||
${RM} $@
|
||||
-${DVIPS} $<
|
||||
|
||||
all: ps info dvi text html
|
||||
nodvi: ps info text html
|
||||
|
||||
PSFILES = bash.ps bashbug.ps article.ps builtins.ps rbash.ps
|
||||
DVIFILES = bashref.dvi bashref.ps
|
||||
INFOFILES = bashref.info
|
||||
MAN0FILES = bash.0 bashbug.0 builtins.0 rbash.0
|
||||
HTMLFILES = bashref.html bash.html
|
||||
PDFFILES = bash.pdf bashref.pdf article.pdf rose94.pdf
|
||||
|
||||
ps: ${PSFILES}
|
||||
dvi: ${DVIFILES}
|
||||
info: ${INFOFILES}
|
||||
text: ${MAN0FILES}
|
||||
html: ${HTMLFILES}
|
||||
pdf: ${PDFFILES}
|
||||
|
||||
bashref.dvi: $(BASHREF_FILES) $(HSUSER) $(RLUSER)
|
||||
${SET_TEXINPUTS} $(TEXI2DVI) $(srcdir)/bashref.texi
|
||||
|
||||
bashref.info: $(BASHREF_FILES) $(HSUSER) $(RLUSER)
|
||||
$(MAKEINFO) --no-split -I$(TEXINPUTDIR) $(srcdir)/bashref.texi
|
||||
|
||||
bashref.html: $(BASHREF_FILES) $(HSUSER) $(RLUSER)
|
||||
$(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/bashref.texi
|
||||
|
||||
b.html: $(BASHREF_FILES) $(HSUSER) $(RLUSER)
|
||||
./texi2html.debug -o $@ -verbose -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/bashref.texi
|
||||
|
||||
bash.info: bashref.info
|
||||
${SHELL} ${INFOPOST} < $(srcdir)/bashref.info > $@ ; \
|
||||
|
||||
bash.txt: bash.1
|
||||
bash.ps: bash.1
|
||||
bash.html: bash.1 $(MAN2HTML)
|
||||
bashbug.ps: bashbug.1
|
||||
builtins.ps: builtins.1 bash.1
|
||||
rbash.ps: rbash.1 bash.1
|
||||
bash.0: bash.1
|
||||
bashbug.0: bashbug.1
|
||||
builtins.0: builtins.1 bash.1
|
||||
rbash.0: rbash.1 bash.1
|
||||
article.ps: article.ms
|
||||
|
||||
bashref.ps: bashref.dvi
|
||||
|
||||
article.pdf: article.ps
|
||||
bashref.pdf: bashref.dvi
|
||||
bash.pdf: bash.ps
|
||||
rose94.pdf: rose94.ps
|
||||
|
||||
$(MAN2HTML): ${topdir}/support/man2html.c
|
||||
-( cd ${BUILD_DIR}/support ; ${MAKE} ${MFLAGS} man2html)
|
||||
|
||||
clean:
|
||||
$(RM) *.aux *.bak *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps \
|
||||
*.pgs *.bt *.bts *.rw *.rws *.fns *.kys *.tps *.vrs *.o
|
||||
${RM} core *.core
|
||||
|
||||
mostlyclean: clean
|
||||
$(RM) Makefile
|
||||
|
||||
distclean: clean maybe-clean
|
||||
$(RM) Makefile
|
||||
|
||||
maintainer-clean: clean
|
||||
${RM} ${PSFILES} ${DVIFILES} ${INFOFILES} ${MAN0FILES} ${HTMLFILES}
|
||||
${RM} ${CREATED_FAQ}
|
||||
$(RM) Makefile
|
||||
|
||||
maybe-clean:
|
||||
-if test "X$(topdir)" != "X$(BUILD_DIR)"; then \
|
||||
$(RM) ${PSFILES} ${DVIFILES} ${INFOFILES} ${MAN0FILES} ${HTMLFILES}; \
|
||||
fi
|
||||
|
||||
installdirs:
|
||||
-$(SHELL) $(SUPPORT_SRCDIR)/mkinstalldirs $(DESTDIR)$(man1dir)
|
||||
-$(SHELL) $(SUPPORT_SRCDIR)/mkinstalldirs $(DESTDIR)$(infodir)
|
||||
-if test -n "$(htmldir)" ; then \
|
||||
$(SHELL) $(SUPPORT_SRCDIR)/mkinstalldirs $(DESTDIR)$(htmldir) ; \
|
||||
fi
|
||||
|
||||
install: info installdirs bash.info
|
||||
-$(INSTALL_DATA) $(srcdir)/bash.1 $(DESTDIR)$(man1dir)/bash${man1ext}
|
||||
-$(INSTALL_DATA) $(srcdir)/bashbug.1 $(DESTDIR)$(man1dir)/bashbug${man1ext}
|
||||
# uncomment the next line to install the builtins man page
|
||||
# -$(INSTALL_DATA) $(srcdir)/builtins.1 $(DESTDIR)$(man1dir)/bash_builtins${man1ext}
|
||||
-$(INSTALL_DATA) $(srcdir)/bash.info $(DESTDIR)$(infodir)/bash.info
|
||||
# run install-info if it is present to update the info directory
|
||||
if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
|
||||
install-info --dir-file=$(DESTDIR)$(infodir)/dir $(DESTDIR)$(infodir)/bash.info; \
|
||||
else true; fi
|
||||
# if htmldir is set, install the html files into that directory
|
||||
-if test -n "${htmldir}" ; then \
|
||||
$(INSTALL_DATA) $(srcdir)/bash.html $(DESTDIR)$(htmldir) ; \
|
||||
$(INSTALL_DATA) $(srcdir)/bashref.html $(DESTDIR)$(htmldir) ; \
|
||||
fi
|
||||
|
||||
uninstall:
|
||||
-$(RM) $(DESTDIR)$(man1dir)/bash${man1ext} $(DESTDIR)$(man1dir)/bashbug${man1ext}
|
||||
$(RM) $(DESTDIR)$(infodir)/bash.info
|
||||
-if test -n "$(htmldir)" ; then \
|
||||
$(RM) $(DESTDIR)$(htmldir)/bash.html ; \
|
||||
$(RM) $(DESTDIR)$(htmldir)/bashref.html ; \
|
||||
fi
|
||||
|
||||
# for use by chet
|
||||
CREATED_FAQ = faq.news faq.news2 faq.mail faq.version
|
||||
|
||||
faq: ${CREATED_FAQ}
|
||||
|
||||
faq.version: FAQ.version FAQ
|
||||
sh mkfaqvers FAQ.version > $@
|
||||
|
||||
faq.headers.mail: FAQ.headers.mail FAQ
|
||||
sh mkfaqvers FAQ.headers.mail > $@
|
||||
|
||||
faq.headers.news: FAQ.headers.news FAQ
|
||||
sh mkfaqvers FAQ.headers.news > $@
|
||||
|
||||
faq.headers.news2: FAQ.headers.news2 FAQ
|
||||
sh mkfaqvers FAQ.headers.news2 > $@
|
||||
|
||||
faq.news: FAQ faq.headers.news faq.version
|
||||
$(RM) $@
|
||||
cat faq.headers.news faq.version FAQ > $@
|
||||
|
||||
faq.news2: FAQ faq.headers.news2 faq.version
|
||||
$(RM) $@
|
||||
cat faq.headers.news2 faq.version FAQ > $@
|
||||
|
||||
faq.mail: FAQ faq.headers.mail faq.version
|
||||
$(RM) $@
|
||||
cat faq.headers.mail faq.version FAQ > $@
|
||||
|
||||
inst: bashref.texi
|
||||
$(SHELL) ./mkinstall
|
||||
cmp -s INSTALL ../INSTALL || mv INSTALL ../INSTALL
|
||||
$(RM) INSTALL
|
||||
|
||||
posix: bashref.texi
|
||||
$(SHELL) ./mkposix
|
||||
cmp -s POSIX ../POSIX || mv POSIX ../POSIX
|
||||
$(RM) POSIX
|
||||
|
||||
rbash: bashref.texi
|
||||
$(SH) ./mkrbash
|
||||
cmp -s RBASH ../RBASH || mv RBASH ../RBASH
|
||||
$(RM) RBASH
|
||||
|
||||
xdist: pdf inst posix rbash
|
||||
+15448
File diff suppressed because it is too large
Load Diff
+31
-6
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Tue Dec 26 19:01:54 EST 2006
|
||||
.\" Last Change: Fri Jan 12 16:29:22 EST 2007
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2006 December 26" "GNU Bash-3.2"
|
||||
.TH BASH 1 "2007 January 12" "GNU Bash-3.2"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -51,8 +51,8 @@ bash \- GNU Bourne-Again SHell
|
||||
[options]
|
||||
[file]
|
||||
.SH COPYRIGHT
|
||||
.if n Bash is Copyright (C) 1989-2005 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2005 by the Free Software Foundation, Inc.
|
||||
.if n Bash is Copyright (C) 1989-2007 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2007 by the Free Software Foundation, Inc.
|
||||
.SH DESCRIPTION
|
||||
.B Bash
|
||||
is an \fBsh\fR-compatible command language interpreter that
|
||||
@@ -1752,6 +1752,8 @@ for \fIstrftime\fP(3) to print the time stamp associated with each history
|
||||
entry displayed by the \fBhistory\fP builtin.
|
||||
If this variable is set, time stamps are written to the history file so
|
||||
they may be preserved across shell sessions.
|
||||
This uses the history comment character to distinguish timestamps from
|
||||
other history lines.
|
||||
.TP
|
||||
.B HOME
|
||||
The home directory of the current user; the default argument for the
|
||||
@@ -5611,6 +5613,13 @@ is truncated, if necessary, to contain no more than
|
||||
the number of lines specified by the value of
|
||||
.SM
|
||||
.BR HISTFILESIZE .
|
||||
When the history file is read,
|
||||
lines beginning with the history comment character followed immediately
|
||||
by a digit are interpreted as timestamps for the preceding history line.
|
||||
These timestamps are optionally displayed depending on the value of the
|
||||
.SM
|
||||
.B HISTTIMEFORMAT
|
||||
variable.
|
||||
When an interactive shell exits, the last
|
||||
.SM
|
||||
.B $HISTSIZE
|
||||
@@ -5631,7 +5640,16 @@ If
|
||||
.SM
|
||||
.B HISTFILE
|
||||
is unset, or if the history file is unwritable, the history is
|
||||
not saved. After saving the history, the history file is truncated
|
||||
not saved.
|
||||
If the
|
||||
.SM
|
||||
.HISTTIMEFORMAT
|
||||
variable is set, time stamps are written to the history file, marked
|
||||
with the history comment character, so
|
||||
they may be preserved across shell sessions.
|
||||
This uses the history comment character to distinguish timestamps from
|
||||
other history lines.
|
||||
After saving the history, the history file is truncated
|
||||
to contain no more than
|
||||
.SM
|
||||
.B HISTFILESIZE
|
||||
@@ -5765,6 +5783,9 @@ history expansion mechanism (see the description of
|
||||
.B histchars
|
||||
above under
|
||||
.BR "Shell Variables" ).
|
||||
The shell uses
|
||||
the history comment character to mark history timestamps when
|
||||
writing the history file.
|
||||
.SS Event Designators
|
||||
.PP
|
||||
An event designator is a reference to a command line entry in the
|
||||
@@ -7169,7 +7190,11 @@ are added.
|
||||
.PD
|
||||
.PP
|
||||
If the \fBHISTTIMEFORMAT\fP is set, the time stamp information
|
||||
associated with each history entry is written to the history file.
|
||||
associated with each history entry is written to the history file,
|
||||
marked with the history comment character.
|
||||
When the history file is read, lines beginning with the history
|
||||
comment character followed immediately by a digit are interpreted
|
||||
as timestamps for the previous history line.
|
||||
The return value is 0 unless an invalid option is encountered, an
|
||||
error occurs while reading or writing the history file, an invalid
|
||||
\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the
|
||||
|
||||
+574
-200
File diff suppressed because it is too large
Load Diff
+36
-4
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Tue Dec 26 19:01:54 EST 2006
|
||||
.\" Last Change: Fri Jan 12 16:29:22 EST 2007
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2006 December 26" "GNU Bash-3.2"
|
||||
.TH BASH 1 "2007 January 12" "GNU Bash-3.2"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -1351,6 +1351,10 @@ This variable is available only in shell functions invoked by the
|
||||
programmable completion facilities (see \fBProgrammable Completion\fP
|
||||
below).
|
||||
.TP
|
||||
.B COMP_KEY
|
||||
The key (or final key of a key sequence) used to invoke the current
|
||||
completion function.
|
||||
.TP
|
||||
.B COMP_LINE
|
||||
The current command line.
|
||||
This variable is available only in shell functions and external
|
||||
@@ -1748,6 +1752,8 @@ for \fIstrftime\fP(3) to print the time stamp associated with each history
|
||||
entry displayed by the \fBhistory\fP builtin.
|
||||
If this variable is set, time stamps are written to the history file so
|
||||
they may be preserved across shell sessions.
|
||||
This uses the history comment character to distinguish timestamps from
|
||||
other history lines.
|
||||
.TP
|
||||
.B HOME
|
||||
The home directory of the current user; the default argument for the
|
||||
@@ -5493,7 +5499,10 @@ When the command or function is invoked, the
|
||||
.BR COMP_LINE ,
|
||||
.SM
|
||||
.BR COMP_POINT ,
|
||||
.SM
|
||||
.BR COMP_KEY ,
|
||||
and
|
||||
.SM
|
||||
.B COMP_TYPE
|
||||
variables are assigned values as described above under
|
||||
\fBShell Variables\fP.
|
||||
@@ -5604,6 +5613,13 @@ is truncated, if necessary, to contain no more than
|
||||
the number of lines specified by the value of
|
||||
.SM
|
||||
.BR HISTFILESIZE .
|
||||
When the history file is read,
|
||||
lines beginning with the history comment character followed immediately
|
||||
by a digit are interpreted as timestamps for the preceding history line.
|
||||
These timestamps are optionally displayed depending on the value of the
|
||||
.SM
|
||||
.B HISTTIMEFORMAT
|
||||
variable.
|
||||
When an interactive shell exits, the last
|
||||
.SM
|
||||
.B $HISTSIZE
|
||||
@@ -5624,7 +5640,16 @@ If
|
||||
.SM
|
||||
.B HISTFILE
|
||||
is unset, or if the history file is unwritable, the history is
|
||||
not saved. After saving the history, the history file is truncated
|
||||
not saved.
|
||||
If the
|
||||
.SM
|
||||
.HISTTIMEFORMAT
|
||||
variable is set, time stamps are written to the history file, marked
|
||||
with the history comment character, so
|
||||
they may be preserved across shell sessions.
|
||||
This uses the history comment character to distinguish timestamps from
|
||||
other history lines.
|
||||
After saving the history, the history file is truncated
|
||||
to contain no more than
|
||||
.SM
|
||||
.B HISTFILESIZE
|
||||
@@ -5758,6 +5783,9 @@ history expansion mechanism (see the description of
|
||||
.B histchars
|
||||
above under
|
||||
.BR "Shell Variables" ).
|
||||
The shell uses
|
||||
the history comment character to mark history timestamps when
|
||||
writing the history file.
|
||||
.SS Event Designators
|
||||
.PP
|
||||
An event designator is a reference to a command line entry in the
|
||||
@@ -7162,7 +7190,11 @@ are added.
|
||||
.PD
|
||||
.PP
|
||||
If the \fBHISTTIMEFORMAT\fP is set, the time stamp information
|
||||
associated with each history entry is written to the history file.
|
||||
associated with each history entry is written to the history file,
|
||||
marked with the history comment character.
|
||||
When the history file is read, lines beginning with the history
|
||||
comment character followed immediately by a digit are interpreted
|
||||
as timestamps for the previous history line.
|
||||
The return value is 0 unless an invalid option is encountered, an
|
||||
error occurs while reading or writing the history file, an invalid
|
||||
\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the
|
||||
|
||||
+1
-1
@@ -11619,6 +11619,6 @@ Array variables may not (yet) be exported.
|
||||
</DL>
|
||||
<HR>
|
||||
This document was created by man2html from bash.1.<BR>
|
||||
Time: 02 January 2007 10:25:26 EST
|
||||
Time: 09 January 2007 09:51:43 EST
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
+217
-198
File diff suppressed because it is too large
Load Diff
+21
-12
@@ -111,13 +111,7 @@ reference on shell behavior.
|
||||
between Bash and historical
|
||||
versions of /bin/sh.
|
||||
* Copying This Manual:: Copying this manual.
|
||||
* Builtin Index:: Index of Bash builtin commands.
|
||||
* Reserved Word Index:: Index of Bash reserved words.
|
||||
* Variable Index:: Quick reference helps you find the
|
||||
variable you want.
|
||||
* Function Index:: Index of bindable Readline functions.
|
||||
* Concept Index:: General index for concepts described in
|
||||
this manual.
|
||||
* Indexes:: Various indexes for this manual.
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
||||
@@ -4644,6 +4638,8 @@ for @var{strftime} to print the time stamp associated with each history
|
||||
entry displayed by the @code{history} builtin.
|
||||
If this variable is set, time stamps are written to the history file so
|
||||
they may be preserved across shell sessions.
|
||||
This uses the history comment character to distinguish timestamps from
|
||||
other history lines.
|
||||
|
||||
@item HOSTFILE
|
||||
Contains the name of a file in the same format as @file{/etc/hosts} that
|
||||
@@ -7467,24 +7463,37 @@ The SVR4.2 shell behaves differently when invoked as @code{jsh}
|
||||
|
||||
@include fdl.texi
|
||||
|
||||
@node Indexes
|
||||
@appendix Indexes
|
||||
|
||||
@menu
|
||||
* Builtin Index:: Index of Bash builtin commands.
|
||||
* Reserved Word Index:: Index of Bash reserved words.
|
||||
* Variable Index:: Quick reference helps you find the
|
||||
variable you want.
|
||||
* Function Index:: Index of bindable Readline functions.
|
||||
* Concept Index:: General index for concepts described in
|
||||
this manual.
|
||||
@end menu
|
||||
|
||||
@node Builtin Index
|
||||
@unnumbered Index of Shell Builtin Commands
|
||||
@appendixsec Index of Shell Builtin Commands
|
||||
@printindex bt
|
||||
|
||||
@node Reserved Word Index
|
||||
@unnumbered Index of Shell Reserved Words
|
||||
@appendixsec Index of Shell Reserved Words
|
||||
@printindex rw
|
||||
|
||||
@node Variable Index
|
||||
@unnumbered Parameter and Variable Index
|
||||
@appendixsec Parameter and Variable Index
|
||||
@printindex vr
|
||||
|
||||
@node Function Index
|
||||
@unnumbered Function Index
|
||||
@appendixsec Function Index
|
||||
@printindex fn
|
||||
|
||||
@node Concept Index
|
||||
@unnumbered Concept Index
|
||||
@appendixsec Concept Index
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+23
-12
@@ -111,13 +111,7 @@ reference on shell behavior.
|
||||
between Bash and historical
|
||||
versions of /bin/sh.
|
||||
* Copying This Manual:: Copying this manual.
|
||||
* Builtin Index:: Index of Bash builtin commands.
|
||||
* Reserved Word Index:: Index of Bash reserved words.
|
||||
* Variable Index:: Quick reference helps you find the
|
||||
variable you want.
|
||||
* Function Index:: Index of bindable Readline functions.
|
||||
* Concept Index:: General index for concepts described in
|
||||
this manual.
|
||||
* Indexes:: Various indexes for this manual.
|
||||
@end menu
|
||||
@end ifnottex
|
||||
|
||||
@@ -4482,6 +4476,10 @@ This variable is available only in shell functions and external
|
||||
commands invoked by the
|
||||
programmable completion facilities (@pxref{Programmable Completion}).
|
||||
|
||||
@item COMP_KEY
|
||||
The key (or final key of a key sequence) used to invoke the current
|
||||
completion function.
|
||||
|
||||
@item COMP_WORDBREAKS
|
||||
The set of characters that the Readline library treats as word
|
||||
separators when performing word completion.
|
||||
@@ -7463,24 +7461,37 @@ The SVR4.2 shell behaves differently when invoked as @code{jsh}
|
||||
|
||||
@include fdl.texi
|
||||
|
||||
@node Indexes
|
||||
@appendix Indexes
|
||||
|
||||
@menu
|
||||
* Builtin Index:: Index of Bash builtin commands.
|
||||
* Reserved Word Index:: Index of Bash reserved words.
|
||||
* Variable Index:: Quick reference helps you find the
|
||||
variable you want.
|
||||
* Function Index:: Index of bindable Readline functions.
|
||||
* Concept Index:: General index for concepts described in
|
||||
this manual.
|
||||
@end menu
|
||||
|
||||
@node Builtin Index
|
||||
@unnumbered Index of Shell Builtin Commands
|
||||
@appendixsec Index of Shell Builtin Commands
|
||||
@printindex bt
|
||||
|
||||
@node Reserved Word Index
|
||||
@unnumbered Index of Shell Reserved Words
|
||||
@appendixsec Index of Shell Reserved Words
|
||||
@printindex rw
|
||||
|
||||
@node Variable Index
|
||||
@unnumbered Parameter and Variable Index
|
||||
@appendixsec Parameter and Variable Index
|
||||
@printindex vr
|
||||
|
||||
@node Function Index
|
||||
@unnumbered Function Index
|
||||
@appendixsec Function Index
|
||||
@printindex fn
|
||||
|
||||
@node Concept Index
|
||||
@unnumbered Concept Index
|
||||
@appendixsec Concept Index
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
From: chet@po.cwru.edu (Chet Ramey)
|
||||
From: chet.ramey@case.edu (Chet Ramey)
|
||||
To: bug-bash@gnu.org
|
||||
Subject: BASH Frequently-Asked Questions (FAQ version 3.35)
|
||||
Reply-To: chet@po.cwru.edu
|
||||
|
||||
Cc: chet.ramey@case.edu
|
||||
Reply-To: chet.ramey@case.edu
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
From: chet@po.cwru.edu (Chet Ramey)
|
||||
From: chet.ramey@case.edu (Chet Ramey)
|
||||
To: bug-bash@gnu.org
|
||||
Subject: BASH Frequently-Asked Questions (FAQ version 3.35)
|
||||
Reply-To: chet@po.cwru.edu
|
||||
|
||||
Cc: chet.ramey@case.edu
|
||||
Reply-To: chet.ramey@case.edu
|
||||
Archive-name: unix-faq/shell/bash
|
||||
Posting-Frequency: monthly
|
||||
Submitted-By: chet@po.cwru.edu (Chet Ramey)
|
||||
|
||||
+10220
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -1,10 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2007 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sat Dec 30 19:31:54 EST 2006
|
||||
@set LASTCHANGE Fri Jan 12 16:29:58 EST 2007
|
||||
|
||||
@set EDITION 3.2
|
||||
@set VERSION 3.2
|
||||
@set UPDATED 30 December 2006
|
||||
@set UPDATED-MONTH December 2006
|
||||
@set UPDATED 12 January 2007
|
||||
@set UPDATED-MONTH January 2007
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Tue Dec 26 16:58:41 EST 2006
|
||||
@set LASTCHANGE Sat Dec 30 19:31:54 EST 2006
|
||||
|
||||
@set EDITION 3.2
|
||||
@set VERSION 3.2
|
||||
@set UPDATED 26 December 2006
|
||||
@set UPDATED 30 December 2006
|
||||
@set UPDATED-MONTH December 2006
|
||||
|
||||
@@ -3071,6 +3071,11 @@ run_builtin:
|
||||
if (command_line == 0)
|
||||
command_line = savestring (the_printed_command_except_trap);
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
|
||||
simple_command->flags &= ~CMD_NO_FORK;
|
||||
#endif
|
||||
|
||||
execute_disk_command (words, simple_command->redirects, command_line,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@ignore
|
||||
This file documents the user interface to the GNU History library.
|
||||
|
||||
Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2007 Free Software Foundation, Inc.
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this manual
|
||||
@@ -97,7 +97,11 @@ to contain no more than @env{$HISTFILESIZE}
|
||||
lines. If @env{HISTFILESIZE} is not set, no truncation is performed.
|
||||
|
||||
If the @env{HISTTIMEFORMAT} is set, the time stamp information
|
||||
associated with each history entry is written to the history file.
|
||||
associated with each history entry is written to the history file,
|
||||
marked with the history comment character.
|
||||
When the history file is read, lines beginning with the history
|
||||
comment character followed immediately by a digit are interpreted
|
||||
as timestamps for the previous history line.
|
||||
|
||||
The builtin command @code{fc} may be used to list or edit and re-execute
|
||||
a portion of the history list.
|
||||
@@ -277,7 +281,10 @@ them, so that they are available for subsequent recall.
|
||||
This is most useful in conjunction with Readline.
|
||||
|
||||
The shell allows control of the various characters used by the
|
||||
history expansion mechanism with the @code{histchars} variable.
|
||||
history expansion mechanism with the @code{histchars} variable,
|
||||
as explained above (@pxref{Bash Variables}). The shell uses
|
||||
the history comment character to mark history timestamps when
|
||||
writing the history file.
|
||||
@end ifset
|
||||
|
||||
@menu
|
||||
|
||||
@@ -97,7 +97,11 @@ to contain no more than @env{$HISTFILESIZE}
|
||||
lines. If @env{HISTFILESIZE} is not set, no truncation is performed.
|
||||
|
||||
If the @env{HISTTIMEFORMAT} is set, the time stamp information
|
||||
associated with each history entry is written to the history file.
|
||||
associated with each history entry is written to the history file,
|
||||
marked with the history comment character.
|
||||
When the history file is read, lines beginning with the history
|
||||
comment character followed immediately by a digit are interpreted
|
||||
as timestamps for the previous history line.
|
||||
|
||||
The builtin command @code{fc} may be used to list or edit and re-execute
|
||||
a portion of the history list.
|
||||
@@ -133,7 +137,7 @@ history list and history file.
|
||||
@item fc
|
||||
@btindex fc
|
||||
@example
|
||||
@code{fc [-e @var{ename}] [-nlr] [@var{first}] [@var{last}]}
|
||||
@code{fc [-e @var{ename}] [-lnr] [@var{first}] [@var{last}]}
|
||||
@code{fc -s [@var{pat}=@var{rep}] [@var{command}]}
|
||||
@end example
|
||||
|
||||
@@ -277,7 +281,10 @@ them, so that they are available for subsequent recall.
|
||||
This is most useful in conjunction with Readline.
|
||||
|
||||
The shell allows control of the various characters used by the
|
||||
history expansion mechanism with the @code{histchars} variable.
|
||||
history expansion mechanism with the @code{histchars} variable,
|
||||
as explained above (@pxref{Bash Variables}). The shell uses
|
||||
the history comment character to mark history timestamps when
|
||||
writing the history file.
|
||||
@end ifset
|
||||
|
||||
@menu
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2007 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 5.2
|
||||
@set VERSION 5.2
|
||||
@set UPDATED 30 December 2006
|
||||
@set UPDATED-MONTH December 2006
|
||||
@set UPDATED 12 January 2007
|
||||
@set UPDATED-MONTH January 2007
|
||||
|
||||
@set LASTCHANGE Sat Dec 30 19:17:22 EST 2006
|
||||
@set LASTCHANGE Fri Jan 12 16:31:33 EST 2007
|
||||
|
||||
@@ -4,7 +4,7 @@ Copyright (C) 1988-2006 Free Software Foundation, Inc.
|
||||
|
||||
@set EDITION 5.2
|
||||
@set VERSION 5.2
|
||||
@set UPDATED 26 April 2006
|
||||
@set UPDATED-MONTH April 2006
|
||||
@set UPDATED 30 December 2006
|
||||
@set UPDATED-MONTH December 2006
|
||||
|
||||
@set LASTCHANGE Wed Apr 26 09:22:57 EDT 2006
|
||||
@set LASTCHANGE Sat Dec 30 19:17:22 EST 2006
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined (__EMX__)
|
||||
# undef HAVE_MMAP
|
||||
#endif
|
||||
@@ -103,7 +105,7 @@ int history_write_timestamps = 0;
|
||||
|
||||
/* Does S look like the beginning of a history timestamp entry? Placeholder
|
||||
for more extensive tests. */
|
||||
#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
|
||||
#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((s)[1]) )
|
||||
|
||||
/* Return the string that should be used in the place of this
|
||||
filename. This only matters when you don't specify the
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (__EMX__) || defined (__CYGWIN__)
|
||||
#if defined (__EMX__)
|
||||
# undef HAVE_MMAP
|
||||
#endif
|
||||
|
||||
|
||||
+4
-1
@@ -1084,6 +1084,7 @@ gen_command_matches (cs, text, line, ind, lwords, nw, cw)
|
||||
char *csbuf, *cscmd, *t;
|
||||
int cmdlen, cmdsize, n, ws, we;
|
||||
WORD_LIST *cmdlist, *cl;
|
||||
WORD_DESC *tw;
|
||||
STRINGLIST *sl;
|
||||
|
||||
bind_compfunc_variables (line, ind, lwords, cw, 1);
|
||||
@@ -1115,7 +1116,9 @@ gen_command_matches (cs, text, line, ind, lwords, nw, cw)
|
||||
}
|
||||
cscmd[cmdlen] = '\0';
|
||||
|
||||
csbuf = command_substitute (cscmd, 0);
|
||||
tw = command_substitute (cscmd, 0);
|
||||
csbuf = tw ? tw->word : (char *)NULL;
|
||||
dispose_word_desc (tw);
|
||||
|
||||
/* Now clean up and destroy everything. */
|
||||
dispose_words (cmdlist);
|
||||
|
||||
@@ -216,7 +216,7 @@ static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
|
||||
#endif
|
||||
static int do_assignment_internal __P((const WORD_DESC *, int));
|
||||
|
||||
static char *string_extract_verbatim __P((char *, size_t, int *, char *));
|
||||
static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
|
||||
static char *string_extract __P((char *, int *, char *, int));
|
||||
static char *string_extract_double_quoted __P((char *, int *, int));
|
||||
static inline char *string_extract_single_quoted __P((char *, int *));
|
||||
@@ -254,7 +254,7 @@ static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, in
|
||||
|
||||
static char *process_substitute __P((char *, int));
|
||||
|
||||
static char *read_comsub __P((int, int));
|
||||
static char *read_comsub __P((int, int, int *));
|
||||
|
||||
#ifdef ARRAY_VARS
|
||||
static arrayind_t array_length_reference __P((char *));
|
||||
@@ -886,11 +886,12 @@ skip_single_quoted (string, slen, sind)
|
||||
/* Just like string_extract, but doesn't hack backslashes or any of
|
||||
that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
|
||||
static char *
|
||||
string_extract_verbatim (string, slen, sindex, charlist)
|
||||
string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
char *string;
|
||||
size_t slen;
|
||||
int *sindex;
|
||||
char *charlist;
|
||||
int flags;
|
||||
{
|
||||
register int i = *sindex;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -1887,7 +1888,13 @@ string_list_dollar_at (list, quoted)
|
||||
sep[1] = '\0';
|
||||
#endif
|
||||
|
||||
/* XXX -- why call quote_list if ifs == 0? we can get away without doing
|
||||
it now that quote_escapes quotes spaces */
|
||||
#if 0
|
||||
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
|
||||
#else
|
||||
tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
#endif
|
||||
? quote_list (list)
|
||||
: list_quote_escapes (list);
|
||||
|
||||
@@ -1973,7 +1980,7 @@ list_string (string, separators, quoted)
|
||||
{
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators);
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, 0);
|
||||
if (current_word == 0)
|
||||
break;
|
||||
|
||||
@@ -2096,7 +2103,7 @@ get_word_from_string (stringp, separators, endptr)
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators);
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, 0);
|
||||
|
||||
/* Set ENDPTR to the first character after the end of the word. */
|
||||
if (endptr)
|
||||
@@ -2922,7 +2929,12 @@ expand_string (string, quoted)
|
||||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. */
|
||||
the word expansion process after the variable is expanded. If IFS is
|
||||
null, we quote spaces as well, just in case we split on spaces later
|
||||
(in the case of unquoted $@, we will eventually attempt to split the
|
||||
entire word on spaces). Corresponding code exists in dequote_escapes.
|
||||
Even if we don't end up splitting on spaces, quoting spaces is not a
|
||||
problem. */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
@@ -2930,17 +2942,19 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL)
|
||||
if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -2982,6 +2996,7 @@ dequote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
if (string == 0)
|
||||
@@ -2996,9 +3011,10 @@ dequote_escapes (string)
|
||||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
{
|
||||
s++;
|
||||
if (*s == '\0')
|
||||
@@ -4129,6 +4145,12 @@ unlink_fifo_list ()
|
||||
nfifo = 0;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_named_pipe ()
|
||||
{
|
||||
@@ -4178,6 +4200,12 @@ add_fifo_list (fd)
|
||||
nfds++;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return 0; /* used for cleanup; not needed with /dev/fd */
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4423,21 +4451,23 @@ process_substitute (string, open_for_read_in_child)
|
||||
/***********************************/
|
||||
|
||||
static char *
|
||||
read_comsub (fd, quoted)
|
||||
read_comsub (fd, quoted, rflag)
|
||||
int fd, quoted;
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp;
|
||||
int istring_index, istring_size, c;
|
||||
int istring_index, istring_size, c, tflag;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = 0;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
#endif
|
||||
|
||||
/* Read the output of the command through the pipe. */
|
||||
/* Read the output of the command through the pipe. This may need to be
|
||||
changed to understand multibyte characters in the future. */
|
||||
while (1)
|
||||
{
|
||||
if (fd < 0)
|
||||
@@ -4462,7 +4492,18 @@ read_comsub (fd, quoted)
|
||||
/* Add the character to ISTRING, possibly after resizing it. */
|
||||
RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
|
||||
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
|
||||
/* This is essentially quote_string inline */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
|
||||
istring[istring_index++] = CTLESC;
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (c == CTLESC)
|
||||
{
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -4486,6 +4527,8 @@ read_comsub (fd, quoted)
|
||||
if (istring_index == 0)
|
||||
{
|
||||
FREE (istring);
|
||||
if (rflag)
|
||||
*rflag = tflag;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
@@ -4510,26 +4553,29 @@ read_comsub (fd, quoted)
|
||||
else
|
||||
strip_trailing (istring, istring_index - 1, 1);
|
||||
|
||||
if (rflag)
|
||||
*rflag = tflag;
|
||||
return istring;
|
||||
}
|
||||
|
||||
/* Perform command substitution on STRING. This returns a string,
|
||||
possibly quoted. */
|
||||
char *
|
||||
/* Perform command substitution on STRING. This returns a WORD_DESC * with the
|
||||
contained string possibly quoted. */
|
||||
WORD_DESC *
|
||||
command_substitute (string, quoted)
|
||||
char *string;
|
||||
int quoted;
|
||||
{
|
||||
pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
|
||||
char *istring;
|
||||
int result, fildes[2], function_value, pflags, rc;
|
||||
int result, fildes[2], function_value, pflags, rc, tflag;
|
||||
WORD_DESC *ret;
|
||||
|
||||
istring = (char *)NULL;
|
||||
|
||||
/* Don't fork () if there is no need to. In the case of no command to
|
||||
run, just return NULL. */
|
||||
if (!string || !*string || (string[0] == '\n' && !string[1]))
|
||||
return ((char *)NULL);
|
||||
return ((WORD_DESC *)NULL);
|
||||
|
||||
if (wordexp_only && read_but_dont_execute)
|
||||
{
|
||||
@@ -4569,11 +4615,7 @@ command_substitute (string, quoted)
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
old_async_pid = last_asynchronous_pid;
|
||||
#if 0
|
||||
pid = make_child ((char *)NULL, 0);
|
||||
#else
|
||||
pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
|
||||
#endif
|
||||
last_asynchronous_pid = old_async_pid;
|
||||
|
||||
if (pid == 0)
|
||||
@@ -4597,7 +4639,7 @@ command_substitute (string, quoted)
|
||||
FREE (istring);
|
||||
close (fildes[0]);
|
||||
close (fildes[1]);
|
||||
return ((char *)NULL);
|
||||
return ((WORD_DESC *)NULL);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
@@ -4671,6 +4713,9 @@ command_substitute (string, quoted)
|
||||
|
||||
last_command_exit_value = rc;
|
||||
rc = run_exit_trap ();
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif
|
||||
exit (rc);
|
||||
}
|
||||
else
|
||||
@@ -4681,7 +4726,8 @@ command_substitute (string, quoted)
|
||||
|
||||
close (fildes[1]);
|
||||
|
||||
istring = read_comsub (fildes[0], quoted);
|
||||
tflag = 0;
|
||||
istring = read_comsub (fildes[0], quoted, &tflag);
|
||||
|
||||
close (fildes[0]);
|
||||
|
||||
@@ -4711,7 +4757,11 @@ command_substitute (string, quoted)
|
||||
give_terminal_to (pipeline_pgrp, 0);
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
return (istring);
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = istring;
|
||||
ret->flags = tflag;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4983,7 +5033,7 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
|
||||
/* If the entire expression is between double quotes, we want to treat
|
||||
the value as a double-quoted string, with the exception that we strip
|
||||
embedded unescaped double quotes. */
|
||||
embedded unescaped double quotes (for sh backwards compatibility). */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
|
||||
{
|
||||
hasdol = 0;
|
||||
@@ -5554,12 +5604,16 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
#if 0
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
temp = tt;
|
||||
break;
|
||||
#endif
|
||||
@@ -5810,12 +5864,16 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
#if 0
|
||||
/* Don't need to do this anymore; array_patsub calls array_quote_escapes
|
||||
as appropriate before adding the space separators. */
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -6578,7 +6636,11 @@ comsub:
|
||||
/* we need zindex+1 because string[zindex] == RPAREN */
|
||||
temp1 = substring (string, *sindex, zindex+1);
|
||||
else
|
||||
temp1 = command_substitute (temp, quoted);
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
break;
|
||||
@@ -6986,7 +7048,9 @@ add_string:
|
||||
else
|
||||
{
|
||||
de_backslash (temp);
|
||||
temp1 = command_substitute (temp, quoted);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7512,11 +7576,7 @@ setifs (v)
|
||||
unsigned char uc;
|
||||
|
||||
ifs_var = v;
|
||||
#if 0
|
||||
ifs_value = v ? value_cell (v) : " \t\n";
|
||||
#else
|
||||
ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
|
||||
#endif
|
||||
|
||||
/* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
|
||||
handle multibyte chars in IFS */
|
||||
|
||||
+8186
File diff suppressed because it is too large
Load Diff
@@ -216,7 +216,7 @@ static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
|
||||
#endif
|
||||
static int do_assignment_internal __P((const WORD_DESC *, int));
|
||||
|
||||
static char *string_extract_verbatim __P((char *, size_t, int *, char *));
|
||||
static char *string_extract_verbatim __P((char *, size_t, int *, char *, int));
|
||||
static char *string_extract __P((char *, int *, char *, int));
|
||||
static char *string_extract_double_quoted __P((char *, int *, int));
|
||||
static inline char *string_extract_single_quoted __P((char *, int *));
|
||||
@@ -254,7 +254,7 @@ static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, in
|
||||
|
||||
static char *process_substitute __P((char *, int));
|
||||
|
||||
static char *read_comsub __P((int, int));
|
||||
static char *read_comsub __P((int, int, int *));
|
||||
|
||||
#ifdef ARRAY_VARS
|
||||
static arrayind_t array_length_reference __P((char *));
|
||||
@@ -886,11 +886,12 @@ skip_single_quoted (string, slen, sind)
|
||||
/* Just like string_extract, but doesn't hack backslashes or any of
|
||||
that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
|
||||
static char *
|
||||
string_extract_verbatim (string, slen, sindex, charlist)
|
||||
string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
char *string;
|
||||
size_t slen;
|
||||
int *sindex;
|
||||
char *charlist;
|
||||
int flags;
|
||||
{
|
||||
register int i = *sindex;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
@@ -1887,7 +1888,13 @@ string_list_dollar_at (list, quoted)
|
||||
sep[1] = '\0';
|
||||
#endif
|
||||
|
||||
/* XXX -- why call quote_list if ifs == 0? we can get away without doing
|
||||
it now that quote_escapes quotes spaces */
|
||||
#if 0
|
||||
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
|
||||
#else
|
||||
tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
#endif
|
||||
? quote_list (list)
|
||||
: list_quote_escapes (list);
|
||||
|
||||
@@ -1973,7 +1980,7 @@ list_string (string, separators, quoted)
|
||||
{
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators);
|
||||
current_word = string_extract_verbatim (string, slen, &sindex, separators, 0);
|
||||
if (current_word == 0)
|
||||
break;
|
||||
|
||||
@@ -2096,7 +2103,7 @@ get_word_from_string (stringp, separators, endptr)
|
||||
/* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
|
||||
unless multibyte chars are possible. */
|
||||
slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators);
|
||||
current_word = string_extract_verbatim (s, slen, &sindex, separators, 0);
|
||||
|
||||
/* Set ENDPTR to the first character after the end of the word. */
|
||||
if (endptr)
|
||||
@@ -2922,7 +2929,12 @@ expand_string (string, quoted)
|
||||
|
||||
/* Quote escape characters in string s, but no other characters. This is
|
||||
used to protect CTLESC and CTLNUL in variable values from the rest of
|
||||
the word expansion process after the variable is expanded. */
|
||||
the word expansion process after the variable is expanded. If IFS is
|
||||
null, we quote spaces as well, just in case we split on spaces later
|
||||
(in the case of unquoted $@, we will eventually attempt to split the
|
||||
entire word on spaces). Corresponding code exists in dequote_escapes.
|
||||
Even if we don't end up splitting on spaces, quoting spaces is not a
|
||||
problem. */
|
||||
char *
|
||||
quote_escapes (string)
|
||||
char *string;
|
||||
@@ -2930,17 +2942,19 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC || *s == CTLNUL)
|
||||
if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -2982,6 +2996,7 @@ dequote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
if (string == 0)
|
||||
@@ -2996,9 +3011,10 @@ dequote_escapes (string)
|
||||
if (strchr (string, CTLESC) == 0)
|
||||
return (strcpy (result, s));
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
while (*s)
|
||||
{
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
|
||||
if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
|
||||
{
|
||||
s++;
|
||||
if (*s == '\0')
|
||||
@@ -4129,12 +4145,18 @@ unlink_fifo_list ()
|
||||
nfifo = 0;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_named_pipe ()
|
||||
{
|
||||
char *tname;
|
||||
|
||||
tname = sh_mktmpname ("sh-np", MT_USERANDOM);
|
||||
tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
|
||||
if (mkfifo (tname, 0600) < 0)
|
||||
{
|
||||
free (tname);
|
||||
@@ -4178,6 +4200,12 @@ add_fifo_list (fd)
|
||||
nfds++;
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return 0; /* used for cleanup; not needed with /dev/fd */
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4423,21 +4451,23 @@ process_substitute (string, open_for_read_in_child)
|
||||
/***********************************/
|
||||
|
||||
static char *
|
||||
read_comsub (fd, quoted)
|
||||
read_comsub (fd, quoted, rflag)
|
||||
int fd, quoted;
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp;
|
||||
int istring_index, istring_size, c;
|
||||
int istring_index, istring_size, c, tflag;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = 0;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
#endif
|
||||
|
||||
/* Read the output of the command through the pipe. */
|
||||
/* Read the output of the command through the pipe. This may need to be
|
||||
changed to understand multibyte characters in the future. */
|
||||
while (1)
|
||||
{
|
||||
if (fd < 0)
|
||||
@@ -4462,7 +4492,18 @@ read_comsub (fd, quoted)
|
||||
/* Add the character to ISTRING, possibly after resizing it. */
|
||||
RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
|
||||
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
|
||||
/* This is essentially quote_string inline */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
|
||||
istring[istring_index++] = CTLESC;
|
||||
/* Escape CTLESC and CTLNUL in the output to protect those characters
|
||||
from the rest of the word expansions (word splitting and globbing.)
|
||||
This is essentially quote_escapes inline. */
|
||||
else if (c == CTLESC)
|
||||
{
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -4486,6 +4527,8 @@ read_comsub (fd, quoted)
|
||||
if (istring_index == 0)
|
||||
{
|
||||
FREE (istring);
|
||||
if (rflag)
|
||||
*rflag = tflag;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
@@ -4510,26 +4553,29 @@ read_comsub (fd, quoted)
|
||||
else
|
||||
strip_trailing (istring, istring_index - 1, 1);
|
||||
|
||||
if (rflag)
|
||||
*rflag = tflag;
|
||||
return istring;
|
||||
}
|
||||
|
||||
/* Perform command substitution on STRING. This returns a string,
|
||||
possibly quoted. */
|
||||
char *
|
||||
/* Perform command substitution on STRING. This returns a WORD_DESC * with the
|
||||
contained string possibly quoted. */
|
||||
WORD_DESC *
|
||||
command_substitute (string, quoted)
|
||||
char *string;
|
||||
int quoted;
|
||||
{
|
||||
pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
|
||||
char *istring;
|
||||
int result, fildes[2], function_value, pflags, rc;
|
||||
int result, fildes[2], function_value, pflags, rc, tflag;
|
||||
WORD_DESC *ret;
|
||||
|
||||
istring = (char *)NULL;
|
||||
|
||||
/* Don't fork () if there is no need to. In the case of no command to
|
||||
run, just return NULL. */
|
||||
if (!string || !*string || (string[0] == '\n' && !string[1]))
|
||||
return ((char *)NULL);
|
||||
return ((WORD_DESC *)NULL);
|
||||
|
||||
if (wordexp_only && read_but_dont_execute)
|
||||
{
|
||||
@@ -4569,11 +4615,7 @@ command_substitute (string, quoted)
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
old_async_pid = last_asynchronous_pid;
|
||||
#if 0
|
||||
pid = make_child ((char *)NULL, 0);
|
||||
#else
|
||||
pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
|
||||
#endif
|
||||
last_asynchronous_pid = old_async_pid;
|
||||
|
||||
if (pid == 0)
|
||||
@@ -4597,7 +4639,7 @@ command_substitute (string, quoted)
|
||||
FREE (istring);
|
||||
close (fildes[0]);
|
||||
close (fildes[1]);
|
||||
return ((char *)NULL);
|
||||
return ((WORD_DESC *)NULL);
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
@@ -4671,6 +4713,9 @@ command_substitute (string, quoted)
|
||||
|
||||
last_command_exit_value = rc;
|
||||
rc = run_exit_trap ();
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif
|
||||
exit (rc);
|
||||
}
|
||||
else
|
||||
@@ -4681,7 +4726,8 @@ command_substitute (string, quoted)
|
||||
|
||||
close (fildes[1]);
|
||||
|
||||
istring = read_comsub (fildes[0], quoted);
|
||||
tflag = 0;
|
||||
istring = read_comsub (fildes[0], quoted, &tflag);
|
||||
|
||||
close (fildes[0]);
|
||||
|
||||
@@ -4711,7 +4757,11 @@ command_substitute (string, quoted)
|
||||
give_terminal_to (pipeline_pgrp, 0);
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
return (istring);
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = istring;
|
||||
ret->flags = tflag;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4983,7 +5033,7 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
|
||||
/* If the entire expression is between double quotes, we want to treat
|
||||
the value as a double-quoted string, with the exception that we strip
|
||||
embedded unescaped double quotes. */
|
||||
embedded unescaped double quotes (for sh backwards compatibility). */
|
||||
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
|
||||
{
|
||||
hasdol = 0;
|
||||
@@ -5810,12 +5860,16 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
#if 0
|
||||
/* Don't need to do this anymore; array_patsub calls array_quote_escapes
|
||||
as appropriate before adding the space separators. */
|
||||
if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -6578,7 +6632,11 @@ comsub:
|
||||
/* we need zindex+1 because string[zindex] == RPAREN */
|
||||
temp1 = substring (string, *sindex, zindex+1);
|
||||
else
|
||||
temp1 = command_substitute (temp, quoted);
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
break;
|
||||
@@ -6986,7 +7044,9 @@ add_string:
|
||||
else
|
||||
{
|
||||
de_backslash (temp);
|
||||
temp1 = command_substitute (temp, quoted);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7512,11 +7572,7 @@ setifs (v)
|
||||
unsigned char uc;
|
||||
|
||||
ifs_var = v;
|
||||
#if 0
|
||||
ifs_value = v ? value_cell (v) : " \t\n";
|
||||
#else
|
||||
ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
|
||||
#endif
|
||||
|
||||
/* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
|
||||
handle multibyte chars in IFS */
|
||||
|
||||
@@ -219,9 +219,10 @@ extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
|
||||
command substitution, arithmetic expansion, and word splitting. */
|
||||
extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
|
||||
|
||||
extern char *command_substitute __P((char *, int));
|
||||
extern WORD_DESC *command_substitute __P((char *, int));
|
||||
extern char *pat_subst __P((char *, char *, char *, int));
|
||||
|
||||
extern int fifos_pending __P((void));
|
||||
extern void unlink_fifo_list __P((void));
|
||||
|
||||
extern WORD_LIST *list_string_with_quotes __P((char *));
|
||||
|
||||
+1
-1
@@ -3564,7 +3564,7 @@ INPUT_LINE: while ($_ = &next_line) {
|
||||
$name = &normalise_node($name);
|
||||
$level = $sec2level{$tag};
|
||||
# check for index
|
||||
$first_index_chapter = $name
|
||||
$first_index_chapter = $node
|
||||
if ($level == 1 && !$first_index_chapter &&
|
||||
$name =~ /index/i);
|
||||
if ($in_top && /heading/){
|
||||
|
||||
Executable
+5439
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -26,7 +26,7 @@
|
||||
|
||||
#if defined (qnx)
|
||||
# if defined (qnx6)
|
||||
# include <sy/netmgr.h>
|
||||
# include <sys/netmgr.h>
|
||||
# else
|
||||
# include <sys/vc.h>
|
||||
# endif /* !qnx6 */
|
||||
@@ -515,6 +515,7 @@ initialize_shell_variables (env, privmode)
|
||||
{
|
||||
sv_history_control ("HISTCONTROL");
|
||||
sv_histignore ("HISTIGNORE");
|
||||
sv_histtimefmt ("HISTTIMEFORMAT");
|
||||
}
|
||||
#endif /* HISTORY */
|
||||
|
||||
|
||||
+22
-1
@@ -26,7 +26,7 @@
|
||||
|
||||
#if defined (qnx)
|
||||
# if defined (qnx6)
|
||||
# include <sy/netmgr.h>
|
||||
# include <sys/netmgr.h>
|
||||
# else
|
||||
# include <sys/vc.h>
|
||||
# endif /* !qnx6 */
|
||||
@@ -192,6 +192,8 @@ static SHELL_VAR *get_lineno __P((SHELL_VAR *));
|
||||
static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
|
||||
static SHELL_VAR *get_subshell __P((SHELL_VAR *));
|
||||
|
||||
static SHELL_VAR *get_bashpid __P((SHELL_VAR *));
|
||||
|
||||
#if defined (HISTORY)
|
||||
static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
|
||||
#endif
|
||||
@@ -1271,6 +1273,22 @@ get_subshell (var)
|
||||
return (var);
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
get_bashpid (var)
|
||||
SHELL_VAR *var;
|
||||
{
|
||||
int pid;
|
||||
char *p;
|
||||
|
||||
pid = getpid ();
|
||||
p = itos (pid);
|
||||
|
||||
FREE (value_cell (var));
|
||||
VSETATTR (var, att_integer|att_readonly);
|
||||
var_setvalue (var, p);
|
||||
return (var);
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
get_bash_command (var)
|
||||
SHELL_VAR *var;
|
||||
@@ -1452,6 +1470,9 @@ initialize_dynamic_variables ()
|
||||
INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
|
||||
VSETATTR (v, att_integer);
|
||||
|
||||
INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
|
||||
VSETATTR (v, att_integer|att_readonly);
|
||||
|
||||
#if defined (HISTORY)
|
||||
INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
|
||||
VSETATTR (v, att_integer);
|
||||
|
||||
Reference in New Issue
Block a user