about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-10-14 15:01:13 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-10-14 15:01:13 +0000
commit356af078596a5e5a85a961e9926be07a8ba092e4 (patch)
tree2d86532ddb056e1f59426f0169b1fdb59774f956
parent537091ddf2db7d4ae4b072b40c546a4ba9ca4148 (diff)
downloadzsh-356af078596a5e5a85a961e9926be07a8ba092e4.tar.gz
zsh-356af078596a5e5a85a961e9926be07a8ba092e4.tar.xz
zsh-356af078596a5e5a85a961e9926be07a8ba092e4.zip
zsh-workers/8254
-rw-r--r--Doc/Zsh/params.yo11
-rw-r--r--Src/params.c52
-rw-r--r--Src/zsh.h1
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 */
 
 /*