commit bash-20040422 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 12:56:49 -05:00
parent 1d7ecd770c
commit de8913bd20
51 changed files with 13071 additions and 634 deletions
+475 -98
View File
@@ -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