diff --git a/src/cmd/ksh93/ksh.1 b/src/cmd/ksh93/ksh.1 index 58a5627..9892ea6 100644 --- a/src/cmd/ksh93/ksh.1 +++ b/src/cmd/ksh93/ksh.1 @@ -1550,18 +1550,17 @@ will be re-evaluated for each element. .TP \f3${\fP\f2parameter\^\fP\f3,,\fP\f2pattern\^\fP\f3}\fP .PD -Case modification. This expansion modifies the case of alphabetic -characters in parameter. The \f2pattern\fP is expanded to produce a pattern -just as in pathname expansion. The \f3^\fP operator converts lowercase -characters matching \f2pattern\fP to uppercase. The \f3,\fP operator -converts matching uppercase characters to lowercase. The \f3^^\fP and -\f3,,\fP expansions convert all matched character in the -expanded value. The \f3^\fP and \f3,\fP expansions match and convert only -the first character in the expanded value. If pattern is omitted -it is treated like a \f2?\fP, which matches every character. -If \f2parameter\fP is \f3@\fP or \f3*\fP, or an array subscripted by \f3@\fP -or \f3*\fP, the case modification operation is applied to each element. - +Case modification. If the shell \f2pattern\fP matches the +value of \f2parameter\fP, then this expansion is the value of the +\f2parameter\fP with alphabetic characters in the matched portion changed +to uppercase for \f3^\fP and \f3^^\fP, or to lowercase for \f3,\fP +and \f3,,\fP. For \f3^\fP and \f3,\fP the transformation is applied only +if the match is at the beginning of the string. For \f3^^\fP and \f3,,\fP +all matches are transformed. If +\f2pattern\fP is unmatched, then \f2parameter\fP is substituted unmodified. +When \f2parameter\fP is \f3@\fP, \f3*\fP, or an array variable with +subscript \f3@\fP or \f3*\fP, +the transformation is applied to each element in turn. .PP The following parameters diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 2527b81..d092684 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -1686,19 +1686,29 @@ retry2: sh_setmatch(mp->shp, 0, 0, nmatch, 0, -1); } } - if (vsize) { - if (c == ',' || c == '^') offset = stktell(stkp); - mac_copy(mp, v, vsize > 0 ? vsize : strlen(v)); - if (c == ',' || c == '^') { - v = stkptr(stkp, offset); - if (type) { - char *sp; - for (sp = v; *sp; sp++) *sp = (c == '^' ? toupper(*sp) : tolower(*sp)); - } else if (*pattern == '?' || (v && *pattern == *v && pattern[1] == 0)) { - *v = (c == '^' ? toupper(*v) : tolower(*v)); + if (c == '^' || c == ',') { + vsize = (int)strlen(v); + while (vsize > 0) { + flag = STR_GROUP | STR_MAXIMAL | ((type) ? 0 : (STR_LEFT)); + nmatch = strngrpmatch(v, vsize, + *pattern ? pattern : "?", + (ssize_t *)match, + elementsof(match) / 2, flag | STR_INT); + if (nmatch == 0) break; + if (match [0]) { + mac_copy(mp, v, match [0]); + } + for (char *cc = v + match[0]; cc < v + match [1]; cc++) { + sfputc (stkp, (c == '^' ? toupper (*cc) : tolower (*cc))); } + v += match [1]; + vsize -= match [1]; + if (!type) break; } } + if (vsize) { + mac_copy(mp, v, vsize > 0 ? vsize : strlen(v)); + } if (addsub) { mp->shp->instance++; sfprintf(mp->shp->strbuf, "[%s]", nv_getsub(np));