diff options
Diffstat (limited to 'Src/Modules')
-rw-r--r-- | Src/Modules/zutil.c | 1245 |
1 files changed, 1015 insertions, 230 deletions
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 590678f98..9dd228930 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -37,81 +37,62 @@ typedef struct style *Style; /* A pattern and the styles for it. */ +struct style { + Style next; /* next in stypat list */ + Stypat pats; /* patterns */ + char *name; +}; + struct stypat { Stypat next; char *pat; /* pattern string */ Patprog prog; /* compiled pattern */ int weight; /* how specific is the pattern? */ - Style styles, lstyles; /* first/last style */ -}; - -struct style { - Style next; - char *name; char **vals; }; - + /* List of styles. */ -static Stypat zstyles, lzstyles; +static Style zstyles, zlstyles; /* Memory stuff. */ static void -freestyle(Style s) +freestypat(Stypat p) { - Style n; - - while (s) { - n = s->next; - - zsfree(s->name); - if (s->vals) - freearray(s->vals); - zfree(s, sizeof(*s)); - - s = n; - } + zsfree(p->pat); + freepatprog(p->prog); + if (p->vals) + freearray(p->vals); + zfree(p, sizeof(*p)); } static void -freestypat(Stypat p) +freeallstyles(void) { - Stypat n; - - while (p) { - n = p->next; - - zsfree(p->pat); - freepatprog(p->prog); - zfree(p, sizeof(*p)); - - p = n; + Style s, sn; + Stypat p, pn; + + for (s = zstyles; s; s = sn) { + sn = s->next; + for (p = s->pats; p; p = pn) { + pn = p->next; + freestypat(p); + } + zsfree(s->name); + zfree(s, sizeof(*s)); } + zstyles = zlstyles = NULL; } -/* Get the struct for a pattern, if any. */ - -static Stypat -getstypat(char *pat) -{ - Stypat p; - - for (p = zstyles; p; p = p->next) - if (!strcmp(pat, p->pat)) - return p; - - return NULL; -} - -/* Get the style stuff for a name. */ +/* Get the style struct for a name. */ static Style -getstyle(Stypat p, char *name) +getstyle(char *name) { Style s; - for (s = p->styles; s; s= s->next) + for (s = zstyles; s; s = s->next) if (!strcmp(name, s->name)) return s; @@ -121,66 +102,48 @@ getstyle(Stypat p, char *name) /* Store a value for a style. */ static void -setstyle(Stypat p, char *name, char **vals) +setstypat(Style s, char *pat, Patprog prog, char **vals) { - Style s; + int weight, tmp, first; + char *str; + Stypat p, q, qq; - for (s = p->styles; s; s = s->next) - if (!strcmp(name, s->name)) { + for (p = s->pats; p; p = p->next) + if (!strcmp(pat, p->pat)) { /* Exists -> replace. */ - if (s->vals) - freearray(s->vals); - PERMALLOC { - s->vals = arrdup(vals); - } LASTALLOC; + if (p->vals) + freearray(p->vals); + p->vals = zarrdup(vals); return; } - /* New style. */ - - s = (Style) zalloc(sizeof(*s)); - - s->name = ztrdup(name); - PERMALLOC { - s->vals = arrdup(vals); - } LASTALLOC; - s->next = NULL; - - if (p->lstyles) - p->lstyles->next = s; - else - p->styles = s; - p->lstyles = s; -} - -/* Add a new pattern. */ + /* New pattern. */ -static Stypat -addstypat(char *pat, Patprog prog) -{ - Stypat p, q, qq; - int weight, tmp, first; - char *s; + p = (Stypat) zalloc(sizeof(*p)); + p->pat = ztrdup(pat); + p->prog = prog; + p->vals = zarrdup(vals); + p->next = NULL; /* Calculate the weight. */ - for (weight = 0, tmp = 2, first = 1, s = pat; *s; s++) { - if (first && *s == '*' && (!s[1] || s[1] == ':')) { + for (weight = 0, tmp = 2, first = 1, str = pat; *str; str++) { + if (first && *str == '*' && (!str[1] || str[1] == ':')) { /* Only `*' in this component. */ tmp = 0; continue; } first = 0; - if (*s == '(' || *s == '|' || *s == '*' || *s == '[' || *s == '<' || - *s == '?' || *s == '#' || *s == '^') + if (*str == '(' || *str == '|' || *str == '*' || *str == '[' || + *str == '<' || *str == '?' || *str == '#' || *str == '^') /* Is pattern. */ tmp = 1; - if (*s == ':') { + if (*str == ':') { /* Yet another component. */ first = 1; @@ -188,91 +151,52 @@ addstypat(char *pat, Patprog prog) tmp = 2; } } - weight += tmp; + p->weight = (weight += tmp); - p = (Stypat) zalloc(sizeof(*p)); - - p->pat = ztrdup(pat); - p->weight = weight; - p->prog = prog; - p->styles = p->lstyles = NULL; - - for (qq = NULL, q = zstyles; q && q->weight >= weight; + for (qq = NULL, q = s->pats; q && q->weight >= weight; qq = q, q = q->next); p->next = q; if (qq) qq->next = p; else - zstyles = p; - if (!q) - lzstyles = p; - - return p; + s->pats = p; } -/* Delete a style. */ - -static void -deletestyle(Stypat p, char *name) -{ - Style ps, s; - - for (ps = NULL, s = p->styles; s; ps = s, s = s->next) - if (!strcmp(name, s->name)) { - if (ps) - ps->next = s->next; - else - p->styles = s->next; - if (s == p->lstyles) - p->lstyles = ps; +/* Add a new style. */ - s->next = NULL; - freestyle(s); - - return; - } -} - -/* Delete a whole pattern with all its styles. */ - -static void -deletestypat(Stypat pat) +static Style +addstyle(char *name) { - Stypat pp, p; + Style s; - for (pp = NULL, p = zstyles; p; pp = p, p = p->next) - if (p == pat) { - if (pp) - pp->next = p->next; - else - zstyles = p->next; - if (p == lzstyles) - lzstyles = pp; + s = (Style) zalloc(sizeof(*s)); + s->next = NULL; + s->pats = NULL; + s->name = ztrdup(name); - p->next = NULL; - zsfree(p->pat); - freepatprog(p->prog); - freestyle(p->styles); - zfree(p, sizeof(*p)); + if (zlstyles) + zlstyles->next = s; + else + zstyles = s; + zlstyles = s; - return; - } + return s; } /* Look up a style for a context pattern. This does the matching. */ -static Style +static Stypat lookupstyle(char *ctxt, char *style) { - Stypat p; Style s; + Stypat p; - for (p = zstyles; p; p = p->next) - if (pattry(p->prog, ctxt)) - for (s = p->styles; s; s = s->next) - if (!strcmp(style, s->name)) - return s; + for (s = zstyles; s; s = s->next) + if (!strcmp(s->name, style)) + for (p = s->pats; p; p = p->next) + if (pattry(p->prog, ctxt)) + return p; return NULL; } @@ -289,7 +213,7 @@ bin_zstyle(char *nam, char **args, char *ops, int func) if ((oc = args[0][1]) && oc != '-') { if (args[0][2]) { - zerrnam(nam, "invalid argument: %s", args[0], 0); + zwarnnam(nam, "invalid argument: %s", args[0], 0); return 1; } if (oc == 'L') @@ -302,47 +226,46 @@ bin_zstyle(char *nam, char **args, char *ops, int func) add = 1; if (add) { - Stypat p; + Style s; + Patprog prog; + char *pat; if (arrlen(args) < 2) { - zerrnam(nam, "not enough arguments", NULL, 0); + zwarnnam(nam, "not enough arguments", NULL, 0); return 1; } - if (!(p = getstypat(args[0]))) { - Patprog prog; - char *pat = dupstring(args[0]); - - tokenize(pat); + pat = dupstring(args[0]); + tokenize(pat); - if (!(prog = patcompile(pat, PAT_ZDUP, NULL))) { - zerrnam(nam, "invalid pattern: %s", args[0], 0); - return 1; - } - p = addstypat(args[0], prog); + if (!(prog = patcompile(pat, PAT_ZDUP, NULL))) { + zwarnnam(nam, "invalid pattern: %s", args[0], 0); + return 1; } - setstyle(p, args[1], args + 2); + if (!(s = getstyle(args[1]))) + s = addstyle(args[1]); + setstypat(s, args[0], prog, args + 2); return 0; } if (list) { - Stypat p; Style s; + Stypat p; char **v; - for (p = zstyles; p; p = p->next) { + for (s = zstyles; s; s = s->next) { if (list == 1) { - quotedzputs(p->pat, stdout); + quotedzputs(s->name, stdout); putchar('\n'); } - for (s = p->styles; s; s = s->next) { + for (p = s->pats; p; p = p->next) { if (list == 1) - printf(" %s", s->name); + printf(" %s", p->pat); else { printf("zstyle "); quotedzputs(p->pat, stdout); printf(" %s", s->name); } - for (v = s->vals; *v; v++) { + for (v = p->vals; *v; v++) { putchar(' '); quotedzputs(*v, stdout); } @@ -358,54 +281,75 @@ bin_zstyle(char *nam, char **args, char *ops, int func) 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; case 'g': min = 1; max = 3; break; default: - zerrnam(nam, "invalid option: %s", args[0], 0); + zwarnnam(nam, "invalid option: %s", args[0], 0); return 1; } n = arrlen(args) - 1; if (n < min) { - zerrnam(nam, "not enough arguments", NULL, 0); + zwarnnam(nam, "not enough arguments", NULL, 0); return 1; } else if (max >= 0 && n > max) { - zerrnam(nam, "too many arguments", NULL, 0); + zwarnnam(nam, "too many arguments", NULL, 0); return 1; } switch (args[0][1]) { case 'd': { - Stypat p; + Style s; if (args[1]) { - if ((p = getstypat(args[1]))) { - if (args[2]) { - char **ap = args + 2; - - while (*ap) - deletestyle(p, *ap++); - - if (!p->styles) - deletestypat(p); - } else - deletestypat(p); + if (args[2]) { + char *pat = args[1]; + + for (args += 2; *args; args++) { + if ((s = getstyle(*args))) { + Stypat p, q; + + for (q = NULL, p = s->pats; p; + q = p, p = p->next) { + if (!strcmp(p->pat, pat)) { + if (q) + q->next = p->next; + else + s->pats = p->next; + freestypat(p); + break; + } + } + } + } + } else { + Stypat p, q; + + for (s = zstyles; s; s = s->next) { + for (q = NULL, p = s->pats; p; q = p, p = p->next) { + if (!strcmp(p->pat, args[1])) { + if (q) + q->next = p->next; + else + s->pats = p->next; + freestypat(p); + break; + } + } + } } - } else { - freestypat(zstyles); - zstyles = lzstyles = NULL; - } + } else + freeallstyles(); } break; case 's': { - Style s; + Stypat s; char *ret; int val; if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) { - PERMALLOC { - ret = sepjoin(s->vals, (args[4] ? args[4] : " ")); - } LASTALLOC; + ret = sepjoin(s->vals, (args[4] ? args[4] : " "), 0); val = 0; } else { ret = ztrdup(""); @@ -418,7 +362,7 @@ bin_zstyle(char *nam, char **args, char *ops, int func) break; case 'b': { - Style s; + Stypat s; char *ret; int val; @@ -442,21 +386,17 @@ bin_zstyle(char *nam, char **args, char *ops, int func) case 'a': case 'h': { - Style s; + Stypat s; char **ret; int val; if ((s = lookupstyle(args[1], args[2]))) { - PERMALLOC { - ret = arrdup(s->vals); - } LASTALLOC; + ret = zarrdup(s->vals); val = 0; } else { char *dummy = NULL; - PERMALLOC { - ret = arrdup(&dummy); - } LASTALLOC; + ret = zarrdup(&dummy); val = 1; } if (args[0][1] == 'a') @@ -468,8 +408,9 @@ bin_zstyle(char *nam, char **args, char *ops, int func) } break; case 't': + case 'T': { - Style s; + Stypat s; if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) { if (args[3]) { @@ -489,12 +430,12 @@ bin_zstyle(char *nam, char **args, char *ops, int func) !strcmp(s->vals[0], "on") || !strcmp(s->vals[0], "1")); } - return 1; + return (args[0][1] == 't' ? (s ? 1 : 2) : 0); } break; case 'm': { - Style s; + Stypat s; Patprog prog; tokenize(args[3]); @@ -514,32 +455,44 @@ bin_zstyle(char *nam, char **args, char *ops, int func) { LinkList l = newlinklist(); int ret = 1; + Style s; Stypat p; if (args[2]) { - if ((p = getstypat(args[2]))) { - Style s; - - if (args[3]) { - if ((s = getstyle(p, args[3]))) { - char **v = s->vals; + if (args[3]) { + if ((s = getstyle(args[3]))) { + for (p = s->pats; p; p = p->next) { + if (!strcmp(args[2], p->pat)) { + char **v = p->vals; - while (*v) - addlinknode(l, *v++); + while (*v) + addlinknode(l, *v++); - ret = 0; + ret = 0; + break; + } } - } else { - for (s = p->styles; s; s = s->next) - addlinknode(l, s->name); - - ret = 0; } + } else { + for (s = zstyles; s; s = s->next) + for (p = s->pats; p; p = p->next) + if (!strcmp(args[2], p->pat)) { + addlinknode(l, s->name); + break; + } + ret = 0; } } else { - for (p = zstyles; p; p = p->next) - addlinknode(l, p->pat); - + LinkNode n; + + for (s = zstyles; s; s = s->next) + for (p = s->pats; p; p = p->next) { + for (n = firstnode(l); n; incnode(n)) + if (!strcmp(p->pat, (char *) getdata(n))) + break; + if (!n) + addlinknode(l, p->pat); + } ret = 0; } set_list_array(args[1], l); @@ -558,7 +511,7 @@ bin_zformat(char *nam, char **args, char *ops, int func) char opt; if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) { - zerrnam(nam, "invalid argument: %s", args[0], 0); + zwarnnam(nam, "invalid argument: %s", args[0], 0); return 1; } args++; @@ -575,7 +528,7 @@ bin_zformat(char *nam, char **args, char *ops, int func) if (!ap[0][0] || ap[0][0] == '-' || ap[0][0] == '.' || (ap[0][0] >= '0' && ap[0][0] <= '9') || ap[0][1] != ':') { - zerrnam(nam, "invalid argument: %s", *ap, 0); + zwarnnam(nam, "invalid argument: %s", *ap, 0); return 1; } specs[STOUC(ap[0][0])] = ap[0] + 2; @@ -717,35 +670,867 @@ bin_zformat(char *nam, char **args, char *ops, int func) } break; } - zerrnam(nam, "invalid option: -%c", 0, opt); + zwarnnam(nam, "invalid option: -%c", 0, opt); return 1; } +/* Zregexparse stuff. */ + +typedef struct { + char **match; + char **mbegin; + char **mend; +} MatchData; + +static void +savematch(MatchData *m) +{ + char **a; + + 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; +} + +static void +restorematch(MatchData *m) +{ + if (m->match) + setaparam("match", m->match); + else + unsetparam("match"); + if (m->mbegin) + setaparam("mbegin", m->mbegin); + else + unsetparam("mbegin"); + if (m->mend) + setaparam("mend", m->mend); + else + unsetparam("mend"); +} + +static void +freematch(MatchData *m) +{ + if (m->match) + freearray(m->match); + if (m->mbegin) + freearray(m->mbegin); + if (m->mend) + freearray(m->mend); +} + +typedef struct { + int cutoff; + char *pattern; + Patprog patprog; + char *guard; + char *action; + LinkList branches; +} RParseState; + +typedef struct { + RParseState *state; + LinkList actions; +} RParseBranch; + +typedef struct { + LinkList nullacts; + LinkList in; + LinkList out; +} RParseResult; + +static char **rparseargs; +static LinkList rparsestates; + +static int rparsealt(RParseResult *result, jmp_buf *perr); + +static void +connectstates(LinkList out, LinkList in) +{ + LinkNode outnode, innode, ln; + + for (outnode = firstnode(out); outnode; outnode = nextnode(outnode)) { + RParseBranch *outbranch = getdata(outnode); + + for (innode = firstnode(in); innode; innode = nextnode(innode)) { + RParseBranch *inbranch = getdata(innode); + RParseBranch *br = hcalloc(sizeof(*br)); + + br->state = inbranch->state; + br->actions = newlinklist(); + for (ln = firstnode(outbranch->actions); ln; ln = nextnode(ln)) + addlinknode(br->actions, getdata(ln)); + for (ln = firstnode(inbranch->actions); ln; ln = nextnode(ln)) + addlinknode(br->actions, getdata(ln)); + addlinknode(outbranch->state->branches, br); + } + } +} + +static int +rparseelt(RParseResult *result, jmp_buf *perr) +{ + int l; + char *s = *rparseargs; + + if (!s) + return 1; + + switch (s[0]) { + case '/': { + RParseState *st; + RParseBranch *br; + char *pattern, *lookahead; + int patternlen, lookaheadlen = 0; + + l = strlen(s); + if (!((2 <= l && s[l - 1] == '/') || + (3 <= l && s[l - 2] == '/' && (s[l - 1] == '+' || + s[l - 1] == '-')))) + return 1; + st = hcalloc(sizeof(*st)); + st->branches = newlinklist(); + st->cutoff = s[l - 1]; + if (s[l - 1] == '/') { + pattern = s + 1; + patternlen = l - 2; + } else { + pattern = s + 1; + patternlen = l - 3; + } + rparseargs++; + if ((s = *rparseargs) && s[0] == '%' && + 2 <= (l = strlen(s)) && s[l - 1] == '%') { + rparseargs++; + lookahead = s + 1; + lookaheadlen = l - 2; + } else { + lookahead = NULL; + } + if (patternlen == 2 && !strncmp(pattern, "[]", 2)) + st->pattern = NULL; + else { + char *cp; + int l = patternlen + 12; /* (#b)((#B)...)...* */ + if(lookahead) + l += lookaheadlen + 4; /* (#B)... */ + cp = st->pattern = hcalloc(l); + strcpy(cp, "(#b)((#B)"); + cp += 9; + strcpy(cp, pattern); + cp += patternlen; + strcpy(cp, ")"); + cp += 1; + if (lookahead) { + strcpy(cp, "(#B)"); + cp += 4; + strcpy(cp, lookahead); + cp += lookaheadlen; + } + strcpy(cp, "*"); + } + st->patprog = NULL; + if ((s = *rparseargs) && *s == '-') { + rparseargs++; + l = strlen(s); + st->guard = hcalloc(l); + memcpy(st->guard, s + 1, l - 1); + st->guard[l - 1] = '\0'; + } else + st->guard = NULL; + if ((s = *rparseargs) && *s == ':') { + rparseargs++; + l = strlen(s); + st->action = hcalloc(l); + memcpy(st->action, s + 1, l - 1); + st->action[l - 1] = '\0'; + } else + st->action = NULL; + result->nullacts = NULL; + result->in = newlinklist(); + br = hcalloc(sizeof(*br)); + br->state = st; + br->actions = newlinklist(); + addlinknode(result->in, br); + result->out = newlinklist(); + br = hcalloc(sizeof(*br)); + br->state = st; + br->actions = newlinklist(); + addlinknode(result->out, br); + break; + } + case '(': + if (s[1]) + return 1; + rparseargs++; + if (rparsealt(result, perr)) + longjmp(*perr, 2); + s = *rparseargs; + if (!s || s[0] != ')' || s[1] != '\0') + longjmp(*perr, 2); + rparseargs++; + break; + default: + return 1; + } + + return 0; +} + +static int +rparseclo(RParseResult *result, jmp_buf *perr) +{ + if (rparseelt(result, perr)) + return 1; + + if (*rparseargs && !strcmp(*rparseargs, "#")) { + rparseargs++; + while (*rparseargs && !strcmp(*rparseargs, "#")) + rparseargs++; + + connectstates(result->out, result->in); + result->nullacts = newlinklist(); + } + return 0; +} + +static void +prependactions(LinkList acts, LinkList branches) +{ + LinkNode aln, bln; + + for (bln = firstnode(branches); bln; bln = nextnode(bln)) { + RParseBranch *br = getdata(bln); + + for (aln = lastnode(acts); aln != (LinkNode)acts; aln = prevnode(aln)) + pushnode(br->actions, getdata(aln)); + } +} + +static void +appendactions(LinkList acts, LinkList branches) +{ + LinkNode aln, bln; + for (bln = firstnode(branches); bln; bln = nextnode(bln)) { + RParseBranch *br = getdata(bln); + + for (aln = firstnode(acts); aln; aln = nextnode(aln)) + addlinknode(br->actions, getdata(aln)); + } +} + +static int +rparseseq(RParseResult *result, jmp_buf *perr) +{ + int l; + char *s; + RParseResult sub; + + result->nullacts = newlinklist(); + result->in = newlinklist(); + result->out = newlinklist(); + + while (1) { + if ((s = *rparseargs) && s[0] == '{' && s[(l = strlen(s)) - 1] == '}') { + char *action = hcalloc(l - 1); + LinkNode ln; + + rparseargs++; + memcpy(action, s + 1, l - 2); + action[l - 2] = '\0'; + if (result->nullacts) + addlinknode(result->nullacts, action); + for (ln = firstnode(result->out); ln; ln = nextnode(ln)) { + RParseBranch *br = getdata(ln); + addlinknode(br->actions, action); + } + } + else if (!rparseclo(&sub, perr)) { + connectstates(result->out, sub.in); + + if (result->nullacts) { + prependactions(result->nullacts, sub.in); + insertlinklist(sub.in, lastnode(result->in), result->in); + } + if (sub.nullacts) { + appendactions(sub.nullacts, result->out); + insertlinklist(sub.out, lastnode(result->out), result->out); + } else + result->out = sub.out; + + if (result->nullacts && sub.nullacts) + insertlinklist(sub.nullacts, lastnode(result->nullacts), + result->nullacts); + else + result->nullacts = NULL; + } + else + break; + } + return 0; +} + +static int +rparsealt(RParseResult *result, jmp_buf *perr) +{ + RParseResult sub; + + if (rparseseq(result, perr)) + return 1; + + while (*rparseargs && !strcmp(*rparseargs, "|")) { + rparseargs++; + if (rparseseq(&sub, perr)) + longjmp(*perr, 2); + if (!result->nullacts && sub.nullacts) + result->nullacts = sub.nullacts; + + insertlinklist(sub.in, lastnode(result->in), result->in); + insertlinklist(sub.out, lastnode(result->out), result->out); + } + return 0; +} + +static int +rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp) +{ + LinkNode ln, lnn; + LinkList nexts; + LinkList nextslist; + RParseBranch *br; + RParseState *st = NULL; + int point1 = 0, point2 = 0; + + setiparam(var1, point1); + setiparam(var2, point2); + + if (!comp && !*subj && sm->nullacts) { + for (ln = firstnode(sm->nullacts); ln; ln = nextnode(ln)) { + char *action = getdata(ln); + + if (action) + execstring(action, 1, 0); + } + return 0; + } + + nextslist = newlinklist(); + nexts = sm->in; + addlinknode(nextslist, nexts); + do { + MatchData match1, match2; + + savematch(&match1); + + for (ln = firstnode(nexts); ln; ln = nextnode(ln)) { + int i; + RParseState *next; + + br = getdata(ln); + next = br->state; + if (next->pattern && !next->patprog) { + tokenize(next->pattern); + if (!(next->patprog = patcompile(next->pattern, 0, NULL))) + 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]); + + for (i = len; i; i--) + if (*subj++ == Meta) + subj++; + + savematch(&match2); + restorematch(&match1); + + for (aln = firstnode(br->actions); aln; aln = nextnode(aln)) { + char *action = getdata(aln); + + if (action) + execstring(action, 1, 0); + } + restorematch(&match2); + + point2 += len; + setiparam(var2, point2); + st = br->state; + nexts = st->branches; + if (next->cutoff == '-' || (next->cutoff == '/' && len)) { + nextslist = newlinklist(); + point1 = point2; + setiparam(var1, point1); + } + addlinknode(nextslist, nexts); + break; + } + } + if (!ln) + freematch(&match1); + } while (ln); + + if (!comp && !*subj) + for (ln = firstnode(sm->out); ln; ln = nextnode(ln)) { + br = getdata(ln); + if (br->state == st) { + for (ln = firstnode(br->actions); ln; ln = nextnode(ln)) { + char *action = getdata(ln); + + if (action) + execstring(action, 1, 0); + } + return 0; + } + } + + for (lnn = firstnode(nextslist); lnn; lnn = nextnode(lnn)) { + nexts = getdata(lnn); + for (ln = firstnode(nexts); ln; ln = nextnode(ln)) { + br = getdata(ln); + if (br->state->action) + execstring(br->state->action, 1, 0); + } + } + return empty(nexts) ? 2 : 1; +} + +/* + usage: zregexparse [-c] var1 var2 string regex... + status: + 0: matched + 1: unmatched (all next state candidates are failed) + 2: unmatched (there is no next state candidates) + 3: regex parse error +*/ + +static int +bin_zregexparse(char *nam, char **args, char *ops, int func) +{ + int oldextendedglob = opts[EXTENDEDGLOB]; + char *var1 = args[0]; + char *var2 = args[1]; + char *subj = args[2]; + int ret; + jmp_buf rparseerr; + RParseResult result; + + opts[EXTENDEDGLOB] = 1; + + rparseargs = args + 3; + + pushheap(); + rparsestates = newlinklist(); + if (setjmp(rparseerr) || rparsealt(&result, &rparseerr) || *rparseargs) { + if (*rparseargs) + zwarnnam(nam, "invalid regex : %s", *rparseargs, 0); + else + zwarnnam(nam, "not enough regex arguments", NULL, 0); + ret = 3; + } else + ret = 0; + + if (!ret) + ret = rmatch(&result, subj, var1, var2, ops['c']); + popheap(); + + opts[EXTENDEDGLOB] = oldextendedglob; + return ret; +} + +typedef struct zoptdesc *Zoptdesc; +typedef struct zoptarr *Zoptarr; +typedef struct zoptval *Zoptval; + +struct zoptdesc { + Zoptdesc next; + char *name; + int flags; + Zoptarr arr; + Zoptval vals, last; +}; + +#define ZOF_ARG 1 +#define ZOF_OPT 2 +#define ZOF_MULT 4 +#define ZOF_SAME 8 + +struct zoptarr { + Zoptarr next; + char *name; + Zoptval vals, last; + int num; +}; + +struct zoptval { + Zoptval next, onext; + char *name; + char *arg; + char *str; +}; + +static Zoptdesc opt_descs; +static Zoptarr opt_arrs; + +static Zoptdesc +get_opt_desc(char *name) +{ + Zoptdesc p; + + for (p = opt_descs; p; p = p->next) + if (!strcmp(name, p->name)) + return p; + + return NULL; +} + +static Zoptdesc +lookup_opt(char *str) +{ + Zoptdesc p; + + for (p = opt_descs; p; p = p->next) { + if ((p->flags & ZOF_ARG) ? strpfx(p->name, str) : !strcmp(p->name, str)) + return p; + } + return NULL; +} + +static Zoptarr +get_opt_arr(char *name) +{ + Zoptarr p; + + for (p = opt_arrs; p; p = p->next) + if (!strcmp(name, p->name)) + return p; + + return NULL; +} + +static void +add_opt_val(Zoptdesc d, char *arg) +{ + Zoptval v = NULL; + char *n = dyncat("-", d->name); + int new = 0; + + if (!(d->flags & ZOF_MULT)) + v = d->vals; + if (!v) { + v = (Zoptval) zhalloc(sizeof(*v)); + v->next = v->onext = NULL; + v->name = n; + new = 1; + } + v->arg = arg; + if ((d->flags & ZOF_ARG) && !(d->flags & (ZOF_OPT | ZOF_SAME))) { + v->str = NULL; + if (d->arr) + d->arr->num += (arg ? 2 : 1); + } else if (arg) { + char *s = (char *) zhalloc(strlen(d->name) + strlen(arg) + 2); + + *s = '-'; + strcpy(s + 1, d->name); + strcat(s, arg); + v->str = s; + if (d->arr) + d->arr->num += 1; + } else { + v->str = NULL; + if (d->arr) + d->arr->num += 1; + } + if (new) { + if (d->arr) { + if (d->arr->last) + d->arr->last->next = v; + else + d->arr->vals = v; + d->arr->last = v; + } + if (d->last) + d->last->onext = v; + else + d->vals = v; + d->last = v; + } +} + +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; + Zoptdesc sopts[256], d; + Zoptarr a, defarr = NULL; + Zoptval v; + + opt_descs = NULL; + opt_arrs = NULL; + memset(sopts, 0, 256 * sizeof(Zoptdesc)); + + while ((o = *args++)) { + if (*o == '-') { + switch (o[1]) { + case '\0': + o = NULL; + break; + case '-': + if (o[2]) + args--; + o = NULL; + break; + case 'D': + if (o[2]) { + args--; + o = NULL; + break; + } + del = 1; + break; + case 'a': + if (defarr) { + zwarnnam(nam, "default array given more than once", NULL, 0); + return 1; + } + if (o[2]) + n = o + 2; + else if (*args) + n = *args++; + else { + zwarnnam(nam, "missing array name", NULL, 0); + return 1; + } + defarr = (Zoptarr) zhalloc(sizeof(*defarr)); + defarr->name = n; + defarr->num = 0; + defarr->vals = defarr->last = NULL; + defarr->next = NULL; + opt_arrs = defarr; + break; + case 'A': + if (o[2]) + assoc = o + 2; + else if (*args) + assoc = *args++; + else { + zwarnnam(nam, "missing array name", NULL, 0); + return 1; + } + break; + } + if (!o) + break; + } else { + args--; + break; + } + } + while ((o = dupstring(*args++))) { + if (!*o) { + zwarnnam(nam, "invalid option description: %s", o, 0); + return 1; + } + f = 0; + for (p = o; *p; p++) { + if (*p == '\\' && p[1]) + p++; + else if (*p == '+') { + f |= ZOF_MULT; + *p = '\0'; + p++; + break; + } else if (*p == ':' || *p == '=') + break; + } + if (*p == ':') { + f |= ZOF_ARG; + *p = '\0'; + if (*++p == ':') { + p++; + f |= ZOF_OPT; + } + if (*p == '-') { + p++; + f |= ZOF_SAME; + } + } + a = NULL; + if (*p == '=') { + *p++ = '\0'; + if (!(a = get_opt_arr(p))) { + a = (Zoptarr) zhalloc(sizeof(*a)); + a->name = p; + a->num = 0; + a->vals = a->last = NULL; + a->next = opt_arrs; + opt_arrs = a; + } + } else if (*p) { + zwarnnam(nam, "invalid option description: %s", args[-1], 0); + return 1; + } else if (!(a = defarr) && !assoc) { + zwarnnam(nam, "no default array defined: %s", args[-1], 0); + return 1; + } + for (p = n = o; *p; p++) { + if (*p == '\\' && p[1]) + p++; + *n++ = *p; + } + if (get_opt_desc(o)) { + zwarnnam(nam, "option defined more than once: %s", o, 0); + return 1; + } + d = (Zoptdesc) zhalloc(sizeof(*d)); + d->name = o; + d->flags = f; + d->arr = a; + d->next = opt_descs; + d->vals = d->last = NULL; + opt_descs = d; + if (!o[1]) + sopts[STOUC(*o)] = d; + } + for (pp = pparams; (o = *pp); pp++) { + if (*o != '-') + break; + if (!o[1] || (o[1] == '-' && !o[2])) { + pp++; + break; + } + if (!(d = lookup_opt(o + 1))) { + while (*++o) { + if (!(d = sopts[STOUC(*o)])) { + o = NULL; + break; + } + if (d->flags & ZOF_ARG) { + if (o[1]) { + add_opt_val(d, o + 1); + break; + } else if (!(d->flags & ZOF_OPT)) { + if (!pp[1]) { + zwarnnam(nam, "missing argument for option: %s", + d->name, 0); + return 1; + } + add_opt_val(d, *++pp); + } else + add_opt_val(d, NULL); + } else + add_opt_val(d, NULL); + } + if (!o) + break; + } else { + if (d->flags & ZOF_ARG) { + char *e = o + strlen(d->name) + 1; + + if (*e) + add_opt_val(d, e); + else if (!(d->flags & ZOF_OPT)) { + if (!pp[1]) { + zwarnnam(nam, "missing argument for option: %s", + d->name, 0); + return 1; + } + add_opt_val(d, *++pp); + } else + add_opt_val(d, NULL); + } else + add_opt_val(d, NULL); + } + } + 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); + } + } + *ap = NULL; + setaparam(a->name, aval); + } + if (assoc) { + int num; + + for (num = 0, d = opt_descs; d; d = d->next) + 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); + } + *n = ' '; + } + *n = '\0'; + } + } + *ap = NULL; + sethparam(assoc, aval); + } + if (del) { + pp = zarrdup(pp); + freearray(pparams); + pparams = pp; + } + return 0; +} + static struct builtin bintab[] = { BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL), BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL), + BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL), + BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL), }; /**/ int -setup_zutil(Module m) +setup_(Module m) { - zstyles = NULL; + zstyles = zlstyles = NULL; return 0; } /**/ int -boot_zutil(Module m) +boot_(Module m) { return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); } /**/ int -cleanup_zutil(Module m) +cleanup_(Module m) { deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); return 0; @@ -753,9 +1538,9 @@ cleanup_zutil(Module m) /**/ int -finish_zutil(Module m) +finish_(Module m) { - freestypat(zstyles); + freeallstyles(); return 0; } |