/* ``Have a little faith, there's magic in the night. You ain't a
beauty, but, hey, you're alright.'' */
-/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
SHELL_VAR *ifs_var;
char *ifs_value;
unsigned char ifs_cmap[UCHAR_MAX + 1];
+int ifs_is_set, ifs_is_null;
#if defined (HANDLE_MULTIBYTE)
unsigned char ifs_firstc[MB_LEN_MAX];
extern int wordexp_only;
extern int expanding_redir;
extern int tempenv_assign_error;
+extern int builtin_ignoring_errexit;
#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
extern wchar_t *wcsdup __P((const wchar_t *));
static int chk_arithsub __P((const char *, int));
static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int, arrayind_t *));
+static char *parameter_brace_find_indir __P((char *, int, int, int));
static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
static void parameter_brace_expand_error __P((char *, char *));
f &= ~W_ASSIGNASSOC;
fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
}
+ if (f & W_ASSIGNARRAY)
+ {
+ f &= ~W_ASSIGNARRAY;
+ fprintf (stderr, "W_ASSIGNARRAY%s", f ? "|" : "");
+ }
if (f & W_HASCTLESC)
{
f &= ~W_HASCTLESC;
f &= ~W_NOGLOB;
fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
}
- if (f & W_GLOBEXP)
+ if (f & W_SPLITSPACE)
{
- f &= ~W_GLOBEXP;
- fprintf (stderr, "W_GLOBEXP%s", f ? "|" : "");
+ f &= ~W_SPLITSPACE;
+ fprintf (stderr, "W_SPLITSPACE%s", f ? "|" : "");
}
if (f & W_ASSIGNMENT)
{
continue;
}
-#if 0
- /* Pass the contents of single-quoted and double-quoted strings
- through verbatim. */
- if (c == '\'' || c == '"')
- {
- si = i + 1;
- i = (c == '\'') ? skip_single_quoted (string, slen, si)
- : skip_double_quoted (string, slen, si);
- /* skip_XXX_quoted leaves index one past close quote */
- continue;
- }
-#else /* XXX - bash-4.2 */
/* Pass the contents of double-quoted strings through verbatim. */
if (c == '"')
{
if (c == '\'')
{
/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
- if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ if (posixly_correct && shell_compatibility_level > 42 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
ADVANCE_CHAR (string, slen, i);
else
{
continue;
}
-#endif
/* move past this character, which was not special. */
ADVANCE_CHAR (string, slen, i);
else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
+ dolbrace_state = DOLBRACE_QUOTE2; /* XXX */
else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1)
dolbrace_state = DOLBRACE_QUOTE;
else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1)
int flags;
{
SHELL_VAR *v;
- int mklocal, mkassoc;
+ int mklocal, mkassoc, mkglobal;
WORD_LIST *list;
mklocal = flags & ASS_MKLOCAL;
mkassoc = flags & ASS_MKASSOC;
+ mkglobal = flags & ASS_MKGLOBAL;
if (mklocal && variable_context)
{
v = make_local_assoc_variable (name);
else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
v = make_local_array_variable (name, 0);
- assign_compound_array_list (v, list, flags);
+ if (v)
+ assign_compound_array_list (v, list, flags);
+ }
+ /* In a function but forcing assignment in global context */
+ else if (mkglobal && variable_context)
+ {
+ v = find_global_variable (name);
+ list = expand_compound_array_assignment (v, value, flags);
+ if (v == 0 && mkassoc)
+ v = make_new_assoc_variable (name);
+ else if (v && mkassoc && assoc_p (v) == 0)
+ v = convert_var_to_assoc (v);
+ else if (v == 0)
+ v = make_new_array_variable (name);
+ else if (v && mkassoc == 0 && array_p (v) == 0)
+ v = convert_var_to_array (v);
+ if (v)
+ assign_compound_array_list (v, list, flags);
}
else
v = assign_array_from_string (name, value, flags);
{
if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL) == 0)
aflags |= ASS_MKLOCAL;
+ if ((word->flags & W_ASSIGNARG) && (word->flags & W_ASSNGLOBAL))
+ aflags |= ASS_MKGLOBAL;
if (word->flags & W_ASSIGNASSOC)
aflags |= ASS_MKASSOC;
entry = do_compound_assignment (name, value, aflags);
char *string;
int quoted;
{
- return (expand_string_if_necessary (string, quoted, expand_string));
+ WORD_DESC td;
+ WORD_LIST *list, *tlist;
+ size_t slen;
+ int i, saw_quote;
+ char *ret;
+ DECLARE_MBSTATE;
+
+ /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
+ i = saw_quote = 0;
+ while (string[i])
+ {
+ if (EXP_CHAR (string[i]))
+ break;
+ else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
+ saw_quote = 1;
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (string[i])
+ {
+ /* This is expanded version of expand_string_internal as it's called by
+ expand_string_leave_quoted */
+ td.flags = W_NOPROCSUB; /* don't want process substitution */
+ td.word = savestring (string);
+ list = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+ /* This takes care of the calls from expand_string_leave_quoted and
+ expand_string */
+ if (list)
+ {
+ tlist = word_list_split (list);
+ dispose_words (list);
+ list = tlist;
+ if (list)
+ dequote_list (list);
+ }
+ /* This comes from expand_string_if_necessary */
+ if (list)
+ {
+ ret = string_list (list);
+ dispose_words (list);
+ }
+ else
+ ret = (char *)NULL;
+ FREE (td.word);
+ }
+ else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ ret = string_quote_removal (string, quoted);
+ else
+ ret = savestring (string);
+
+ return ret;
}
#if defined (COND_COMMAND)
last_command_exit_value = EXECUTION_FAILURE;
exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
/* NOTREACHED */
+ return (NULL);
}
else
return (result);
return ((xret == param) ? savestring (param) : xret);
}
n = xdupmbstowcs (&wparam, NULL, param);
+
if (n == (size_t)-1)
{
free (wpattern);
{
if (match_pattern_char (pat, p))
{
-#if 0
- for (p1 = end; p1 >= p; p1--)
-#else
p1 = (mlen == -1) ? end : p + mlen;
/* p1 - p = length of portion of string to be considered
p = current position in string
if (p1 > end)
break;
for ( ; p1 >= p; p1--)
-#endif
{
c = *p1; *p1 = '\0';
if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
if (match_pattern_char (pat, string) == 0)
return (0);
-#if 0
- for (p = end; p >= string; p--)
-#else
for (p = (mlen == -1) ? end : string + mlen; p >= string; p--)
-#endif
{
c = *p; *p = '\0';
if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
return 1;
}
*p = c;
-#if 1
/* If MLEN != -1, we have a fixed length pattern. */
if (mlen != -1)
break;
-#endif
}
return (0);
case MATCH_END:
-#if 0
- for (p = string; p <= end; p++)
-#else
for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++)
-#endif
{
if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
{
*ep = end;
return 1;
}
-#if 1
/* If MLEN != -1, we have a fixed length pattern. */
if (mlen != -1)
break;
-#endif
}
return (0);
case MATCH_ANY:
for (n = 0; n <= wstrlen; n++)
{
-#if 1
n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
-#else
- n2 = match_pattern_wchar (wpat, wstring + n);
-#endif
if (n2)
{
-#if 0
- for (n1 = wstrlen; n1 >= n; n1--)
-#else
n1 = (mlen == -1) ? wstrlen : n + mlen;
if (n1 > wstrlen)
break;
for ( ; n1 >= n; n1--)
-#endif
{
wc = wstring[n1]; wstring[n1] = L'\0';
if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
return 1;
}
wstring[n1] = wc;
-#if 1
/* If MLEN != -1, we have a fixed length pattern. */
if (mlen != -1)
break;
-#endif
}
}
}
if (match_pattern_wchar (wpat, wstring) == 0)
return (0);
-#if 0
- for (n = wstrlen; n >= 0; n--)
-#else
for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--)
-#endif
{
wc = wstring[n]; wstring[n] = L'\0';
if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
return 1;
}
wstring[n] = wc;
-#if 1
/* If MLEN != -1, we have a fixed length pattern. */
if (mlen != -1)
break;
-#endif
}
return (0);
case MATCH_END:
-#if 0
- for (n = 0; n <= wstrlen; n++)
-#else
for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++)
-#endif
{
if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
{
*ep = indices[wstrlen];
return 1;
}
-#if 1
/* If MLEN != -1, we have a fixed length pattern. */
if (mlen != -1)
break;
-#endif
}
return (0);
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1)
{
-#if 0
- slen = STRLEN (string);
- mslen = MBSLEN (string);
- plen = STRLEN (pat);
- mplen = MBSLEN (pat);
- if (slen == mslen && plen == mplen)
-#else
if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
-#endif
return (match_upattern (string, pat, mtype, sp, ep));
n = xdupmbstowcs (&wpat, NULL, pat);
/* compute itype from varname here */
v = array_variable_part (varname, &ret, 0);
+
+ /* XXX */
+ if (v && invisible_p (var))
+ return ((char *)NULL);
+
itype = ret[0];
a = (v && array_p (v)) ? array_cell (v) : 0;
dev_fd_list[parent_pipe_fd] = 0;
#endif /* HAVE_DEV_FD */
+ /* subshells shouldn't have this flag, which controls using the temporary
+ environment for variable lookups. */
+ expanding_redir = 0;
+
result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
#if !defined (HAVE_DEV_FD)
close (open_for_read_in_child ? 0 : 1);
#endif /* !HAVE_DEV_FD */
+ last_command_exit_value = result;
+ result = run_exit_trap ();
exit (result);
/*NOTREACHED*/
}
/* When not in POSIX mode, command substitution does not inherit
the -e flag. */
if (posixly_correct == 0)
- exit_immediately_on_error = 0;
+ {
+ builtin_ignoring_errexit = 0;
+ change_flag ('e', FLAG_OFF);
+ set_shellopts ();
+ }
remove_quoted_escapes (string);
startup_state = 2; /* see if we can avoid a fork */
/* Give command substitution a place to jump back to on failure,
so we don't go back up to main (). */
- result = setjmp (top_level);
+ result = setjmp_nosigs (top_level);
/* If we're running a command substitution inside a shell function,
trap `return' so we don't return from the function in the subshell
and go off to never-never land. */
if (result == 0 && return_catch_flag)
- function_value = setjmp (return_catch);
+ function_value = setjmp_nosigs (return_catch);
else
function_value = 0;
/* If unbound variables should generate an error, report one and return
failure. */
- if ((var == 0 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
+ if ((var == 0 || invisible_p (var) || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
{
c = *--t;
*t = '\0';
*t = c;
return (-1);
}
- else if (var == 0)
+ else if (var == 0 || invisible_p (var))
return 0;
/* We support a couple of expansions for variables that are not arrays.
{
expand_arrayref:
/* XXX - does this leak if name[@] or name[*]? */
- temp = array_value (name, quoted, 0, &atype, &ind);
+ if (pflags & PF_ASSIGNRHS)
+ {
+ temp = array_variable_name (name, &tt, (int *)0);
+ if (ALL_ELEMENT_SUB (tt[0]) && tt[1] == ']')
+ temp = array_value (name, quoted|Q_DOUBLE_QUOTES, 0, &atype, &ind);
+ else
+ temp = array_value (name, quoted, 0, &atype, &ind);
+ }
+ else
+ temp = array_value (name, quoted, 0, &atype, &ind);
if (atype == 0 && temp)
{
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
name = temp;
goto expand_arrayref;
}
+ else
#endif
/* y=2 ; typeset -n x=y; echo ${x} is not the same as echo ${2} in ksh */
- else if (temp && *temp && legal_identifier (temp) == 0)
+ if (temp && *temp && legal_identifier (temp) == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
report_error (_("%s: invalid variable name for name reference"), temp);
return ret;
}
+static char *
+parameter_brace_find_indir (name, var_is_special, quoted, find_nameref)
+ char *name;
+ int var_is_special, quoted, find_nameref;
+{
+ char *temp, *t;
+ WORD_DESC *w;
+ SHELL_VAR *v;
+
+ if (find_nameref && var_is_special == 0 && (v = find_variable_last_nameref (name)) &&
+ nameref_p (v) && (t = nameref_cell (v)) && *t)
+ return (savestring (t));
+
+ /* If var_is_special == 0, and name is not an array reference, this does
+ more expansion than necessary. It should really look up the variable's
+ value and not try to expand it. */
+ w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
+ t = w->word;
+ /* Have to dequote here if necessary */
+ if (t)
+ {
+ temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ ? dequote_string (t)
+ : dequote_escapes (t);
+ free (t);
+ t = temp;
+ }
+ dispose_word_desc (w);
+
+ return t;
+}
+
/* Expand an indirect reference to a variable: ${!NAME} expands to the
value of the variable whose name is the value of NAME. */
static WORD_DESC *
}
}
- /* If var_is_special == 0, and name is not an array reference, this does
- more expansion than necessary. It should really look up the variable's
- value and not try to expand it. */
- w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND, 0);
- t = w->word;
- /* Have to dequote here if necessary */
- if (t)
- {
- temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
- ? dequote_string (t)
- : dequote_escapes (t);
- free (t);
- t = temp;
- }
- dispose_word_desc (w);
+ t = parameter_brace_find_indir (name, var_is_special, quoted, 0);
chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
if (t == 0)
else
#endif /* ARRAY_VARS */
bind_variable (name, t1, 0);
+#if 0
+ if (STREQ (name, "IFS") == 0)
+#endif
+ stupidly_hack_special_variables (name);
/* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
free (temp);
SHELL_VAR **varp;
char **valp;
{
- int vtype;
- char *temp;
+ int vtype, want_indir;
+ char *temp, *vname;
+ WORD_DESC *wd;
#if defined (ARRAY_VARS)
SHELL_VAR *v;
#endif
arrayind_t lind;
+ want_indir = *varname == '!' &&
+ (legal_variable_starter ((unsigned char)varname[1]) || DIGIT (varname[1])
+ || VALID_INDIR_PARAM (varname[1]));
+ if (want_indir)
+ vname = parameter_brace_find_indir (varname+1, SPECIAL_VAR (varname, 1), quoted, 1);
+ else
+ vname = varname;
+
/* This sets vtype to VT_VARIABLE or VT_POSPARMS */
- vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
- if (vtype == VT_POSPARMS && varname[0] == '*')
+ vtype = (vname[0] == '@' || vname[0] == '*') && vname[1] == '\0';
+ if (vtype == VT_POSPARMS && vname[0] == '*')
vtype |= VT_STARSUB;
*varp = (SHELL_VAR *)NULL;
#if defined (ARRAY_VARS)
- if (valid_array_reference (varname))
+ if (valid_array_reference (vname))
{
- v = array_variable_part (varname, &temp, (int *)0);
+ v = array_variable_part (vname, &temp, (int *)0);
/* If we want to signal array_value to use an already-computed index,
set LIND to that index */
lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
+ if (v && invisible_p (v))
+ {
+ vtype = VT_ARRAYMEMBER;
+ *varp = (SHELL_VAR *)NULL;
+ *valp = (char *)NULL;
+ }
if (v && (array_p (v) || assoc_p (v)))
{ /* [ */
if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
else
{
vtype = VT_ARRAYMEMBER;
- *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
+ *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
}
*varp = v;
}
{
vtype = VT_ARRAYMEMBER;
*varp = v;
- *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
+ *valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
}
}
- else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
+ else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
{
vtype = VT_ARRAYMEMBER;
*varp = v;
*valp = value;
}
+ if (want_indir)
+ free (vname);
+
return vtype;
}
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
-#if 0
- if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
- ret = string_list_dollar_star (quote_list (save));
- else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
- ret = string_list_dollar_star (save);
- else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
- ret = string_list_dollar_at (save, qflags);
- else
- ret = string_list_dollar_star (save);
-#else
ret = string_list_pos_params (pchar, save, qflags);
-#endif
dispose_words (save);
pat = getpattern (lpatsub, quoted, 1);
if (rep)
- /* We want to perform quote removal on the expanded replacement even if
- the entire expansion is double-quoted because the parser and string
- extraction functions treated quotes in the replacement string as
- special. */
- rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
+ {
+ /* We want to perform quote removal on the expanded replacement even if
+ the entire expansion is double-quoted because the parser and string
+ extraction functions treated quotes in the replacement string as
+ special. THIS IS NOT BACKWARDS COMPATIBLE WITH BASH-4.2. */
+ if (shell_compatibility_level > 42)
+ rep = expand_string_if_necessary (rep, quoted & ~(Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT), expand_string_unsplit);
+ /* This is the bash-4.2 code. */
+ else if ((mflags & MATCH_QUOTED) == 0)
+ rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
+ else
+ rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
+ }
/* ksh93 doesn't allow the match specifier to be a part of the expanded
pattern. This is an extension. Make sure we don't anchor the pattern
if (want_indir)
tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
else
- tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind);
+ tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND|(pflags&(PF_NOSPLIT2|PF_ASSIGNRHS)), &ind);
if (tdesc)
{
var_is_set = temp != (char *)0;
var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
+ /* XXX - this may not need to be restricted to special variables */
+ if (check_nullness)
+ var_is_null |= var_is_set && var_is_special && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && QUOTED_NULL (temp);
/* Get the rest of the stuff inside the braces. */
if (c && c != RBRACE)
an assignment statement. In that case, we don't separate the
arguments at all. Otherwise, if the $* is not quoted it is
identical to $@ */
-#if 1
# if defined (HANDLE_MULTIBYTE)
if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
# else
# endif
temp = string_list_dollar_star (list);
else
- temp = string_list_dollar_at (list, quoted);
-#else
- temp = string_list_dollar_at (list, quoted);
-#endif
+ {
+ temp = string_list_dollar_at (list, quoted);
+ if (quoted == 0 && (ifs_is_set == 0 || ifs_is_null))
+ tflag |= W_SPLITSPACE;
+ }
+
if (expand_no_split_dollar_star == 0 && contains_dollar_at)
*contains_dollar_at = 1;
}
/* State flags */
int had_quoted_null;
int has_dollar_at, temp_has_dollar_at;
+ int split_on_spaces;
int tflag;
int pflags; /* flags passed to param_expand */
istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
istring[istring_index = 0] = '\0';
quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
+ split_on_spaces = 0;
quoted_state = UNQUOTED;
string = word->word;
&temp_has_dollar_at, "ed_dollar_at,
&had_quoted_null, pflags);
has_dollar_at += temp_has_dollar_at;
+ split_on_spaces += (tword->flags & W_SPLITSPACE);
if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
{
a } in ${...} is removed. Issue 0000221 */
if ((quoted & Q_DOLBRACE) && c == RBRACE)
{
+ SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
+ }
+ /* This is the fix for " $@\ " */
+ else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0) & isexp == 0 && isifs (c))
+ {
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
+ DEFAULT_ARRAY_SIZE);
+ istring[istring_index++] = CTLESC;
+ istring[istring_index++] = '\\';
+ istring[istring_index] = '\0';
+
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
break;
case '"':
-#if 0
- if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
-#else
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-#endif
goto add_character;
t_index = ++sindex;
{
if (list->next)
{
-#if 0
- if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
- temp = string_list_internal (quote_list (list), " ");
- else
-#endif
/* Testing quoted_dollar_at makes sure that "$@" is
split correctly when $IFS does not contain a space. */
temp = quoted_dollar_at
/* break; */
case '\'':
-#if 0
- if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
-#else
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
-#endif
goto add_character;
t_index = ++sindex;
positional parameters with a space, so we split on space (we have
set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
string_list_dollar_at has separated the positional parameters
- with the first character of $IFS, so we split on $IFS. */
- if (has_dollar_at && ifs_chars)
+ with the first character of $IFS, so we split on $IFS. If
+ SPLIT_ON_SPACES is set, we expanded $* (unquoted) with IFS either
+ unset or null, and we want to make sure that we split on spaces
+ regardless of what else has happened to IFS since the expansion. */
+ if (split_on_spaces)
+ list = list_string (istring, " ", 1); /* XXX quoted == 1? */
+ else if (has_dollar_at && ifs_chars)
list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
else
{
ifs_var = v;
ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
+ ifs_is_set = ifs_var != 0;
+ ifs_is_null = ifs_is_set && (*ifs_value == 0);
+
/* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
handle multibyte chars in IFS */
memset (ifs_cmap, '\0', sizeof (ifs_cmap));
for (glob_index = 0; glob_array[glob_index]; glob_index++)
{
tword = make_bare_word (glob_array[glob_index]);
- tword->flags |= W_GLOBEXP; /* XXX */
glob_list = make_word_list (tword, glob_list);
}
if (tlist->word->flags & W_NOBRACE)
{
-itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);
+/*itrace("brace_expand_word_list: %s: W_NOBRACE", tlist->word->word);*/
PREPEND_LIST (tlist, output_list);
continue;
}
{
int t;
- if (tlist->word->flags & W_ASSIGNASSOC)
+ if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL)) == (W_ASSIGNASSOC|W_ASSNGLOBAL))
+ make_internal_declare (tlist->word->word, "-gA");
+ else if (tlist->word->flags & W_ASSIGNASSOC)
make_internal_declare (tlist->word->word, "-A");
+ else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
+ make_internal_declare (tlist->word->word, "-ga");
+ else if (tlist->word->flags & W_ASSIGNARRAY)
+ make_internal_declare (tlist->word->word, "-a");
+ else if (tlist->word->flags & W_ASSNGLOBAL)
+ make_internal_declare (tlist->word->word, "-g");
t = do_word_assignment (tlist->word, 0);
if (t == 0)
/* Now transform the word as ksh93 appears to do and go on */
t = assignment (tlist->word->word, 0);
tlist->word->word[t] = '\0';
- tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC);
+ tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC|W_ASSIGNARRAY);
}
#endif
WORD_LIST *new_list, *temp_list;
int tint;
+ tempenv_assign_error = 0;
if (list == 0)
return ((WORD_LIST *)NULL);
subst_assign_varlist = (WORD_LIST *)NULL;
}
-#if 0
- tint = list_length (new_list) + 1;
- RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
- for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
- glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
- glob_argv_flags[tint] = '\0';
-#endif
-
return (new_list);
}