diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Doc/Zsh/expn.yo | 8 | ||||
-rw-r--r-- | Src/glob.c | 45 | ||||
-rw-r--r-- | Src/subst.c | 106 |
4 files changed, 114 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog index 915f54038..4e29c62d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2002-02-22 Oliver Kiddle <opk@zsh.org> + + * 16620, 16697: Src/subst.c, Src/glob.c, Doc/Zsh/expn.yo: + add a and n parameter expansion flags for numeric sorting and + reverse index ordering of arrays + 2002-02-21 Clint Adams <clint@zsh.org> * 16689: Etc/.distfiles, Etc/TODO: list some things to do. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 3d40da10b..c01e5ce3e 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -620,6 +620,11 @@ arrays; the var(word) part em(must) be converted to an array, for example by using `tt(${(AA)=)var(name)tt(=)...tt(})' to activate field splitting, when creating an associative array. ) +item(tt(a))( +With tt(o) or tt(O), sort in array index order. Note that `tt(oa)' is +therefore equivalent to the default but `tt(Oa)' is useful for +obtaining an array's elements in reverse order. +) item(tt(c))( With tt(${#)var(name)tt(}), count the total number of characters in an array, as if the elements were concatenated with spaces between them. @@ -655,6 +660,9 @@ this flag may not be combined with subscript ranges. item(tt(L))( Convert all letters in the result to lower case. ) +item(tt(n))( +With tt(o) or tt(O), sort numerically. +) item(tt(o))( Sort the resulting words in ascending order. ) diff --git a/Src/glob.c b/Src/glob.c index aa82b91c1..75509fee5 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -854,7 +854,10 @@ gmatchcmp(Gmatch a, Gmatch b) for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) { switch (*s & ~GS_DESC) { case GS_NAME: - r = notstrcmp(&a->name, &b->name); + if (gf_numsort) + r = nstrpcmp(&b->name, &a->name); + else + r = strpcmp(&b->name, &a->name); break; case GS_DEPTH: { @@ -1611,46 +1614,6 @@ zglob(LinkList list, LinkNode np, int nountok) restore_globstate(saved); } -/* Return the order of two strings, taking into account * - * possible numeric order if NUMERICGLOBSORT is set. * - * The comparison here is reversed. */ - -/**/ -static int -notstrcmp(char **a, char **b) -{ - char *c = *b, *d = *a; - int cmp; - -#ifdef HAVE_STRCOLL - cmp = strcoll(c, d); -#endif - for (; *c == *d && *c; c++, d++); -#ifndef HAVE_STRCOLL - cmp = (int)STOUC(*c) - (int)STOUC(*d); -#endif - if (gf_numsort && (idigit(*c) || idigit(*d))) { - for (; c > *b && idigit(c[-1]); c--, d--); - if (idigit(*c) && idigit(*d)) { - while (*c == '0') - c++; - while (*d == '0') - d++; - for (; idigit(*c) && *c == *d; c++, d++); - if (idigit(*c) || idigit(*d)) { - cmp = (int)STOUC(*c) - (int)STOUC(*d); - while (idigit(*c) && idigit(*d)) - c++, d++; - if (idigit(*c) && !idigit(*d)) - return 1; - if (idigit(*d) && !idigit(*c)) - return -1; - } - } - } - return cmp; -} - /* Return the trailing character for marking file types */ /**/ diff --git a/Src/subst.c b/Src/subst.c index 607e9b979..7a0a8b16b 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -540,6 +540,72 @@ invcstrpcmp(const void *a, const void *b) } /**/ +int +nstrpcmp(const void *a, const void *b) +{ + char *c = *(char **)a, *d = *(char **)b; + int cmp; + +#ifdef HAVE_STRCOLL + cmp = strcoll(c, d); +#endif + for (; *c == *d && *c; c++, d++); +#ifndef HAVE_STRCOLL + cmp = (int)STOUC(*c) - (int)STOUC(*d); +#endif + if (idigit(*c) || idigit(*d)) { + for (; c > *(char **)b && idigit(c[-1]); c--, d--); + if (idigit(*c) && idigit(*d)) { + while (*c == '0') + c++; + while (*d == '0') + d++; + for (; idigit(*c) && *c == *d; c++, d++); + if (idigit(*c) || idigit(*d)) { + cmp = (int)STOUC(*c) - (int)STOUC(*d); + while (idigit(*c) && idigit(*d)) + c++, d++; + if (idigit(*c) && !idigit(*d)) + return 1; + if (idigit(*d) && !idigit(*c)) + return -1; + } + } + } + return cmp; +} + +/**/ +int +invnstrpcmp(const void *a, const void *b) +{ + return -nstrpcmp(a, b); +} + +/**/ +int +instrpcmp(const void *a, const void *b) +{ + VARARR(char, c, strlen(*(char **) a) + 1); + VARARR(char, d, strlen(*(char **) b) + 1); + char **e = (char **)&c; + char **f = (char **)&d; + char *s, *t; + + for (s = *(char **) a, t = c; (*t++ = tulower(*s++));); + for (s = *(char **) b, t = d; (*t++ = tulower(*s++));); + + return nstrpcmp(&e, &f); +} + +/**/ +int +invinstrpcmp(const void *a, const void *b) +{ + return -instrpcmp(a, b); +} + +/**/ static char * dopadding(char *str, int prenum, int postnum, char *preone, char *postone, char *premul, char *postmul) { @@ -773,7 +839,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) Value v = NULL; int flags = 0; int flnum = 0; - int sortit = 0, casind = 0; + int sortit = 0, casind = 0, numord = 0, indord = 0; int unique = 0; int casmod = 0; int quotemod = 0, quotetype = 0, quoteerr = 0; @@ -881,6 +947,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) case 'i': casind = 1; break; + case 'n': + numord = 1; + break; + case 'a': + indord = 1; + break; case 'V': visiblemod++; @@ -1018,7 +1090,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) } } if (sortit) - sortit += (casind << 1); + sortit += (casind << 1) + (numord << 2); if (!premul) premul = " "; @@ -1894,16 +1966,30 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) zhuniqarray(aval); } if (sortit) { - static CompareFn sortfn[] = { - strpcmp, invstrpcmp, cstrpcmp, invcstrpcmp - }; - if (!copied) aval = arrdup(aval); - - i = arrlen(aval); - if (i && (*aval[i-1] || --i)) - qsort(aval, i, sizeof(char *), sortfn[sortit-1]); + if (indord) { + if (sortit & 2) { + char *copy; + char **end = aval + arrlen(aval) - 1, **start = aval; + + /* reverse the array */ + while (start < end) { + copy = *end; + *end-- = *start; + *start++ = copy; + } + } + } else { + static CompareFn sortfn[] = { + strpcmp, invstrpcmp, cstrpcmp, invcstrpcmp, + nstrpcmp, invnstrpcmp, instrpcmp, invinstrpcmp + }; + + i = arrlen(aval); + if (i && (*aval[i-1] || --i)) + qsort(aval, i, sizeof(char *), sortfn[sortit-1]); + } } if (plan9) { LinkNode tn; |