summaryrefslogtreecommitdiff
path: root/subst.c.save2
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2011-12-07 09:24:46 -0500
committerChet Ramey <chet.ramey@case.edu>2011-12-07 09:24:46 -0500
commite33f22038cc3dc3146a8cc58e2c5b603e8578972 (patch)
tree8df8a3e07f6edb3568a674e5134c3d1c9a1bfa06 /subst.c.save2
parented35cb4a6394a5121724fc8a2c0ace6eb5be9de1 (diff)
downloadbash-e33f22038cc3dc3146a8cc58e2c5b603e8578972.tar.gz
commit bash-20080605 snapshot
Diffstat (limited to 'subst.c.save2')
-rw-r--r--subst.c.save2425
1 files changed, 282 insertions, 143 deletions
diff --git a/subst.c.save2 b/subst.c.save2
index 9944f5bc..080da0f8 100644
--- a/subst.c.save2
+++ b/subst.c.save2
@@ -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-2007 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -69,6 +69,7 @@ extern int errno;
#define VT_POSPARMS 1
#define VT_ARRAYVAR 2
#define VT_ARRAYMEMBER 3
+#define VT_ASSOCVAR 4
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
@@ -78,13 +79,6 @@ extern int errno;
#define ST_SQUOTE 0x04 /* unused yet */
#define ST_DQUOTE 0x08 /* unused yet */
-/* Flags for the string extraction functions. */
-#define SX_NOALLOC 0x01 /* just skip; don't return substring */
-#define SX_VARNAME 0x02 /* variable name; for string_extract () */
-#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
-#define SX_COMMAND 0x08 /* extracting a shell script/command */
-#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
-
/* Flags for the `pflags' argument to param_expand() */
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
@@ -135,6 +129,8 @@ size_t ifs_firstc_len;
unsigned char ifs_firstc;
#endif
+int assigning_in_environment;
+
/* Extern functions and variables from different files. */
extern int last_command_exit_value, last_command_exit_signal;
extern int subshell_environment;
@@ -206,7 +202,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 char *remove_quoted_escapes __P((char *));
static char *remove_quoted_nulls __P((char *));
static int unquoted_substring __P((char *, char *));
@@ -713,7 +708,7 @@ add_one_character:
si = i + 2;
if (string[i + 1] == LPAREN)
- ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
+ ret = extract_command_subst (string, &si, 0);
else
ret = extract_dollar_brace_string (string, &si, 1, 0);
@@ -815,7 +810,7 @@ skip_double_quoted (string, slen, sind)
{
si = i + 2;
if (string[i + 1] == LPAREN)
- ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
+ ret = extract_command_subst (string, &si, SX_NOALLOC);
else
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
@@ -933,11 +928,12 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
/* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
through, to protect the CTLNULs from later calls to
remove_quoted_nulls. */
- else if (c == CTLESC && string[i+1] == CTLNUL)
+ else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
{
i += 2;
continue;
}
+
#if defined (HANDLE_MULTIBYTE)
mblength = MBLEN (string + i, slen - i);
if (mblength > 1)
@@ -985,13 +981,21 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
/* Extract the $( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$(".
- Make (SINDEX) get the position of the matching ")". ) */
+ Make (SINDEX) get the position of the matching ")". )
+ XFLAGS is additional flags to pass to other extraction functions, */
char *
-extract_command_subst (string, sindex)
+extract_command_subst (string, sindex, xflags)
char *string;
int *sindex;
+ int xflags;
{
- return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
+ if (string[*sindex] == '(') /*)*/
+ return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
+ else
+ {
+ xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
+ return (xparse_dolparen (string, string+*sindex, sindex, xflags));
+ }
}
/* Extract the $[ construct in STRING, and return a new string. (])
@@ -1098,7 +1102,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
/* Not exactly right yet; should handle shell metacharacters and
multibyte characters, too. */
- if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
+ if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
{
in_comment = 1;
ADVANCE_CHAR (string, slen, i);
@@ -1263,7 +1267,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|SX_NOALLOC|SX_COMMAND); /*)*/
+ t = extract_command_subst (string, &si, flags|SX_NOALLOC);
i = si + 1;
continue;
}
@@ -1360,6 +1364,91 @@ unquote_bang (string)
}
#endif
+#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
+
+/* Skip characters in STRING until we find a character in DELIMS, and return
+ the index of that character. START is the index into string at which we
+ begin. This is similar in spirit to strpbrk, but it returns an index into
+ STRING and takes a starting index. This little piece of code knows quite
+ a lot of shell syntax. It's very similar to skip_double_quoted and other
+ functions of that ilk. */
+int
+skip_to_delim (string, start, delims, flags)
+ char *string;
+ int start;
+ char *delims;
+ int flags;
+{
+ int i, pass_next, backq, si, c;
+ size_t slen;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + start) + start;
+ if (flags & SD_NOJMP)
+ no_longjmp_on_fatal_error = 1;
+ i = start;
+ pass_next = backq = 0;
+ while (c = string[i])
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (c == 0)
+ CQ_RETURN(i);
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (backq)
+ {
+ if (c == '`')
+ backq = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '`')
+ {
+ backq = 1;
+ i++;
+ continue;
+ }
+ else if (c == '\'' || c == '"')
+ {
+ i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
+ : skip_double_quoted (string, slen, ++i);
+ /* no increment, the skip functions increment past the closing quote. */
+ }
+ else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
+ {
+ si = i + 2;
+ if (string[si] == '\0')
+ CQ_RETURN(si);
+
+ if (string[i+1] == LPAREN)
+ temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
+ else
+ temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
+ i = si;
+ if (string[i] == '\0') /* don't increment i past EOS in loop */
+ break;
+ i++;
+ continue;
+ }
+ else if (member (c, delims))
+ break;
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ CQ_RETURN(i);
+}
+
#if defined (READLINE)
/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
an unclosed quoted string), or if the character at EINDEX is quoted
@@ -1369,8 +1458,6 @@ unquote_bang (string)
recognizes need to be the same as the contents of
rl_completer_quote_characters. */
-#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
-
int
char_is_quoted (string, eindex)
char *string;
@@ -1463,87 +1550,6 @@ unclosed_pair (string, eindex, openstr)
return (openc);
}
-/* Skip characters in STRING until we find a character in DELIMS, and return
- the index of that character. START is the index into string at which we
- begin. This is similar in spirit to strpbrk, but it returns an index into
- STRING and takes a starting index. This little piece of code knows quite
- a lot of shell syntax. It's very similar to skip_double_quoted and other
- functions of that ilk. */
-int
-skip_to_delim (string, start, delims)
- char *string;
- int start;
- char *delims;
-{
- int i, pass_next, backq, si, c;
- size_t slen;
- char *temp;
- DECLARE_MBSTATE;
-
- slen = strlen (string + start) + start;
- no_longjmp_on_fatal_error = 1;
- i = start;
- pass_next = backq = 0;
- while (c = string[i])
- {
- if (pass_next)
- {
- pass_next = 0;
- if (c == 0)
- CQ_RETURN(i);
- ADVANCE_CHAR (string, slen, i);
- continue;
- }
- else if (c == '\\')
- {
- pass_next = 1;
- i++;
- continue;
- }
- else if (backq)
- {
- if (c == '`')
- backq = 0;
- ADVANCE_CHAR (string, slen, i);
- continue;
- }
- else if (c == '`')
- {
- backq = 1;
- i++;
- continue;
- }
- else if (c == '\'' || c == '"')
- {
- i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
- : skip_double_quoted (string, slen, ++i);
- /* no increment, the skip functions increment past the closing quote. */
- }
- else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
- {
- si = i + 2;
- if (string[si] == '\0')
- CQ_RETURN(si);
-
- if (string[i+1] == LPAREN)
- temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
- else
- temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
- i = si;
- if (string[i] == '\0') /* don't increment i past EOS in loop */
- break;
- i++;
- continue;
- }
- else if (member (c, delims))
- break;
- else
- ADVANCE_CHAR (string, slen, i);
- }
-
- CQ_RETURN(i);
-}
-
/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
individual words. If DELIMS is NULL, the current value of $IFS is used
to split the string, and the function follows the shell field splitting
@@ -1628,7 +1634,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
cw = -1;
while (1)
{
- te = skip_to_delim (string, ts, d);
+ te = skip_to_delim (string, ts, d, SD_NOJMP);
/* If we have a non-whitespace delimiter character, use it to make a
separate field. This is just about what $IFS splitting does and
@@ -1794,6 +1800,42 @@ string_list (list)
return (string_list_internal (list, " "));
}
+/* An external interface that can be used by the rest of the shell to
+ obtain a string containing the first character in $IFS. Handles all
+ the multibyte complications. If LENP is non-null, it is set to the
+ length of the returned string. */
+char *
+ifs_firstchar (lenp)
+ int *lenp;
+{
+ char *ret;
+ int len;
+
+ ret = xmalloc (MB_LEN_MAX + 1);
+#if defined (HANDLE_MULTIBYTE)
+ if (ifs_firstc_len == 1)
+ {
+ ret[0] = ifs_firstc[0];
+ ret[1] = '\0';
+ len = ret[0] ? 1 : 0;
+ }
+ else
+ {
+ memcpy (ret, ifs_firstc, ifs_firstc_len);
+ ret[len = ifs_firstc_len] = '\0';
+ }
+#else
+ ret[0] = ifs_firstc;
+ ret[1] = '\0';
+ len = ret[0] ? 0 : 1;
+#endif
+
+ if (lenp)
+ *lenp = len;
+
+ return ret;
+}
+
/* Return a single string of all the words present in LIST, obeying the
quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
expansion [of $*] appears within a double quoted string, it expands
@@ -1913,6 +1955,47 @@ string_list_dollar_at (list, quoted)
return ret;
}
+/* Turn the positional paramters into a string, understanding quoting and
+ the various subtleties of using the first character of $IFS as the
+ separator. Calls string_list_dollar_at, string_list_dollar_star, and
+ string_list as appropriate. */
+char *
+string_list_pos_params (pchar, list, quoted)
+ int pchar;
+ WORD_LIST *list;
+ int quoted;
+{
+ char *ret;
+
+ if (pchar == '*')
+ {
+ if (quoted & Q_DOUBLE_QUOTES)
+ ret = string_list_dollar_star (quote_list (list));
+ else if (quoted & Q_HERE_DOCUMENT)
+ ret = string_list (quote_list (list));
+ else
+ /* Even when unquoted, string_list_dollar_star does the right thing
+ making sure that the first character of $IFS is used as the
+ separator. */
+ ret = string_list_dollar_star (list);
+ }
+ else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ /* We use string_list_dollar_at, but only if the string is quoted, since
+ that quotes the escapes if it's not, which we don't want. We could
+ use string_list (the old code did), but that doesn't do the right
+ thing if the first character of $IFS is not a space. We use
+ string_list_dollar_star if the string is unquoted so we make sure that
+ the elements of $@ are separated by the first character of $IFS for
+ later splitting. */
+ ret = string_list_dollar_at (list, quoted);
+ else if (pchar == '@')
+ ret = string_list_dollar_star (list);
+ else
+ ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
+
+ return ret;
+}
+
/* Return the list of words present in STRING. Separate the string into
words at any of the characters found in SEPARATORS. If QUOTED is
non-zero then word in the list will have its quoted flag set, otherwise
@@ -1964,7 +2047,10 @@ list_string (string, separators, quoted)
separators[2] == '\n' &&
separators[3] == '\0';
for (xflags = 0, s = ifs_value; s && *s; s++)
- if (*s == CTLESC) xflags |= SX_NOCTLESC;
+ {
+ if (*s == CTLESC) xflags |= SX_NOCTLESC;
+ else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
+ }
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
@@ -2083,7 +2169,10 @@ get_word_from_string (stringp, separators, endptr)
separators[2] == '\n' &&
separators[3] == '\0';
for (xflags = 0, s = ifs_value; s && *s; s++)
- if (*s == CTLESC) xflags |= SX_NOCTLESC;
+ {
+ if (*s == CTLESC) xflags |= SX_NOCTLESC;
+ if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
+ }
s = *stringp;
slen = 0;
@@ -2271,7 +2360,7 @@ do_assignment_internal (word, expand)
const WORD_DESC *word;
int expand;
{
- int offset, tlen, appendop, assign_list, aflags;
+ int offset, tlen, appendop, assign_list, aflags, retval;
char *name, *value;
SHELL_VAR *entry;
#if defined (ARRAY_VARS)
@@ -2362,11 +2451,27 @@ do_assignment_internal (word, expand)
stupidly_hack_special_variables (name);
+#if 1
+ /* Return 1 if the assignment seems to have been performed correctly. */
+ if (entry == 0 || readonly_p (entry))
+ retval = 0; /* assignment failure */
+ else if (noassign_p (entry))
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ retval = 1; /* error status, but not assignment failure */
+ }
+ else
+ retval = 1;
+ ASSIGN_RETURN (retval);
+
+ if (entry && retval != 0)
+ VUNSETATTR (entry, att_invisible);
+#else
if (entry)
VUNSETATTR (entry, att_invisible);
- /* Return 1 if the assignment seems to have been performed correctly. */
ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
+#endif
}
/* Perform the assignment statement in STRING, and expand the
@@ -2516,17 +2621,9 @@ pos_params (string, start, end, quoted)
}
t->next = (WORD_LIST *)NULL;
- if (string[0] == '*')
- {
- if (quoted & Q_DOUBLE_QUOTES)
- ret = string_list_dollar_star (quote_list (h));
- else if (quoted & Q_HERE_DOCUMENT)
- ret = string_list (quote_list (h));
- else
- ret = string_list (h);
- }
- else
- ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
+
+ ret = string_list_pos_params (string[0], h, quoted);
+
if (t != params)
t->next = params;
@@ -2832,9 +2929,10 @@ expand_string_assignment (string, quoted)
passed string when an error occurs. Might want to trap other calls
to jump_to_top_level here so we don't endlessly loop. */
WORD_LIST *
-expand_prompt_string (string, quoted)
+expand_prompt_string (string, quoted, wflags)
char *string;
int quoted;
+ int wflags;
{
WORD_LIST *value;
WORD_DESC td;
@@ -2842,7 +2940,7 @@ expand_prompt_string (string, quoted)
if (string == 0 || *string == 0)
return ((WORD_LIST *)NULL);
- td.flags = 0;
+ td.flags = wflags;
td.word = savestring (string);
no_longjmp_on_fatal_error = 1;
@@ -2960,7 +3058,7 @@ quote_escapes (string)
register char *s, *t;
size_t slen;
char *result, *send;
- int quote_spaces, skip_ctlesc;
+ int quote_spaces, skip_ctlesc, skip_ctlnul;
DECLARE_MBSTATE;
slen = strlen (string);
@@ -2968,15 +3066,15 @@ quote_escapes (string)
quote_spaces = (ifs_value && *ifs_value == 0);
- for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
- skip_ctlesc |= *s == CTLESC;
+ for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
+ skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
t = result = (char *)xmalloc ((slen * 2) + 1);
s = string;
while (*s)
{
- if ((skip_ctlesc == 0 && *s == CTLESC) || *s == CTLNUL || (quote_spaces && *s == ' '))
+ if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
*t++ = CTLESC;
COPY_CHAR_P (t, s, send);
}
@@ -3190,7 +3288,7 @@ dequote_list (list)
/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
string. */
-static char *
+char *
remove_quoted_escapes (string)
char *string;
{
@@ -3920,12 +4018,9 @@ list_remove_pattern (list, pattern, patspec, itype, quoted)
}
l = REVERSE_LIST (new, WORD_LIST *);
- if (itype == '*')
- tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
- else
- tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
-
+ tword = string_list_pos_params (itype, l, quoted);
dispose_words (l);
+
return (tword);
}
@@ -3999,7 +4094,11 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
patstr++;
- pattern = getpattern (patstr, quoted, 1);
+ /* Need to pass getpattern newly-allocated memory in case of expansion --
+ the expansion code will free the passed string on an error. */
+ temp1 = savestring (patstr);
+ pattern = getpattern (temp1, quoted, 1);
+ free (temp1);
temp1 = (char *)NULL; /* shut up gcc */
switch (vtype)
@@ -4363,6 +4462,7 @@ process_substitute (string, open_for_read_in_child)
#if defined (JOB_CONTROL)
set_sigchld_handler ();
stop_making_children ();
+ /* XXX - should we only do this in the parent? (as in command subst) */
pipeline_pgrp = old_pipeline_pgrp;
#endif /* JOB_CONTROL */
@@ -4481,14 +4581,14 @@ read_comsub (fd, quoted, rflag)
int *rflag;
{
char *istring, buf[128], *bufp, *s;
- int istring_index, istring_size, c, tflag, skip_ctlesc;
+ int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
ssize_t bufn;
istring = (char *)NULL;
istring_index = istring_size = bufn = tflag = 0;
- for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
- skip_ctlesc |= *s == CTLESC;
+ for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
+ skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
#ifdef __CYGWIN__
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
@@ -4531,7 +4631,7 @@ read_comsub (fd, quoted, rflag)
tflag |= W_HASCTLESC;
istring[istring_index++] = CTLESC;
}
- else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
+ else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
istring[istring_index++] = CTLESC;
istring[istring_index++] = c;
@@ -4652,9 +4752,11 @@ command_substitute (string, quoted)
reset_signal_handlers ();
#if defined (JOB_CONTROL)
+ /* XXX DO THIS ONLY IN PARENT ? XXX */
set_sigchld_handler ();
stop_making_children ();
- pipeline_pgrp = old_pipeline_pgrp;
+ if (pid != 0)
+ pipeline_pgrp = old_pipeline_pgrp;
#else
stop_making_children ();
#endif /* JOB_CONTROL */
@@ -4944,10 +5046,11 @@ parameter_brace_expand_word (name, var_is_special, quoted)
char *temp, *tt;
intmax_t arg_index;
SHELL_VAR *var;
- int atype;
+ int atype, rflags;
ret = 0;
temp = 0;
+ rflags = 0;
/* Handle multiple digit arguments, as in ${11}. */
if (legal_number (name, &arg_index))
@@ -4980,6 +5083,8 @@ parameter_brace_expand_word (name, var_is_special, quoted)
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
? quote_string (temp)
: quote_escapes (temp);
+ else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ rflags |= W_HASQUOTEDNULL;
}
#endif
else if (var = find_variable (name))
@@ -5007,6 +5112,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
{
ret = alloc_word_desc ();
ret->word = temp;
+ ret->flags |= rflags;
}
return ret;
}
@@ -5739,6 +5845,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
WORD_LIST *save, *params;
WORD_DESC *w;
char *ret;
+ int pchar;
save = params = list_rest_of_args ();
if (save == 0)
@@ -5755,8 +5862,11 @@ pos_params_pat_subst (string, pat, rep, mflags)
if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
ret = string_list_dollar_star (quote_list (save));
+ else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
+ ret = string_list_dollar_star (quote_list (save));
else
- ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
+ ret = string_list_dollar_star (save);
+
dispose_words (save);
return (ret);
@@ -5771,7 +5881,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
char *varname, *value, *patsub;
int quoted;
{
- int vtype, mflags, starsub;
+ int vtype, mflags, starsub, delim;
char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
SHELL_VAR *v;
@@ -5806,10 +5916,21 @@ parameter_brace_patsub (varname, value, patsub, quoted)
/* If the pattern starts with a `/', make sure we skip over it when looking
for the replacement delimiter. */
+#if 0
if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
*rep++ = '\0';
else
rep = (char *)NULL;
+#else
+ delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
+ if (lpatsub[delim] == '/')
+ {
+ lpatsub[delim] = 0;
+ rep = lpatsub + delim + 1;
+ }
+ else
+ rep = (char *)NULL;
+#endif
if (rep && *rep == '\0')
rep = (char *)NULL;
@@ -5967,7 +6088,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
int t_index, sindex, c, tflag;
intmax_t number;
- value = (char *)NULL;
+ temp = temp1 = value = (char *)NULL;
var_is_set = var_is_null = var_is_special = check_nullness = 0;
want_substring = want_indir = want_patsub = 0;
@@ -6592,7 +6713,7 @@ param_expand (string, sindex, quoted, expanded_something,
case LPAREN:
/* We have to extract the contents of this paren substitution. */
t_index = zindex + 1;
- temp = extract_command_subst (string, &t_index);
+ temp = extract_command_subst (string, &t_index, 0);
zindex = t_index;
/* For Posix.2-style `$(( ))' arithmetic substitution,
@@ -6651,7 +6772,8 @@ comsub:
{
tdesc = command_substitute (temp, quoted);
temp1 = tdesc ? tdesc->word : (char *)NULL;
- dispose_word_desc (tdesc);
+ if (tdesc)
+ dispose_word_desc (tdesc);
}
FREE (temp);
temp = temp1;
@@ -6664,6 +6786,13 @@ comsub:
t_index = zindex + 1;
temp = extract_arithmetic_subst (string, &t_index);
zindex = t_index;
+ if (temp == 0)
+ {
+ temp = savestring (string);
+ if (expanded_something)
+ *expanded_something = 0;
+ goto return0;
+ }
/* Do initial variable expansion. */
temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
@@ -6993,7 +7122,7 @@ add_string:
free (temp);
temp = temp1;
sindex += t_index;
- goto add_string;
+ goto add_quoted_string; /* XXX was add_string */
}
else
{
@@ -7062,7 +7191,8 @@ add_string:
de_backslash (temp);
tword = command_substitute (temp, quoted);
temp1 = tword ? tword->word : (char *)NULL;
- dispose_word_desc (tword);
+ if (tword)
+ dispose_word_desc (tword);
}
FREE (temp);
temp = temp1;
@@ -7490,6 +7620,11 @@ string_quote_removal (string, quoted)
{
case '\\':
c = string[++sindex];
+ if (c == 0)
+ {
+ *r++ = '\\';
+ break;
+ }
if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
*r++ = '\\';
/* FALLTHROUGH */
@@ -7690,7 +7825,9 @@ exp_jump_to_top_level (v)
/* Cleanup code goes here. */
expand_no_split_dollar_star = 0; /* XXX */
expanding_redir = 0;
+ assigning_in_environment = 0;
+ top_level_cleanup (); /* from sig.c */
jump_to_top_level (v);
}
@@ -7908,7 +8045,7 @@ glob_expand_word_list (tlist, eflags)
else if (fail_glob_expansion != 0)
{
report_error (_("no match: %s"), tlist->word->word);
- jump_to_top_level (DISCARD);
+ exp_jump_to_top_level (DISCARD);
}
else if (allow_null_glob_expansion == 0)
{
@@ -8190,7 +8327,9 @@ expand_word_list_internal (list, eflags)
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
+ assigning_in_environment = (assign_func == assign_in_env);
tint = (*assign_func) (temp_list->word);
+ assigning_in_environment = 0;
/* Variable assignment errors in non-interactive shells running
in Posix.2 mode cause the shell to exit. */
if (tint == 0)