summaryrefslogtreecommitdiff
path: root/Src/Modules/zutil.c
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-12-10 14:48:04 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-12-10 14:48:04 +0000
commit9141828e71dac723102ebd652e8a21e26c4b8e65 (patch)
tree0ce18cd17940d2b1e509312fe27039df24c0048d /Src/Modules/zutil.c
parent0f4d66156a39a30ffa79717a345f5e6af3706022 (diff)
downloadzsh-9141828e71dac723102ebd652e8a21e26c4b8e65.tar.gz
zsh-9141828e71dac723102ebd652e8a21e26c4b8e65.zip
Initial revision
Diffstat (limited to 'Src/Modules/zutil.c')
-rw-r--r--Src/Modules/zutil.c761
1 files changed, 761 insertions, 0 deletions
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
new file mode 100644
index 000000000..590678f98
--- /dev/null
+++ b/Src/Modules/zutil.c
@@ -0,0 +1,761 @@
+/*
+ * zutil.c - misc utilities
+ *
+ * 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"
+
+/* Style stuff. */
+
+typedef struct stypat *Stypat;
+typedef struct style *Style;
+
+/* A pattern and the styles for it. */
+
+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;
+
+/* Memory stuff. */
+
+static void
+freestyle(Style s)
+{
+ Style n;
+
+ while (s) {
+ n = s->next;
+
+ zsfree(s->name);
+ if (s->vals)
+ freearray(s->vals);
+ zfree(s, sizeof(*s));
+
+ s = n;
+ }
+}
+
+static void
+freestypat(Stypat p)
+{
+ Stypat n;
+
+ while (p) {
+ n = p->next;
+
+ zsfree(p->pat);
+ freepatprog(p->prog);
+ zfree(p, sizeof(*p));
+
+ p = n;
+ }
+}
+
+/* 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. */
+
+static Style
+getstyle(Stypat p, char *name)
+{
+ Style s;
+
+ for (s = p->styles; s; s= s->next)
+ if (!strcmp(name, s->name))
+ return s;
+
+ return NULL;
+}
+
+/* Store a value for a style. */
+
+static void
+setstyle(Stypat p, char *name, char **vals)
+{
+ Style s;
+
+ for (s = p->styles; s; s = s->next)
+ if (!strcmp(name, s->name)) {
+
+ /* Exists -> replace. */
+
+ if (s->vals)
+ freearray(s->vals);
+ PERMALLOC {
+ s->vals = arrdup(vals);
+ } LASTALLOC;
+
+ 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. */
+
+static Stypat
+addstypat(char *pat, Patprog prog)
+{
+ Stypat p, q, qq;
+ int weight, tmp, first;
+ char *s;
+
+ /* Calculate the weight. */
+
+ for (weight = 0, tmp = 2, first = 1, s = pat; *s; s++) {
+ if (first && *s == '*' && (!s[1] || s[1] == ':')) {
+ /* Only `*' in this component. */
+ tmp = 0;
+ continue;
+ }
+ first = 0;
+
+ if (*s == '(' || *s == '|' || *s == '*' || *s == '[' || *s == '<' ||
+ *s == '?' || *s == '#' || *s == '^')
+ /* Is pattern. */
+ tmp = 1;
+
+ if (*s == ':') {
+ /* Yet another component. */
+
+ first = 1;
+ weight += tmp;
+ tmp = 2;
+ }
+ }
+ 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;
+ qq = q, q = q->next);
+
+ p->next = q;
+ if (qq)
+ qq->next = p;
+ else
+ zstyles = p;
+ if (!q)
+ lzstyles = p;
+
+ return 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;
+
+ s->next = NULL;
+ freestyle(s);
+
+ return;
+ }
+}
+
+/* Delete a whole pattern with all its styles. */
+
+static void
+deletestypat(Stypat pat)
+{
+ Stypat pp, p;
+
+ 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;
+
+ p->next = NULL;
+ zsfree(p->pat);
+ freepatprog(p->prog);
+ freestyle(p->styles);
+ zfree(p, sizeof(*p));
+
+ return;
+ }
+}
+
+/* Look up a style for a context pattern. This does the matching. */
+
+static Style
+lookupstyle(char *ctxt, char *style)
+{
+ Stypat p;
+ Style s;
+
+ 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;
+
+ return NULL;
+}
+
+static int
+bin_zstyle(char *nam, char **args, char *ops, int func)
+{
+ int min, max, n, add = 0, list = 0;
+
+ if (!args[0])
+ list = 1;
+ else if (args[0][0] == '-') {
+ char oc;
+
+ if ((oc = args[0][1]) && oc != '-') {
+ if (args[0][2]) {
+ zerrnam(nam, "invalid argument: %s", args[0], 0);
+ return 1;
+ }
+ if (oc == 'L')
+ list = 2;
+ } else {
+ add = 1;
+ args++;
+ }
+ } else
+ add = 1;
+
+ if (add) {
+ Stypat p;
+
+ if (arrlen(args) < 2) {
+ zerrnam(nam, "not enough arguments", NULL, 0);
+ return 1;
+ }
+ if (!(p = getstypat(args[0]))) {
+ Patprog prog;
+ char *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);
+ }
+ setstyle(p, args[1], args + 2);
+
+ return 0;
+ }
+ if (list) {
+ Stypat p;
+ Style s;
+ char **v;
+
+ for (p = zstyles; p; p = p->next) {
+ if (list == 1) {
+ quotedzputs(p->pat, stdout);
+ putchar('\n');
+ }
+ for (s = p->styles; s; s = s->next) {
+ if (list == 1)
+ printf(" %s", s->name);
+ else {
+ printf("zstyle ");
+ quotedzputs(p->pat, stdout);
+ printf(" %s", s->name);
+ }
+ for (v = s->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 'h': min = 3; max = 3; 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);
+ return 1;
+ }
+ n = arrlen(args) - 1;
+ if (n < min) {
+ zerrnam(nam, "not enough arguments", NULL, 0);
+ return 1;
+ } else if (max >= 0 && n > max) {
+ zerrnam(nam, "too many arguments", NULL, 0);
+ return 1;
+ }
+ switch (args[0][1]) {
+ case 'd':
+ {
+ Stypat p;
+
+ 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);
+ }
+ } else {
+ freestypat(zstyles);
+ zstyles = lzstyles = NULL;
+ }
+ }
+ break;
+ case 's':
+ {
+ Style 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;
+ val = 0;
+ } else {
+ ret = ztrdup("");
+ val = 1;
+ }
+ setsparam(args[3], ret);
+
+ return val;
+ }
+ break;
+ case 'b':
+ {
+ Style s;
+ char *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"))) {
+ ret = "yes";
+ val = 0;
+ } else {
+ ret = "no";
+ val = 1;
+ }
+ setsparam(args[3], ztrdup(ret));
+
+ return val;
+ }
+ break;
+ case 'a':
+ case 'h':
+ {
+ Style s;
+ char **ret;
+ int val;
+
+ if ((s = lookupstyle(args[1], args[2]))) {
+ PERMALLOC {
+ ret = arrdup(s->vals);
+ } LASTALLOC;
+ val = 0;
+ } else {
+ char *dummy = NULL;
+
+ PERMALLOC {
+ ret = arrdup(&dummy);
+ } LASTALLOC;
+ val = 1;
+ }
+ if (args[0][1] == 'a')
+ setaparam(args[3], ret);
+ else
+ sethparam(args[3], ret);
+
+ return val;
+ }
+ break;
+ case 't':
+ {
+ Style s;
+
+ if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) {
+ if (args[3]) {
+ char **ap = args + 3, **p;
+
+ while (*ap) {
+ p = s->vals;
+ while (*p)
+ if (!strcmp(*ap, *p++))
+ return 0;
+ ap++;
+ }
+ 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 1;
+ }
+ break;
+ case 'm':
+ {
+ Style s;
+ Patprog prog;
+
+ tokenize(args[3]);
+
+ if ((s = lookupstyle(args[1], args[2])) &&
+ (prog = patcompile(args[3], PAT_STATIC, NULL))) {
+ char **p = s->vals;
+
+ while (*p)
+ if (pattry(prog, *p++))
+ return 0;
+ }
+ return 1;
+ }
+ break;
+ case 'g':
+ {
+ LinkList l = newlinklist();
+ int ret = 1;
+ 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;
+
+ while (*v)
+ addlinknode(l, *v++);
+
+ ret = 0;
+ }
+ } else {
+ for (s = p->styles; s; s = s->next)
+ addlinknode(l, s->name);
+
+ ret = 0;
+ }
+ }
+ } else {
+ for (p = zstyles; p; p = p->next)
+ addlinknode(l, p->pat);
+
+ ret = 0;
+ }
+ set_list_array(args[1], l);
+
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/* Format stuff. */
+
+static int
+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);
+ return 1;
+ }
+ args++;
+
+ switch (opt) {
+ case 'f':
+ {
+ char **ap, *specs[256], *out, *s;
+ int olen, oused = 0;
+
+ memset(specs, 0, 256 * sizeof(char *));
+
+ 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] != ':') {
+ zerrnam(nam, "invalid argument: %s", *ap, 0);
+ return 1;
+ }
+ specs[STOUC(ap[0][0])] = ap[0] + 2;
+ }
+ out = (char *) zhalloc(olen = 128);
+
+ for (s = args[1]; *s; s++) {
+ if (*s == '%') {
+ int right, min = -1, max = -1, outl;
+ 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';
+ }
+ if (*s == '.' && s[1] >= '0' && s[1] <= '9') {
+ for (max = 0, s++; *s >= '0' && *s <= '9'; s++)
+ max = (max * 10) + (int) STOUC(*s) - '0';
+ }
+ 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 (oused + outl >= olen) {
+ int nlen = olen + outl + 128;
+ char *tmp = (char *) zhalloc(nlen);
+
+ memcpy(tmp, out, olen);
+ olen = nlen;
+ out = tmp;
+ }
+ if (len >= outl) {
+ memcpy(out + oused, spec, outl);
+ oused += outl;
+ } else {
+ int diff = outl - len;
+
+ if (right) {
+ while (diff--)
+ out[oused++] = ' ';
+ memcpy(out + oused, spec, len);
+ oused += len;
+ } else {
+ memcpy(out + oused, spec, len);
+ oused += len;
+ while (diff--)
+ out[oused++] = ' ';
+ }
+ }
+ } else {
+ int len = s - start + 1;
+
+ if (oused + len >= olen) {
+ int nlen = olen + len + 128;
+ char *tmp = (char *) zhalloc(nlen);
+
+ memcpy(tmp, out, olen);
+ olen = nlen;
+ out = tmp;
+ }
+ memcpy(out + oused, start, len);
+ oused += len;
+ }
+ } else {
+ if (oused + 1 >= olen) {
+ char *tmp = (char *) zhalloc(olen << 1);
+
+ memcpy(tmp, out, olen);
+ olen <<= 1;
+ out = tmp;
+ }
+ out[oused++] = *s;
+ }
+ }
+ 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;
+ }
+ zerrnam(nam, "invalid option: -%c", 0, opt);
+ return 1;
+}
+
+static struct builtin bintab[] = {
+ BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
+ BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL),
+};
+
+
+/**/
+int
+setup_zutil(Module m)
+{
+ zstyles = NULL;
+
+ return 0;
+}
+
+/**/
+int
+boot_zutil(Module m)
+{
+ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+}
+
+/**/
+int
+cleanup_zutil(Module m)
+{
+ deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+ return 0;
+}
+
+/**/
+int
+finish_zutil(Module m)
+{
+ freestypat(zstyles);
+
+ return 0;
+}