From 356af078596a5e5a85a961e9926be07a8ba092e4 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 14 Oct 1999 15:01:13 +0000 Subject: zsh-workers/8254 --- Doc/Zsh/params.yo | 11 +++++++++++ Src/params.c | 52 +++++++++++++++++++++++++++++++++++++++------------- Src/zsh.h | 1 + 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 4eeabd6c6..e9d88cd5b 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -139,6 +139,17 @@ item(tt(R))( Like `tt(r)', but gives the last match. For associative arrays, gives all possible matches. ) +item(tt(k))( +If used in a subscript on a parameter that is not an associative +array, this behaves like `tt(r)', but if used on an association, it +makes the keys be interpreted as patterns and returns the first value +whose key matches the var(exp). +) +item(tt(K))( +On an associtation this is like `tt(k)' but returns all values whose +keys match the var(exp). On other types of parameters this has the +same effect as `tt(R)'. +) item(tt(i))( like `tt(r)', but gives the index of the match instead; this may not be combined with a second argument. For associative arrays, the key diff --git a/Src/params.c b/Src/params.c index 20ffc0aaf..9f54084af 100644 --- a/Src/params.c +++ b/Src/params.c @@ -359,6 +359,7 @@ scancountparams(HashNode hn, int flags) } static Patprog scanprog; +static char *scanstr; static char **paramvals; /**/ @@ -366,12 +367,20 @@ void scanparamvals(HashNode hn, int flags) { struct value v; - if (numparamvals && (flags & (SCANPM_MATCHVAL|SCANPM_MATCHKEY)) && - !(flags & SCANPM_MATCHMANY)) + Patprog prog; + + if (numparamvals && !(flags & SCANPM_MATCHMANY) && + (flags & (SCANPM_MATCHVAL|SCANPM_MATCHKEY|SCANPM_KEYMATCH))) return; v.pm = (Param)hn; - if ((flags & SCANPM_MATCHKEY) && - !pattry(scanprog, v.pm->nam)) { + if ((flags & SCANPM_KEYMATCH)) { + char *tmp = dupstring(v.pm->nam); + + tokenize(tmp); + + if (!(prog = patcompile(tmp, 0, NULL)) || !pattry(prog, scanstr)) + return; + } else if ((flags & SCANPM_MATCHKEY) && !pattry(scanprog, v.pm->nam)) { return; } if (flags & SCANPM_WANTKEYS) { @@ -736,9 +745,10 @@ static zlong getarg(char **str, int *inv, Value v, int a2, zlong *w) { int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash; + int keymatch = 0; char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt; zlong num = 1, beg = 0, r = 0; - Patprog pprog; + Patprog pprog = NULL; ishash = (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED); @@ -750,18 +760,29 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) switch (*s) { case 'r': rev = 1; - down = ind = 0; + keymatch = down = ind = 0; break; case 'R': + rev = down = 1; + keymatch = ind = 0; + break; + case 'k': + keymatch = ishash; + rev = 1; + down = ind = 0; + break; + case 'K': + keymatch = ishash; rev = down = 1; ind = 0; break; case 'i': rev = ind = 1; - down = 0; + down = keymatch = 0; break; case 'I': rev = ind = down = 1; + keymatch = 0; break; case 'w': /* If the parameter is a scalar, then make subscription * @@ -818,7 +839,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) default: flagerr: num = 1; - word = rev = ind = down = 0; + word = rev = ind = down = keymatch = 0; sep = NULL; s = *str - 1; } @@ -841,7 +862,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) v->isarr &= ~SCANPM_WANTVALS; } else if (rev) v->isarr |= SCANPM_WANTVALS; - if (!down && ishash) + if (!down && !keymatch && ishash) v->isarr &= ~SCANPM_MATCHMANY; } *inv = ind; @@ -938,13 +959,16 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) } tokenize(s); - if ((pprog = patcompile(s, 0, NULL))) { + if (keymatch || (pprog = patcompile(s, 0, NULL))) { int len; if (v->isarr) { if (ishash) { scanprog = pprog; - if (ind) + scanstr = s; + if (keymatch) + v->isarr |= SCANPM_KEYMATCH; + else if (ind) v->isarr |= SCANPM_MATCHKEY; else v->isarr |= SCANPM_MATCHVAL; @@ -952,7 +976,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) v->isarr |= SCANPM_MATCHMANY; if ((ta = getvaluearr(v)) && (*ta || ((v->isarr & SCANPM_MATCHMANY) && - (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL))))) { + (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL | + SCANPM_KEYMATCH))))) { *inv = v->inv; *w = v->b; return 1; @@ -1131,7 +1156,8 @@ getindex(char **pptr, Value v) s++; if (v->isarr && a == b && (!(v->isarr & SCANPM_MATCHMANY) || - !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL)))) + !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL | + SCANPM_KEYMATCH)))) v->isarr = 0; v->a = a; v->b = b; diff --git a/Src/zsh.h b/Src/zsh.h index b8613135b..db7514d77 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1086,6 +1086,7 @@ struct param { #define SCANPM_MATCHVAL (1<<4) #define SCANPM_MATCHMANY (1<<5) #define SCANPM_ASSIGNING (1<<6) +#define SCANPM_KEYMATCH (1<<7) #define SCANPM_ISVAR_AT ((-1)<<15) /* Only sign bit is significant */ /* -- cgit 1.4.1