about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-08-30 10:17:30 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-08-30 10:17:30 +0000
commit5e1dc5dc013a510fdb971566dab86f4987419cac (patch)
tree4dbe8a1069224b603703acf2adf927f193245689
parentffa18a29ab864c60153601616053e0e3158235e9 (diff)
downloadzsh-5e1dc5dc013a510fdb971566dab86f4987419cac.tar.gz
zsh-5e1dc5dc013a510fdb971566dab86f4987419cac.tar.xz
zsh-5e1dc5dc013a510fdb971566dab86f4987419cac.zip
zsh-workers/7540
-rw-r--r--Doc/Zsh/expn.yo15
-rw-r--r--Src/subst.c122
2 files changed, 118 insertions, 19 deletions
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index b9af9b83f..cafd1feaa 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -447,6 +447,21 @@ match for tt(t*e) is substituted and the result is `tt(spy star)',
 while in the second case, the shortest matches are taken and the
 result is `tt(spy spy lispy star)'.
 )
+xitem(tt(${)var(name)tt(^)var(pattern)tt(^)var(then)tt(^)var(else)tt(}))
+item(tt(${)var(name)tt(^^)var(pattern)tt(^)var(then)tt(^)var(else)tt(}))(
+If the expansion of var(name) matches the var(pattern), the var(then)
+string is substituted, otherwise the var(else) string is
+substituted. In the second form the var(pattern) is taken to be
+negated (even if the tt(EXTENDED_GLOB) option is not set. The
+var(else) string with the preceding `tt(^)' may be omitted in which
+case the expansion behaves as if var(name) were unset (or, if
+var(name) is an array, as if the element compared did not exist). In
+the var(pattern) and the var(then) string a `tt(^)' may be included by 
+preceding it with two backslashes. Finally, the var(then) and
+var(else) string may consist of only a dot to make it expand to the
+original string. To make them expand to only a dot, the string
+`tt(\.)' has to be used.
+)
 item(tt(${#)var(spec)tt(}))(
 If var(spec) is one of the above substitutions, substitute
 the length in characters of the result instead of
diff --git a/Src/subst.c b/Src/subst.c
index 7619c94a9..a3853472c 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -725,6 +725,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
     char *sep = NULL, *spsep = NULL;
     char *premul = NULL, *postmul = NULL, *preone = NULL, *postone = NULL;
     char *replstr = NULL;	/* replacement string for /orig/repl */
+    char *thenstr, *elsestr;    /* then and else for ${..^..^..^..} */
+    int negpat = 0;
     zlong prenum = 0, postnum = 0;
     int copied = 0;
     int arrasg = 0;
@@ -1227,7 +1229,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		    *s == '%' ||
 		    *s == '#' || *s == Pound ||
 		    *s == '?' || *s == Quest ||
-		    *s == '/')) {
+		    *s == '/' ||
+		    *s == '^' || *s == Hat)) {
 
 	if (!flnum)
 	    flnum++;
@@ -1282,7 +1285,47 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    untokenize(replstr);
 	    *ptr = '\0';
 	}
+	if (s[-1] == '^' || s[-1] == Hat) {
+	    char *ptr = s;
 
+	    if (*s == s[-1]) {
+		s++;
+		negpat = 1;
+	    }
+	    for (ptr = s; *ptr && *ptr != '^' && *ptr != Hat; ptr++)
+		if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat))
+		    chuck(ptr);
+	    if (!*ptr || !ptr[1]) {
+		zerr("missing `then' string", NULL, 0);
+		return NULL;
+	    }
+	    *ptr++ = '\0';
+	    thenstr = ptr;
+	    for (; *ptr && *ptr != '^' && *ptr != Hat; ptr++)
+		if (*ptr == '\\' && (ptr[1] == '^' || ptr[1] == Hat))
+		    chuck(ptr);
+	    if (*ptr) {
+		elsestr = ptr + 1;
+		if (elsestr[0] == '\\' && elsestr[1] == '.')
+		    elsestr++;
+		if (elsestr[0] == '.' && !elsestr[1])
+		    elsestr = (char *) 1;
+		else {
+		    singsub(&elsestr);
+		    untokenize(elsestr);
+		}
+		*ptr = '\0';
+	    } else
+		elsestr = NULL;
+	    if (thenstr[0] == '\\' && thenstr[1] == '.')
+		thenstr++;
+	    if (thenstr[0] == '.' && !thenstr[1])
+		thenstr = (char *) 1;
+	    else {
+		singsub(&thenstr);
+		untokenize(thenstr);
+	    }
+	}
 	if (colf)
 	    flags |= SUB_ALL;
 	/*
@@ -1396,6 +1439,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	case '#':
 	case Pound:
 	case '/':
+	case '^':
+	case Hat:
 	    if (qt) {
 		int one = noerrs, oef = errflag, haserr;
 
@@ -1417,27 +1462,66 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 		char t = s[-1];
 
 		singsub(&s);
-		if (t == '/' && (flags & SUB_SUBSTR)) {
-		    if (*s == '#' || *s == '%') {
-			flags &= ~SUB_SUBSTR;
-			if (*s == '%')
-			    flags |= SUB_END;
-			s++;
-		    } else if (*s == '\\') {
-			s++;
+		if (t == '^' || t == Hat) {
+		    if (!vunset && isarr) {
+			char **ap, **pp;
+			Patprog pprg;
+
+			if (!(pprg = patcompile(s, PAT_STATIC, NULL))) {
+			    zerr("bad pattern: %s", s, 0);
+			    return NULL;
+			}
+			if (!copied)
+			    aval = arrdup(aval), copied = 1;
+			for (ap = pp = aval; *ap; ap++) {
+			    if ((!!pattry(pprg, *ap)) ^ negpat)
+				*pp++ = dupstring(thenstr == ((char *) 1) ?
+						  *ap : thenstr);
+			    else if (elsestr)
+				*pp++ = dupstring(elsestr == ((char *) 1) ?
+						  *ap : elsestr);
+			}
+			*pp = NULL;
+		    } else {
+			Patprog pprg;
+
+			if (vunset)
+			    val = dupstring("");
+			if ((pprg = patcompile(s, PAT_STATIC, NULL)) &&
+			    ((!!pattry(pprg, val)) ^ negpat))
+			    val = dupstring(thenstr == ((char *) 1) ?
+					    val : thenstr);
+			else if (elsestr)
+			    val = dupstring(elsestr == ((char *) 1) ?
+					    val : elsestr);
+			else {
+			    vunset = 1;
+			    val = dupstring("");
+			}
+			copied = 1;
+		    }
+		} else {
+		    if (t == '/' && (flags & SUB_SUBSTR)) {
+			if (*s == '#' || *s == '%') {
+			    flags &= ~SUB_SUBSTR;
+			    if (*s == '%')
+				flags |= SUB_END;
+			    s++;
+			} else if (*s == '\\') {
+			    s++;
+			}
+		    }
+		    if (!vunset && isarr) {
+			getmatcharr(&aval, s, flags, flnum, replstr);
+			copied = 1;
+		    } else {
+			if (vunset)
+			    val = dupstring("");
+			getmatch(&val, s, flags, flnum, replstr);
+			copied = 1;
 		    }
 		}
 	    }
-
-	    if (!vunset && isarr) {
-		getmatcharr(&aval, s, flags, flnum, replstr);
-		copied = 1;
-	    } else {
-		if (vunset)
-		    val = dupstring("");
-		getmatch(&val, s, flags, flnum, replstr);
-		copied = 1;
-	    }
 	    break;
 	}
     } else {			/* no ${...=...} or anything, but possible modifiers. */