[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[patch] UTF-8: ${var%...}-style parameter expansion broken
From: |
Tim Waugh |
Subject: |
[patch] UTF-8: ${var%...}-style parameter expansion broken |
Date: |
Mon, 5 Jan 2004 11:00:32 +0000 |
User-agent: |
Mutt/1.4.1i |
> Repeat-By:
> See:
> https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=112657
Here is a patch that works for me.
Tim.
*/
--- bash-2.05b/subst.c.subst 2004-01-05 10:41:32.575765192 +0000
+++ bash-2.05b/subst.c 2004-01-05 10:44:18.680813090 +0000
@@ -2813,6 +2813,8 @@
register int len;
register char *end;
register char *p, *ret, c;
+ unsigned char *mblen;
+ DECLARE_MBSTATE;
if (param == NULL || *param == '\0')
return (param);
@@ -2822,10 +2824,35 @@
len = STRLEN (param);
end = param + len;
+ /* Pre-calculate character boundaries. */
+ if (MB_CUR_MAX > 1)
+ switch (op)
+ {
+ int i, offset;
+ char *p;
+ unsigned char last;
+
+ case RP_LONG_LEFT:
+ case RP_SHORT_RIGHT:
+ i = offset = 0;
+ last = 0;
+ mblen = xmalloc (len);
+ memset (mblen, 0, len);
+ while (param[last])
+ {
+ ADVANCE_CHAR (param, len, offset);
+ mblen[last] = offset - last;
+ last = offset;
+ }
+ }
+
switch (op)
{
+ int offset;
+
case RP_LONG_LEFT: /* remove longest match at start */
- for (p = end; p >= param; p--)
+ p = end;
+ while (p >= param)
{
c = *p; *p = '\0';
if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2834,11 +2861,21 @@
return (savestring (p));
}
*p = c;
+
+ if (MB_CUR_MAX > 1)
+ {
+ while (p >= param)
+ if (mblen[--p - param])
+ break;
+ }
+ else p--;
}
break;
case RP_SHORT_LEFT: /* remove shortest match at start */
- for (p = param; p <= end; p++)
+ p = param;
+ offset = 0;
+ while (p <= end)
{
c = *p; *p = '\0';
if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
@@ -2847,11 +2884,20 @@
return (savestring (p));
}
*p = c;
+ if (MB_CUR_MAX > 1)
+ {
+ ADVANCE_CHAR (param, len, offset);
+ p = param + offset;
+ }
+ else
+ p++;
}
break;
case RP_LONG_RIGHT: /* remove longest match at end */
- for (p = param; p <= end; p++)
+ p = param;
+ offset = 0;
+ while (p <= end)
{
if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
{
@@ -2860,11 +2906,20 @@
*p = c;
return (ret);
}
+
+ if (MB_CUR_MAX > 1)
+ {
+ ADVANCE_CHAR (param, len, offset);
+ p = param + offset;
+ }
+ else
+ p++;
}
break;
case RP_SHORT_RIGHT: /* remove shortest match at end */
- for (p = end; p >= param; p--)
+ p = end;
+ while (p >= param)
{
if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
{
@@ -2873,6 +2928,15 @@
*p = c;
return (ret);
}
+
+ if (MB_CUR_MAX > 1)
+ {
+ while (p >= param)
+ if (mblen[--p - param])
+ break;
+ }
+ else
+ p--;
}
break;
}
@@ -4492,7 +4556,22 @@
{
case VT_VARIABLE:
case VT_ARRAYMEMBER:
- tt = substring (val, e1, e2);
+ if (MB_CUR_MAX > 1)
+ {
+ int start = 0, stop, i, slen = strlen (val);
+ DECLARE_MBSTATE;
+ i = e1;
+ while (val[start] && i--)
+ ADVANCE_CHAR (val, slen, start);
+ stop = start;
+ i = e2 - e1;
+ while (val[stop] && i--)
+ ADVANCE_CHAR (val, slen, stop);
+ tt = substring (val, start, stop);
+ }
+ else
+ tt = substring (val, e1, e2);
+
if (vtype == VT_VARIABLE)
FREE (val);
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))