From 7579e23e4ac7bfcc92773f3718a0604e31bb2662 Mon Sep 17 00:00:00 2001 From: Sven Wischnowsky Date: Wed, 24 Apr 2002 08:05:51 +0000 Subject: 17029: fix memory leak (found by Felix): pre-compiled patterns for styles --- Src/Modules/zutil.c | 298 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 198 insertions(+), 100 deletions(-) (limited to 'Src') 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; } -- cgit 1.4.1