about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2002-04-24 08:05:51 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2002-04-24 08:05:51 +0000
commit7579e23e4ac7bfcc92773f3718a0604e31bb2662 (patch)
treec3b3a78d7ab4e358eb83cd25d8b8fbb046d08b46 /Src
parent377938212a3a4a5e78b466d57b1b7e2233ebe231 (diff)
downloadzsh-7579e23e4ac7bfcc92773f3718a0604e31bb2662.tar.gz
zsh-7579e23e4ac7bfcc92773f3718a0604e31bb2662.tar.xz
zsh-7579e23e4ac7bfcc92773f3718a0604e31bb2662.zip
17029: fix memory leak (found by Felix): pre-compiled patterns for styles
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/zutil.c298
1 files changed, 198 insertions, 100 deletions
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index ef00ccdee..20e99ae1d 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -48,6 +48,7 @@ struct stypat {
     char *pat;			/* pattern string */
     Patprog prog;		/* compiled pattern */
     int weight;			/* how specific is the pattern? */
+    Eprog eval;			/* eval-on-retrieve? */
     char **vals;
 };
     
@@ -64,6 +65,8 @@ freestypat(Stypat p)
     freepatprog(p->prog);
     if (p->vals)
 	freearray(p->vals);
+    if (p->eval)
+	freeeprog(p->eval);
     zfree(p, sizeof(*p));
 }
 
@@ -101,13 +104,25 @@ getstyle(char *name)
 
 /* Store a value for a style. */
 
-static void
-setstypat(Style s, char *pat, Patprog prog, char **vals)
+static int
+setstypat(Style s, char *pat, Patprog prog, char **vals, int eval)
 {
     int weight, tmp, first;
     char *str;
     Stypat p, q, qq;
+    Eprog eprog = NULL;
+
+    if (eval) {
+	int ef = errflag;
+
+	eprog = parse_string(zjoin(vals, ' ', 1), 0);
+	errflag = ef;
 
+	if (!eprog)
+	    return 1;
+
+	eprog = dupeprog(eprog, 0);
+    }
     for (p = s->pats; p; p = p->next)
 	if (!strcmp(pat, p->pat)) {
 
@@ -115,9 +130,13 @@ setstypat(Style s, char *pat, Patprog prog, char **vals)
 
 	    if (p->vals)
 		freearray(p->vals);
+	    if (p->eval)
+		freeeprog(p->eval);
+            freepatprog(p->prog);
 	    p->vals = zarrdup(vals);
+	    p->eval = eprog;
 
-	    return;
+	    return 0;
 	}
 
     /* New pattern. */
@@ -126,6 +145,7 @@ setstypat(Style s, char *pat, Patprog prog, char **vals)
     p->pat = ztrdup(pat);
     p->prog = prog;
     p->vals = zarrdup(vals);
+    p->eval = eprog;
     p->next = NULL;
 
     /* Calculate the weight. */
@@ -161,6 +181,8 @@ setstypat(Style s, char *pat, Patprog prog, char **vals)
 	qq->next = p;
     else
 	s->pats = p;
+
+    return 0;
 }
 
 /* Add a new style. */
@@ -184,9 +206,36 @@ addstyle(char *name)
     return s;
 }
 
+static char **
+evalstyle(Stypat p)
+{
+    int ef = errflag;
+    char **ret, *str;
+
+    unsetparam("reply");
+    execode(p->eval, 1, 0);
+    if (errflag) {
+	errflag = ef;
+	return NULL;
+    }
+    errflag = ef;
+
+    queue_signals();
+    if ((ret = getaparam("reply")))
+	ret = arrdup(ret);
+    else if ((str = getsparam("reply"))) {
+	ret = (char **) hcalloc(2 * sizeof(char *));
+	ret[0] = dupstring(str);
+    }
+    unqueue_signals();
+    unsetparam("reply");
+
+    return ret;
+}
+
 /* Look up a style for a context pattern. This does the matching. */
 
-static Stypat
+static char **
 lookupstyle(char *ctxt, char *style)
 {
     Style s;
@@ -196,7 +245,7 @@ lookupstyle(char *ctxt, char *style)
 	if (!strcmp(s->name, style))
 	    for (p = s->pats; p; p = p->next)
 		if (pattry(p->prog, ctxt))
-		    return p;
+		    return (p->eval ? evalstyle(p) : p->vals);
 
     return NULL;
 }
@@ -204,7 +253,7 @@ lookupstyle(char *ctxt, char *style)
 static int
 bin_zstyle(char *nam, char **args, char *ops, int func)
 {
-    int min, max, n, add = 0, list = 0;
+    int min, max, n, add = 0, list = 0, eval = 0;
 
     if (!args[0])
 	list = 1;
@@ -218,6 +267,10 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	    }
 	    if (oc == 'L')
 		list = 2;
+	    else if (oc == 'e') {
+		eval = add = 1;
+		args++;
+	    }
 	} else {
 	    add = 1;
 	    args++;
@@ -243,9 +296,7 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	}
 	if (!(s = getstyle(args[1])))
 	    s = addstyle(args[1]);
-	setstypat(s, args[0], prog, args + 2);
-
-	return 0;
+	return setstypat(s, args[0], prog, args + 2, eval);
     }
     if (list) {
 	Style s;
@@ -259,9 +310,9 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	    }
 	    for (p = s->pats; p; p = p->next) {
 		if (list == 1)
-		    printf("    %s", p->pat);
+		    printf("%s  %s", (p->eval ? "(eval)" : "      "), p->pat);
 		else {
-		    printf("zstyle ");
+		    printf("zstyle %s", (p->eval ? "-e " : ""));
 		    quotedzputs(p->pat, stdout);
 		    printf(" %s", s->name);
 		}
@@ -279,7 +330,6 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
     case 's': min = 3; max =  4; break;
     case 'b': min = 3; max =  3; break;
     case 'a': min = 3; max =  3; break;
-    case 'h': min = 3; max =  3; break;
     case 't': min = 2; max = -1; break;
     case 'T': min = 2; max = -1; break;
     case 'm': min = 3; max =  3; break;
@@ -344,12 +394,11 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	break;
     case 's':
 	{
-	    Stypat s;
-	    char *ret;
+	    char **vals, *ret;
 	    int val;
 
-	    if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) {
-		ret = sepjoin(s->vals, (args[4] ? args[4] : " "), 0);
+	    if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
+		ret = sepjoin(vals, (args[4] ? args[4] : " "), 0);
 		val = 0;
 	    } else {
 		ret = ztrdup("");
@@ -362,16 +411,15 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	break;
     case 'b':
 	{
-	    Stypat s;
-	    char *ret;
+	    char **vals, *ret;
 	    int val;
 
-	    if ((s = lookupstyle(args[1], args[2])) &&
-		s->vals[0] && !s->vals[1] &&
-		(!strcmp(s->vals[0], "yes") ||
-		 !strcmp(s->vals[0], "true") ||
-		 !strcmp(s->vals[0], "on") ||
-		 !strcmp(s->vals[0], "1"))) {
+	    if ((vals = lookupstyle(args[1], args[2])) &&
+		vals[0] && !vals[1] &&
+		(!strcmp(vals[0], "yes") ||
+		 !strcmp(vals[0], "true") ||
+		 !strcmp(vals[0], "on") ||
+		 !strcmp(vals[0], "1"))) {
 		ret = "yes";
 		val = 0;
 	    } else {
@@ -384,14 +432,12 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 	}
 	break;
     case 'a':
-    case 'h':
 	{
-	    Stypat s;
-	    char **ret;
+	    char **vals, **ret;
 	    int val;
 
-	    if ((s = lookupstyle(args[1], args[2]))) {
-		ret = zarrdup(s->vals);
+	    if ((vals = lookupstyle(args[1], args[2]))) {
+		ret = zarrdup(vals);
 		val = 0;
 	    } else {
 		char *dummy = NULL;
@@ -399,10 +445,7 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 		ret = zarrdup(&dummy);
 		val = 1;
 	    }
-	    if (args[0][1] == 'a')
-		setaparam(args[3], ret);
-	    else
-		sethparam(args[3], ret);
+	    setaparam(args[3], ret);
 
 	    return val;
 	}
@@ -410,14 +453,14 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
     case 't':
     case 'T':
 	{
-	    Stypat s;
+	    char **vals;
 
-	    if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) {
+	    if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
 		if (args[3]) {
 		    char **ap = args + 3, **p;
 
 		    while (*ap) {
-			p = s->vals;
+			p = vals;
 			while (*p)
 			    if (!strcmp(*ap, *p++))
 				return 0;
@@ -425,27 +468,25 @@ bin_zstyle(char *nam, char **args, char *ops, int func)
 		    }
 		    return 1;
 		} else
-		    return !(!strcmp(s->vals[0], "true") ||
-			     !strcmp(s->vals[0], "yes") ||
-			     !strcmp(s->vals[0], "on") ||
-			     !strcmp(s->vals[0], "1"));
+		    return !(!strcmp(vals[0], "true") ||
+			     !strcmp(vals[0], "yes") ||
+			     !strcmp(vals[0], "on") ||
+			     !strcmp(vals[0], "1"));
 	    }
-	    return (args[0][1] == 't' ? (s ? 1 : 2) : 0);
+	    return (args[0][1] == 't' ? (vals ? 1 : 2) : 0);
 	}
 	break;
     case 'm':
 	{
-	    Stypat s;
+	    char **vals;
 	    Patprog prog;
 
 	    tokenize(args[3]);
 
-	    if ((s = lookupstyle(args[1], args[2])) &&
+	    if ((vals = lookupstyle(args[1], args[2])) &&
 		(prog = patcompile(args[3], PAT_STATIC, NULL))) {
-		char **p = s->vals;
-
-		while (*p)
-		    if (pattry(prog, *p++))
+		while (*vals)
+		    if (pattry(prog, *vals++))
 			return 0;
 	    }
 	    return 1;
@@ -687,12 +728,14 @@ savematch(MatchData *m)
 {
     char **a;
 
+    queue_signals();
     a = getaparam("match");
     m->match = a ? zarrdup(a) : NULL;
     a = getaparam("mbegin");
     m->mbegin = a ? zarrdup(a) : NULL;
     a = getaparam("mend");
     m->mend = a ? zarrdup(a) : NULL;
+    unqueue_signals();
 }
 
 static void
@@ -1008,14 +1051,13 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
     setiparam(var1, point1);
     setiparam(var2, point2);
 
-    if (!*subj) {
-	if (sm->nullacts)
-	    for (ln = firstnode(sm->nullacts); ln; ln = nextnode(ln)) {
-	        char *action = getdata(ln);
+    if (!comp && !*subj && sm->nullacts) {
+	for (ln = firstnode(sm->nullacts); ln; ln = nextnode(ln)) {
+	    char *action = getdata(ln);
 
-		if (action)
-		    execstring(action, 1, 0);
-	    }
+	    if (action)
+		execstring(action, 1, 0);
+	}
 	return 0;
     }
 
@@ -1036,13 +1078,18 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
 	    if (next->pattern && !next->patprog) {
 	        tokenize(next->pattern);
 		if (!(next->patprog = patcompile(next->pattern, 0, NULL)))
-		    return 2;
+		    return 3;
 	    }
 	    if (next->pattern && pattry(next->patprog, subj) &&
 		(!next->guard || (execstring(next->guard, 1, 0), !lastval))) {
 		LinkNode aln;
-		char **mend = getaparam("mend");
-		int len = atoi(mend[0]);
+		char **mend;
+		int len;
+
+		queue_signals();
+		mend = getaparam("mend");
+		len = atoi(mend[0]);
+		unqueue_signals();
 
 		for (i = len; i; i--)
 		  if (*subj++ == Meta)
@@ -1102,7 +1149,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
 }
 
 /*
-  usage: zregexparse string regex...
+  usage: zregexparse [-c] var1 var2 string regex...
   status:
     0: matched
     1: unmatched (all next state candidates are failed)
@@ -1267,8 +1314,8 @@ add_opt_val(Zoptdesc d, char *arg)
 static int
 bin_zparseopts(char *nam, char **args, char *ops, int func)
 {
-    char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL;
-    int del = 0, f;
+    char *o, *p, *n, **pp, **aval, **ap, *assoc = NULL, **cp, **np;
+    int del = 0, f, extract = 0, keep = 0;
     Zoptdesc sopts[256], d;
     Zoptarr a, defarr = NULL;
     Zoptval v;
@@ -1296,6 +1343,22 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 		}
 		del = 1;
 		break;
+	    case 'E':
+		if (o[2]) {
+		    args--;
+		    o = NULL;
+		    break;
+		}
+		extract = 1;
+		break;
+	    case 'K':
+		if (o[2]) {
+		    args--;
+		    o = NULL;
+		    break;
+		}
+		keep = 1;
+		break;
 	    case 'a':
 		if (defarr) {
 		    zwarnnam(nam, "default array given more than once", NULL, 0);
@@ -1327,13 +1390,19 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 		}
 		break;
 	    }
-	    if (!o)
+	    if (!o) {
+		o = "";
 		break;
+	    }
 	} else {
 	    args--;
 	    break;
 	}
     }
+    if (!o) {
+	zwarnnam(nam, "missing option descriptions", NULL, 0);
+	return 1;
+    }
     while ((o = dupstring(*args++))) {
 	if (!*o) {
 	    zwarnnam(nam, "invalid option description: %s", o, 0);
@@ -1400,10 +1469,19 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 	if (!o[1])
 	    sopts[STOUC(*o)] = d;
     }
-    for (pp = pparams; (o = *pp); pp++) {
-	if (*o != '-')
-	    break;
+    np = cp = pp = ((extract && del) ? arrdup(pparams) : pparams);
+    for (; (o = *pp); pp++) {
+	if (*o != '-') {
+	    if (extract) {
+		if (del)
+		    *cp++ = o;
+		continue;
+	    } else
+		break;
+	}
 	if (!o[1] || (o[1] == '-' && !o[2])) {
+	    if (del && extract)
+		*cp++ = o;
 	    pp++;
 	    break;
 	}
@@ -1429,8 +1507,14 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 		} else
 		    add_opt_val(d, NULL);
 	    }
-	    if (!o)
-		break;
+	    if (!o) {
+		if (extract) {
+		    if (del)
+			*cp++ = *pp;
+		    continue;
+		} else
+		    break;
+	    }
 	} else {
 	    if (d->flags & ZOF_ARG) {
 		char *e = o + strlen(d->name) + 1;
@@ -1450,19 +1534,25 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 		add_opt_val(d, NULL);
 	}
     }
+    if (extract && del)
+	while (*pp)
+	    *cp++ = *pp++;
+
     for (a = opt_arrs; a; a = a->next) {
-	aval = (char **) zalloc((a->num + 1) * sizeof(char *));
-	for (ap = aval, v = a->vals; v; ap++, v = v->next) {
-	    if (v->str)
-		*ap = ztrdup(v->str);
-	    else {
-		*ap = ztrdup(v->name);
-		if (v->arg)
-		    *++ap = ztrdup(v->arg);
+	if (!keep || a->num) {
+	    aval = (char **) zalloc((a->num + 1) * sizeof(char *));
+	    for (ap = aval, v = a->vals; v; ap++, v = v->next) {
+		if (v->str)
+		    *ap = ztrdup(v->str);
+		else {
+		    *ap = ztrdup(v->name);
+		    if (v->arg)
+			*++ap = ztrdup(v->arg);
+		}
 	    }
+	    *ap = NULL;
+	    setaparam(a->name, aval);
 	}
-	*ap = NULL;
-	setaparam(a->name, aval);
     }
     if (assoc) {
 	int num;
@@ -1471,36 +1561,44 @@ bin_zparseopts(char *nam, char **args, char *ops, int func)
 	    if (d->vals)
 		num++;
 
-	aval = (char **) zalloc(((num * 2) + 1) * sizeof(char *));
-	for (ap = aval, d = opt_descs; d; d = d->next) {
-	    if (d->vals) {
-		*ap++ = n = (char *) zalloc(strlen(d->name) + 2);
-		*n = '-';
-		strcpy(n + 1, d->name);
-
-		for (num = 1, v = d->vals; v; v = v->onext) {
-		    num += (v->arg ? strlen(v->arg) : 0);
-		    if (v->next)
-			num++;
-		}
-		*ap++ = n = (char *) zalloc(num);
-		for (v = d->vals; v; v = v->onext) {
-		    if (v->arg) {
-			strcpy(n, v->arg);
-			n += strlen(v->arg);
+	if (!keep || num) {
+	    aval = (char **) zalloc(((num * 2) + 1) * sizeof(char *));
+	    for (ap = aval, d = opt_descs; d; d = d->next) {
+		if (d->vals) {
+		    *ap++ = n = (char *) zalloc(strlen(d->name) + 2);
+		    *n = '-';
+		    strcpy(n + 1, d->name);
+
+		    for (num = 1, v = d->vals; v; v = v->onext) {
+			num += (v->arg ? strlen(v->arg) : 0);
+			if (v->next)
+			    num++;
 		    }
-		    *n = ' ';
+		    *ap++ = n = (char *) zalloc(num);
+		    for (v = d->vals; v; v = v->onext) {
+			if (v->arg) {
+			    strcpy(n, v->arg);
+			    n += strlen(v->arg);
+			}
+			*n = ' ';
+		    }
+		    *n = '\0';
 		}
-		*n = '\0';
 	    }
+	    *ap = NULL;
+	    sethparam(assoc, aval);
 	}
-	*ap = NULL;
-	sethparam(assoc, aval);
     }
     if (del) {
-	pp = zarrdup(pp);
-	freearray(pparams);
-	pparams = pp;
+	if (extract) {
+	    *cp = NULL;
+	    freearray(pparams);
+	    pparams = zarrdup(np);
+	} else {
+	    pp = zarrdup(pp);
+	    freearray(pparams);
+	    pparams = pp;
+	}
     }
     return 0;
 }