commit bash-20070329 snapshot

This commit is contained in:
Chet Ramey
2011-12-07 09:05:53 -05:00
parent 28157acd2d
commit d3ad40dee6
265 changed files with 56692 additions and 40436 deletions
+258 -136
View File
@@ -4,7 +4,7 @@
/* ``Have a little faith, there's magic in the night. You ain't a
beauty, but, hey, you're alright.'' */
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -82,6 +82,7 @@ extern int errno;
#define EX_NOALLOC 0x01 /* just skip; don't return substring */
#define EX_VARNAME 0x02 /* variable name; for string_extract () */
#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
#define EX_COMMAND 0x08 /* extracting a shell script/command */
/* Flags for the `pflags' argument to param_expand() */
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
@@ -147,6 +148,10 @@ extern int wordexp_only;
extern int expanding_redir;
extern int tempenv_assign_error;
#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
extern wchar_t *wcsdup __P((const wchar_t *));
#endif
/* Non-zero means to allow unmatched globbed filenames to expand to
a null file. */
int allow_null_glob_expansion;
@@ -200,7 +205,6 @@ static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
static char *dequote_escapes __P((char *));
static char *make_quoted_char __P((int));
static WORD_LIST *quote_list __P((WORD_LIST *));
static WORD_LIST *dequote_list __P((WORD_LIST *));
static char *remove_quoted_escapes __P((char *));
static char *remove_quoted_nulls __P((char *));
@@ -212,11 +216,11 @@ 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 *));
static inline int skip_single_quoted __P((char *, size_t, int));
static inline int skip_single_quoted __P((const char *, size_t, int));
static int skip_double_quoted __P((char *, size_t, int));
static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
static char *extract_dollar_brace_string __P((char *, int *, int, int));
@@ -226,10 +230,7 @@ static char *pos_params __P((char *, int, int, int));
static unsigned char *mb_getcharlens __P((char *, int));
static char *remove_upattern __P((char *, char *, int));
#if defined (HANDLE_MULTIBYTE)
# if !defined (HAVE_WCSDUP)
static wchar_t *wcsdup __P((wchar_t *));
# endif
#if defined (HANDLE_MULTIBYTE)
static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
#endif
static char *remove_pattern __P((char *, char *, int));
@@ -253,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 *));
@@ -261,6 +262,7 @@ static arrayind_t array_length_reference __P((char *));
static int valid_brace_expansion_word __P((char *, int));
static int chk_atstar __P((char *, int, int *, int *));
static int chk_arithsub __P((const char *, int));
static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
@@ -710,7 +712,7 @@ add_one_character:
si = i + 2;
if (string[i + 1] == LPAREN)
ret = extract_delimited_string (string, &si, "$(", "(", ")", 0); /*)*/
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_COMMAND); /*)*/
else
ret = extract_dollar_brace_string (string, &si, 1, 0);
@@ -812,7 +814,7 @@ skip_double_quoted (string, slen, sind)
{
si = i + 2;
if (string[i + 1] == LPAREN)
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
else
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
@@ -865,7 +867,7 @@ string_extract_single_quoted (string, sindex)
static inline int
skip_single_quoted (string, slen, sind)
char *string;
const char *string;
size_t slen;
int sind;
{
@@ -884,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)
@@ -946,8 +949,8 @@ string_extract_verbatim (string, slen, sindex, charlist)
len = mbstowcs (wcharlist, charlist, 0);
if (len == -1)
len = 0;
wcharlist = (wchar_t *)xmalloc ((sizeof (wchar_t) * len) + 1);
mbstowcs (wcharlist, charlist, len);
wcharlist = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
mbstowcs (wcharlist, charlist, len + 1);
}
if (wcschr (wcharlist, wc))
@@ -980,7 +983,7 @@ extract_command_subst (string, sindex)
char *string;
int *sindex;
{
return (extract_delimited_string (string, sindex, "$(", "(", ")", 0)); /*)*/
return (extract_delimited_string (string, sindex, "$(", "(", ")", EX_COMMAND)); /*)*/
}
/* Extract the $[ construct in STRING, and return a new string. (])
@@ -1049,7 +1052,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
int i, c, si;
size_t slen;
char *t, *result;
int pass_character, nesting_level;
int pass_character, nesting_level, in_comment;
int len_closer, len_opener, len_alt_opener;
DECLARE_MBSTATE;
@@ -1058,7 +1061,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
len_alt_opener = STRLEN (alt_opener);
len_closer = STRLEN (closer);
pass_character = 0;
pass_character = in_comment = 0;
nesting_level = 1;
i = *sindex;
@@ -1070,6 +1073,14 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
if (c == 0)
break;
if (in_comment)
{
if (c == '\n')
in_comment = 0;
ADVANCE_CHAR (string, slen, i);
continue;
}
if (pass_character) /* previous char was backslash */
{
pass_character = 0;
@@ -1077,6 +1088,15 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
continue;
}
/* Not exactly right yet; should handle shell metacharacters and
multibyte characters, too. */
if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
{
in_comment = 1;
ADVANCE_CHAR (string, slen, i);
continue;
}
if (c == CTLESC || c == '\\')
{
pass_character++;
@@ -1235,7 +1255,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
if (string[i] == '$' && string[i+1] == LPAREN)
{
si = i + 2;
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC); /*)*/
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC|EX_COMMAND); /*)*/
i = si + 1;
continue;
}
@@ -1259,7 +1279,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
{
if (no_longjmp_on_fatal_error == 0)
{ /* { */
report_error ("bad substitution: no closing `%s' in %s", "}", string);
report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
last_command_exit_value = EXECUTION_FAILURE;
exp_jump_to_top_level (DISCARD);
}
@@ -1498,7 +1518,7 @@ skip_to_delim (string, start, delims)
CQ_RETURN(si);
if (string[i+1] == LPAREN)
temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC|EX_COMMAND); /* ) */
else
temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
i = si;
@@ -1563,7 +1583,8 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
while (delims[i])
{
#if defined (HANDLE_MULTIBYTE)
mbstate_t state_bak = state;
mbstate_t state_bak;
state_bak = state;
mblength = MBRLEN (delims + i, slength, &state);
if (MB_INVALIDCH (mblength))
state = state_bak;
@@ -1867,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);
@@ -1953,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;
@@ -2015,7 +2042,7 @@ list_string (string, separators, quoted)
sindex++;
/* An IFS character that is not IFS white space, along with any
adjacent IFS white space, shall delimit a field. (SUSv3) */
while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
while (string[sindex] && spctabnl (string[sindex]) && isifs (string[sindex]))
sindex++;
}
}
@@ -2076,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)
@@ -2203,16 +2230,18 @@ do_compound_assignment (name, value, flags)
int flags;
{
SHELL_VAR *v;
int off, mklocal;
int mklocal;
WORD_LIST *list;
mklocal = flags & ASS_MKLOCAL;
if (mklocal && variable_context)
{
list = expand_compound_array_assignment (value, flags);
v = find_variable (name);
if (v == 0 || array_p (v) == 0 || v->context != variable_context)
v = make_local_array_variable (name);
v = assign_array_var_from_string (v, value, flags);
assign_compound_array_list (v, list, flags);
}
else
v = assign_array_from_string (name, value, flags);
@@ -2232,7 +2261,7 @@ do_assignment_internal (word, expand)
int expand;
{
int offset, tlen, appendop, assign_list, aflags;
char *name, *value, *ovalue, *nvalue;
char *name, *value;
SHELL_VAR *entry;
#if defined (ARRAY_VARS)
char *t;
@@ -2264,11 +2293,7 @@ do_assignment_internal (word, expand)
tlen = STRLEN (temp);
#if defined (ARRAY_VARS)
# if 0
if (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
#else
if (expand && (word->flags & W_COMPASSIGN))
#endif
{
assign_list = ni = 1;
value = extract_array_assignment_list (temp, &ni);
@@ -2463,6 +2488,12 @@ pos_params (string, start, end, quoted)
if (save == 0)
return ((char *)NULL);
if (start == 0) /* handle ${@:0[:x]} specially */
{
t = make_word_list (make_word (dollar_vars[0]), params);
save = params = t;
}
for (i = 1; params && i < start; i++)
params = params->next;
if (params == 0)
@@ -2599,10 +2630,10 @@ expand_assignment_string_to_string (string, quoted)
}
char *
expand_arith_string (string)
expand_arith_string (string, quoted)
char *string;
{
return (expand_string_if_necessary (string, Q_DOUBLE_QUOTES, expand_string));
return (expand_string_if_necessary (string, quoted, expand_string));
}
#if defined (COND_COMMAND)
@@ -2628,11 +2659,12 @@ remove_backslashes (string)
/* This needs better error handling. */
/* Expand W for use as an argument to a unary or binary operator in a
[[...]] expression. If SPECIAL is nonzero, this is the rhs argument
[[...]] expression. If SPECIAL is 1, this is the rhs argument
to the != or == operator, and should be treated as a pattern. In
this case, we quote the string specially for the globbing code. The
caller is responsible for removing the backslashes if the unquoted
words is needed later. */
this case, we quote the string specially for the globbing code. If
SPECIAL is 2, this is an rhs argument for the =~ operator, and should
be quoted appropriately for regcomp/regexec. The caller is responsible
for removing the backslashes if the unquoted word is needed later. */
char *
cond_expand_word (w, special)
WORD_DESC *w;
@@ -2640,6 +2672,7 @@ cond_expand_word (w, special)
{
char *r, *p;
WORD_LIST *l;
int qflags;
if (w->word == 0 || w->word[0] == '\0')
return ((char *)NULL);
@@ -2654,8 +2687,11 @@ cond_expand_word (w, special)
}
else
{
qflags = QGLOB_CVTNULL;
if (special == 2)
qflags |= QGLOB_REGEXP;
p = string_list (l);
r = quote_string_for_globbing (p, QGLOB_CVTNULL);
r = quote_string_for_globbing (p, qflags);
free (p);
}
dispose_words (l);
@@ -2898,7 +2934,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;
@@ -2906,17 +2947,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);
}
@@ -2958,6 +3001,7 @@ dequote_escapes (string)
register char *s, *t;
size_t slen;
char *result, *send;
int quote_spaces;
DECLARE_MBSTATE;
if (string == 0)
@@ -2972,9 +3016,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')
@@ -2986,7 +3031,9 @@ dequote_escapes (string)
return result;
}
/* Return a new string with the quoted representation of character C. */
/* Return a new string with the quoted representation of character C.
This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
set in any resultant WORD_DESC where this value is the word. */
static char *
make_quoted_char (c)
int c;
@@ -3008,7 +3055,9 @@ make_quoted_char (c)
return (temp);
}
/* Quote STRING. Return a new string. */
/* Quote STRING, returning a new string. This turns "" into QUOTED_NULL, so
the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
this value is the word. */
char *
quote_string (string)
char *string;
@@ -3042,7 +3091,7 @@ quote_string (string)
return (result);
}
/* De-quoted quoted characters in STRING. */
/* De-quote quoted characters in STRING. */
char *
dequote_string (string)
char *string;
@@ -3098,11 +3147,13 @@ quote_list (list)
w->word->word = quote_string (t);
free (t);
w->word->flags |= W_QUOTED;
/* XXX - turn on W_HAVEQUOTEDNULL here? */
}
return list;
}
static WORD_LIST *
/* De-quote quoted characters in each word in LIST. */
WORD_LIST *
dequote_list (list)
WORD_LIST *list;
{
@@ -3114,6 +3165,7 @@ dequote_list (list)
s = dequote_string (tlist->word->word);
free (tlist->word->word);
tlist->word->word = s;
/* XXX - turn off W_HAVEQUOTEDNULL here? */
}
return list;
}
@@ -3317,23 +3369,6 @@ remove_upattern (param, pattern, op)
}
#if defined (HANDLE_MULTIBYTE)
#if !defined (HAVE_WCSDUP)
static wchar_t *
wcsdup (ws)
wchar_t *ws;
{
wchar_t *ret;
size_t len;
len = wcslen (ws);
ret = xmalloc ((len + 1) * sizeof (wchar_t));
if (ret == 0)
return ret;
return (wcscpy (ret, ws));
}
#endif /* !HAVE_WCSDUP */
static wchar_t *
remove_wpattern (wparam, wstrlen, wpattern, op)
wchar_t *wparam;
@@ -3341,9 +3376,8 @@ remove_wpattern (wparam, wstrlen, wpattern, op)
wchar_t *wpattern;
int op;
{
wchar_t wc;
int n, n1;
wchar_t *ret;
wchar_t wc, *ret;
int n;
switch (op)
{
@@ -3797,7 +3831,9 @@ getpattern (value, quoted, expandpat)
{
char *pat, *tword;
WORD_LIST *l;
#if 0
int i;
#endif
/* There is a problem here: how to handle single or double quotes in the
pattern string when the whole expression is between double quotes?
@@ -4114,12 +4150,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);
@@ -4163,6 +4205,12 @@ add_fifo_list (fd)
nfds++;
}
int
fifos_pending ()
{
return 0; /* used for cleanup; not needed with /dev/fd */
}
void
unlink_fifo_list ()
{
@@ -4289,7 +4337,7 @@ process_substitute (string, open_for_read_in_child)
/* Cancel traps, in trap.c. */
restore_original_signals ();
setup_async_signals ();
subshell_environment |= SUBSHELL_COMSUB;
subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
}
#if defined (JOB_CONTROL)
@@ -4355,7 +4403,7 @@ process_substitute (string, open_for_read_in_child)
{
if (sh_unset_nodelay_mode (fd) < 0)
{
sys_error (_("cannout reset nodelay mode for fd %d"), fd);
sys_error (_("cannot reset nodelay mode for fd %d"), fd);
exit (127);
}
}
@@ -4408,21 +4456,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)
@@ -4447,7 +4497,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;
@@ -4471,6 +4532,8 @@ read_comsub (fd, quoted)
if (istring_index == 0)
{
FREE (istring);
if (rflag)
*rflag = tflag;
return (char *)NULL;
}
@@ -4495,26 +4558,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)
{
@@ -4554,11 +4620,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)
@@ -4582,7 +4644,7 @@ command_substitute (string, quoted)
FREE (istring);
close (fildes[0]);
close (fildes[1]);
return ((char *)NULL);
return ((WORD_DESC *)NULL);
}
if (pid == 0)
@@ -4656,6 +4718,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
@@ -4666,7 +4731,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]);
@@ -4696,7 +4762,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;
}
}
@@ -4968,7 +5038,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;
@@ -5008,9 +5078,7 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
a $@ in TEMP. It does not matter if the $@ is quoted, as long as
it does not expand to anything. In this case, we want to return
a quoted empty string. */
temp = (char *)xmalloc (2);
temp[0] = CTLNUL;
temp[1] = '\0';
temp = make_quoted_char ('\0');
w->flags |= W_HASQUOTEDNULL;
}
else
@@ -5278,11 +5346,7 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
else
t = (char *)0;
#if 0
temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
#else
temp1 = expand_arith_string (substr);
#endif
temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
*e1p = evalexp (temp1, &expok);
free (temp1);
if (expok == 0)
@@ -5297,6 +5361,8 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
break;
case VT_POSPARMS:
len = number_of_args () + 1;
if (*e1p == 0)
len++; /* add one arg if counting from $0 */
break;
#if defined (ARRAY_VARS)
case VT_ARRAYVAR:
@@ -5327,11 +5393,7 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
{
t++;
temp2 = savestring (t);
#if 0
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
#else
temp1 = expand_arith_string (temp2);
#endif
temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
free (temp2);
t[-1] = ':';
*e2p = evalexp (temp1, &expok);
@@ -5488,22 +5550,27 @@ parameter_brace_substring (varname, value, substr, quoted)
{
intmax_t e1, e2;
int vtype, r, starsub;
char *temp, *val, *tt;
char *temp, *val, *tt, *oname;
SHELL_VAR *v;
if (value == 0)
return ((char *)NULL);
oname = this_command_name;
this_command_name = varname;
vtype = get_var_and_type (varname, value, quoted, &v, &val);
if (vtype == -1)
return ((char *)NULL);
{
this_command_name = oname;
return ((char *)NULL);
}
starsub = vtype & VT_STARSUB;
vtype &= ~VT_STARSUB;
r = verify_substring_values (val, substr, vtype, &e1, &e2);
this_command_name = oname;
if (r <= 0)
return ((r == 0) ? &expand_param_error : (char *)NULL);
@@ -5542,12 +5609,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
@@ -5653,7 +5724,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
{
WORD_LIST *save, *params;
WORD_DESC *w;
char *ret, *tt;
char *ret;
save = params = list_rest_of_args ();
if (save == 0)
@@ -5703,6 +5774,11 @@ parameter_brace_patsub (varname, value, patsub, quoted)
vtype &= ~VT_STARSUB;
mflags = 0;
if (patsub && *patsub == '/')
{
mflags |= MATCH_GLOBREP;
patsub++;
}
/* Malloc this because expand_string_if_necessary or one of the expansion
functions in its call chain may free it on a substitution error. */
@@ -5737,13 +5813,12 @@ parameter_brace_patsub (varname, value, patsub, quoted)
}
/* ksh93 doesn't allow the match specifier to be a part of the expanded
pattern. This is an extension. */
pattern. This is an extension. Make sure we don't anchor the pattern
at the beginning or end of the string if we're doing global replacement,
though. */
p = pat;
if (pat && pat[0] == '/')
{
mflags |= MATCH_GLOBREP|MATCH_ANY;
p++;
}
if (mflags & MATCH_GLOBREP)
mflags |= MATCH_ANY;
else if (pat && pat[0] == '#')
{
mflags |= MATCH_BEG;
@@ -5794,12 +5869,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
}
@@ -5811,6 +5890,57 @@ parameter_brace_patsub (varname, value, patsub, quoted)
return temp;
}
/* Check for unbalanced parens in S, which is the contents of $(( ... )). If
any occur, this must be a nested command substitution, so return 0.
Otherwise, return 1. A valid arithmetic expression must always have a
( before a matching ), so any cases where there are more right parens
means that this must not be an arithmetic expression, though the parser
will not accept it without a balanced total number of parens. */
static int
chk_arithsub (s, len)
const char *s;
int len;
{
int i, count;
DECLARE_MBSTATE;
i = count = 0;
while (i < len)
{
if (s[i] == '(')
count++;
else if (s[i] == ')')
{
count--;
if (count < 0)
return 0;
}
switch (s[i])
{
default:
ADVANCE_CHAR (s, len, i);
break;
case '\\':
i++;
if (s[i])
ADVANCE_CHAR (s, len, i);
break;
case '\'':
i = skip_single_quoted (s, len, ++i);
break;
case '"':
i = skip_double_quoted ((char *)s, len, ++i);
break;
}
}
return (count == 0);
}
/****************************************************************/
/* */
/* Functions to perform parameter expansion on a string */
@@ -6094,6 +6224,8 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
ret = alloc_word_desc ();
ret->word = temp1;
if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
return ret;
}
else if (want_patsub)
@@ -6422,7 +6554,6 @@ param_expand (string, sindex, quoted, expanded_something,
quoted_dollar_at_p,
contains_dollar_at);
/* Fix this later when parameter_brace_expand returns a WORD_DESC * */
if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
return (tdesc);
temp = tdesc ? tdesc->word : (char *)0;
@@ -6435,12 +6566,7 @@ param_expand (string, sindex, quoted, expanded_something,
in the string, discard TEMP, and go on. The exception to
this is when we have "${@}" and $1 is '', since $@ needs
special handling. */
/* XXX - fix this once parameter_brace_expand returns a WORD_DESC * */
#if 0
if (temp && QUOTED_NULL (temp))
#else
if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
#endif
{
if (had_quoted_null_p)
*had_quoted_null_p = 1;
@@ -6480,12 +6606,14 @@ param_expand (string, sindex, quoted, expanded_something,
/* Cut off ending `)' */
temp2[t_index] = '\0';
if (chk_arithsub (temp2, t_index) == 0)
{
free (temp2);
goto comsub;
}
/* Expand variables found inside the expression. */
#if 0
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
#else
temp1 = expand_arith_string (temp2);
#endif
temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
free (temp2);
arithsub:
@@ -6513,7 +6641,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;
@@ -6527,11 +6659,7 @@ comsub:
zindex = t_index;
/* Do initial variable expansion. */
#if 0
temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
#else
temp1 = expand_arith_string (temp);
#endif
temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
goto arithsub;
@@ -6909,7 +7037,7 @@ add_string:
sindex = t_index;
goto add_character;
}
report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
report_error (_("bad substitution: no closing \"`\" in %s") , string+t_index);
free (string);
free (istring);
return ((temp == &extract_string_error) ? &expand_word_error
@@ -6925,7 +7053,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;
@@ -7451,11 +7581,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 */
@@ -7531,9 +7657,6 @@ word_list_split (list)
for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
{
tresult = word_split (t->word, ifs_value);
#if 0
result = (WORD_LIST *) list_append (result, tresult);
#else
if (result == 0)
result = e = tresult;
else
@@ -7542,7 +7665,6 @@ word_list_split (list)
while (e->next)
e = e->next;
}
#endif
}
return (result);
}