summaryrefslogtreecommitdiff
path: root/Src/Zle/computil.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2000-04-01 20:49:47 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2000-04-01 20:49:47 +0000
commit48525452555a24b9d41748f26b4b77f160f01220 (patch)
treed814ca2f017d9d843fec7d286fefbca78244beb5 /Src/Zle/computil.c
parente025336f2f6d9f107ee1e03b9900f04af0544ba9 (diff)
downloadzsh-48525452555a24b9d41748f26b4b77f160f01220.tar.gz
zsh-48525452555a24b9d41748f26b4b77f160f01220.zip
Updated from list as far as 10376
Diffstat (limited to 'Src/Zle/computil.c')
-rw-r--r--Src/Zle/computil.c1498
1 files changed, 1119 insertions, 379 deletions
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index aed3d9808..a844ee1ef 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -33,22 +33,32 @@
/* Help for `_display'. */
+/* Calculation state. */
+
typedef struct cdisp *Cdisp;
struct cdisp {
- int pre, suf, colon;
+ int pre; /* prefix length */
+ int suf; /* suffix length */
+ int colon; /* number of strings with descriptions */
};
+/* Calculate longest prefix and suffix and count the strings with
+ * descriptions. */
+
static void
cdisp_calc(Cdisp disp, char **args)
{
char *cp;
- int i;
+ int i, nbc;
for (; *args; args++) {
- if ((cp = strchr(*args, ':')) && cp[1]) {
+ for (nbc = 0, cp = *args; *cp && *cp != ':'; cp++)
+ if (*cp == '\\' && cp[1])
+ cp++, nbc++;
+ if (*cp == ':' && cp[1]) {
disp->colon++;
- if ((i = cp - *args) > disp->pre)
+ if ((i = cp - *args - nbc) > disp->pre)
disp->pre = i;
if ((i = strlen(cp + 1)) > disp->suf)
disp->suf = i;
@@ -56,78 +66,29 @@ cdisp_calc(Cdisp disp, char **args)
}
}
-static char **
-cdisp_build(Cdisp disp, char *sep, char **args)
-{
- int sl = strlen(sep), pre = disp->pre, suf;
- VARARR(char, buf, disp->pre + disp->suf + sl + 1);
- char **ret, **rp, *cp;
-
- ret = (char **) zalloc((arrlen(args) + 1) * sizeof(char *));
-
- memcpy(buf + pre, sep, sl);
- suf = pre + sl;
-
- for (rp = ret; *args; args++) {
- if ((cp = strchr(*args, ':')) && cp[1]) {
- memset(buf, ' ', pre);
- memcpy(buf, *args, (cp - *args));
- strcpy(buf + suf, cp + 1);
- *rp++ = ztrdup(buf);
- } else {
- if (cp)
- *cp = '\0';
- *rp++ = ztrdup(*args);
- if (cp)
- *cp = ':';
- }
- }
- *rp = NULL;
-
- return ret;
-}
-
-/**/
-static int
-bin_compdisplay(char *nam, char **args, char *ops, int func)
-{
- struct cdisp disp;
-
- if (incompfunc != 1) {
- zerrnam(nam, "can only be called from completion function", NULL, 0);
- return 1;
- }
- disp.pre = disp.suf = disp.colon = 0;
-
- cdisp_calc(&disp, args + 2);
- setaparam(args[0], cdisp_build(&disp, args[1], args + 2));
-
- return !disp.colon;
-}
-
/* Help fuer `_describe'. */
typedef struct cdset *Cdset;
struct cdstate {
- int showd;
- char *sep;
- Cdset sets;
- struct cdisp disp;
+ int showd; /* != 0 if descriptions should be shown */
+ char *sep; /* the separator string */
+ Cdset sets; /* the sets of matches */
+ struct cdisp disp; /* used to calculate the alignment */
};
struct cdset {
- Cdset next;
- char **opts;
- char **strs;
- char **matches;
+ Cdset next; /* guess what */
+ char **opts; /* the compadd-options */
+ char **strs; /* the display-strings */
+ char **matches; /* the matches (or NULL) */
};
static struct cdstate cd_state;
static int cd_parsed = 0;
static void
-free_cdsets(Cdset p)
+freecdsets(Cdset p)
{
Cdset n;
@@ -143,6 +104,8 @@ free_cdsets(Cdset p)
}
}
+/* Initialisation. Store and calculate the string and matches and so on. */
+
static int
cd_init(char *nam, char *sep, char **args, int disp)
{
@@ -151,7 +114,7 @@ cd_init(char *nam, char *sep, char **args, int disp)
if (cd_parsed) {
zsfree(cd_state.sep);
- free_cdsets(cd_state.sets);
+ freecdsets(cd_state.sets);
}
setp = &(cd_state.sets);
cd_state.sep = ztrdup(sep);
@@ -164,24 +127,20 @@ cd_init(char *nam, char *sep, char **args, int disp)
setp = &(set->next);
if (!(ap = get_user_var(*args))) {
- zerrnam(nam, "invalid argument: %s", *args, 0);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
return 1;
}
- PERMALLOC {
- set->strs = arrdup(ap);
- } LASTALLOC;
+ set->strs = zarrdup(ap);
if (disp)
cdisp_calc(&(cd_state.disp), set->strs);
if (*++args && **args != '-') {
if (!(ap = get_user_var(*args))) {
- zerrnam(nam, "invalid argument: %s", *args, 0);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
return 1;
}
- PERMALLOC {
- set->matches = arrdup(ap);
- } LASTALLOC;
+ set->matches = zarrdup(ap);
args++;
}
for (ap = args; *args &&
@@ -190,15 +149,15 @@ cd_init(char *nam, char *sep, char **args, int disp)
tmp = *args;
*args = NULL;
- PERMALLOC {
- set->opts = arrdup(ap);
- } LASTALLOC;
+ set->opts = zarrdup(ap);
if ((*args = tmp))
args++;
}
return 0;
}
+/* Get the next set. */
+
static int
cd_get(char **params)
{
@@ -206,15 +165,21 @@ cd_get(char **params)
if ((set = cd_state.sets)) {
char **sd, **sdp, **md, **mdp, **ss, **ssp, **ms, **msp;
- char **p, **mp, *cp;
+ char **p, **mp, *cp, *copy, *cpp, oldc;
int dl = 1, sl = 1, sepl = strlen(cd_state.sep);
int pre = cd_state.disp.pre, suf = cd_state.disp.suf;
VARARR(char, buf, pre + suf + sepl + 1);
for (p = set->strs; *p; p++)
- if (cd_state.showd && (cp = strchr(*p, ':')) && cp[1])
- dl++;
- else
+ if (cd_state.showd) {
+ for (cp = *p; *cp && *cp != ':'; cp++)
+ if (*cp == '\\' && cp[1])
+ cp++;
+ if (*cp == ':' && cp[1])
+ dl++;
+ else
+ sl++;
+ } else
sl++;
sd = (char **) zalloc(dl * sizeof(char *));
@@ -226,41 +191,44 @@ cd_get(char **params)
memcpy(buf + pre, cd_state.sep, sepl);
suf = pre + sepl;
}
+
+ /* Build the aligned display strings. */
+
for (sdp = sd, ssp = ss, mdp = md, msp = ms,
p = set->strs, mp = set->matches; *p; p++) {
- if ((cp = strchr(*p, ':')) && cp[1] && cd_state.showd) {
+ copy = dupstring(*p);
+ 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] &&
+ cd_state.showd) {
memset(buf, ' ', pre);
- memcpy(buf, *p, (cp - *p));
+ memcpy(buf, copy, (cpp - copy));
strcpy(buf + suf, cp + 1);
*sdp++ = ztrdup(buf);
if (mp) {
*mdp++ = ztrdup(*mp);
if (*mp)
mp++;
- } else {
- *cp = '\0';
- *mdp++ = ztrdup(*p);
- *cp = ':';
- }
+ } else
+ *mdp++ = ztrdup(copy);
} else {
- if (cp)
- *cp = '\0';
- *ssp++ = ztrdup(*p);
+ *ssp++ = ztrdup(copy);
if (mp) {
*msp++ = ztrdup(*mp);
if (*mp)
mp++;
} else
- *msp++ = ztrdup(*p);
- if (cp)
- *cp = ':';
+ *msp++ = ztrdup(copy);
}
}
*sdp = *ssp = *mdp = *msp = NULL;
- PERMALLOC {
- p = arrdup(set->opts);
- } LASTALLOC;
+ p = zarrdup(set->opts);
setaparam(params[0], p);
setaparam(params[1], sd);
@@ -270,7 +238,7 @@ cd_get(char **params)
cd_state.sets = set->next;
set->next = NULL;
- free_cdsets(set);
+ freecdsets(set);
return 0;
}
@@ -282,34 +250,36 @@ static int
bin_compdescribe(char *nam, char **args, char *ops, int func)
{
if (incompfunc != 1) {
- zerrnam(nam, "can only be called from completion function", NULL, 0);
+ zwarnnam(nam, "can only be called from completion function", NULL, 0);
return 1;
}
if (!args[0][0] || !args[0][1] || args[0][2]) {
- zerrnam(nam, "invalid argument: %s", args[0], 0);
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
return 1;
}
switch (args[0][1]) {
case 'i':
+ cd_parsed = 1;
+ return cd_init(nam, "", args + 1, 0);
case 'I':
cd_parsed = 1;
- return cd_init(nam, args[1], args + 2, (args[0][1] == 'I'));
+ return cd_init(nam, args[1], args + 2, 1);
case 'g':
if (cd_parsed) {
int n = arrlen(args);
if (n != 6) {
- zerrnam(nam, (n < 6 ? "not enough arguments" :
+ zwarnnam(nam, (n < 6 ? "not enough arguments" :
"too many arguments"), NULL, 0);
return 1;
}
return cd_get(args + 1);
} else {
- zerrnam(nam, "no parsed state", NULL, 0);
+ zwarnnam(nam, "no parsed state", NULL, 0);
return 1;
}
}
- zerrnam(nam, "invalid option: %s", args[0], 0);
+ zwarnnam(nam, "invalid option: %s", args[0], 0);
return 1;
}
@@ -319,29 +289,34 @@ typedef struct cadef *Cadef;
typedef struct caopt *Caopt;
typedef struct caarg *Caarg;
+/* Cache for a set of _arguments-definitions. */
+
struct cadef {
- Cadef next;
- Caopt opts;
- int nopts, ndopts, nodopts;
- Caarg args;
- Caarg rest;
- char **defs;
- int ndefs;
- int lastt;
- Caopt *single;
- char *match;
- int argsactive;
+ Cadef next; /* next in cache */
+ Caopt opts; /* the options */
+ int nopts, ndopts, nodopts; /* number of options/direct/optional direct */
+ Caarg args; /* the normal arguments */
+ Caarg rest; /* the rest-argument */
+ char **defs; /* the original strings */
+ int ndefs; /* number of ... */
+ int lastt; /* last time this was used */
+ Caopt *single; /* array of single-letter options */
+ char *match; /* -M spec to use */
+ int argsactive; /* if arguments are still allowed */
+ /* used while parsing a command line */
};
+/* Description for an option. */
+
struct caopt {
Caopt next;
- char *name;
- char *descr;
- char **xor;
- int type;
- Caarg args;
- int active;
- int num;
+ char *name; /* option name */
+ char *descr; /* the description */
+ char **xor; /* if this, then not ... */
+ int type; /* type, CAO_* */
+ Caarg args; /* option arguments */
+ int active; /* still allowed on command line */
+ int num; /* it's the num'th option */
};
#define CAO_NEXT 1
@@ -349,13 +324,18 @@ struct caopt {
#define CAO_ODIRECT 3
#define CAO_EQUAL 4
+/* Description for an argument */
+
struct caarg {
Caarg next;
- char *descr;
- char *action;
- int type;
- char *end;
- int num;
+ char *descr; /* description */
+ char **xor; /* if this, then not ... */
+ char *action; /* what to do for it */
+ int type; /* CAA_* below */
+ char *end; /* end-pattern for ::<pat>:... */
+ char *opt; /* option name if for an option */
+ int num; /* it's the num'th argument */
+ int active; /* still allowed on command line */
};
#define CAA_NORMAL 1
@@ -364,9 +344,13 @@ struct caarg {
#define CAA_RARGS 4
#define CAA_RREST 5
+/* The cache of parsed descriptons. */
+
#define MAX_CACACHE 8
static Cadef cadef_cache[MAX_CACACHE];
+/* Compare two arrays of strings for equality. */
+
static int
arrcmp(char **a, char **b)
{
@@ -383,45 +367,54 @@ arrcmp(char **a, char **b)
}
}
+/* Memory stuff. Obviously. */
+
static void
-free_caargs(Caarg a)
+freecaargs(Caarg a)
{
Caarg n;
for (; a; a = n) {
n = a->next;
zsfree(a->descr);
+ if (a->xor)
+ freearray(a->xor);
zsfree(a->action);
zsfree(a->end);
+ zsfree(a->opt);
zfree(a, sizeof(*a));
}
}
static void
-free_cadef(Cadef d)
+freecadef(Cadef d)
{
if (d) {
Caopt p, n;
zsfree(d->match);
- freearray(d->defs);
+ if (d->defs)
+ freearray(d->defs);
for (p = d->opts; p; p = n) {
n = p->next;
zsfree(p->name);
zsfree(p->descr);
- freearray(p->xor);
- free_caargs(p->args);
+ if (p->xor)
+ freearray(p->xor);
+ freecaargs(p->args);
zfree(p, sizeof(*p));
}
- free_caargs(d->args);
- free_caargs(d->rest);
+ freecaargs(d->args);
+ freecaargs(d->rest);
if (d->single)
zfree(d->single, 256 * sizeof(Caopt));
zfree(d, sizeof(*d));
}
}
+/* Remove backslashes before colons. */
+
static char *
rembslashcolon(char *s)
{
@@ -439,16 +432,41 @@ rembslashcolon(char *s)
return r;
}
+/* Add backslashes before colons. */
+
+static char *
+bslashcolon(char *s)
+{
+ char *p, *r;
+
+ r = p = zhalloc((2 * strlen(s)) + 1);
+
+ while (*s) {
+ if (*s == ':')
+ *p++ = '\\';
+ *p++ = *s++;
+ }
+ *p = '\0';
+
+ return r;
+}
+
+/* Parse an argument definition. */
+
static Caarg
-parse_caarg(int mult, int type, int num, char **def)
+parse_caarg(int mult, int type, int num, char *oname, char **def)
{
Caarg ret = (Caarg) zalloc(sizeof(*ret));
char *p = *def, *d, sav;
ret->next = NULL;
ret->descr = ret->action = ret->end = NULL;
+ ret->xor = NULL;
ret->num = num;
ret->type = type;
+ ret->opt = ztrdup(oname);
+
+ /* Get the description. */
for (d = p; *p && *p != ':'; p++)
if (*p == '\\' && p[1])
@@ -456,6 +474,9 @@ parse_caarg(int mult, int type, int num, char **def)
sav = *p;
*p = '\0';
ret->descr = ztrdup(rembslashcolon(d));
+
+ /* Get the action if there is one. */
+
if (sav) {
if (mult) {
for (d = ++p; *p && *p != ':'; p++)
@@ -474,6 +495,8 @@ parse_caarg(int mult, int type, int num, char **def)
return ret;
}
+/* Parse an array of definitions. */
+
static Cadef
parse_cadef(char *nam, char **args)
{
@@ -485,6 +508,8 @@ parse_cadef(char *nam, char **args)
nopts = ndopts = nodopts = 0;
+ /* First string is the auto-description definition. */
+
for (p = args[0]; *p && (p[0] != '%' || p[1] != 'd'); p++);
if (*p) {
@@ -495,6 +520,8 @@ parse_cadef(char *nam, char **args)
} else
adpre = adsuf = NULL;
+ /* Now get the -s and -M options. */
+
args++;
while ((p = *args)) {
if (!strcmp(p, "-s"))
@@ -515,26 +542,30 @@ parse_cadef(char *nam, char **args)
if (!*args)
return NULL;
- PERMALLOC {
- ret = (Cadef) zalloc(sizeof(*ret));
- ret->next = NULL;
- ret->opts = NULL;
- ret->args = ret->rest = NULL;
- ret->defs = arrdup(oargs);
- ret->ndefs = arrlen(oargs);
- ret->lastt = time(0);
- if (single) {
- ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
- memset(ret->single, 0, 256 * sizeof(Caopt));
- } else
- ret->single = NULL;
- ret->match = ztrdup(match);
- } LASTALLOC;
+ /* Looks good. Optimistically allocate the cadef structure. */
+
+ ret = (Cadef) zalloc(sizeof(*ret));
+ ret->next = NULL;
+ ret->opts = NULL;
+ ret->args = ret->rest = NULL;
+ ret->defs = zarrdup(oargs);
+ ret->ndefs = arrlen(oargs);
+ ret->lastt = time(0);
+ if (single) {
+ ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
+ memset(ret->single, 0, 256 * sizeof(Caopt));
+ } else
+ ret->single = NULL;
+ ret->match = ztrdup(match);
+
+ /* Get the definitions. */
for (optp = &(ret->opts); *args; args++) {
p = dupstring(*args);
xnum = 0;
if (*p == '(') {
+ /* There is a xor list, get it. */
+
LinkList list = newlinklist();
LinkNode node;
char **xp, sav;
@@ -555,9 +586,10 @@ parse_cadef(char *nam, char **args)
xnum++;
*p = sav;
}
+ /* Oops, end-of-string. */
if (*p != ')') {
- free_cadef(ret);
- zerrnam(nam, "invalid argument: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
return NULL;
}
xor = (char **) zalloc((xnum + 2) * sizeof(char *));
@@ -568,9 +600,10 @@ parse_cadef(char *nam, char **args)
p++;
} else
xor = NULL;
-
+
if (*p == '-' || *p == '+' ||
(*p == '*' && (p[1] == '-' || p[1] == '+'))) {
+ /* It's an option. */
Caopt opt;
Caarg oargs = NULL;
int multi, otype = CAO_NEXT, again = 0;
@@ -578,25 +611,39 @@ parse_cadef(char *nam, char **args)
rec:
+ /* Allowed more than once? */
if ((multi = (*p == '*')))
p++;
- if ((p[0] == '-' && p[1] == '+') ||
- (p[0] == '+' && p[1] == '-')) {
+ if (((p[0] == '-' && p[1] == '+') ||
+ (p[0] == '+' && p[1] == '-')) &&
+ p[2] && p[2] != ':' && p[2] != '[' &&
+ p[2] != '=' && p[2] != '-' && p[2] != '+') {
+ /* It's a -+ or +- definition. We just execute the whole
+ * stuff twice for such things. */
name = ++p;
*p = (again ? '-' : '+');
again = 1 - again;
} else {
name = p;
+ /* If it's a long option skip over the first `-'. */
if (p[0] == '-' && p[1] == '-')
p++;
}
+ if (!p[1]) {
+ freecadef(ret);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
+ return NULL;
+ }
+
+ /* Skip over the name. */
for (p++; *p && *p != ':' && *p != '[' &&
((*p != '-' && *p != '+' && *p != '=') ||
(p[1] != ':' && p[1] != '[')); p++)
if (*p == '\\' && p[1])
p++;
+ /* The character after the option name specifies the type. */
c = *p;
*p = '\0';
if (c == '-') {
@@ -609,14 +656,15 @@ parse_cadef(char *nam, char **args)
otype = CAO_EQUAL;
c = *++p;
}
+ /* Get the optional description, if any. */
if (c == '[') {
for (descr = ++p; *p && *p != ']'; p++)
if (*p == '\\' && p[1])
p++;
if (!*p) {
- free_cadef(ret);
- zerrnam(nam, "invalid option definition: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "invalid option definition: %s", *args, 0);
return NULL;
}
*p++ = '\0';
@@ -625,10 +673,11 @@ parse_cadef(char *nam, char **args)
descr = NULL;
if (c && c != ':') {
- free_cadef(ret);
- zerrnam(nam, "invalid option definition: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "invalid option definition: %s", *args, 0);
return NULL;
}
+ /* Add the option name to the xor list if not `*-...'. */
if (!multi) {
if (!xor) {
xor = (char **) zalloc(2 * sizeof(char *));
@@ -637,27 +686,39 @@ parse_cadef(char *nam, char **args)
xor[xnum] = ztrdup(name);
}
if (c == ':') {
+ /* There's at least one argument. */
+
Caarg *oargp = &oargs;
- int atype, rest;
+ int atype, rest, oanum = 1;
char *end;
+ /* Loop over the arguments. */
+
while (c == ':') {
rest = 0;
end = NULL;
+ /* Get the argument type. */
if (*++p == ':') {
atype = CAA_OPT;
p++;
} else if (*p == '*') {
if (*++p != ':') {
- for (end = ++p; *p && *p != ':'; p++)
+ char sav;
+
+ for (end = p++; *p && *p != ':'; p++)
if (*p == '\\' && p[1])
p++;
+ sav = *p;
+ *p = '\0';
+ end = dupstring(end);
+ tokenize(end);
+ *p = sav;
}
if (*p != ':') {
- free_cadef(ret);
- free_caargs(oargs);
- zerrnam(nam, "invalid option definition: %s",
+ freecadef(ret);
+ freecaargs(oargs);
+ zwarnnam(nam, "invalid option definition: %s",
*args, 0);
return NULL;
}
@@ -672,54 +733,74 @@ parse_cadef(char *nam, char **args)
rest = 1;
} else
atype = CAA_NORMAL;
- *oargp = parse_caarg(!rest, atype, 0, &p);
+
+ /* And the definition. */
+
+ *oargp = parse_caarg(!rest, atype, oanum++, name, &p);
+ if (end)
+ (*oargp)->end = ztrdup(end);
oargp = &((*oargp)->next);
if (rest)
break;
c = *p;
}
}
- PERMALLOC {
- *optp = opt = (Caopt) zalloc(sizeof(*opt));
- optp = &((*optp)->next);
-
- opt->next = NULL;
- opt->name = ztrdup(name);
- if (descr)
- opt->descr = ztrdup(descr);
- else if (adpre && oargs && !oargs->next)
+ /* Store the option definition. */
+
+ *optp = opt = (Caopt) zalloc(sizeof(*opt));
+ optp = &((*optp)->next);
+
+ opt->next = NULL;
+ opt->name = ztrdup(rembslashcolon(name));
+ if (descr)
+ opt->descr = ztrdup(descr);
+ else if (adpre && oargs && !oargs->next) {
+ char *d;
+
+ for (d = oargs->descr; *d; d++)
+ if (!iblank(*d))
+ break;
+
+ if (*d)
opt->descr = tricat(adpre, oargs->descr, adsuf);
else
opt->descr = NULL;
- opt->xor = xor;
- opt->type = otype;
- opt->args = oargs;
- opt->num = nopts++;
- } LASTALLOC;
+ } else
+ opt->descr = NULL;
+ opt->xor = xor;
+ opt->type = otype;
+ opt->args = oargs;
+ opt->num = nopts++;
if (otype == CAO_DIRECT)
ndopts++;
else if (otype == CAO_ODIRECT || otype == CAO_EQUAL)
nodopts++;
+ /* If this is for single-letter option we also store a
+ * pointer for the definition in the array for fast lookup. */
+
if (single && name[1] && !name[2])
ret->single[STOUC(name[1])] = opt;
if (again) {
+ /* Do it all again for `*-...'. */
p = dupstring(*args);
goto rec;
}
} else if (*p == '*') {
+ /* It's a rest-argument definition. */
+
int type = CAA_REST;
if (*++p != ':') {
- free_cadef(ret);
- zerrnam(nam, "invalid rest argument definition: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "invalid rest argument definition: %s", *args, 0);
return NULL;
}
if (ret->rest) {
- free_cadef(ret);
- zerrnam(nam, "doubled rest argument definition: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "doubled rest argument definition: %s", *args, 0);
return NULL;
}
if (*++p == ':') {
@@ -729,40 +810,49 @@ parse_cadef(char *nam, char **args)
} else
type = CAA_RARGS;
}
- ret->rest = parse_caarg(0, type, -1, &p);
+ ret->rest = parse_caarg(0, type, -1, NULL, &p);
+ ret->rest->xor = xor;
} else {
+ /* It's a normal argument definition. */
+
int type = CAA_NORMAL;
Caarg arg, tmp, pre;
if (idigit(*p)) {
+ /* Argment number is given. */
int num = 0;
while (*p && idigit(*p))
- num = (num * 10) + ((int) *p++);
+ num = (num * 10) + (((int) *p++) - '0');
anum = num + 1;
} else
+ /* Default number. */
anum++;
if (*p != ':') {
- free_cadef(ret);
- zerrnam(nam, "invalid argument: %s", *args, 0);
+ freecadef(ret);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
return NULL;
}
if (*++p == ':') {
+ /* Optional argument. */
type = CAA_OPT;
p++;
}
- arg = parse_caarg(0, type, anum - 1, &p);
+ arg = parse_caarg(0, type, anum - 1, NULL, &p);
+ arg->xor = xor;
+
+ /* Sort the new definition into the existing list. */
for (tmp = ret->args, pre = NULL;
tmp && tmp->num < anum - 1;
pre = tmp, tmp = tmp->next);
if (tmp && tmp->num == anum - 1) {
- free_cadef(ret);
- free_caargs(arg);
- zerrnam(nam, "doubled argument definition: %s", *args, 0);
+ freecadef(ret);
+ freecaargs(arg);
+ zwarnnam(nam, "doubled argument definition: %s", *args, 0);
return NULL;
}
arg->next = tmp;
@@ -779,13 +869,16 @@ parse_cadef(char *nam, char **args)
return ret;
}
+/* Given an array of definitions, return the cadef for it. From the cache
+ * are newly built. */
+
static Cadef
get_cadef(char *nam, char **args)
{
Cadef *p, *min, new;
int i, na = arrlen(args);
- for (i = MAX_CACACHE, p = cadef_cache, min = NULL; *p && i--; p++)
+ for (i = MAX_CACACHE, p = cadef_cache, min = NULL; *p && i; p++, i--)
if (*p && na == (*p)->ndefs && arrcmp(args, (*p)->defs)) {
(*p)->lastt = time(0);
@@ -795,26 +888,36 @@ get_cadef(char *nam, char **args)
if (i)
min = p;
if ((new = parse_cadef(nam, args))) {
- free_cadef(*min);
+ freecadef(*min);
*min = new;
}
return new;
}
+/* Get the option used in a word from the line, if any. */
+
static Caopt
ca_get_opt(Cadef d, char *line, int full, char **end)
{
Caopt p;
- if (full) {
- for (p = d->opts; p; p = p->next)
- if (p->active && !strcmp(p->name, line))
- return p;
- } else {
+ /* The full string may be an option. */
+
+ for (p = d->opts; p; p = p->next)
+ if (p->active && !strcmp(p->name, line)) {
+ if (end)
+ *end = line + strlen(line);
+
+ return p;
+ }
+
+ if (!full) {
+ /* The string from the line probably only begins with an option. */
for (p = d->opts; p; p = p->next)
- if (p->active && p->args && p->type != CAO_NEXT &&
- strpfx(p->name, line)) {
+ if (p->active && ((!p->args || p->type == CAO_NEXT) ?
+ !strcmp(p->name, line) : strpfx(p->name, line))) {
if (end) {
+ /* Return a pointer to the end of the option. */
int l = strlen(p->name);
if (p->type == CAO_EQUAL && line[l] == '=')
@@ -828,12 +931,13 @@ ca_get_opt(Cadef d, char *line, int full, char **end)
return NULL;
}
+/* Same as above, only for single-letter-style. */
+
static Caopt
ca_get_sopt(Cadef d, char *line, int full, char **end)
{
Caopt p;
-
- line++;
+ char pre = *line++;
if (full) {
for (p = NULL; *line; line++)
@@ -844,7 +948,7 @@ ca_get_sopt(Cadef d, char *line, int full, char **end)
} else {
for (p = NULL; *line; line++)
if ((p = d->single[STOUC(*line)]) && p->active &&
- p->args && p->type != CAO_NEXT) {
+ p->args && p->type != CAO_NEXT && p->name[0] == pre) {
if (end) {
line++;
if (p->type == CAO_EQUAL && *line == '=')
@@ -852,13 +956,18 @@ ca_get_sopt(Cadef d, char *line, int full, char **end)
*end = line;
}
break;
- } else if (!p || !p->active || (line[1] && p->args))
+ } else if (!p || !p->active || (line[1] && p->args) ||
+ p->name[0] != pre)
return NULL;
+ if (p && end)
+ *end = line;
return p;
}
return NULL;
}
+/* Return the n'th argument definition. */
+
static Caarg
ca_get_arg(Cadef d, int n)
{
@@ -868,14 +977,16 @@ ca_get_arg(Cadef d, int n)
while (a && a->num < n)
a = a->next;
- if (a && a->num == n)
+ if (a && a->num == n && a->active)
return a;
- return d->rest;
+ return (d->rest && d->rest->active ? d->rest : NULL);
}
return NULL;
}
+/* Use a xor list, marking options as inactive. */
+
static void
ca_inactive(Cadef d, char **xor)
{
@@ -885,17 +996,32 @@ ca_inactive(Cadef d, char **xor)
for (; *xor; xor++) {
if (xor[0][0] == ':' && !xor[0][1])
d->argsactive = 0;
- else if ((opt = ca_get_opt(d, *xor, 1, NULL)))
+ else if (xor[0][0] == '*' && !xor[0][1]) {
+ if (d->rest)
+ d->rest->active = 0;
+ } else if (xor[0][0] >= '0' && xor[0][0] <= '9') {
+ int n = atoi(xor[0]);
+ Caarg a = d->args;
+
+ while (a && a->num < n)
+ a = a->next;
+
+ if (a && a->num == n)
+ a->active = 0;
+ } else if ((opt = ca_get_opt(d, *xor, 1, NULL)))
opt->active = 0;
}
}
}
+/* State when parsing a command line. */
+
struct castate {
Cadef d;
+ int nopts;
Caarg def, ddef;
Caopt curopt;
- int opt, arg, argbeg, optbeg, nargbeg, restbeg;
+ int opt, arg, argbeg, optbeg, nargbeg, restbeg, curpos;
int inopt, inrest, inarg, nth, doff, singles;
LinkList args;
LinkList *oargs;
@@ -904,40 +1030,55 @@ struct castate {
static struct castate ca_laststate;
static int ca_parsed = 0, ca_alloced = 0;
+/* Pars a command line. */
+
static void
ca_parse_line(Cadef d)
{
Caarg adef, ddef;
- Caopt ptr;
+ Caopt ptr, wasopt;
struct castate state;
- char *line, *pe;
+ char *line, *pe, **argxor = NULL;
int cur, doff;
Patprog endpat = NULL;
+ /* Free old state. */
+
if (ca_alloced) {
- int i = ca_laststate.d->nopts;
+ int i = ca_laststate.nopts;
LinkList *p = ca_laststate.oargs;
freelinklist(ca_laststate.args, freestr);
while (i--)
if (*p++)
freelinklist(p[-1], freestr);
+
+ zfree(ca_laststate.oargs, ca_laststate.d->nopts * sizeof(LinkList));
}
+ /* Mark everything as active. */
+
for (ptr = d->opts; ptr; ptr = ptr->next)
ptr->active = 1;
d->argsactive = 1;
+ if (d->rest)
+ d->rest->active = 1;
+ for (adef = d->args; adef; adef = adef->next)
+ adef->active = 1;
+
+ /* Default values for the state. */
state.d = d;
+ state.nopts = d->nopts;
state.def = state.ddef = NULL;
state.curopt = NULL;
state.argbeg = state.optbeg = state.nargbeg = state.restbeg =
state.nth = state.inopt = state.inarg = state.opt = state.arg = 1;
state.inrest = state.doff = state.singles = state.doff = 0;
- PERMALLOC {
- state.args = newlinklist();
- state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
- memset(state.oargs, 0, d->nopts * sizeof(LinkList));
- } LASTALLOC;
+ state.curpos = compcurrent;
+ state.args = znewlinklist();
+ state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
+ memset(state.oargs, 0, d->nopts * sizeof(LinkList));
+
ca_alloced = 1;
memcpy(&ca_laststate, &state, sizeof(state));
@@ -947,46 +1088,67 @@ ca_parse_line(Cadef d)
return;
}
+ /* Loop over the words from the line. */
+
for (line = compwords[1], cur = 2, state.curopt = NULL, state.def = NULL;
line; line = compwords[cur++]) {
ddef = adef = NULL;
doff = state.singles = 0;
+
+ ca_inactive(d, argxor);
+
+ /* We've a definition for an argument, skip to the next. */
+
if (state.def) {
state.arg = 0;
- if (state.curopt) {
- PERMALLOC {
- addlinknode(state.oargs[state.curopt->num], ztrdup(line));
- } LASTALLOC;
- }
- state.opt = (state.def->type == CAA_OPT && line[0] && line[1]);
+ if (state.curopt)
+ zaddlinknode(state.oargs[state.curopt->num], ztrdup(line));
+
+ state.opt = (state.def->type == CAA_OPT);
if (state.def->type == CAA_REST || state.def->type == CAA_RARGS ||
state.def->type == CAA_RREST) {
if (state.def->end && pattry(endpat, line)) {
state.def = NULL;
state.curopt = NULL;
+ state.opt = state.arg = 1;
continue;
}
} else if ((state.def = state.def->next))
state.argbeg = cur;
- else
+ else {
state.curopt = NULL;
+ state.opt = 1;
+ }
} else {
- state.opt = (line[0] && line[1]);
- state.arg = 1;
+ state.opt = state.arg = 1;
state.curopt = NULL;
}
+ if (state.opt)
+ state.opt = (line[0] ? (line[1] ? 2 : 1) : 0);
+
pe = NULL;
- if (state.opt && (state.curopt = ca_get_opt(d, line, 0, &pe))) {
+ wasopt = NULL;
+
+ /* See if it's an option. */
+
+ if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) &&
+ (state.curopt->type != CAO_EQUAL ||
+ compwords[cur] || pe[-1] == '=')) {
+
ddef = state.def = state.curopt->args;
doff = pe - line;
state.optbeg = state.argbeg = state.inopt = cur;
- PERMALLOC {
- state.oargs[state.curopt->num] = newlinklist();
- } LASTALLOC;
+ state.singles = (d->single && (!pe || !*pe) &&
+ state.curopt->name[1] && !state.curopt->name[2]);
+
+ state.oargs[state.curopt->num] = znewlinklist();
+
ca_inactive(d, state.curopt->xor);
+ /* Collect the argument strings. Maybe. */
+
if (state.def &&
(state.curopt->type == CAO_DIRECT ||
(state.curopt->type == CAO_ODIRECT && pe[0]) ||
@@ -996,27 +1158,32 @@ ca_parse_line(Cadef d)
state.def->type != CAA_RARGS &&
state.def->type != CAA_RREST)
state.def = state.def->next;
- PERMALLOC {
- addlinknode(state.oargs[state.curopt->num], ztrdup(pe));
- } LASTALLOC;
+
+ zaddlinknode(state.oargs[state.curopt->num], ztrdup(pe));
}
- if (!state.def)
+ if (state.def)
+ state.opt = 0;
+ else {
+ if (!d->single || (state.curopt->name[1] && state.curopt->name[2]))
+ wasopt = state.curopt;
state.curopt = NULL;
- } else if (state.opt && d->single &&
+ }
+ } else if (state.opt == 2 && d->single &&
(state.curopt = ca_get_sopt(d, line, 0, &pe))) {
+ /* Or maybe it's a single-letter option? */
+
char *p;
Caopt tmpopt;
ddef = state.def = state.curopt->args;
doff = pe - line;
state.optbeg = state.argbeg = state.inopt = cur;
- state.singles = !*pe;
+ state.singles = (!pe || !*pe);
- for (p = line + 1; p <= pe; p++) {
+ for (p = line + 1; p < pe; p++) {
if ((tmpopt = d->single[STOUC(*p)])) {
- PERMALLOC {
- state.oargs[tmpopt->num] = newlinklist();
- } LASTALLOC;
+ state.oargs[tmpopt->num] = znewlinklist();
+
ca_inactive(d, tmpopt->xor);
}
}
@@ -1029,31 +1196,40 @@ ca_parse_line(Cadef d)
state.def->type != CAA_RARGS &&
state.def->type != CAA_RREST)
state.def = state.def->next;
- PERMALLOC {
- addlinknode(state.oargs[state.curopt->num], ztrdup(pe));
- } LASTALLOC;
+
+ zaddlinknode(state.oargs[state.curopt->num], ztrdup(pe));
}
- if (!state.def)
+ if (state.def)
+ state.opt = 0;
+ else
state.curopt = NULL;
} else if (state.arg) {
- PERMALLOC {
- addlinknode(state.args, ztrdup(line));
- } LASTALLOC;
+ /* Otherwise it's a normal argument. */
+ if (state.inopt) {
+ state.inopt = 0;
+ state.nargbeg = cur - 1;
+ }
if ((adef = state.def = ca_get_arg(d, state.nth)) &&
(state.def->type == CAA_RREST ||
state.def->type == CAA_RARGS)) {
state.inrest = 0;
- for (; line; line = compwords[cur++]) {
- PERMALLOC {
- addlinknode(state.args, ztrdup(line));
- } LASTALLOC;
- }
+ state.opt = (cur == state.nargbeg + 1);
+ state.optbeg = state.nargbeg;
+ state.argbeg = cur - 1;
+
+ for (; line; line = compwords[cur++])
+ zaddlinknode(state.args, ztrdup(line));
+
+ memcpy(&ca_laststate, &state, sizeof(state));
+ ca_laststate.ddef = NULL;
+ ca_laststate.doff = 0;
break;
}
- if (state.inopt) {
- state.inopt = 0;
- state.nargbeg = cur - 1;
- }
+ zaddlinknode(state.args, ztrdup(line));
+
+ if (state.def)
+ argxor = state.def->xor;
+
if (state.def && state.def->type != CAA_NORMAL &&
state.def->type != CAA_OPT && state.inarg) {
state.restbeg = cur;
@@ -1064,6 +1240,8 @@ ca_parse_line(Cadef d)
state.nth++;
state.def = NULL;
}
+ /* Do the end-pattern test if needed. */
+
if (state.def && state.curopt &&
(state.def->type == CAA_RREST || state.def->type == CAA_RARGS)) {
if (state.def->end)
@@ -1071,52 +1249,77 @@ ca_parse_line(Cadef d)
else {
LinkList l = state.oargs[state.curopt->num];
- for (; line; line = compwords[cur++]) {
- PERMALLOC {
- addlinknode(l, line);
- } LASTALLOC;
- }
+ if (cur < compcurrent)
+ memcpy(&ca_laststate, &state, sizeof(state));
+
+ for (; line; line = compwords[cur++])
+ zaddlinknode(l, ztrdup(line));
+
+ ca_laststate.ddef = NULL;
+ ca_laststate.doff = 0;
break;
}
- }
+ } else if (state.def && state.def->end)
+ endpat = patcompile(state.def->end, 0, NULL);
+
+ /* Copy the state into the global one. */
+
if (cur + 1 == compcurrent) {
memcpy(&ca_laststate, &state, sizeof(state));
ca_laststate.ddef = NULL;
ca_laststate.doff = 0;
} else if (cur == compcurrent && !ca_laststate.def) {
- if ((ca_laststate.def = ddef))
- ca_laststate.doff = doff;
- else {
+ if ((ca_laststate.def = ddef)) {
+ ca_laststate.singles = state.singles;
+ if (state.curopt && state.curopt->type == CAO_NEXT) {
+ ca_laststate.ddef = ddef;
+ ca_laststate.def = NULL;
+ ca_laststate.opt = 1;
+ state.curopt->active = 1;
+ } else {
+ ca_laststate.doff = doff;
+ ca_laststate.opt = 0;
+ }
+ } else {
ca_laststate.def = adef;
ca_laststate.ddef = NULL;
- ca_laststate.argbeg = state.nargbeg;
- ca_laststate.optbeg = state.restbeg;
+ ca_laststate.optbeg = state.nargbeg;
+ ca_laststate.argbeg = state.restbeg;
ca_laststate.singles = state.singles;
+ if (wasopt)
+ wasopt->active = 1;
}
}
}
}
+/* Build a colon-list from a list. */
+
static char *
ca_colonlist(LinkList l)
{
if (l) {
LinkNode n;
- int len = 1;
+ int len = 0;
char *p, *ret, *q;
- for (n = firstnode(l); n; incnode(n))
+ for (n = firstnode(l); n; incnode(n)) {
+ len++;
for (p = (char *) getdata(n); *p; p++)
len += (*p == ':' ? 2 : 1);
-
+ }
ret = q = (char *) zalloc(len);
- for (n = firstnode(l); n; incnode(n))
+ for (n = firstnode(l); n;) {
for (p = (char *) getdata(n); *p; p++) {
if (*p == ':')
*q++ = '\\';
*q++ = *p;
}
+ incnode(n);
+ if (n)
+ *q++ = ':';
+ }
*q = '\0';
return ret;
@@ -1130,36 +1333,37 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
int min, max, n;
if (incompfunc != 1) {
- zerrnam(nam, "can only be called from completion function", NULL, 0);
+ zwarnnam(nam, "can only be called from completion function", NULL, 0);
return 1;
}
if (args[0][0] != '-' || !args[0][1] || args[0][2]) {
- zerrnam(nam, "invalid argument: %s", args[0], 0);
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
return 1;
}
if (args[0][1] != 'i' && !ca_parsed) {
- zerrnam(nam, "no parsed state", NULL, 0);
+ zwarnnam(nam, "no parsed state", NULL, 0);
return 1;
}
switch (args[0][1]) {
case 'i': min = 2; max = -1; break;
case 'D': min = 2; max = 2; break;
+ case 'C': min = 1; max = 1; break;
case 'O': min = 4; max = 4; break;
- case 'L': min = 3; max = 3; break;
+ case 'L': min = 3; max = 4; break;
case 's': min = 1; max = 1; break;
case 'M': min = 1; max = 1; break;
case 'a': min = 0; max = 0; break;
case 'W': min = 2; max = 2; 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]) {
@@ -1189,19 +1393,45 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
setsparam(args[1], ztrdup(arg->descr));
setsparam(args[2], ztrdup(arg->action));
- ignore_prefix(ca_laststate.doff);
+ if (ca_laststate.doff > 0)
+ ignore_prefix(ca_laststate.doff);
if (arg->type == CAA_RARGS)
- restrict_range(ca_laststate.argbeg - 1,
+ restrict_range(ca_laststate.optbeg,
arrlen(compwords) - 1);
else if (arg->type == CAA_RREST)
- restrict_range(ca_laststate.optbeg - 1,
+ restrict_range(ca_laststate.argbeg,
arrlen(compwords) - 1);
return 0;
}
return 1;
}
+ case 'C':
+ {
+ Caarg arg = ca_laststate.def;
+
+ if (arg) {
+ char buf[20];
+
+ if (arg->num > 0)
+ sprintf(buf, "%d", arg->num);
+ else
+ strcpy(buf, "rest");
+
+ setsparam(args[1], (arg->opt ? tricat(arg->opt, "-", buf) :
+ tricat("argument-", buf, "")));
+ return 0;
+ }
+ return 1;
+ }
case 'O':
- if (ca_laststate.opt) {
+ if ((ca_laststate.opt || (ca_laststate.doff && ca_laststate.def) ||
+ (ca_laststate.def &&
+ (ca_laststate.def->type == CAA_OPT ||
+ ca_laststate.def->type >= CAA_RARGS))) &&
+ (!ca_laststate.def || ca_laststate.def->type < CAA_RARGS ||
+ (ca_laststate.def->type == CAA_RARGS ?
+ (ca_laststate.curpos == ca_laststate.argbeg + 1) :
+ (compcurrent == 1)))) {
LinkList next = newlinklist();
LinkList direct = newlinklist();
LinkList odirect = newlinklist();
@@ -1218,14 +1448,15 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
default: l = equal; break;
}
if (p->descr) {
- int len = strlen(p->name) + strlen(p->descr) + 2;
+ char *n = bslashcolon(p->name);
+ int len = strlen(n) + strlen(p->descr) + 2;
str = (char *) zhalloc(len);
- strcpy(str, p->name);
+ strcpy(str, n);
strcat(str, ":");
strcat(str, p->descr);
} else
- str = p->name;
+ str = bslashcolon(p->name);
addlinknode(l, str);
}
}
@@ -1235,8 +1466,8 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
set_list_array(args[4], equal);
return 0;
- } else
- return 1;
+ }
+ return 1;
case 'L':
{
Caopt opt = ca_get_opt(ca_laststate.d, args[1], 1, NULL);
@@ -1245,12 +1476,16 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
setsparam(args[2], ztrdup(opt->args->descr));
setsparam(args[3], ztrdup(opt->args->action));
+ if (args[4])
+ setsparam(args[4], tricat(opt->name, "-1", ""));
+
return 0;
}
return 1;
}
case 's':
- if (ca_laststate.d->single && ca_laststate.singles) {
+ if (ca_laststate.d->single && ca_laststate.singles &&
+ ca_laststate.opt) {
setsparam(args[1],
ztrdup(ca_laststate.ddef ?
(ca_laststate.ddef->type == CAO_DIRECT ?
@@ -1258,8 +1493,8 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
(ca_laststate.ddef->type == CAO_EQUAL ?
"equal" : "next")) : ""));
return 0;
- } else
- return 1;
+ }
+ return 1;
case 'M':
setsparam(args[1], ztrdup(ca_laststate.d->match));
return 0;
@@ -1310,67 +1545,79 @@ bin_comparguments(char *nam, char **args, char *ops, int func)
typedef struct cvdef *Cvdef;
typedef struct cvval *Cvval;
+/* Definitions for _values. */
+
struct cvdef {
- char *descr;
- int hassep;
- char sep;
- Cvdef next;
- Cvval vals;
- char **defs;
- int ndefs;
- int lastt;
+ char *descr; /* global description */
+ int hassep; /* multiple values allowed */
+ char sep; /* separator character */
+ Cvdef next; /* next in cache */
+ Cvval vals; /* value definitions */
+ char **defs; /* original strings */
+ int ndefs; /* number of ... */
+ int lastt; /* last time used */
};
+/* One value definition. */
+
struct cvval {
Cvval next;
- char *name;
- char *descr;
- char **xor;
- int type;
- Caarg arg;
- int active;
+ char *name; /* value name */
+ char *descr; /* description */
+ char **xor; /* xor-list */
+ int type; /* CVV_* below */
+ Caarg arg; /* argument definition */
+ int active; /* still allowed */
};
#define CVV_NOARG 0
#define CVV_ARG 1
#define CVV_OPT 2
+/* Cache. */
+
#define MAX_CVCACHE 8
static Cvdef cvdef_cache[MAX_CVCACHE];
+/* Memory stuff. */
+
static void
-free_cvdef(Cvdef d)
+freecvdef(Cvdef d)
{
if (d) {
Cvval p, n;
zsfree(d->descr);
- freearray(d->defs);
+ if (d->defs)
+ freearray(d->defs);
for (p = d->vals; p; p = n) {
n = p->next;
zsfree(p->name);
zsfree(p->descr);
- freearray(p->xor);
- free_caargs(p->arg);
+ if (p->xor)
+ freearray(p->xor);
+ freecaargs(p->arg);
zfree(p, sizeof(*p));
}
zfree(d, sizeof(*d));
}
}
+/* Parse option definitions. */
+
static Cvdef
parse_cvdef(char *nam, char **args)
{
Cvdef ret;
Cvval val, *valp;
Caarg arg;
- char **oargs = args, sep, *name, *descr, *p, *q, **xor, c;
- int xnum, multi, vtype, hassep;
+ char **oargs = args, sep = '\0', *name, *descr, *p, *q, **xor, c;
+ int xnum, multi, vtype, hassep = 0;
if (args[0][0] == '-' && args[0][1] == 's' && !args[0][2]) {
if (args[1][0] && args[1][1]) {
- zerrnam(nam, "invalid separator: %s", args[1], 0);
+ zwarnnam(nam, "invalid separator: %s", args[1], 0);
return NULL;
}
hassep = 1;
@@ -1378,26 +1625,26 @@ parse_cvdef(char *nam, char **args)
args += 2;
}
if (!args[0] || !args[1]) {
- zerrnam(nam, "not enough arguments", NULL, 0);
+ zwarnnam(nam, "not enough arguments", NULL, 0);
return NULL;
}
descr = *args++;
- PERMALLOC {
- ret = (Cvdef) zalloc(sizeof(*ret));
- ret->descr = ztrdup(descr);
- ret->hassep = hassep;
- ret->sep = sep;
- ret->next = NULL;
- ret->vals = NULL;
- ret->defs = arrdup(oargs);
- ret->ndefs = arrlen(oargs);
- ret->lastt = time(0);
- } LASTALLOC;
+ ret = (Cvdef) zalloc(sizeof(*ret));
+ ret->descr = ztrdup(descr);
+ ret->hassep = hassep;
+ ret->sep = sep;
+ ret->next = NULL;
+ ret->vals = NULL;
+ ret->defs = zarrdup(oargs);
+ ret->ndefs = arrlen(oargs);
+ ret->lastt = time(0);
for (valp = &(ret->vals); *args; args++) {
p = dupstring(*args);
xnum = 0;
+
+ /* xor list? */
if (*p == '(') {
LinkList list = newlinklist();
LinkNode node;
@@ -1420,8 +1667,8 @@ parse_cvdef(char *nam, char **args)
*p = sav;
}
if (*p != ')') {
- free_cvdef(ret);
- zerrnam(nam, "invalid argument: %s", *args, 0);
+ freecvdef(ret);
+ zwarnnam(nam, "invalid argument: %s", *args, 0);
return NULL;
}
xor = (char **) zalloc((xnum + 2) * sizeof(char *));
@@ -1433,18 +1680,23 @@ parse_cvdef(char *nam, char **args)
} else
xor = NULL;
+ /* More than once allowed? */
if ((multi = (*p == '*')))
p++;
+ /* Skip option name. */
+
for (name = p; *p && *p != ':' && *p != '['; p++)
if (*p == '\\' && p[1])
p++;
if (hassep && !sep && name + 1 != p) {
- free_cvdef(ret);
- zerrnam(nam, "no multi-letter values with empty separator allowed", NULL, 0);
+ freecvdef(ret);
+ zwarnnam(nam, "no multi-letter values with empty separator allowed", NULL, 0);
return NULL;
}
+ /* Optional description? */
+
if ((c = *p) == '[') {
*p = '\0';
for (descr = ++p; *p && *p != ']'; p++)
@@ -1452,8 +1704,8 @@ parse_cvdef(char *nam, char **args)
p++;
if (!*p) {
- free_cvdef(ret);
- zerrnam(nam, "invalid value definition: %s", *args, 0);
+ freecvdef(ret);
+ zwarnnam(nam, "invalid value definition: %s", *args, 0);
return NULL;
}
*p++ = '\0';
@@ -1463,8 +1715,8 @@ parse_cvdef(char *nam, char **args)
descr = NULL;
}
if (c && c != ':') {
- free_cvdef(ret);
- zerrnam(nam, "invalid value definition: %s", *args, 0);
+ freecvdef(ret);
+ zwarnnam(nam, "invalid value definition: %s", *args, 0);
return NULL;
}
if (!multi) {
@@ -1474,10 +1726,12 @@ parse_cvdef(char *nam, char **args)
}
xor[xnum] = ztrdup(name);
}
+ /* Get argument? */
+
if (c == ':') {
if (hassep && !sep) {
- free_cvdef(ret);
- zerrnam(nam, "no value with argument with empty separator allowed", NULL, 0);
+ freecvdef(ret);
+ zwarnnam(nam, "no value with argument with empty separator allowed", NULL, 0);
return NULL;
}
if (*++p == ':') {
@@ -1485,26 +1739,26 @@ parse_cvdef(char *nam, char **args)
vtype = CVV_OPT;
} else
vtype = CVV_ARG;
- arg = parse_caarg(0, 0, 0, &p);
+ arg = parse_caarg(0, 0, 0, name, &p);
} else {
vtype = CVV_NOARG;
arg = NULL;
}
- PERMALLOC {
- *valp = val = (Cvval) zalloc(sizeof(*val));
- valp = &((*valp)->next);
-
- val->next = NULL;
- val->name = ztrdup(name);
- val->descr = ztrdup(descr);
- val->xor = xor;
- val->type = vtype;
- val->arg = arg;
- } LASTALLOC;
+ *valp = val = (Cvval) zalloc(sizeof(*val));
+ valp = &((*valp)->next);
+
+ val->next = NULL;
+ val->name = ztrdup(name);
+ val->descr = ztrdup(descr);
+ val->xor = xor;
+ val->type = vtype;
+ val->arg = arg;
}
return ret;
}
+/* Get the definition from the cache or newly built. */
+
static Cvdef
get_cvdef(char *nam, char **args)
{
@@ -1521,12 +1775,14 @@ get_cvdef(char *nam, char **args)
if (i)
min = p;
if ((new = parse_cvdef(nam, args))) {
- free_cvdef(*min);
+ freecvdef(*min);
*min = new;
}
return new;
}
+/* Get the definition for a value. */
+
static Cvval
cv_get_val(Cvdef d, char *name)
{
@@ -1539,6 +1795,8 @@ cv_get_val(Cvdef d, char *name)
return NULL;
}
+/* Handle a xor list. */
+
static void
cv_inactive(Cvdef d, char **xor)
{
@@ -1551,6 +1809,8 @@ cv_inactive(Cvdef d, char **xor)
}
}
+/* Parse state. */
+
struct cvstate {
Cvdef d;
Caarg def;
@@ -1561,6 +1821,8 @@ struct cvstate {
static struct cvstate cv_laststate;
static int cv_parsed = 0, cv_alloced = 0;
+/* Parse the current word. */
+
static void
cv_parse_word(Cvdef d)
{
@@ -1577,9 +1839,8 @@ cv_parse_word(Cvdef d)
state.d = d;
state.def = NULL;
state.val = NULL;
- PERMALLOC {
- state.vals = (LinkList) newlinklist();
- } LASTALLOC;
+ state.vals = (LinkList) znewlinklist();
+
cv_alloced = 1;
if (d->hassep) {
@@ -1596,10 +1857,8 @@ cv_parse_word(Cvdef d)
eq = "";
if ((ptr = cv_get_val(d, str))) {
- PERMALLOC {
- addlinknode(state.vals, ztrdup(str));
- addlinknode(state.vals, ztrdup(eq));
- } LASTALLOC;
+ zaddlinknode(state.vals, ztrdup(str));
+ zaddlinknode(state.vals, ztrdup(eq));
cv_inactive(d, ptr->xor);
}
@@ -1625,10 +1884,8 @@ cv_parse_word(Cvdef d)
eq = "";
if ((ptr = cv_get_val(d, str))) {
- PERMALLOC {
- addlinknode(state.vals, ztrdup(str));
- addlinknode(state.vals, ztrdup(eq));
- } LASTALLOC;
+ zaddlinknode(state.vals, ztrdup(str));
+ zaddlinknode(state.vals, ztrdup(eq));
cv_inactive(d, ptr->xor);
}
@@ -1647,10 +1904,8 @@ cv_parse_word(Cvdef d)
for (str = compprefix; *str; str++) {
tmp[0] = *str;
if ((ptr = cv_get_val(d, tmp))) {
- PERMALLOC {
- addlinknode(state.vals, ztrdup(tmp));
- addlinknode(state.vals, ztrdup(""));
- } LASTALLOC;
+ zaddlinknode(state.vals, ztrdup(tmp));
+ zaddlinknode(state.vals, ztrdup(""));
cv_inactive(d, ptr->xor);
}
@@ -1658,10 +1913,8 @@ cv_parse_word(Cvdef d)
for (str = compsuffix; *str; str++) {
tmp[0] = *str;
if ((ptr = cv_get_val(d, tmp))) {
- PERMALLOC {
- addlinknode(state.vals, ztrdup(tmp));
- addlinknode(state.vals, ztrdup(""));
- } LASTALLOC;
+ zaddlinknode(state.vals, ztrdup(tmp));
+ zaddlinknode(state.vals, ztrdup(""));
cv_inactive(d, ptr->xor);
}
@@ -1696,35 +1949,36 @@ bin_compvalues(char *nam, char **args, char *ops, int func)
int min, max, n;
if (incompfunc != 1) {
- zerrnam(nam, "can only be called from completion function", NULL, 0);
+ zwarnnam(nam, "can only be called from completion function", NULL, 0);
return 1;
}
if (args[0][0] != '-' || !args[0][1] || args[0][2]) {
- zerrnam(nam, "invalid argument: %s", args[0], 0);
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
return 1;
}
if (args[0][1] != 'i' && !cv_parsed) {
- zerrnam(nam, "no parsed state", NULL, 0);
+ zwarnnam(nam, "no parsed state", NULL, 0);
return 1;
}
switch (args[0][1]) {
case 'i': min = 2; max = -1; break;
case 'D': min = 2; max = 2; break;
+ case 'C': min = 1; max = 1; break;
case 'V': min = 3; max = 3; break;
case 's': min = 1; max = 1; break;
case 'd': min = 1; max = 1; break;
- case 'L': min = 3; max = 3; break;
+ case 'L': min = 3; max = 4; break;
case 'v': min = 1; max = 1; 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]) {
@@ -1758,6 +2012,17 @@ bin_compvalues(char *nam, char **args, char *ops, int func)
}
return 1;
}
+ case 'C':
+ {
+ Caarg arg = cv_laststate.def;
+
+ if (arg) {
+ setsparam(args[1], ztrdup(arg->opt));
+
+ return 0;
+ }
+ return 1;
+ }
case 'V':
{
LinkList noarg = newlinklist();
@@ -1813,6 +2078,9 @@ bin_compvalues(char *nam, char **args, char *ops, int func)
setsparam(args[2], val->arg->descr);
setsparam(args[3], val->arg->action);
+ if (args[4])
+ setsparam(args[4], ztrdup(val->name));
+
return 0;
}
return 1;
@@ -1838,37 +2106,508 @@ bin_compvalues(char *nam, char **args, char *ops, int func)
return 1;
}
+static int
+bin_compquote(char *nam, char **args, char *ops, int func)
+{
+ char *name;
+ struct value vbuf;
+ Value v;
+
+ /* Anything to do? */
+
+ if (!compqstack || !*compqstack)
+ return 0;
+
+ /* For all parameters given... */
+
+ while ((name = *args++)) {
+ name = dupstring(name);
+ if ((v = getvalue(&vbuf, &name, 0))) {
+ switch (PM_TYPE(v->pm->flags)) {
+ case PM_SCALAR:
+ {
+ char *val = getstrvalue(v);
+
+ val = bslashquote(val, NULL,
+ (*compqstack == '\'' ? 1 :
+ (*compqstack == '"' ? 2 : 0)));
+
+ setstrvalue(v, ztrdup(val));
+ }
+ break;
+ case PM_ARRAY:
+ {
+ char **val = v->pm->gets.afn(v->pm);
+ char **new = (char **) zalloc((arrlen(val) + 1) *
+ sizeof(char *));
+ char **p = new;
+
+ for (; *val; val++, p++)
+ *p = ztrdup(bslashquote(*val, NULL,
+ (*compqstack == '\'' ? 1 :
+ (*compqstack == '"' ? 2 :
+ 0))));
+ *p = NULL;
+
+ setarrvalue(v, new);
+ }
+ break;
+ default:
+ zwarnnam(nam, "invalid parameter type: %s", args[-1], 0);
+ }
+ } else
+ zwarnnam(nam, "unknown parameter: %s", args[-1], 0);
+ }
+ return 0;
+}
+
+/* Tags stuff. */
+
+typedef struct ctags *Ctags;
+typedef struct ctset *Ctset;
+
+/* A bunch of tag sets. */
+
+struct ctags {
+ char **all; /* all tags offered */
+ char *context; /* the current context */
+ int init; /* not yet used */
+ Ctset sets; /* the tag sets */
+};
+
+/* A tag set. */
+
+struct ctset {
+ Ctset next;
+ char **tags; /* the tags */
+ char *tag; /* last tag checked for -A */
+ char **ptr; /* ptr into tags for -A */
+};
+
+/* Array of tag-set infos. Index is the locallevel. */
+
+#define MAX_TAGS 256
+static Ctags comptags[MAX_TAGS];
+
+/* locallevel at last comptags -i */
+
+static int lasttaglevel;
+
+static void
+freectset(Ctset s)
+{
+ Ctset n;
+
+ while (s) {
+ n = s->next;
+
+ if (s->tags)
+ freearray(s->tags);
+ zsfree(s->tag);
+ zfree(s, sizeof(*s));
+
+ s = n;
+ }
+}
+
+static void
+freectags(Ctags t)
+{
+ if (t) {
+ if (t->all)
+ freearray(t->all);
+ zsfree(t->context);
+ freectset(t->sets);
+ zfree(t, sizeof(*t));
+ }
+}
+
+/* Set the tags for the current local level. */
+
+static void
+settags(int level, char **tags)
+{
+ Ctags t;
+
+ if (comptags[level])
+ freectags(comptags[level]);
+
+ comptags[level] = t = (Ctags) zalloc(sizeof(*t));
+
+ t->all = zarrdup(tags + 1);
+ t->context = ztrdup(*tags);
+ t->sets = NULL;
+ t->init = 1;
+}
+
+/* Check if an array contains a string. */
+
+static int
+arrcontains(char **a, char *s, int colon)
+{
+ char *p, *q;
+
+ while (*a) {
+ if (colon) {
+ for (p = s, q = *a++; *p && *q && *p != ':' && *q != ':'; p++, q++)
+ if (*p != *q)
+ break;
+ if ((!*p || *p == ':') && (!*q || *q == ':'))
+ return 1;
+ } else if (!strcmp(*a++, s))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+bin_comptags(char *nam, char **args, char *ops, int func)
+{
+ int min, max, n, level;
+
+ if (incompfunc != 1) {
+ zwarnnam(nam, "can only be called from completion function", NULL, 0);
+ return 1;
+ }
+ if (args[0][0] != '-' || !args[0][1] ||
+ (args[0][2] && (args[0][2] != '-' || args[0][3]))) {
+ zwarnnam(nam, "invalid argument: %s", args[0], 0);
+ return 1;
+ }
+ level = locallevel - (args[0][2] ? 1 : 0);
+ if (level >= MAX_TAGS) {
+ zwarnnam(nam, "nesting level too deep", NULL, 0);
+ return 1;
+ }
+ if (args[0][1] != 'i' && args[0][1] != 'I' && !comptags[level]) {
+ zwarnnam(nam, "no tags registered", NULL, 0);
+ return 1;
+ }
+ switch (args[0][1]) {
+ case 'i': min = 2; max = -1; break;
+ case 'C': min = 1; max = 1; break;
+ case 'T': min = 0; max = 0; break;
+ case 'N': min = 0; max = 0; break;
+ case 'R': min = 1; max = 1; break;
+ case 'S': min = 1; max = 1; break;
+ case 'A': min = 2; max = 2; 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 'i':
+ settags(level, args + 1);
+ lasttaglevel = level;
+ break;
+ case 'C':
+ setsparam(args[1], ztrdup(comptags[level]->context));
+ break;
+ case 'T':
+ return !comptags[level]->sets;
+ case 'N':
+ {
+ Ctset s;
+
+ if (comptags[level]->init)
+ comptags[level]->init = 0;
+ else if ((s = comptags[level]->sets)) {
+ comptags[level]->sets = s->next;
+ s->next = NULL;
+ freectset(s);
+ }
+ return !comptags[level]->sets;
+ }
+ case 'R':
+ {
+ Ctset s;
+
+ return !((s = comptags[level]->sets) &&
+ arrcontains(s->tags, args[1], 1));
+ }
+ case 'A':
+ {
+ Ctset s;
+
+ if (comptags[level] && (s = comptags[level]->sets)) {
+ char **q, *v = NULL;
+ int l = strlen(args[1]);
+
+ if (!s->tag || strcmp(s->tag, args[1])) {
+ zsfree(s->tag);
+ s->tag = ztrdup(args[1]);
+ s->ptr = s->tags;
+ }
+ for (q = s->ptr; *q; q++) {
+ if (strpfx(args[1], *q)) {
+ if (!(*q)[l]) {
+ v = *q;
+ break;
+ } else if ((*q)[l] == ':') {
+ v = (*q) + l + 1;
+ break;
+ }
+ }
+ }
+ if (!v) {
+ zsfree(s->tag);
+ s->tag = NULL;
+ return 1;
+ }
+ s->ptr = q + 1;
+ setsparam(args[2], ztrdup(*v == '-' ? dyncat(args[1], v) : v));
+ return 0;
+ }
+ return 1;
+ }
+ case 'S':
+ if (comptags[level]->sets) {
+ char **ret;
+
+ ret = zarrdup(comptags[level]->sets->tags);
+ setaparam(args[1], ret);
+ } else
+ return 1;
+
+ break;
+ }
+ return 0;
+}
+
+static int
+bin_comptry(char *nam, char **args, char *ops, int func)
+{
+ if (incompfunc != 1) {
+ zwarnnam(nam, "can only be called from completion function", NULL, 0);
+ return 1;
+ }
+ if (!lasttaglevel || !comptags[lasttaglevel]) {
+ zwarnnam(nam, "no tags registered", NULL, 0);
+ return 1;
+ }
+ if (*args) {
+ if (!strcmp(*args, "-m")) {
+ char *s, *p, *q, *c, **all = comptags[lasttaglevel]->all;
+ LinkList list = newlinklist();
+ LinkNode node;
+ int num = 0;
+ Ctset set;
+
+ while ((s = *++args)) {
+ while (*s) {
+ while (*s && iblank(*s))
+ s++;
+ for (p = q = s, c = NULL; *s && !iblank(*s); s++) {
+ if (!c && *s == ':')
+ c = p;
+ if (*s == '\\' && s[1])
+ s++;
+ *p++ = *s;
+ }
+ if (*s)
+ s++;
+ *p = '\0';
+ if (*q) {
+ char *qq = dupstring(q);
+ if (c)
+ *c = '\0';
+
+ tokenize(qq);
+ if (haswilds(qq)) {
+ Patprog prog;
+
+ if ((prog = patcompile(qq, PAT_STATIC, NULL))) {
+ char **a, *n;
+ int l = (c ? strlen(c + 1) + 2 : 1), al;
+
+ for (a = all; *a; a++) {
+ if (pattry(prog, *a)) {
+ n = (char *) zhalloc((al = strlen(*a)) + l);
+ strcpy(n, *a);
+ if (c) {
+ n[al] = ':';
+ strcpy(n + al + 1, c + 1);
+ }
+ addlinknode(list, n);
+ num++;
+ }
+ }
+ }
+ } else if (arrcontains(all, q, 0)) {
+ for (set = comptags[lasttaglevel]->sets; set;
+ set = set->next)
+ if (arrcontains(set->tags, q, 0))
+ break;
+ if (!set) {
+ addlinknode(list, q);
+ num++;
+ }
+ }
+ if (c)
+ *c = ':';
+ }
+ }
+ if (num) {
+ char **a;
+ Ctset l;
+
+ set = (Ctset) zalloc(sizeof(*set));
+
+ a = set->tags = (char **) zalloc((num + 1) * sizeof(char *));
+ for (node = firstnode(list); node; incnode(node))
+ *a++ = ztrdup((char *) getdata(node));
+
+ *a = NULL;
+ set->next = NULL;
+ set->ptr = NULL;
+ set->tag = NULL;
+
+ if ((l = comptags[lasttaglevel]->sets)) {
+ while (l->next)
+ l = l->next;
+
+ l->next = set;
+ } else
+ comptags[lasttaglevel]->sets = set;
+ }
+ }
+ } else {
+ char **p, **q, **all;
+ int sep = 0;
+
+ if ((sep = !strcmp(*args, "-s")))
+ args++;
+
+ for (p = q = args, all = comptags[lasttaglevel]->all; *p; p++)
+ if (arrcontains(all, *p, 1)) {
+ Ctset s;
+
+ for (s = comptags[lasttaglevel]->sets; s; s = s->next)
+ if (arrcontains(s->tags, *p, 0))
+ break;
+
+ if (!s)
+ *q++ = *p;
+ }
+ *q = NULL;
+
+ if (*args) {
+ char *dummy[2];
+
+ do {
+ Ctset s = (Ctset) zalloc(sizeof(*s)), l;
+
+ if (sep) {
+ dummy[0] = *args++;
+ dummy[1] = NULL;
+ s->tags = zarrdup(dummy);
+ } else
+ s->tags = zarrdup(args);
+ s->next = NULL;
+ s->ptr = NULL;
+ s->tag = NULL;
+
+ if ((l = comptags[lasttaglevel]->sets)) {
+ while (l->next)
+ l = l->next;
+
+ l->next = s;
+ } else
+ comptags[lasttaglevel]->sets = s;
+ } while (sep && *args);
+ }
+ }
+ }
+ return 0;
+}
+
+static char *
+fmtstr(char *str, char c, char *repl)
+{
+ int len, num, rlen;
+ char *s, *ret, *rp;
+
+ len = strlen(str);
+ rlen = strlen(repl);
+
+ for (num = 0, s = str; *s; s++)
+ if (*s == '%' && s[1] == c)
+ num++, s++;
+
+ ret = (char *) zhalloc((num * (rlen - 2)) + len + 1);
+
+ for (s = str, rp = ret; *s; s++) {
+ if (*s == '%' && s[1] == c) {
+ strcpy(rp, repl);
+ rp += rlen;
+ s++;
+ } else
+ *rp++ = *s;
+ }
+ *rp = '\0';
+
+ return ret;
+}
+
+static int
+bin_compfmt(char *nam, char **args, char *ops, int func)
+{
+ char *param = args[0], *str = args[1];
+
+ for (args += 2; *args; args++) {
+ if (args[0][1] != ':') {
+ zwarnnam(nam, "invalid argument `%s'", args[0], 0);
+ return 1;
+ }
+ str = fmtstr(str, **args, *args + 2);
+ }
+ setsparam(param, ztrdup(str));
+ return 0;
+}
static struct builtin bintab[] = {
- BUILTIN("compdisplay", 0, bin_compdisplay, 2, -1, 0, NULL, NULL),
BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL),
BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL),
+ BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, NULL, NULL),
+ BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL),
+ BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL),
+ BUILTIN("compfmt", 0, bin_compfmt, 2, -1, 0, NULL, NULL),
};
/**/
int
-setup_computil(Module m)
+setup_(Module m)
{
memset(cadef_cache, 0, sizeof(cadef_cache));
memset(cvdef_cache, 0, sizeof(cvdef_cache));
+ memset(comptags, 0, sizeof(comptags));
+
+ lasttaglevel = 0;
+
return 0;
}
/**/
int
-boot_computil(Module m)
+boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
}
-#ifdef MODULE
-
/**/
int
-cleanup_computil(Module m)
+cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
@@ -1876,16 +2615,17 @@ cleanup_computil(Module m)
/**/
int
-finish_computil(Module m)
+finish_(Module m)
{
int i;
for (i = 0; i < MAX_CACACHE; i++)
- free_cadef(cadef_cache[i]);
+ freecadef(cadef_cache[i]);
for (i = 0; i < MAX_CVCACHE; i++)
- free_cvdef(cvdef_cache[i]);
+ freecvdef(cvdef_cache[i]);
+
+ for (i = 0; i < MAX_TAGS; i++)
+ freectags(comptags[i]);
return 0;
}
-
-#endif