summaryrefslogtreecommitdiff
path: root/Src/subst.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2006-06-28 13:12:55 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2006-06-28 13:12:55 +0000
commit6157c14d0602c698aa9ebfac9a2135ef095a76b4 (patch)
treecae7cb80281a1426c06734889fd8f0b83292c6ca /Src/subst.c
parentf95a6a913c885932827e9c0219221f7de7ccdd79 (diff)
downloadzsh-6157c14d0602c698aa9ebfac9a2135ef095a76b4.tar.gz
zsh-6157c14d0602c698aa9ebfac9a2135ef095a76b4.zip
22525: lengths and cases of multibyte strings in parameters and history
Diffstat (limited to 'Src/subst.c')
-rw-r--r--Src/subst.c67
1 files changed, 25 insertions, 42 deletions
diff --git a/Src/subst.c b/Src/subst.c
index 803f8d99d..d69f34c4b 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1019,7 +1019,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
/* (u): straightforward. */
int unique = 0;
/* combination of (L), (U) and (C) flags. */
- int casmod = 0;
+ int casmod = CASMOD_NONE;
/*
* quotemod says we are doing either (q) (positive), (Q) (negative)
* or not (0). quotetype counts the q's for the first case.
@@ -1211,13 +1211,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
break;
case 'L':
- casmod = 2;
+ casmod = CASMOD_LOWER;
break;
case 'U':
- casmod = 1;
+ casmod = CASMOD_UPPER;
break;
case 'C':
- casmod = 3;
+ casmod = CASMOD_CAPS;
break;
case 'o':
@@ -1819,17 +1819,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
break;
}
switch (v->pm->node.flags & (PM_LOWER | PM_UPPER)) {
- char *t;
-
case PM_LOWER:
- t = val;
- for (; (c = *t); t++)
- *t = tulower(c);
+ val = casemodify(val, CASMOD_LOWER);
+ copied = 1;
break;
case PM_UPPER:
- t = val;
- for (; (c = *t); t++)
- *t = tuupper(c);
+ val = casemodify(val, CASMOD_UPPER);
+ copied = 1;
break;
}
}
@@ -2316,14 +2312,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
if (isarr) {
char **ctr;
- int sl = sep ? ztrlen(sep) : 1;
+ int sl = sep ? MB_METASTRLEN(sep) : 1;
if (getlen == 1)
for (ctr = aval; *ctr; ctr++, len++);
else if (getlen == 2) {
if (*aval)
for (len = -sl, ctr = aval;
- len += sl + ztrlen(*ctr), *++ctr;);
+ len += sl + MB_METASTRLEN(*ctr), *++ctr;);
}
else
for (ctr = aval;
@@ -2331,7 +2327,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
len += wordcount(*ctr, spsep, getlen > 3), ctr++);
} else {
if (getlen < 3)
- len = ztrlen(val);
+ len = MB_METASTRLEN(val);
else
len = wordcount(val, spsep, getlen > 3);
}
@@ -2387,33 +2383,19 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
/*
* Perform case modififications.
*/
- if (casmod) {
+ if (casmod != CASMOD_NONE) {
+ copied = 1; /* string is always modified by copy */
if (isarr) {
- char **ap;
+ char **ap, **ap2;
- if (!copied)
- aval = arrdup(aval), copied = 1;
ap = aval;
+ ap2 = aval = (char **) zhalloc(sizeof(char *) * (arrlen(aval)+1));
- if (casmod == 1)
- for (; *ap; ap++)
- makeuppercase(ap);
- else if (casmod == 2)
- for (; *ap; ap++)
- makelowercase(ap);
- else
- for (; *ap; ap++)
- makecapitals(ap);
-
+ while (*ap)
+ *ap2++ = casemodify(*ap++, casmod);
+ *ap2++ = NULL;
} else {
- if (!copied)
- val = dupstring(val), copied = 1;
- if (casmod == 1)
- makeuppercase(&val);
- else if (casmod == 2)
- makelowercase(&val);
- else
- makecapitals(&val);
+ val = casemodify(val, casmod);
}
}
/*
@@ -2975,7 +2957,8 @@ modify(char **str, char **ptr)
for (t = e = *str; (tt = findword(&e, sep));) {
tc = *e;
*e = '\0';
- copy = dupstring(tt);
+ if (c != 'l' && c != 'u')
+ copy = dupstring(tt);
*e = tc;
switch (c) {
case 'h':
@@ -2991,10 +2974,10 @@ modify(char **str, char **ptr)
remlpaths(&copy);
break;
case 'l':
- downcase(&copy);
+ copy = casemodify(tt, CASMOD_LOWER);
break;
case 'u':
- upcase(&copy);
+ copy = casemodify(tt, CASMOD_UPPER);
break;
case 's':
if (hsubl && hsubr)
@@ -3050,10 +3033,10 @@ modify(char **str, char **ptr)
remlpaths(str);
break;
case 'l':
- downcase(str);
+ *str = casemodify(*str, CASMOD_LOWER);
break;
case 'u':
- upcase(str);
+ *str = casemodify(*str, CASMOD_UPPER);
break;
case 's':
if (hsubl && hsubr) {