--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openenvutils/commandshell/shell/src/modules/zutil.c Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,1730 @@
+#ifndef __SYMBIAN32__
+// zutil.c - misc utilities
+//
+// © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
+//
+/*
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1999 Sven Wischnowsky
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Sven Wischnowsky and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+#include "zutil.mdh"
+#include "zutil.pro"
+
+#ifdef __SYMBIAN32__
+#ifdef __WINSCW__
+#pragma warn_unusedarg off
+#pragma warn_possunwant off
+#endif//__WINSCW__
+#endif//__SYMBIAN32__
+
+/* Style stuff. */
+
+typedef struct stypat *Stypat;
+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? */
+ Eprog eval; /* eval-on-retrieve? */
+ char **vals;
+};
+
+/* List of styles. */
+
+static Style zstyles, zlstyles;
+
+/* Memory stuff. */
+
+static void
+freestypat(Stypat p)
+{
+ zsfree(p->pat);
+ freepatprog(p->prog);
+ if (p->vals)
+ freearray(p->vals);
+ if (p->eval)
+ freeeprog(p->eval);
+ zfree(p, sizeof(*p));
+}
+
+static void
+freeallstyles(void)
+{
+ 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 style struct for a name. */
+
+static Style
+getstyle(char *name)
+{
+ Style s;
+
+ for (s = zstyles; s; s = s->next)
+ if (!strcmp(name, s->name))
+ return s;
+
+ return NULL;
+}
+
+/* Store a value for a style. */
+
+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));
+ errflag = ef;
+
+ if (!eprog)
+ {
+ freepatprog(prog);
+ return 1;
+ }
+
+ eprog = dupeprog(eprog, 0);
+ }
+ for (p = s->pats; p; p = p->next)
+ if (!strcmp(pat, p->pat)) {
+
+ /* Exists -> replace. */
+
+ if (p->vals)
+ freearray(p->vals);
+ if (p->eval)
+ freeeprog(p->eval);
+ p->vals = zarrdup(vals);
+ p->eval = eprog;
+ freepatprog(prog);
+
+ return 0;
+ }
+
+ /* New pattern. */
+
+ p = (Stypat) zalloc(sizeof(*p));
+ p->pat = ztrdup(pat);
+ p->prog = prog;
+ p->vals = zarrdup(vals);
+ p->eval = eprog;
+ p->next = NULL;
+
+ /* Calculate the weight. */
+
+ 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 (*str == '(' || *str == '|' || *str == '*' || *str == '[' ||
+ *str == '<' || *str == '?' || *str == '#' || *str == '^')
+ /* Is pattern. */
+ tmp = 1;
+
+ if (*str == ':') {
+ /* Yet another component. */
+
+ first = 1;
+ weight += tmp;
+ tmp = 2;
+ }
+ }
+ p->weight = (weight += tmp);
+
+ for (qq = NULL, q = s->pats; q && q->weight >= weight;
+ qq = q, q = q->next);
+
+ p->next = q;
+ if (qq)
+ qq->next = p;
+ else
+ s->pats = p;
+
+ return 0;
+}
+
+/* Add a new style. */
+
+static Style
+addstyle(char *name)
+{
+ Style s;
+
+ s = (Style) zalloc(sizeof(*s));
+ s->next = NULL;
+ s->pats = NULL;
+ s->name = ztrdup(name);
+
+ if (zlstyles)
+ zlstyles->next = s;
+ else
+ zstyles = s;
+ zlstyles = s;
+
+ 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 char **
+lookupstyle(char *ctxt, char *style)
+{
+ Style s;
+ Stypat p;
+
+ 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->eval ? evalstyle(p) : p->vals);
+
+ return NULL;
+}
+
+static int
+bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
+{
+ int min, max, n, add = 0, list = 0, eval = 0;
+
+ if (!args[0])
+ list = 1;
+ else if (args[0][0] == '-') {
+ char oc;
+
+ if ((oc = args[0][1]) && oc != '-') {
+ if (args[0][2]) {
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
+ return 1;
+ }
+ if (oc == 'L')
+ list = 2;
+ else if (oc == 'e') {
+ eval = add = 1;
+ args++;
+ }
+ } else {
+ add = 1;
+ args++;
+ }
+ } else
+ add = 1;
+
+ if (add) {
+ Style s;
+ Patprog prog;
+ char *pat;
+
+ if (arrlen(args) < 2) {
+ zwarnnam(nam, "not enough arguments", NULL, 0);
+ return 1;
+ }
+ pat = dupstring(args[0]);
+ tokenize(pat);
+
+ if (!(prog = patcompile(pat, PAT_ZDUP, NULL))) {
+ zwarnnam(nam, "invalid pattern: %s", args[0], 0);
+ return 1;
+ }
+ if (!(s = getstyle(args[1])))
+ s = addstyle(args[1]);
+ return setstypat(s, args[0], prog, args + 2, eval);
+ }
+ if (list) {
+ Style s;
+ Stypat p;
+ char **v;
+
+ for (s = zstyles; s; s = s->next) {
+ if (list == 1) {
+ quotedzputs(s->name, stdout);
+ putchar('\n');
+ }
+ for (p = s->pats; p; p = p->next) {
+ if (list == 1)
+ printf("%s %s", (p->eval ? "(eval)" : " "), p->pat);
+ else {
+ printf("zstyle %s", (p->eval ? "-e " : ""));
+ quotedzputs(p->pat, stdout);
+ printf(" %s", s->name);
+ }
+ for (v = p->vals; *v; v++) {
+ putchar(' ');
+ quotedzputs(*v, stdout);
+ }
+ putchar('\n');
+ }
+ }
+ return 0;
+ }
+ switch (args[0][1]) {
+ case 'd': min = 0; max = -1; break;
+ case 's': min = 3; max = 4; break;
+ case 'b': min = 3; max = 3; break;
+ case 'a': 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:
+ zwarnnam(nam, "invalid option: %s", args[0], 0);
+ return 1;
+ }
+ n = arrlen(args) - 1;
+ if (n < min) {
+ zwarnnam(nam, "not enough arguments", NULL, 0);
+ return 1;
+ } else if (max >= 0 && n > max) {
+ zwarnnam(nam, "too many arguments", NULL, 0);
+ return 1;
+ }
+ switch (args[0][1]) {
+ case 'd':
+ {
+ Style s;
+
+ if (args[1]) {
+ 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
+ freeallstyles();
+ }
+ break;
+ case 's':
+ {
+ char **vals, *ret;
+ int val;
+
+ if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
+ ret = sepjoin(vals, (args[4] ? args[4] : " "), 0);
+ val = 0;
+ } else {
+ ret = ztrdup("");
+ val = 1;
+ }
+ setsparam(args[3], ret);
+
+ return val;
+ }
+ break;
+ case 'b':
+ {
+ char **vals, *ret;
+ int val;
+
+ 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 {
+ ret = "no";
+ val = 1;
+ }
+ setsparam(args[3], ztrdup(ret));
+
+ return val;
+ }
+ break;
+ case 'a':
+ {
+ char **vals, **ret;
+ int val;
+
+ if ((vals = lookupstyle(args[1], args[2]))) {
+ ret = zarrdup(vals);
+ val = 0;
+ } else {
+ char *dummy = NULL;
+
+ ret = zarrdup(&dummy);
+ val = 1;
+ }
+ setaparam(args[3], ret);
+
+ return val;
+ }
+ break;
+ case 't':
+ case 'T':
+ {
+ char **vals;
+
+ if ((vals = lookupstyle(args[1], args[2])) && vals[0]) {
+ if (args[3]) {
+ char **ap = args + 3, **p;
+
+ while (*ap) {
+ p = vals;
+ while (*p)
+ if (!strcmp(*ap, *p++))
+ return 0;
+ ap++;
+ }
+ return 1;
+ } else
+ return !(!strcmp(vals[0], "true") ||
+ !strcmp(vals[0], "yes") ||
+ !strcmp(vals[0], "on") ||
+ !strcmp(vals[0], "1"));
+ }
+ return (args[0][1] == 't' ? (vals ? 1 : 2) : 0);
+ }
+ break;
+ case 'm':
+ {
+ char **vals;
+ Patprog prog;
+
+ tokenize(args[3]);
+
+ if ((vals = lookupstyle(args[1], args[2])) &&
+ (prog = patcompile(args[3], PAT_STATIC, NULL))) {
+ while (*vals)
+ if (pattry(prog, *vals++))
+ return 0;
+ }
+ return 1;
+ }
+ break;
+ case 'g':
+ {
+ LinkList l = newlinklist();
+ int ret = 1;
+ Style s;
+ Stypat p;
+
+ if (args[2]) {
+ 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++);
+
+ ret = 0;
+ break;
+ }
+ }
+ }
+ } 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 {
+ 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);
+
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/* Format stuff. */
+
+/*
+ * One chunk of text, to allow recursive handling of ternary
+ * expressions in zformat -f output.
+ * instr The input string.
+ * specs The format specifiers, specs[c] is the string from c:string
+ * outp *outp is the start of the output string
+ * ousedp (*outp)[*ousedp] is where to write next
+ * olenp *olenp is the size allocated for *outp
+ * endchar Terminator character in addition to `\0' (may be '\0')
+ * skip If 1, don't output, just parse.
+ */
+static char *zformat_substring(char* instr, char **specs, char **outp,
+ int *ousedp, int *olenp, int endchar, int skip)
+{
+ char *s;
+
+ for (s = instr; *s && *s != endchar; s++) {
+ if (*s == '%') {
+ int right, min = -1, max = -1, outl, testit;
+ char *spec, *start = s;
+
+ if ((right = (*++s == '-')))
+ s++;
+
+ if (*s >= '0' && *s <= '9') {
+ for (min = 0; *s >= '0' && *s <= '9'; s++)
+ min = (min * 10) + (int) STOUC(*s) - '0';
+ }
+
+ /* Ternary expressions */
+ testit = (STOUC(*s) == '(');
+ if (testit && s[1] == '-')
+ {
+ /* Allow %(-1... etc. */
+ right = 1;
+ s++;
+ }
+ if ((*s == '.' || testit) && s[1] >= '0' && s[1] <= '9') {
+ for (max = 0, s++; *s >= '0' && *s <= '9'; s++)
+ max = (max * 10) + (int) STOUC(*s) - '0';
+ }
+ else if (testit)
+ s++;
+
+ if (testit && STOUC(*s)) {
+ int actval, testval, endcharl;
+
+ /*
+ * One one number is useful for ternary expressions.
+ * Remember to put the sign back.
+ */
+ testval = (min >= 0) ? min : (max >= 0) ? max : 0;
+ if (right)
+ testval *= -1;
+
+ if (specs[STOUC(*s)])
+ actval = (int)mathevali(specs[STOUC(*s)]);
+ else
+ actval = 0;
+ /* zero means values are equal, i.e. true */
+ actval -= testval;
+
+ /* careful about premature end of string */
+ if (!(endcharl = *++s))
+ return NULL;
+
+ /*
+ * Either skip true text and output false text, or
+ * vice versa... unless we are already skipping.
+ */
+ if (!(s = zformat_substring(s+1, specs, outp, ousedp,
+ olenp, endcharl, skip || actval)))
+ return NULL;
+ if (!(s = zformat_substring(s+1, specs, outp, ousedp,
+ olenp, ')', skip || !actval)))
+ return NULL;
+ } else if (skip) {
+ continue;
+ } else if ((spec = specs[STOUC(*s)])) {
+ int len;
+
+ if ((len = strlen(spec)) > max && max >= 0)
+ len = max;
+ outl = (min >= 0 ? (min > len ? min : len) : len);
+
+ if (*ousedp + outl >= *olenp) {
+ int nlen = *olenp + outl + 128;
+ char *tmp = (char *) zhalloc(nlen);
+
+ memcpy(tmp, *outp, *olenp);
+ *olenp = nlen;
+ *outp = tmp;
+ }
+ if (len >= outl) {
+ memcpy(*outp + *ousedp, spec, outl);
+ *ousedp += outl;
+ } else {
+ int diff = outl - len;
+
+ if (right) {
+ while (diff--)
+ (*outp)[(*ousedp)++] = ' ';
+ memcpy(*outp + *ousedp, spec, len);
+ *ousedp += len;
+ } else {
+ memcpy(*outp + *ousedp, spec, len);
+ *ousedp += len;
+ while (diff--)
+ (*outp)[(*ousedp)++] = ' ';
+ }
+ }
+ } else {
+ int len = s - start + 1;
+
+ if (*ousedp + len >= *olenp) {
+ int nlen = *olenp + len + 128;
+ char *tmp = (char *) zhalloc(nlen);
+
+ memcpy(tmp, *outp, *olenp);
+ *olenp = nlen;
+ *outp = tmp;
+ }
+ memcpy(*outp + *ousedp, start, len);
+ *ousedp += len;
+ }
+ } else {
+ if (skip)
+ continue;
+ if (*ousedp + 1 >= *olenp) {
+ char *tmp = (char *) zhalloc((*olenp) << 1);
+
+ memcpy(tmp, *outp, *olenp);
+ *olenp <<= 1;
+ *outp = tmp;
+ }
+ (*outp)[(*ousedp)++] = *s;
+ }
+ }
+
+ return s;
+}
+
+static int
+bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
+{
+ char opt;
+
+ if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
+ return 1;
+ }
+ args++;
+
+ switch (opt) {
+ case 'f':
+ {
+ char **ap, *specs[256], *out;
+ int olen, oused = 0;
+
+ memset(specs, 0, 256 * sizeof(char *));
+
+ specs['%'] = "%";
+ specs[')'] = ")";
+ for (ap = args + 2; *ap; ap++) {
+ if (!ap[0][0] || ap[0][0] == '-' || ap[0][0] == '.' ||
+ (ap[0][0] >= '0' && ap[0][0] <= '9') ||
+ ap[0][1] != ':') {
+ zwarnnam(nam, "invalid argument: %s", *ap, 0);
+ return 1;
+ }
+ specs[STOUC(ap[0][0])] = ap[0] + 2;
+ }
+ out = (char *) zhalloc(olen = 128);
+
+ zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0);
+ out[oused] = '\0';
+
+ setsparam(args[0], ztrdup(out));
+ return 0;
+ }
+ break;
+ case 'a':
+ {
+ char **ap, *cp;
+ int nbc = 0, colon = 0, pre = 0, suf = 0;
+
+ for (ap = args + 2; *ap; ap++) {
+ for (nbc = 0, cp = *ap; *cp && *cp != ':'; cp++)
+ if (*cp == '\\' && cp[1])
+ cp++, nbc++;
+ if (*cp == ':' && cp[1]) {
+ int d;
+
+ colon++;
+ if ((d = cp - *ap - nbc) > pre)
+ pre = d;
+ if ((d = strlen(cp + 1)) > suf)
+ suf = d;
+ }
+ }
+ {
+ int sl = strlen(args[1]);
+ VARARR(char, buf, pre + suf + sl + 1);
+ char **ret, **rp, *copy, *cpp, oldc;
+
+ ret = (char **) zalloc((arrlen(args + 2) + 1) *
+ sizeof(char *));
+
+ memcpy(buf + pre, args[1], sl);
+ suf = pre + sl;
+
+ for (rp = ret, ap = args + 2; *ap; ap++) {
+ copy = dupstring(*ap);
+ for (cp = cpp = copy; *cp && *cp != ':'; cp++) {
+ if (*cp == '\\' && cp[1])
+ cp++;
+ *cpp++ = *cp;
+ }
+ oldc = *cpp;
+ *cpp = '\0';
+ if (((cpp == cp && oldc == ':') || *cp == ':') && cp[1]) {
+ memset(buf, ' ', pre);
+ memcpy(buf, copy, (cpp - copy));
+ strcpy(buf + suf, cp + 1);
+ *rp++ = ztrdup(buf);
+ } else
+ *rp++ = ztrdup(copy);
+ }
+ *rp = NULL;
+
+ setaparam(args[0], ret);
+ return 0;
+ }
+ }
+ break;
+ }
+ 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;
+
+ 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
+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;
+ int len;
+
+ queue_signals();
+ mend = getaparam("mend");
+ len = atoi(mend[0]);
+ unqueue_signals();
+
+ 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, Options ops, UNUSED(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, OPT_ISSET(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, UNUSED(Options ops), UNUSED(int func))
+{
+ 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;
+
+ 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 '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);
+ 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) {
+ 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);
+ 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;
+ }
+ 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;
+ }
+ 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) {
+ if (extract) {
+ if (del)
+ *cp++ = *pp;
+ continue;
+ } else
+ 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);
+ }
+ }
+ if (extract && del)
+ while (*pp)
+ *cp++ = *pp++;
+
+ for (a = opt_arrs; a; a = a->next) {
+ 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);
+ }
+ }
+ if (assoc) {
+ int num;
+
+ for (num = 0, d = opt_descs; d; d = d->next)
+ if (d->vals)
+ num++;
+
+ 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++;
+ }
+ *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) {
+ if (extract) {
+ *cp = NULL;
+ freearray(pparams);
+ pparams = zarrdup(np);
+ } else {
+ 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_(UNUSED(Module m))
+{
+ zstyles = zlstyles = NULL;
+
+ return 0;
+}
+
+/**/
+int
+boot_(Module m)
+{
+ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+}
+
+/**/
+int
+cleanup_(Module m)
+{
+ deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+ return 0;
+}
+
+/**/
+int
+finish_(UNUSED(Module m))
+{
+ freeallstyles();
+
+ return 0;
+}
+
+#endif //__SYMBIAN32__