mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-01 16:03:39 +02:00
commit bash-20040422 snapshot
This commit is contained in:
+475
-98
@@ -210,8 +210,23 @@ static char *extract_dollar_brace_string __P((char *, int *, int, int));
|
||||
|
||||
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
|
||||
static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
|
||||
#endif
|
||||
static char *remove_pattern __P((char *, char *, int));
|
||||
|
||||
static int match_pattern_char __P((char *, char *));
|
||||
static int match_upattern __P((char *, char *, int, char **, char **));
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static int match_pattern_wchar __P((wchar_t *, wchar_t *));
|
||||
static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
|
||||
#endif
|
||||
static int match_pattern __P((char *, char *, int, char **, char **));
|
||||
static int getpatspec __P((int, char *));
|
||||
static char *getpattern __P((char *, int, int));
|
||||
@@ -244,7 +259,8 @@ static intmax_t parameter_brace_expand_length __P((char *));
|
||||
|
||||
static char *skiparith __P((char *, int));
|
||||
static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
|
||||
static int get_var_and_type __P((char *, char *, SHELL_VAR **, char **));
|
||||
static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
|
||||
static char *mb_substring __P((char *, int, int));
|
||||
static char *parameter_brace_substring __P((char *, char *, char *, int));
|
||||
|
||||
static char *pos_params_pat_subst __P((char *, char *, char *, int));
|
||||
@@ -1168,9 +1184,9 @@ de_backslash (string)
|
||||
prev_i = i;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
if (j < prev_i)
|
||||
do string[j++] = string[prev_i++]; while (prev_i < i);
|
||||
do string[j++] = string[prev_i++]; while (prev_i < i);
|
||||
else
|
||||
j = i;
|
||||
j = i;
|
||||
}
|
||||
string[j] = '\0';
|
||||
|
||||
@@ -1562,6 +1578,10 @@ string_list_internal (list, sep)
|
||||
if (list == 0)
|
||||
return ((char *)NULL);
|
||||
|
||||
/* Short-circuit quickly if we don't need to separate anything. */
|
||||
if (list->next == 0)
|
||||
return (savestring (list->word->word));
|
||||
|
||||
/* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
|
||||
sep_len = STRLEN (sep);
|
||||
result_size = 0;
|
||||
@@ -1957,8 +1977,9 @@ do_assignment_internal (string, expand)
|
||||
SHELL_VAR *entry;
|
||||
#if defined (ARRAY_VARS)
|
||||
char *t;
|
||||
int ni, assign_list = 0;
|
||||
int ni;
|
||||
#endif
|
||||
int assign_list = 0;
|
||||
|
||||
offset = assignment (string, 0);
|
||||
name = savestring (string);
|
||||
@@ -2001,14 +2022,7 @@ do_assignment_internal (string, expand)
|
||||
}
|
||||
|
||||
if (echo_command_at_execute)
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (assign_list)
|
||||
fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
|
||||
}
|
||||
xtrace_print_assignment (name, value, assign_list, 1);
|
||||
|
||||
#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
|
||||
|
||||
@@ -2792,17 +2806,17 @@ remove_quoted_nulls (string)
|
||||
while (i < slen)
|
||||
{
|
||||
if (string[i] == CTLESC)
|
||||
{
|
||||
{
|
||||
/* Old code had j++, but we cannot assume that i == j at this
|
||||
point -- what if a CTLNUL has already been removed from the
|
||||
string? We don't want to drop the CTLESC or recopy characters
|
||||
that we've already copied down. */
|
||||
i++; string[j++] = CTLESC;
|
||||
if (i == slen)
|
||||
break;
|
||||
}
|
||||
if (i == slen)
|
||||
break;
|
||||
}
|
||||
else if (string[i] == CTLNUL)
|
||||
i++;
|
||||
i++;
|
||||
|
||||
prev_i = i;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -2836,6 +2850,33 @@ word_list_remove_quoted_nulls (list)
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
#if 0 /* Currently unused */
|
||||
static unsigned char *
|
||||
mb_getcharlens (string, len)
|
||||
char *string;
|
||||
int len;
|
||||
{
|
||||
int i, offset, last;
|
||||
unsigned char *ret;
|
||||
char *p;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
i = offset = 0;
|
||||
last = 0;
|
||||
ret = (unsigned char *)xmalloc (len);
|
||||
memset (ret, 0, len);
|
||||
while (string[last])
|
||||
{
|
||||
ADVANCE_CHAR (string, len, offset);
|
||||
ret[last] = offset - last;
|
||||
last = offset;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
|
||||
can have one of 4 values:
|
||||
RP_LONG_LEFT remove longest matching portion at start of PARAM
|
||||
@@ -2850,7 +2891,7 @@ word_list_remove_quoted_nulls (list)
|
||||
#define RP_SHORT_RIGHT 4
|
||||
|
||||
static char *
|
||||
remove_pattern (param, pattern, op)
|
||||
remove_upattern (param, pattern, op)
|
||||
char *param, *pattern;
|
||||
int op;
|
||||
{
|
||||
@@ -2858,18 +2899,12 @@ remove_pattern (param, pattern, op)
|
||||
register char *end;
|
||||
register char *p, *ret, c;
|
||||
|
||||
if (param == NULL)
|
||||
return (param);
|
||||
if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
|
||||
return (savestring (param));
|
||||
|
||||
len = STRLEN (param);
|
||||
end = param + len;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case RP_LONG_LEFT: /* remove longest match at start */
|
||||
/* BACKUP_CHAR_P (param, len, p); */
|
||||
for (p = end; p >= param; p--)
|
||||
{
|
||||
c = *p; *p = '\0';
|
||||
@@ -2879,11 +2914,11 @@ remove_pattern (param, pattern, op)
|
||||
return (savestring (p));
|
||||
}
|
||||
*p = c;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case RP_SHORT_LEFT: /* remove shortest match at start */
|
||||
/* ADVANCE_CHAR_P (p, end - p),p++ */
|
||||
for (p = param; p <= end; p++)
|
||||
{
|
||||
c = *p; *p = '\0';
|
||||
@@ -2897,7 +2932,6 @@ remove_pattern (param, pattern, op)
|
||||
break;
|
||||
|
||||
case RP_LONG_RIGHT: /* remove longest match at end */
|
||||
/* ADVANCE_CHAR_P (p, end - p),p++ */
|
||||
for (p = param; p <= end; p++)
|
||||
{
|
||||
if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
@@ -2911,7 +2945,6 @@ remove_pattern (param, pattern, op)
|
||||
break;
|
||||
|
||||
case RP_SHORT_RIGHT: /* remove shortest match at end */
|
||||
/* BACKUP_CHAR_P (param, len, p); */
|
||||
for (p = end; p >= param; p--)
|
||||
{
|
||||
if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
@@ -2924,9 +2957,144 @@ remove_pattern (param, pattern, op)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (savestring (param)); /* no match, return original string */
|
||||
}
|
||||
|
||||
#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;
|
||||
size_t wstrlen;
|
||||
wchar_t *wpattern;
|
||||
int op;
|
||||
{
|
||||
wchar_t wc;
|
||||
int n, n1;
|
||||
wchar_t *ret;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case RP_LONG_LEFT: /* remove longest match at start */
|
||||
for (n = wstrlen; n >= 0; n--)
|
||||
{
|
||||
wc = wparam[n]; wparam[n] = L'\0';
|
||||
if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
{
|
||||
wparam[n] = wc;
|
||||
return (wcsdup (wparam + n));
|
||||
}
|
||||
wparam[n] = wc;
|
||||
}
|
||||
break;
|
||||
|
||||
case RP_SHORT_LEFT: /* remove shortest match at start */
|
||||
for (n = 0; n <= wstrlen; n++)
|
||||
{
|
||||
wc = wparam[n]; wparam[n] = L'\0';
|
||||
if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
{
|
||||
wparam[n] = wc;
|
||||
return (wcsdup (wparam + n));
|
||||
}
|
||||
wparam[n] = wc;
|
||||
}
|
||||
break;
|
||||
|
||||
case RP_LONG_RIGHT: /* remove longest match at end */
|
||||
for (n = 0; n <= wstrlen; n++)
|
||||
{
|
||||
if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
{
|
||||
wc = wparam[n]; wparam[n] = L'\0';
|
||||
ret = wcsdup (wparam);
|
||||
wparam[n] = wc;
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RP_SHORT_RIGHT: /* remove shortest match at end */
|
||||
for (n = wstrlen; n >= 0; n--)
|
||||
{
|
||||
if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
|
||||
{
|
||||
wc = wparam[n]; wparam[n] = L'\0';
|
||||
ret = wcsdup (wparam);
|
||||
wparam[n] = wc;
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (wcsdup (wparam)); /* no match, return original string */
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
static char *
|
||||
remove_pattern (param, pattern, op)
|
||||
char *param, *pattern;
|
||||
int op;
|
||||
{
|
||||
if (param == NULL)
|
||||
return (param);
|
||||
if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
|
||||
return (savestring (param));
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1)
|
||||
{
|
||||
wchar_t *ret, *oret;
|
||||
size_t n;
|
||||
wchar_t *wparam, *wpattern;
|
||||
mbstate_t ps;
|
||||
char *xret;
|
||||
|
||||
n = xdupmbstowcs (&wpattern, NULL, pattern);
|
||||
if (n == (size_t)-1)
|
||||
return (remove_upattern (param, pattern, op));
|
||||
n = xdupmbstowcs (&wparam, NULL, param);
|
||||
if (n == (size_t)-1)
|
||||
{
|
||||
free (wpattern);
|
||||
return (remove_upattern (param, pattern, op));
|
||||
}
|
||||
oret = ret = remove_wpattern (wparam, n, wpattern, op);
|
||||
|
||||
free (wparam);
|
||||
free (wpattern);
|
||||
|
||||
n = strlen (param);
|
||||
xret = xmalloc (n + 1);
|
||||
memset (&ps, '\0', sizeof (mbstate_t));
|
||||
n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
|
||||
xret[n] = '\0'; /* just to make sure */
|
||||
free (oret);
|
||||
return xret;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return (remove_upattern (param, pattern, op));
|
||||
}
|
||||
|
||||
/* Return 1 of the first character of STRING could match the first
|
||||
character of pattern PAT. Used to avoid n2 calls to strmatch(). */
|
||||
static int
|
||||
@@ -2964,7 +3132,7 @@ match_pattern_char (pat, string)
|
||||
MATCH_BEG and MATCH_END anchor the match at the beginning and end
|
||||
of the string, respectively. The longest match is returned. */
|
||||
static int
|
||||
match_pattern (string, pat, mtype, sp, ep)
|
||||
match_upattern (string, pat, mtype, sp, ep)
|
||||
char *string, *pat;
|
||||
int mtype;
|
||||
char **sp, **ep;
|
||||
@@ -2973,21 +3141,16 @@ match_pattern (string, pat, mtype, sp, ep)
|
||||
register char *p, *p1;
|
||||
char *end;
|
||||
|
||||
if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
|
||||
return (0);
|
||||
|
||||
len = STRLEN (string);
|
||||
end = string + len;
|
||||
|
||||
switch (mtype)
|
||||
{
|
||||
case MATCH_ANY:
|
||||
/* ADVANCE_CHAR_P (p, end - p),p++ */
|
||||
for (p = string; p <= end; p++)
|
||||
{
|
||||
if (match_pattern_char (pat, p))
|
||||
{
|
||||
/* BACKUP_CHAR_P (p, end - p, p1) */
|
||||
for (p1 = end; p1 >= p; p1--)
|
||||
{
|
||||
c = *p1; *p1 = '\0';
|
||||
@@ -3002,12 +3165,13 @@ match_pattern (string, pat, mtype, sp, ep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
case MATCH_BEG:
|
||||
if (match_pattern_char (pat, string) == 0)
|
||||
return (0);
|
||||
/* BACKUP_CHAR_P (string, len, p) */
|
||||
|
||||
for (p = end; p >= string; p--)
|
||||
{
|
||||
c = *p; *p = '\0';
|
||||
@@ -3020,23 +3184,180 @@ match_pattern (string, pat, mtype, sp, ep)
|
||||
}
|
||||
*p = c;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
case MATCH_END:
|
||||
/* ADVANCE_CHAR_P(p, end - p), p++ */
|
||||
for (p = string; p <= end; p++)
|
||||
if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
|
||||
{
|
||||
*sp = p;
|
||||
*ep = end;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
|
||||
{
|
||||
*sp = p;
|
||||
*ep = end;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* Return 1 of the first character of WSTRING could match the first
|
||||
character of pattern WPAT. Wide character version. */
|
||||
static int
|
||||
match_pattern_wchar (wpat, wstring)
|
||||
wchar_t *wpat, *wstring;
|
||||
{
|
||||
wchar_t wc;
|
||||
|
||||
if (*wstring == 0)
|
||||
return (0);
|
||||
|
||||
switch (wc = *wpat++)
|
||||
{
|
||||
default:
|
||||
return (*wstring == wc);
|
||||
case L'\\':
|
||||
return (*wstring == *wpat);
|
||||
case L'?':
|
||||
return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
|
||||
case L'*':
|
||||
return (1);
|
||||
case L'+':
|
||||
case L'!':
|
||||
case L'@':
|
||||
return (*wpat == LPAREN ? 1 : (*wstring == wc));
|
||||
case L'[':
|
||||
return (*wstring != L'\0');
|
||||
}
|
||||
}
|
||||
|
||||
/* Match WPAT anywhere in WSTRING and return the match boundaries.
|
||||
This returns 1 in case of a successful match, 0 otherwise. Wide
|
||||
character version. */
|
||||
static int
|
||||
match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
|
||||
wchar_t *wstring;
|
||||
char **indices;
|
||||
size_t wstrlen;
|
||||
wchar_t *wpat;
|
||||
int mtype;
|
||||
char **sp, **ep;
|
||||
{
|
||||
wchar_t wc;
|
||||
int len;
|
||||
#if 0
|
||||
size_t n, n1; /* Apple's gcc seems to miscompile this badly */
|
||||
#else
|
||||
int n, n1;
|
||||
#endif
|
||||
|
||||
switch (mtype)
|
||||
{
|
||||
case MATCH_ANY:
|
||||
for (n = 0; n <= wstrlen; n++)
|
||||
{
|
||||
if (match_pattern_wchar (wpat, wstring + n))
|
||||
{
|
||||
for (n1 = wstrlen; n1 >= n; n1--)
|
||||
{
|
||||
wc = wstring[n1]; wstring[n1] = L'\0';
|
||||
if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
|
||||
{
|
||||
wstring[n1] = wc;
|
||||
*sp = indices[n];
|
||||
*ep = indices[n1];
|
||||
return 1;
|
||||
}
|
||||
wstring[n1] = wc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
case MATCH_BEG:
|
||||
if (match_pattern_wchar (wpat, wstring) == 0)
|
||||
return (0);
|
||||
|
||||
for (n = wstrlen; n >= 0; n--)
|
||||
{
|
||||
wc = wstring[n]; wstring[n] = L'\0';
|
||||
if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
|
||||
{
|
||||
wstring[n] = wc;
|
||||
*sp = indices[0];
|
||||
*ep = indices[n];
|
||||
return 1;
|
||||
}
|
||||
wstring[n] = wc;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
case MATCH_END:
|
||||
for (n = 0; n <= wstrlen; n++)
|
||||
{
|
||||
if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
|
||||
{
|
||||
*sp = indices[n];
|
||||
*ep = indices[wstrlen];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
static int
|
||||
match_pattern (string, pat, mtype, sp, ep)
|
||||
char *string, *pat;
|
||||
int mtype;
|
||||
char **sp, **ep;
|
||||
{
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int ret;
|
||||
size_t n;
|
||||
wchar_t *wstring, *wpat;
|
||||
char **indices;
|
||||
#endif
|
||||
|
||||
if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
|
||||
return (0);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1)
|
||||
{
|
||||
n = xdupmbstowcs (&wpat, NULL, pat);
|
||||
if (n == (size_t)-1)
|
||||
return (match_upattern (string, pat, mtype, sp, ep));
|
||||
n = xdupmbstowcs (&wstring, &indices, string);
|
||||
if (n == (size_t)-1)
|
||||
{
|
||||
free (wpat);
|
||||
return (match_upattern (string, pat, mtype, sp, ep));
|
||||
}
|
||||
ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
|
||||
|
||||
free (wpat);
|
||||
free (wstring);
|
||||
free (indices);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return (match_upattern (string, pat, mtype, sp, ep));
|
||||
}
|
||||
|
||||
static int
|
||||
getpatspec (c, value)
|
||||
int c;
|
||||
@@ -3203,7 +3524,7 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -4119,7 +4440,12 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
if (legal_number (name, &arg_index))
|
||||
{
|
||||
tt = get_dollar_var_value (arg_index);
|
||||
temp = tt ? quote_escapes (tt) : (char *)NULL;
|
||||
if (tt)
|
||||
temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (tt)
|
||||
: quote_escapes (tt);
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
FREE (tt);
|
||||
}
|
||||
else if (var_is_special) /* ${@} */
|
||||
@@ -4138,7 +4464,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
{
|
||||
temp = array_value (name, quoted, &atype);
|
||||
if (atype == 0 && temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
#endif
|
||||
else if (var = find_variable (name))
|
||||
@@ -4152,7 +4480,9 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
#endif
|
||||
|
||||
if (temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
@@ -4174,6 +4504,15 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
|
||||
char *temp, *t;
|
||||
|
||||
t = parameter_brace_expand_word (name, var_is_special, quoted);
|
||||
/* 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;
|
||||
}
|
||||
chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
|
||||
if (t == 0)
|
||||
return (t);
|
||||
@@ -4224,11 +4563,16 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
|
||||
if (l)
|
||||
{
|
||||
/* The expansion of TEMP returned something. We need to treat things
|
||||
slightly differently if HASDOL is non-zero. */
|
||||
temp = string_list (l);
|
||||
slightly differently if HASDOL is non-zero. If we have "$@", the
|
||||
individual words have already been quoted. We need to turn them
|
||||
into a string with the words separated by the first character of
|
||||
$IFS without any additional quoting, so string_list_dollar_at won't
|
||||
do the right thing. We use string_list_dollar_star instead. */
|
||||
temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
|
||||
|
||||
/* If l->next is not null, we know that TEMP contained "$@", since that
|
||||
is the only expansion that creates more than one word. */
|
||||
if ((hasdol && quoted) || l->next)
|
||||
if (qdollaratp && ((hasdol && quoted) || l->next))
|
||||
*qdollaratp = 1;
|
||||
dispose_words (l);
|
||||
}
|
||||
@@ -4563,8 +4907,9 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
|
||||
characters in the value are quoted with CTLESC and takes appropriate
|
||||
steps. For convenience, *VALP is set to the dequoted VALUE. */
|
||||
static int
|
||||
get_var_and_type (varname, value, varp, valp)
|
||||
get_var_and_type (varname, value, quoted, varp, valp)
|
||||
char *varname, *value;
|
||||
int quoted;
|
||||
SHELL_VAR **varp;
|
||||
char **valp;
|
||||
{
|
||||
@@ -4611,7 +4956,21 @@ get_var_and_type (varname, value, varp, valp)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if 1
|
||||
{
|
||||
if (value && vtype == VT_VARIABLE)
|
||||
{
|
||||
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
*valp = dequote_string (value);
|
||||
else
|
||||
*valp = dequote_escapes (value);
|
||||
}
|
||||
else
|
||||
*valp = value;
|
||||
}
|
||||
#else
|
||||
*valp = (value && vtype == VT_VARIABLE) ? dequote_escapes (value) : value;
|
||||
#endif
|
||||
|
||||
return vtype;
|
||||
}
|
||||
@@ -4622,6 +4981,35 @@ get_var_and_type (varname, value, varp, valp)
|
||||
/* */
|
||||
/******************************************************/
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* Character-oriented rather than strictly byte-oriented substrings. S and
|
||||
E, rather being strict indices into STRING, indicate character (possibly
|
||||
multibyte character) positions that require calculation.
|
||||
Used by the ${param:offset[:length]} expansion. */
|
||||
static char *
|
||||
mb_substring (string, s, e)
|
||||
char *string;
|
||||
int s, e;
|
||||
{
|
||||
char *tt;
|
||||
int start, stop, i, slen;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
start = 0;
|
||||
slen = STRLEN (string);
|
||||
|
||||
i = s;
|
||||
while (string[start] && i--)
|
||||
ADVANCE_CHAR (string, slen, start);
|
||||
stop = start;
|
||||
i = e - s;
|
||||
while (string[stop] && i--)
|
||||
ADVANCE_CHAR (string, slen, stop);
|
||||
tt = substring (string, start, stop);
|
||||
return tt;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
|
||||
is `@', use the positional parameters; otherwise, use the value of
|
||||
VARNAME. If VARNAME is an array variable, use the array elements. */
|
||||
@@ -4641,7 +5029,7 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -4656,7 +5044,13 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
{
|
||||
case VT_VARIABLE:
|
||||
case VT_ARRAYMEMBER:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1)
|
||||
tt = mb_substring (val, e1, e2);
|
||||
else
|
||||
#endif
|
||||
tt = substring (val, e1, e2);
|
||||
|
||||
if (vtype == VT_VARIABLE)
|
||||
FREE (val);
|
||||
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
@@ -4678,8 +5072,8 @@ parameter_brace_substring (varname, value, substr, quoted)
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
/* We want E2 to be the number of elements desired (arrays can be sparse,
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
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 ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
{
|
||||
@@ -4834,7 +5228,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
|
||||
this_command_name = varname;
|
||||
|
||||
vtype = get_var_and_type (varname, value, &v, &val);
|
||||
vtype = get_var_and_type (varname, value, quoted, &v, &val);
|
||||
if (vtype == -1)
|
||||
return ((char *)NULL);
|
||||
|
||||
@@ -5369,7 +5763,16 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
return (interactive_shell ? &expand_param_error : &expand_param_fatal);
|
||||
}
|
||||
#if 1
|
||||
if (temp1)
|
||||
temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp1)
|
||||
: quote_escapes (temp1);
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
#else
|
||||
temp = temp1 ? quote_escapes (temp1) : (char *)NULL;
|
||||
#endif
|
||||
break;
|
||||
|
||||
/* $$ -- pid of the invoking shell. */
|
||||
@@ -5606,11 +6009,22 @@ comsub:
|
||||
{
|
||||
temp = array_reference (array_cell (var), 0);
|
||||
if (temp)
|
||||
temp = quote_escapes (temp);
|
||||
temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
else if (unbound_vars_is_error)
|
||||
goto unbound_variable;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
temp = quote_escapes (value_cell (var));
|
||||
{
|
||||
temp = value_cell (var);
|
||||
|
||||
temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
}
|
||||
|
||||
free (temp1);
|
||||
|
||||
goto return0;
|
||||
@@ -5618,6 +6032,7 @@ comsub:
|
||||
|
||||
temp = (char *)NULL;
|
||||
|
||||
unbound_variable:
|
||||
if (unbound_vars_is_error)
|
||||
err_unboundvar (temp1);
|
||||
else
|
||||
@@ -5747,26 +6162,7 @@ expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_somethin
|
||||
#if HANDLE_MULTIBYTE
|
||||
if (MB_CUR_MAX > 1 && string[sindex])
|
||||
{
|
||||
int i;
|
||||
mbstate_t state_bak;
|
||||
size_t mblength;
|
||||
|
||||
state_bak = state;
|
||||
mblength = mbrlen (string + sindex, string_size - sindex, &state);
|
||||
if (MB_INVALIDCH (mblength))
|
||||
{
|
||||
state = state_bak;
|
||||
mblength = 1;
|
||||
}
|
||||
if (mblength < 1)
|
||||
mblength = 1;
|
||||
temp = (char *)xmalloc (mblength + 2);
|
||||
temp[0] = CTLESC;
|
||||
for (i = 0; i < mblength; i++)
|
||||
temp[i+1] = string[sindex++];
|
||||
temp[mblength + 1] = '\0';
|
||||
|
||||
goto add_string;
|
||||
SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -6106,31 +6502,12 @@ add_twochars:
|
||||
else
|
||||
{
|
||||
#if HANDLE_MULTIBYTE
|
||||
/* XXX - I'd like to use SCOPY_CHAR_I here. */
|
||||
if (MB_CUR_MAX > 1)
|
||||
sindex--;
|
||||
|
||||
if (MB_CUR_MAX > 1)
|
||||
{
|
||||
int i;
|
||||
mbstate_t state_bak;
|
||||
size_t mblength;
|
||||
|
||||
sindex--;
|
||||
state_bak = state;
|
||||
mblength = mbrlen (string + sindex, string_size - sindex, &state);
|
||||
if (MB_INVALIDCH (mblength))
|
||||
{
|
||||
state = state_bak;
|
||||
mblength = 1;
|
||||
}
|
||||
if (mblength < 1)
|
||||
mblength = 1;
|
||||
|
||||
temp = (char *)xmalloc (mblength + 2);
|
||||
temp[0] = CTLESC;
|
||||
for (i = 0; i < mblength; i++)
|
||||
temp[i + 1] = string[sindex++];
|
||||
temp[mblength + 1] = '\0';
|
||||
|
||||
goto add_string;
|
||||
SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user