about summary refs log tree commit diff
path: root/Src/Modules/pcre.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-01-17 21:48:25 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-01-17 21:48:25 +0000
commit8890e6e19ffa0bede585527671987972137009c7 (patch)
tree624d1830c56f33b2f3f1a3560306bad6336a4d32 /Src/Modules/pcre.c
parenta2c89eb701e5ec3ffca33f25673a9600a9735930 (diff)
downloadzsh-8890e6e19ffa0bede585527671987972137009c7.tar.gz
zsh-8890e6e19ffa0bede585527671987972137009c7.tar.xz
zsh-8890e6e19ffa0bede585527671987972137009c7.zip
27600: extend =~ syntax to set positional variables for matches
Diffstat (limited to 'Src/Modules/pcre.c')
-rw-r--r--Src/Modules/pcre.c79
1 files changed, 73 insertions, 6 deletions
diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index 08205d144..f8b79adea 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -138,8 +138,9 @@ bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int f
 
 /**/
 static int
-zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, char *substravar, 
-    int want_offset_pair, int matchedinarr)
+zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
+		     char *substravar, int want_offset_pair, int matchedinarr,
+		     int want_begin_end)
 {
     char **captures, *match_all, **matches;
     char offset_all[50];
@@ -154,6 +155,7 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, char *substr
     
     /* captures[0] will be entire matched string, [1] first substring */
     if (!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) {
+	int nelem = arrlen(captures)-1;
 	/* Set to the offsets of the complete match */
 	if (want_offset_pair) {
 	    sprintf(offset_all, "%d %d", ovec[0], ovec[1]);
@@ -161,8 +163,70 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, char *substr
 	}
 	match_all = ztrdup(captures[0]);
 	setsparam(matchvar, match_all);
-	matches = zarrdup(&captures[capture_start]);
-	setaparam(substravar, matches);
+	/*
+	 * If we're setting match, mbegin, mend we only do
+	 * so if there were parenthesised matches, for consistency
+	 * (c.f. regex.c).
+	 */
+	if (!want_begin_end || nelem) {
+	    matches = zarrdup(&captures[capture_start]);
+	    setaparam(substravar, matches);
+	}
+
+	if (want_begin_end) {
+	    char *ptr = arg;
+	    zlong offs = 0;
+
+	    /* Count the characters before the match */
+	    MB_METACHARINIT();
+	    while (ptr < arg + ovec[0]) {
+		offs++;
+		ptr += MB_METACHARLEN(ptr);
+	    }
+	    setiparam("MBEGIN", offs + !isset(KSHARRAYS));
+	    /* Add on the characters in the match */
+	    while (ptr < arg + ovec[1]) {
+		offs++;
+		ptr += MB_METACHARLEN(ptr);
+	    }
+	    setiparam("MEND", offs + !isset(KSHARRAYS) - 1);
+	    if (nelem) {
+		char **mbegin, **mend, **bptr, **eptr;
+		int i, *ipair;
+
+		bptr = mbegin = zalloc(nelem+1);
+		eptr = mend = zalloc(nelem+1);
+
+		for (ipair = ovec + 2, i = 0;
+		     i < nelem;
+		     ipair += 2, i++, bptr++, eptr++)
+		{
+		    char buf[DIGBUFSIZE];
+		    ptr = arg;
+		    offs = 0;
+		    /* Find the start offset */
+		    MB_METACHARINIT();
+		    while (ptr < arg + ipair[0]) {
+			offs++;
+			ptr += MB_METACHARLEN(ptr);
+		    }
+		    convbase(buf, offs + !isset(KSHARRAYS), 10);
+		    *bptr = ztrdup(buf);
+		    /* Continue to the end offset */
+		    while (ptr < arg + ipair[1]) {
+			offs++;
+			ptr += MB_METACHARLEN(ptr);
+		    }
+		    convbase(buf, offs + !isset(KSHARRAYS) - 1, 10);
+		    *eptr = ztrdup(buf);
+		}
+		*bptr = *eptr = NULL;
+
+		setaparam("mbegin", mbegin);
+		setaparam("mend", mend);
+	    }
+	}
+
 	pcre_free_substring_list((const char **)captures);
     }
 
@@ -238,7 +302,8 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
     if (ret==0) return_value = 0;
     else if (ret==PCRE_ERROR_NOMATCH) /* no match */;
     else if (ret>0) {
-	zpcre_get_substrings(*args, ovec, ret, matched_portion, receptacle, want_offset_pair, 0);
+	zpcre_get_substrings(*args, ovec, ret, matched_portion, receptacle,
+			     want_offset_pair, 0, 0);
 	return_value = 0;
     }
     else {
@@ -297,7 +362,9 @@ cond_pcre_match(char **a, int id)
 		    break;
 		}
                 else if (r>0) {
-		    zpcre_get_substrings(lhstr, ov, r, NULL, avar, 0, isset(BASHREMATCH));
+		    zpcre_get_substrings(lhstr, ov, r, NULL, avar, 0,
+					 isset(BASHREMATCH),
+					 !isset(BASHREMATCH));
 		    return_value = 1;
 		    break;
 		}