26763: fix problem on failed cd -s to relative path
[zsh.git] / Src / Zle / computil.c
blobaa5983b9477ca54d48afbc671bc8ded28b5f8a62
1 /*
2 * computil.c - completion utilities
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1999 Sven Wischnowsky
7 * All rights reserved.
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
15 * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Sven Wischnowsky and the Zsh Development Group have been advised of
19 * the possibility of such damage.
21 * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
30 #include "computil.mdh"
31 #include "computil.pro"
34 /* Help for `_describe'. */
36 typedef struct cdset *Cdset;
37 typedef struct cdstr *Cdstr;
38 typedef struct cdrun *Cdrun;
40 struct cdstate {
41 int showd; /* != 0 if descriptions should be shown */
42 char *sep; /* the separator string */
43 int slen; /* its metafied length */
44 int swidth; /* its screen width */
45 int maxmlen; /* maximum length to allow for the matches */
46 Cdset sets; /* the sets of matches */
47 int pre; /* longest prefix length (before description) */
48 int premaxw; /* ... and its screen width */
49 int suf; /* longest suffix (description) */
50 int maxg; /* size of largest group */
51 int maxglen; /* columns for matches of largest group */
52 int groups; /* number of groups */
53 int descs; /* number of non-group matches with desc */
54 int gprew; /* prefix screen width for group display */
55 Cdrun runs; /* runs to report to shell code */
58 struct cdstr {
59 Cdstr next; /* the next one in this set */
60 char *str; /* the string to display */
61 char *desc; /* the description or NULL */
62 char *match; /* the match to add */
63 char *sortstr; /* unmetafied string used to sort matches */
64 int len; /* length of str or match */
65 int width; /* ... and its screen width */
66 Cdstr other; /* next string with the same description */
67 int kind; /* 0: not in a group, 1: the first, 2: other */
68 Cdset set; /* the set this string is in */
69 Cdstr run; /* next in this run */
72 struct cdrun {
73 Cdrun next; /* ... */
74 int type; /* see CRT_* below */
75 Cdstr strs; /* strings in this run */
76 int count; /* number of strings in this run */
79 #define CRT_SIMPLE 0
80 #define CRT_DESC 1
81 #define CRT_SPEC 2
82 #define CRT_DUMMY 3
83 #define CRT_EXPL 4
85 struct cdset {
86 Cdset next; /* guess what */
87 char **opts; /* the compadd-options */
88 Cdstr strs; /* the strings/matches */
89 int count; /* number of matches in this set */
90 int desc; /* number of matches with description */
93 static struct cdstate cd_state;
94 static int cd_parsed = 0;
96 static void
97 freecdsets(Cdset p)
99 Cdset n;
100 Cdstr s, sn;
101 Cdrun r, rn;
103 for (; p; p = n) {
104 n = p->next;
105 if (p->opts)
106 freearray(p->opts);
107 for (s = p->strs; s; s = sn) {
108 sn = s->next;
109 zfree(s->sortstr, strlen(s->str) + 1);
110 zsfree(s->str);
111 zsfree(s->desc);
112 if (s->match != s->str)
113 zsfree(s->match);
114 zfree(s, sizeof(*s));
116 for (r = cd_state.runs; r; r = rn) {
117 rn = r->next;
118 zfree(r, sizeof(*r));
120 zfree(p, sizeof(*p));
124 /* Find matches with same descriptions and group them. */
126 static void
127 cd_group(int maxg)
129 Cdset set1, set2;
130 Cdstr str1, str2, *strp;
131 int num, width;
133 cd_state.groups = cd_state.descs = cd_state.maxglen = 0;
134 cd_state.maxg = 0;
136 for (set1 = cd_state.sets; set1; set1 = set1->next)
137 for (str1 = set1->strs; str1; str1 = str1->next) {
138 str1->kind = 0;
139 str1->other = NULL;
142 for (set1 = cd_state.sets; set1; set1 = set1->next) {
143 for (str1 = set1->strs; str1; str1 = str1->next) {
144 if (!str1->desc || str1->kind != 0)
145 continue;
147 num = 1;
148 width = str1->width + cd_state.swidth;
149 if (width > cd_state.maxglen)
150 cd_state.maxglen = width;
151 strp = &(str1->other);
153 for (set2 = set1; set2; set2 = set2->next) {
154 for (str2 = (set2 == set1 ? str1->next : set2->strs);
155 str2; str2 = str2->next)
156 if (str2->desc && !strcmp(str1->desc, str2->desc)) {
157 width += CM_SPACE + str2->width;
158 if (width > cd_state.maxmlen || num == maxg)
159 break;
160 if (width > cd_state.maxglen)
161 cd_state.maxglen = width;
162 str1->kind = 1;
163 str2->kind = 2;
164 num++;
165 *strp = str2;
166 strp = &(str2->other);
168 if (str2)
169 break;
171 *strp = NULL;
173 if (num > 1)
174 cd_state.groups++;
175 else
176 cd_state.descs++;
178 if (num > cd_state.maxg)
179 cd_state.maxg = num;
184 /* Calculate longest prefix and suffix and count the strings with
185 * descriptions. */
187 static void
188 cd_calc()
190 Cdset set;
191 Cdstr str;
192 int l;
194 cd_state.pre = cd_state.suf = 0;
196 for (set = cd_state.sets; set; set = set->next) {
197 set->count = set->desc = 0;
198 for (str = set->strs; str; str = str->next) {
199 set->count++;
200 if ((l = strlen(str->str)) > cd_state.pre)
201 cd_state.pre = l;
202 if ((l = MB_METASTRWIDTH(str->str)) > cd_state.premaxw)
203 cd_state.premaxw = l;
204 if (str->desc) {
205 set->desc++;
206 if ((l = strlen(str->desc)) > cd_state.suf)
207 cd_state.suf = l;
213 static int
214 cd_sort(const void *a, const void *b)
216 return zstrcmp((*((Cdstr *) a))->sortstr, (*((Cdstr *) b))->sortstr, 0);
219 static int
220 cd_prep()
222 Cdrun run, *runp;
223 Cdset set;
224 Cdstr str, *strp;
226 runp = &(cd_state.runs);
228 if (cd_state.groups) {
229 int lines = cd_state.groups + cd_state.descs;
230 VARARR(Cdstr, grps, lines);
231 VARARR(int, wids, cd_state.maxg);
232 Cdstr gs, gp, gn, *gpp;
233 int i, j, d;
234 Cdrun expl;
235 Cdstr *strp2;
237 memset(wids, 0, cd_state.maxg * sizeof(int));
238 strp = grps;
240 for (set = cd_state.sets; set; set = set->next)
241 for (str = set->strs; str; str = str->next) {
242 if (str->kind != 1) {
243 if (!str->kind && str->desc) {
244 if (str->width > wids[0])
245 wids[0] = str->width;
246 str->other = NULL;
247 *strp++ = str;
249 continue;
251 gs = str;
252 gs->kind = 2;
253 gp = str->other;
254 gs->other = NULL;
255 for (; gp; gp = gn) {
256 gn = gp->other;
257 gp->other = NULL;
258 for (gpp = &gs; *gpp && (*gpp)->width > gp->width;
259 gpp = &((*gpp)->other));
260 gp->other = *gpp;
261 *gpp = gp;
263 for (gp = gs, i = 0; gp; gp = gp->other, i++)
264 if (gp->width > wids[i])
265 wids[i] = gp->width;
267 *strp++ = gs;
270 cd_state.gprew = 0;
271 for (i = 0; i < cd_state.maxg; i++) {
272 cd_state.gprew += wids[i] + CM_SPACE;
275 if (cd_state.gprew > cd_state.maxmlen && cd_state.maxglen > 1)
276 return 1;
278 for (i = 0; i < lines; i++) {
279 Cdstr s = grps[i];
280 int dummy;
282 s->sortstr = ztrdup(s->str);
283 unmetafy(s->sortstr, &dummy);
286 qsort(grps, lines, sizeof(Cdstr), cd_sort);
288 for (i = lines, strp = grps; i > 1; i--, strp++) {
289 strp2 = strp + 1;
290 if (!strcmp((*strp)->desc, (*strp2)->desc))
291 continue;
292 for (j = i - 2, strp2++; j > 0; j--, strp2++)
293 if (!strcmp((*strp)->desc, (*strp2)->desc)) {
294 Cdstr tmp = *strp2;
296 memmove(strp + 2, strp + 1,
297 (strp2 - strp - 1) * sizeof(Cdstr));
299 *++strp = tmp;
300 i--;
303 expl = (Cdrun) zalloc(sizeof(*run));
304 expl->type = CRT_EXPL;
305 expl->strs = grps[0];
306 expl->count = lines;
308 for (i = lines, strp = grps, strp2 = NULL; i; i--, strp++) {
309 str = *strp;
310 *strp = str->other;
311 if (strp2)
312 *strp2 = str;
313 strp2 = &(str->run);
315 *runp = run = (Cdrun) zalloc(sizeof(*run));
316 runp = &(run->next);
317 run->type = CRT_SPEC;
318 run->strs = str;
319 run->count = 1;
321 *strp2 = NULL;
323 for (i = cd_state.maxg - 1; i; i--) {
324 for (d = 0, j = lines, strp = grps; j; j--, strp++) {
325 if ((str = *strp)) {
326 if (d) {
327 *runp = run = (Cdrun) zalloc(sizeof(*run));
328 runp = &(run->next);
329 run->type = CRT_DUMMY;
330 run->strs = expl->strs;
331 run->count = d;
332 d = 0;
334 *runp = run = (Cdrun) zalloc(sizeof(*run));
335 runp = &(run->next);
336 run->type = CRT_SPEC;
337 run->strs = str;
338 run->strs->run = NULL;
339 run->count = 1;
341 *strp = str->other;
342 } else
343 d++;
345 if (d) {
346 *runp = run = (Cdrun) zalloc(sizeof(*run));
347 runp = &(run->next);
348 run->type = CRT_DUMMY;
349 run->strs = expl->strs;
350 run->count = d;
353 *runp = expl;
354 runp = &(expl->next);
356 for (set = cd_state.sets; set; set = set->next) {
357 for (i = 0, gs = NULL, gpp = &gs, str = set->strs;
358 str; str = str->next) {
359 if (str->kind || str->desc)
360 continue;
362 i++;
363 *gpp = str;
364 gpp = &(str->run);
366 *gpp = NULL;
367 if (i) {
368 *runp = run = (Cdrun) zalloc(sizeof(*run));
369 runp = &(run->next);
370 run->type = CRT_SIMPLE;
371 run->strs = gs;
372 run->count = i;
375 } else if (cd_state.showd) {
376 for (set = cd_state.sets; set; set = set->next) {
377 if (set->desc) {
378 *runp = run = (Cdrun) zalloc(sizeof(*run));
379 runp = &(run->next);
380 run->type = CRT_DESC;
381 strp = &(run->strs);
382 for (str = set->strs; str; str = str->next)
383 if (str->desc) {
384 *strp = str;
385 strp = &(str->run);
387 *strp = NULL;
388 run->count = set->desc;
390 if (set->desc != set->count) {
391 *runp = run = (Cdrun) zalloc(sizeof(*run));
392 runp = &(run->next);
393 run->type = CRT_SIMPLE;
394 strp = &(run->strs);
395 for (str = set->strs; str; str = str->next)
396 if (!str->desc) {
397 *strp = str;
398 strp = &(str->run);
400 *strp = NULL;
401 run->count = set->count - set->desc;
404 } else {
405 for (set = cd_state.sets; set; set = set->next)
406 if (set->count) {
407 *runp = run = (Cdrun) zalloc(sizeof(*run));
408 runp = &(run->next);
409 run->type = CRT_SIMPLE;
410 run->strs = set->strs;
411 for (str = set->strs; str; str = str->next)
412 str->run = str->next;
413 run->count = set->count;
416 *runp = NULL;
418 return 0;
421 /* Duplicate and concatenate two arrays. Return the result. */
423 static char **
424 cd_arrcat(char **a, char **b)
426 if (!b)
427 return zarrdup(a);
428 else {
429 char **r = (char **) zalloc((arrlen(a) + arrlen(b) + 1) *
430 sizeof(char *));
431 char **p = r;
433 for (; *a; a++)
434 *p++ = ztrdup(*a);
435 for (; *b; b++)
436 *p++ = ztrdup(*b);
438 *p = NULL;
440 return r;
444 /* Initialisation. Store and calculate the string and matches and so on. */
446 static int
447 cd_init(char *nam, char *hide, char *mlen, char *sep,
448 char **opts, char **args, int disp)
450 Cdset *setp, set;
451 Cdstr *strp, str;
452 char **ap, *tmp;
453 int grp = 0, itmp;
455 if (cd_parsed) {
456 zsfree(cd_state.sep);
457 freecdsets(cd_state.sets);
458 cd_parsed = 0;
460 setp = &(cd_state.sets);
461 cd_state.sep = ztrdup(sep);
462 cd_state.slen = strlen(sep);
463 cd_state.swidth = MB_METASTRWIDTH(sep);
464 cd_state.sets = NULL;
465 cd_state.showd = disp;
466 cd_state.maxg = cd_state.groups = cd_state.descs = 0;
467 cd_state.maxmlen = atoi(mlen);
468 itmp = columns - cd_state.swidth - 4;
469 if (cd_state.maxmlen > itmp)
470 cd_state.maxmlen = itmp;
471 if (cd_state.maxmlen < 4)
472 cd_state.maxmlen = 4;
473 if (*args && !strcmp(*args, "-g")) {
474 args++;
475 grp = 1;
477 while (*args) {
478 *setp = set = (Cdset) zshcalloc(sizeof(*set));
479 setp = &(set->next);
480 *setp = NULL;
481 set->opts = NULL;
482 set->strs = NULL;
484 if (!(ap = get_user_var(*args))) {
485 zwarnnam(nam, "invalid argument: %s", *args);
486 zsfree(cd_state.sep);
487 freecdsets(cd_state.sets);
488 return 1;
490 for (str = NULL, strp = &(set->strs); *ap; ap++) {
491 *strp = str = (Cdstr) zalloc(sizeof(*str));
492 strp = &(str->next);
494 str->kind = 0;
495 str->other = NULL;
496 str->set = set;
498 for (tmp = *ap; *tmp && *tmp != ':'; tmp++)
499 if (*tmp == '\\' && tmp[1])
500 tmp++;
502 if (*tmp)
503 str->desc = ztrdup(rembslash(tmp + 1));
504 else
505 str->desc = NULL;
506 *tmp = '\0';
507 str->str = str->match = ztrdup(rembslash(*ap));
508 str->len = strlen(str->str);
509 str->width = MB_METASTRWIDTH(str->str);
510 str->sortstr = NULL;
512 if (str)
513 str->next = NULL;
515 if (*++args && **args != '-') {
516 if (!(ap = get_user_var(*args))) {
517 zwarnnam(nam, "invalid argument: %s", *args);
518 zsfree(cd_state.sep);
519 freecdsets(cd_state.sets);
520 return 1;
522 for (str = set->strs; str && *ap; str = str->next, ap++)
523 str->match = ztrdup(*ap);
525 args++;
527 if (hide && *hide) {
528 for (str = set->strs; str; str = str->next) {
529 if (str->str == str->match)
530 str->str = ztrdup(str->str);
531 if (hide[1] && str->str[0] == '-' && str->str[1] == '-')
532 strcpy(str->str, str->str + 2);
533 else if (str->str[0] == '-' || str->str[0] == '+')
534 strcpy(str->str, str->str + 1);
537 for (ap = args; *args &&
538 (args[0][0] != '-' || args[0][1] != '-' || args[0][2]);
539 args++);
541 tmp = *args;
542 *args = NULL;
543 set->opts = cd_arrcat(ap, opts);
544 if ((*args = tmp))
545 args++;
547 if (disp && grp) {
548 int mg = columns;
550 do {
551 cd_group(mg);
552 mg = cd_state.maxg - 1;
553 cd_calc();
554 } while (cd_prep());
556 } else {
557 cd_calc();
558 cd_prep();
560 cd_parsed = 1;
561 return 0;
564 /* Copy an array with one element in reserve (at the beginning). */
566 static char **
567 cd_arrdup(char **a)
569 char **r = (char **) zalloc((arrlen(a) + 2) * sizeof(char *));
570 char **p = r + 1;
572 while (*a)
573 *p++ = ztrdup(*a++);
574 *p = NULL;
576 return r;
579 /* Get the next set. */
581 static int
582 cd_get(char **params)
584 Cdrun run;
586 if ((run = cd_state.runs)) {
587 Cdstr str;
588 char **mats, **mp, **dpys, **dp, **opts, *csl = "";
590 cd_state.runs = run->next;
592 switch (run->type) {
593 case CRT_SIMPLE:
594 mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *));
595 dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *));
597 for (str = run->strs; str; str = str->run) {
598 *mp++ = ztrdup(str->match);
599 *dp++ = ztrdup(str->str ? str->str : str->match);
601 *mp = *dp = NULL;
602 opts = zarrdup(run->strs->set->opts);
603 if (cd_state.groups) {
604 /* We are building a columnised list with dummy matches
605 * but there are also matches without descriptions.
606 * Those end up in a different group, so make sure that
607 * group doesn't have an explanation. */
609 for (mp = dp = opts; *mp; mp++) {
610 if (dp[0][0] == '-' && dp[0][1] == 'X') {
611 if (!dp[0][2] && dp[1])
612 mp++;
613 } else
614 *dp++ = *mp;
616 *dp = NULL;
618 break;
620 case CRT_DESC:
623 * The buffer size:
624 * max prefix length (cd_state.pre) +
625 * max padding (cd_state.premaxw generously :) +
626 * separator length (cd_state.slen) +
627 * inter matches gap (CM_SPACE) +
628 * max description length (cd_state.suf) +
629 * trailing \0
631 VARARR(char, buf,
632 cd_state.pre + cd_state.suf +
633 cd_state.premaxw + cd_state.slen + 3);
634 mats = mp = (char **) zalloc((run->count + 1) * sizeof(char *));
635 dpys = dp = (char **) zalloc((run->count + 1) * sizeof(char *));
637 for (str = run->strs; str; str = str->run) {
638 char *p = buf, *pp, *d;
639 int l, remw, w;
641 *mp++ = ztrdup(str->match);
642 strcpy(p, str->str);
643 p += str->len;
644 memset(p, ' ', (l = (cd_state.premaxw - str->width + CM_SPACE)));
645 p += l;
646 strcpy(p, cd_state.sep);
647 p += cd_state.slen;
650 * copy a character at once until no more screen width
651 * is available. Leave 1 character at the end of screen
652 * as safety margin
654 remw = columns - cd_state.premaxw - cd_state.swidth - 3;
655 d = str->desc;
656 w = MB_METASTRWIDTH(d);
657 if (w <= remw)
658 strcpy(p, d);
659 else {
660 pp = p;
661 while (remw > 0 && *d) {
662 l = MB_METACHARLEN(d);
663 memcpy(pp, d, l);
664 pp[l] = '\0';
665 w = MB_METASTRWIDTH(pp);
666 if (w > remw) {
667 *pp = '\0';
668 break;
671 pp += l;
672 d += l;
673 remw -= w;
677 *dp++ = ztrdup(buf);
679 *mp = *dp = NULL;
680 opts = cd_arrdup(run->strs->set->opts);
681 opts[0] = ztrdup("-l");
682 break;
685 case CRT_SPEC:
686 mats = (char **) zalloc(2 * sizeof(char *));
687 dpys = (char **) zalloc(2 * sizeof(char *));
688 mats[0] = ztrdup(run->strs->match);
689 dpys[0] = ztrdup(run->strs->str);
690 mats[1] = dpys[1] = NULL;
691 opts = cd_arrdup(run->strs->set->opts);
692 for (dp = opts + 1; *dp; dp++)
693 if (dp[0][0] == '-' && dp[0][1] == 'J')
694 break;
695 if (*dp) {
696 char *s = tricat("-2V", "", dp[0] + 2);
698 zsfree(*dp);
699 *dp = s;
701 memmove(opts, opts + 1,
702 (arrlen(opts + 1) + 1) * sizeof(char *));
704 } else
705 opts[0] = ztrdup("-2V-default-");
706 csl = "packed";
707 break;
709 case CRT_DUMMY:
711 char buf[20];
713 sprintf(buf, "-E%d", run->count);
715 mats = (char **) zalloc(sizeof(char *));
716 dpys = (char **) zalloc(sizeof(char *));
717 mats[0] = dpys[0] = NULL;
719 opts = cd_arrdup(run->strs->set->opts);
720 opts[0] = ztrdup(buf);
722 csl = "packed";
724 break;
726 default: /* This silences the "might be used uninitialized" warnings */
727 case CRT_EXPL:
729 /* add columns as safety margin */
730 VARARR(char, dbuf, cd_state.suf + cd_state.slen + columns);
731 char buf[20], *p, *pp, *d;
732 int i = run->count, remw, w, l;
734 sprintf(buf, "-E%d", i);
736 mats = (char **) zalloc(sizeof(char *));
737 dpys = (char **) zalloc((i + 1) * sizeof(char *));
739 for (dp = dpys, str = run->strs; str; str = str->run) {
740 if (str->run && !strcmp(str->desc, str->run->desc)) {
741 *dp++ = ztrdup("");
742 continue;
745 strcpy(dbuf, cd_state.sep);
746 remw = columns - cd_state.gprew - cd_state.swidth - CM_SPACE;
747 p = pp = dbuf + cd_state.slen;
748 d = str->desc;
749 w = MB_METASTRWIDTH(d);
750 if (w <= remw) {
751 strcpy(p, d);
752 remw -= w;
753 pp += strlen(d);
754 } else
755 while (remw > 0 && *d) {
756 l = MB_METACHARLEN(d);
757 memcpy(pp, d, l);
758 pp[l] = '\0';
759 w = MB_METASTRWIDTH(pp);
760 if (w > remw) {
761 *pp = '\0';
762 break;
765 pp += l;
766 d += l;
767 remw -= w;
770 while (remw-- > 0)
771 *pp++ = ' ';
772 *pp = '\0';
774 *dp++ = ztrdup(dbuf);
776 mats[0] = *dp = NULL;
778 opts = cd_arrdup(run->strs->set->opts);
779 opts[0] = ztrdup(buf);
781 csl = "packed";
783 break;
785 setsparam(params[0], ztrdup(csl));
786 setaparam(params[1], opts);
787 setaparam(params[2], mats);
788 setaparam(params[3], dpys);
790 zfree(run, sizeof(*run));
792 return 0;
794 return 1;
797 /**/
798 static int
799 bin_compdescribe(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
801 int n = arrlen(args);
803 if (incompfunc != 1) {
804 zwarnnam(nam, "can only be called from completion function");
805 return 1;
807 if (!args[0][0] || !args[0][1] || args[0][2]) {
808 zwarnnam(nam, "invalid argument: %s", args[0]);
809 return 1;
811 switch (args[0][1]) {
812 case 'i':
813 if (n < 3) {
814 zwarnnam(nam, "not enough arguments");
816 return 1;
818 return cd_init(nam, args[1], args[2], "", NULL, args + 3, 0);
819 case 'I':
820 if (n < 6) {
821 zwarnnam(nam, "not enough arguments");
823 return 1;
824 } else {
825 char **opts;
827 if (!(opts = getaparam(args[4]))) {
828 zwarnnam(nam, "unknown parameter: %s", args[4]);
829 return 1;
831 return cd_init(nam, args[1], args[2], args[3], opts, args + 5, 1);
833 case 'g':
834 if (cd_parsed) {
835 if (n != 5) {
836 zwarnnam(nam, (n < 5 ? "not enough arguments" :
837 "too many arguments"));
838 return 1;
840 return cd_get(args + 1);
841 } else {
842 zwarnnam(nam, "no parsed state");
843 return 1;
846 zwarnnam(nam, "invalid option: %s", args[0]);
847 return 1;
850 /* Help for `_arguments'. */
852 typedef struct cadef *Cadef;
853 typedef struct caopt *Caopt;
854 typedef struct caarg *Caarg;
856 /* Cache for a set of _arguments-definitions. */
858 struct cadef {
859 Cadef next; /* next in cache */
860 Cadef snext; /* next set */
861 Caopt opts; /* the options */
862 int nopts, ndopts, nodopts; /* number of options/direct/optional direct */
863 Caarg args; /* the normal arguments */
864 Caarg rest; /* the rest-argument */
865 char **defs; /* the original strings */
866 int ndefs; /* number of ... */
867 int lastt; /* last time this was used */
868 Caopt *single; /* array of single-letter options */
869 char *match; /* -M spec to use */
870 int argsactive; /* if arguments are still allowed */
871 /* used while parsing a command line */
872 char *set; /* set name prefix (<name>-), shared */
873 char *sname; /* set name */
874 int flags; /* see CDF_* below */
875 char *nonarg; /* pattern for non-args (-A argument) */
878 #define CDF_SEP 1
880 /* Description for an option. */
882 struct caopt {
883 Caopt next;
884 char *name; /* option name */
885 char *descr; /* the description */
886 char **xor; /* if this, then not ... */
887 int type; /* type, CAO_* */
888 Caarg args; /* option arguments */
889 int active; /* still allowed on command line */
890 int num; /* it's the num'th option */
891 char *set; /* set name, shared */
892 int not; /* don't complete this option (`!...') */
895 #define CAO_NEXT 1
896 #define CAO_DIRECT 2
897 #define CAO_ODIRECT 3
898 #define CAO_EQUAL 4
899 #define CAO_OEQUAL 5
901 /* Description for an argument */
903 struct caarg {
904 Caarg next;
905 char *descr; /* description */
906 char **xor; /* if this, then not ... */
907 char *action; /* what to do for it */
908 int type; /* CAA_* below */
909 char *end; /* end-pattern for ::<pat>:... */
910 char *opt; /* option name if for an option */
911 int num; /* it's the num'th argument */
912 int min; /* it's also this argument, using opt. args */
913 int direct; /* number was given directly */
914 int active; /* still allowed on command line */
915 char *set; /* set name, shared */
918 #define CAA_NORMAL 1
919 #define CAA_OPT 2
920 #define CAA_REST 3
921 #define CAA_RARGS 4
922 #define CAA_RREST 5
924 /* The cache of parsed descriptons. */
926 #define MAX_CACACHE 8
927 static Cadef cadef_cache[MAX_CACACHE];
929 /* Compare two arrays of strings for equality. */
931 static int
932 arrcmp(char **a, char **b)
934 if (!a && !b)
935 return 1;
936 else if (!a || !b)
937 return 0;
938 else {
939 while (*a && *b)
940 if (strcmp(*a++, *b++))
941 return 0;
943 return (!*a && !*b);
947 /* Memory stuff. Obviously. */
949 static void
950 freecaargs(Caarg a)
952 Caarg n;
954 for (; a; a = n) {
955 n = a->next;
956 zsfree(a->descr);
957 if (a->xor)
958 freearray(a->xor);
959 zsfree(a->action);
960 zsfree(a->end);
961 zsfree(a->opt);
962 zfree(a, sizeof(*a));
966 static void
967 freecadef(Cadef d)
969 Cadef s;
970 Caopt p, n;
972 while (d) {
973 s = d->snext;
974 zsfree(d->match);
975 zsfree(d->set);
976 zsfree(d->sname);
977 if (d->defs)
978 freearray(d->defs);
980 for (p = d->opts; p; p = n) {
981 n = p->next;
982 zsfree(p->name);
983 zsfree(p->descr);
984 if (p->xor)
985 freearray(p->xor);
986 freecaargs(p->args);
987 zfree(p, sizeof(*p));
989 freecaargs(d->args);
990 freecaargs(d->rest);
991 zsfree(d->nonarg);
992 if (d->single)
993 zfree(d->single, 256 * sizeof(Caopt));
994 zfree(d, sizeof(*d));
995 d = s;
999 /* Remove backslashes before colons. */
1001 static char *
1002 rembslashcolon(char *s)
1004 char *p, *r;
1006 r = p = s = dupstring(s);
1008 while (*s) {
1009 if (s[0] != '\\' || s[1] != ':')
1010 *p++ = *s;
1011 s++;
1013 *p = '\0';
1015 return r;
1018 /* Add backslashes before colons. */
1020 static char *
1021 bslashcolon(char *s)
1023 char *p, *r;
1025 r = p = zhalloc((2 * strlen(s)) + 1);
1027 while (*s) {
1028 if (*s == ':')
1029 *p++ = '\\';
1030 *p++ = *s++;
1032 *p = '\0';
1034 return r;
1037 /* Parse an argument definition. */
1039 static Caarg
1040 parse_caarg(int mult, int type, int num, int opt, char *oname, char **def,
1041 char *set)
1043 Caarg ret = (Caarg) zalloc(sizeof(*ret));
1044 char *p = *def, *d, sav;
1046 ret->next = NULL;
1047 ret->descr = ret->action = ret->end = NULL;
1048 ret->xor = NULL;
1049 ret->num = num;
1050 ret->min = num - opt;
1051 ret->type = type;
1052 ret->opt = ztrdup(oname);
1053 ret->direct = 0;
1054 ret->set = set;
1056 /* Get the description. */
1058 for (d = p; *p && *p != ':'; p++)
1059 if (*p == '\\' && p[1])
1060 p++;
1061 sav = *p;
1062 *p = '\0';
1063 ret->descr = ztrdup(rembslashcolon(d));
1065 /* Get the action if there is one. */
1067 if (sav) {
1068 if (mult) {
1069 for (d = ++p; *p && *p != ':'; p++)
1070 if (*p == '\\' && p[1])
1071 p++;
1072 sav = *p;
1073 *p = '\0';
1074 ret->action = ztrdup(rembslashcolon(d));
1075 if (sav)
1076 *p = ':';
1077 } else
1078 ret->action = ztrdup(rembslashcolon(p + 1));
1079 } else
1080 ret->action = ztrdup("");
1081 *def = p;
1083 return ret;
1086 static Cadef
1087 alloc_cadef(char **args, int single, char *match, char *nonarg, int flags)
1089 Cadef ret;
1091 ret = (Cadef) zalloc(sizeof(*ret));
1092 ret->next = ret->snext = NULL;
1093 ret->opts = NULL;
1094 ret->args = ret->rest = NULL;
1095 ret->nonarg = ztrdup(nonarg);
1096 if (args) {
1097 ret->defs = zarrdup(args);
1098 ret->ndefs = arrlen(args);
1099 } else {
1100 ret->defs = NULL;
1101 ret->ndefs = 0;
1103 ret->lastt = time(0);
1104 ret->set = ret->sname = NULL;
1105 if (single) {
1106 ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
1107 memset(ret->single, 0, 256 * sizeof(Caopt));
1108 } else
1109 ret->single = NULL;
1110 ret->match = ztrdup(match);
1111 ret->flags = flags;
1113 return ret;
1116 static void
1117 set_cadef_opts(Cadef def)
1119 Caarg argp;
1120 int xnum;
1122 for (argp = def->args, xnum = 0; argp; argp = argp->next) {
1123 if (!argp->direct)
1124 argp->min = argp->num - xnum;
1125 if (argp->type == CAA_OPT)
1126 xnum++;
1130 /* Parse an array of definitions. */
1132 static Cadef
1133 parse_cadef(char *nam, char **args)
1135 Cadef all, ret;
1136 Caopt *optp;
1137 char **orig_args = args, *p, *q, *match = "r:|[_-]=* r:|=*", **xor, **sargs;
1138 char *adpre, *adsuf, *axor = NULL, *doset = NULL, **setp = NULL;
1139 char *nonarg = NULL;
1140 int single = 0, anum = 1, xnum, nopts, ndopts, nodopts, flags = 0;
1141 int state = 0, not = 0;
1143 nopts = ndopts = nodopts = 0;
1145 /* First string is the auto-description definition. */
1147 for (p = args[0]; *p && (p[0] != '%' || p[1] != 'd'); p++);
1149 if (*p) {
1150 *p = '\0';
1151 adpre = dupstring(args[0]);
1152 *p = '%';
1153 adsuf = dupstring(p + 2);
1154 } else
1155 adpre = adsuf = NULL;
1157 /* Now get the -s, -A, -S and -M options. */
1159 args++;
1160 while ((p = *args) && *p == '-' && p[1]) {
1161 for (q = ++p; *q; q++)
1162 if (*q == 'M' || *q == 'A') {
1163 q = "";
1164 break;
1165 } else if (*q != 's' && *q != 'S')
1166 break;
1168 if (*q)
1169 break;
1171 for (; *p; p++) {
1172 if (*p == 's')
1173 single = 1;
1174 else if (*p == 'S')
1175 flags |= CDF_SEP;
1176 else if (*p == 'A') {
1177 if (p[1]) {
1178 nonarg = p + 1;
1179 p = "" - 1;
1180 } else if (args[1])
1181 nonarg = *++args;
1182 else
1183 break;
1184 } else if (*p == 'M') {
1185 if (p[1]) {
1186 match = p + 1;
1187 p = "" - 1;
1188 } else if (args[1])
1189 match = *++args;
1190 else
1191 break;
1194 if (*p)
1195 break;
1197 args++;
1199 if (*args && !strcmp(*args, ":"))
1200 args++;
1201 if (!*args)
1202 return NULL;
1204 if (nonarg)
1205 tokenize(nonarg = dupstring(nonarg));
1207 /* Looks good. Optimistically allocate the cadef structure. */
1209 all = ret = alloc_cadef(orig_args, single, match, nonarg, flags);
1210 optp = &(ret->opts);
1211 anum = 1;
1213 sargs = args;
1215 /* Get the definitions. */
1217 for (; *args; args++) {
1218 if (args[0][0] == '-' && !args[0][1] && args[1]) {
1219 if (!state) {
1220 char *p;
1221 int l;
1223 if (setp)
1224 args = setp;
1225 p = *++args;
1226 l = strlen(p) - 1;
1227 if (*p == '(' && p[l] == ')') {
1228 axor = p = dupstring(p + 1);
1229 p[l - 1] = '\0';
1230 } else
1231 axor = NULL;
1232 ret->set = doset = tricat(p, "-", "");
1233 ret->sname = ztrdup(p);
1234 state = 1;
1235 } else {
1236 setp = args;
1237 state = 0;
1238 args = sargs - 1;
1239 doset = NULL;
1240 ret->nopts = nopts;
1241 ret->ndopts = ndopts;
1242 ret->nodopts = nodopts;
1243 set_cadef_opts(ret);
1244 ret = ret->snext = alloc_cadef(NULL, single, NULL, nonarg, flags);
1245 optp = &(ret->opts);
1246 nopts = ndopts = nodopts = 0;
1247 anum = 1;
1249 continue;
1251 p = dupstring(*args);
1252 xnum = 0;
1253 if ((not = (*p == '!')))
1254 p++;
1255 if (*p == '(') {
1256 /* There is a xor list, get it. */
1258 LinkList list = newlinklist();
1259 LinkNode node;
1260 char **xp, sav;
1262 while (*p && *p != ')') {
1263 for (p++; inblank(*p); p++);
1265 if (*p == ')')
1266 break;
1267 for (q = p++; *p && *p != ')' && !inblank(*p); p++);
1269 if (!*p)
1270 break;
1272 sav = *p;
1273 *p = '\0';
1274 addlinknode(list, dupstring(q));
1275 xnum++;
1276 *p = sav;
1278 /* Oops, end-of-string. */
1279 if (*p != ')') {
1280 freecadef(all);
1281 zwarnnam(nam, "invalid argument: %s", *args);
1282 return NULL;
1284 if (doset && axor)
1285 xnum++;
1286 xor = (char **) zalloc((xnum + 2) * sizeof(char *));
1287 for (node = firstnode(list), xp = xor; node; incnode(node), xp++)
1288 *xp = ztrdup((char *) getdata(node));
1289 if (doset && axor)
1290 *xp++ = ztrdup(axor);
1291 xp[0] = xp[1] = NULL;
1293 p++;
1294 } else if (doset && axor) {
1295 xnum = 1;
1296 xor = (char **) zalloc(3 * sizeof(char *));
1297 xor[0] = ztrdup(axor);
1298 xor[1] = xor[2] = NULL;
1299 } else
1300 xor = NULL;
1302 if (*p == '-' || *p == '+' ||
1303 (*p == '*' && (p[1] == '-' || p[1] == '+'))) {
1304 /* It's an option. */
1305 Caopt opt;
1306 Caarg oargs = NULL;
1307 int multi, otype = CAO_NEXT, again = 0;
1308 char *name, *descr, c, *againp = NULL;
1310 rec:
1312 /* Allowed more than once? */
1313 if ((multi = (*p == '*')))
1314 p++;
1316 if (((p[0] == '-' && p[1] == '+') ||
1317 (p[0] == '+' && p[1] == '-')) &&
1318 p[2] && p[2] != ':' && p[2] != '[' &&
1319 p[2] != '=' && p[2] != '-' && p[2] != '+') {
1320 /* It's a -+ or +- definition. We just execute the whole
1321 * stuff twice for such things. */
1322 againp = dupstring(p);
1323 name = ++p;
1324 *p = (again ? '-' : '+');
1325 again++;
1326 } else {
1327 name = p;
1328 /* If it's a long option skip over the first `-'. */
1329 if (p[0] == '-' && p[1] == '-')
1330 p++;
1332 if (!p[1]) {
1333 freecadef(all);
1334 zwarnnam(nam, "invalid argument: %s", *args);
1335 return NULL;
1338 /* Skip over the name. */
1339 for (p++; *p && *p != ':' && *p != '[' &&
1340 ((*p != '-' && *p != '+') ||
1341 (p[1] != ':' && p[1] != '[')) &&
1342 (*p != '=' ||
1343 (p[1] != ':' && p[1] != '[' && p[1] != '-')); p++)
1344 if (*p == '\\' && p[1])
1345 p++;
1347 /* The character after the option name specifies the type. */
1348 c = *p;
1349 *p = '\0';
1350 if (c == '-') {
1351 otype = CAO_DIRECT;
1352 c = *++p;
1353 } else if (c == '+') {
1354 otype = CAO_ODIRECT;
1355 c = *++p;
1356 } else if (c == '=') {
1357 otype = CAO_OEQUAL;
1358 if ((c = *++p) == '-') {
1359 otype = CAO_EQUAL;
1360 c = *++p;
1363 /* Get the optional description, if any. */
1364 if (c == '[') {
1365 for (descr = ++p; *p && *p != ']'; p++)
1366 if (*p == '\\' && p[1])
1367 p++;
1369 if (!*p) {
1370 freecadef(all);
1371 zwarnnam(nam, "invalid option definition: %s", *args);
1372 return NULL;
1374 *p++ = '\0';
1375 c = *p;
1376 } else
1377 descr = NULL;
1379 if (c && c != ':') {
1380 freecadef(all);
1381 zwarnnam(nam, "invalid option definition: %s", *args);
1382 return NULL;
1384 /* Add the option name to the xor list if not `*-...'. */
1385 if (!multi) {
1386 if (!xor) {
1387 xor = (char **) zalloc(2 * sizeof(char *));
1388 xor[0] = xor[1] = NULL;
1390 zsfree(xor[xnum]);
1391 xor[xnum] = ztrdup(rembslashcolon(name));
1393 if (c == ':') {
1394 /* There's at least one argument. */
1396 Caarg *oargp = &oargs;
1397 int atype, rest, oanum = 1, onum = 0;
1398 char *end;
1400 /* Loop over the arguments. */
1402 while (c == ':') {
1403 rest = 0;
1404 end = NULL;
1406 /* Get the argument type. */
1407 if (*++p == ':') {
1408 atype = CAA_OPT;
1409 p++;
1410 } else if (*p == '*') {
1411 if (*++p != ':') {
1412 char sav;
1414 for (end = p++; *p && *p != ':'; p++)
1415 if (*p == '\\' && p[1])
1416 p++;
1417 sav = *p;
1418 *p = '\0';
1419 end = dupstring(end);
1420 tokenize(end);
1421 *p = sav;
1423 if (*p != ':') {
1424 freecadef(all);
1425 freecaargs(oargs);
1426 zwarnnam(nam, "invalid option definition: %s",
1427 *args);
1428 return NULL;
1430 if (*++p == ':') {
1431 if (*++p == ':') {
1432 atype = CAA_RREST;
1433 p++;
1434 } else
1435 atype = CAA_RARGS;
1436 } else
1437 atype = CAA_REST;
1438 rest = 1;
1439 } else
1440 atype = CAA_NORMAL;
1442 /* And the definition. */
1444 *oargp = parse_caarg(!rest, atype, oanum++, onum,
1445 name, &p, doset);
1446 if (atype == CAA_OPT)
1447 onum++;
1448 if (end)
1449 (*oargp)->end = ztrdup(end);
1450 oargp = &((*oargp)->next);
1451 if (rest)
1452 break;
1453 c = *p;
1456 /* Store the option definition. */
1458 *optp = opt = (Caopt) zalloc(sizeof(*opt));
1459 optp = &((*optp)->next);
1461 opt->next = NULL;
1462 opt->set = doset;
1463 opt->name = ztrdup(rembslashcolon(name));
1464 if (descr)
1465 opt->descr = ztrdup(descr);
1466 else if (adpre && oargs && !oargs->next) {
1467 char *d;
1469 for (d = oargs->descr; *d; d++)
1470 if (!iblank(*d))
1471 break;
1473 if (*d)
1474 opt->descr = tricat(adpre, oargs->descr, adsuf);
1475 else
1476 opt->descr = NULL;
1477 } else
1478 opt->descr = NULL;
1479 opt->xor = (again == 1 && xor ? zarrdup(xor) : xor);
1480 opt->type = otype;
1481 opt->args = oargs;
1482 opt->num = nopts++;
1483 opt->not = not;
1485 if (otype == CAO_DIRECT || otype == CAO_EQUAL)
1486 ndopts++;
1487 else if (otype == CAO_ODIRECT || otype == CAO_OEQUAL)
1488 nodopts++;
1490 /* If this is for single-letter option we also store a
1491 * pointer for the definition in the array for fast lookup. */
1493 if (single && name[1] && !name[2])
1494 ret->single[STOUC(name[1])] = opt;
1496 if (again == 1) {
1497 /* Do it all again for `*-...'. */
1498 p = againp;
1499 goto rec;
1501 } else if (*p == '*') {
1502 /* It's a rest-argument definition. */
1504 int type = CAA_REST;
1506 if (not)
1507 continue;
1509 if (*++p != ':') {
1510 freecadef(all);
1511 zwarnnam(nam, "invalid rest argument definition: %s", *args);
1512 return NULL;
1514 if (ret->rest) {
1515 freecadef(all);
1516 zwarnnam(nam, "doubled rest argument definition: %s", *args);
1517 return NULL;
1519 if (*++p == ':') {
1520 if (*++p == ':') {
1521 type = CAA_RREST;
1522 p++;
1523 } else
1524 type = CAA_RARGS;
1526 ret->rest = parse_caarg(0, type, -1, 0, NULL, &p, doset);
1527 ret->rest->xor = xor;
1528 } else {
1529 /* It's a normal argument definition. */
1531 int type = CAA_NORMAL, direct;
1532 Caarg arg, tmp, pre;
1534 if (not)
1535 continue;
1537 if ((direct = idigit(*p))) {
1538 /* Argment number is given. */
1539 int num = 0;
1541 while (*p && idigit(*p))
1542 num = (num * 10) + (((int) *p++) - '0');
1544 anum = num + 1;
1545 } else
1546 /* Default number. */
1547 anum++;
1549 if (*p != ':') {
1550 freecadef(all);
1551 zwarnnam(nam, "invalid argument: %s", *args);
1552 if (xor)
1553 free(xor);
1554 return NULL;
1556 if (*++p == ':') {
1557 /* Optional argument. */
1558 type = CAA_OPT;
1559 p++;
1561 arg = parse_caarg(0, type, anum - 1, 0, NULL, &p, doset);
1562 arg->xor = xor;
1563 arg->direct = direct;
1565 /* Sort the new definition into the existing list. */
1567 for (tmp = ret->args, pre = NULL;
1568 tmp && tmp->num < anum - 1;
1569 pre = tmp, tmp = tmp->next);
1571 if (tmp && tmp->num == anum - 1) {
1572 freecadef(all);
1573 freecaargs(arg);
1574 zwarnnam(nam, "doubled argument definition: %s", *args);
1575 return NULL;
1577 arg->next = tmp;
1578 if (pre)
1579 pre->next = arg;
1580 else
1581 ret->args = arg;
1584 ret->nopts = nopts;
1585 ret->ndopts = ndopts;
1586 ret->nodopts = nodopts;
1587 set_cadef_opts(ret);
1589 return all;
1592 /* Given an array of definitions, return the cadef for it. From the cache
1593 * are newly built. */
1595 static Cadef
1596 get_cadef(char *nam, char **args)
1598 Cadef *p, *min, new;
1599 int i, na = arrlen(args);
1601 for (i = MAX_CACACHE, p = cadef_cache, min = NULL; i && *p; p++, i--)
1602 if (*p && na == (*p)->ndefs && arrcmp(args, (*p)->defs)) {
1603 (*p)->lastt = time(0);
1605 return *p;
1606 } else if (!min || !*p || (*p)->lastt < (*min)->lastt)
1607 min = p;
1608 if (i)
1609 min = p;
1610 if ((new = parse_cadef(nam, args))) {
1611 freecadef(*min);
1612 *min = new;
1614 return new;
1618 * Get the option used in a word from the line, if any.
1620 * "d" is a complete set of argument/option definitions to scan.
1621 * "line" is the word we are scanning.
1622 * "full" indicates that the option must match a full word; otherwise
1623 * we look for "=" arguments or prefixes.
1624 * *"end" is set to point to the end of the option, in some cases
1625 * leaving an option argument after it.
1628 static Caopt
1629 ca_get_opt(Cadef d, char *line, int full, char **end)
1631 Caopt p;
1633 /* The full string may be an option. */
1635 for (p = d->opts; p; p = p->next)
1636 if (p->active && !strcmp(p->name, line)) {
1637 if (end)
1638 *end = line + strlen(line);
1640 return p;
1643 if (!full) {
1644 /* The string from the line probably only begins with an option. */
1645 for (p = d->opts; p; p = p->next)
1646 if (p->active && ((!p->args || p->type == CAO_NEXT) ?
1647 !strcmp(p->name, line) : strpfx(p->name, line))) {
1648 if (end) {
1649 /* Return a pointer to the end of the option. */
1650 int l = strlen(p->name);
1652 if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) &&
1653 line[l] == '=')
1654 l++;
1656 *end = line + l;
1658 return p;
1661 return NULL;
1664 /* Same as above, only for single-letter-style. */
1666 static Caopt
1667 ca_get_sopt(Cadef d, char *line, char **end, LinkList *lp)
1669 Caopt p, pp = NULL;
1670 char pre = *line++;
1671 LinkList l = NULL;
1673 *lp = NULL;
1674 for (p = NULL; *line; line++) {
1675 if ((p = d->single[STOUC(*line)]) && p->active &&
1676 p->args && p->name[0] == pre) {
1677 if (p->type == CAO_NEXT) {
1678 if (!l)
1679 *lp = l = newlinklist();
1680 addlinknode(l, p);
1681 } else {
1682 if (end) {
1683 line++;
1684 if ((p->type == CAO_OEQUAL || p->type == CAO_EQUAL) &&
1685 *line == '=')
1686 line++;
1687 *end = line;
1689 pp = p;
1690 break;
1692 } else if (!p || (p && !p->active))
1693 return NULL;
1694 pp = (p->name[0] == pre ? p : NULL);
1695 p = NULL;
1697 if (pp && end)
1698 *end = line;
1699 return pp;
1702 /* Return the n'th argument definition. */
1704 static Caarg
1705 ca_get_arg(Cadef d, int n)
1707 if (d->argsactive) {
1708 Caarg a = d->args;
1710 while (a && (!a->active || n < a->min || n > a->num)) {
1711 if (!a->active)
1712 n++;
1713 a = a->next;
1715 if (a && a->min <= n && a->num >= n && a->active)
1716 return a;
1718 return (d->rest && d->rest->active ? d->rest : NULL);
1720 return NULL;
1723 /* Use a xor list, marking options as inactive. */
1725 static LinkList ca_xor;
1727 static int
1728 ca_inactive(Cadef d, char **xor, int cur, int opts, char *optname)
1730 if ((xor || opts) && cur <= compcurrent) {
1731 Caopt opt;
1732 char *x;
1733 int sl = (d->set ? (int)strlen(d->set) : -1), set = 0;
1735 for (; (x = (opts ? "-" : *xor)); xor++) {
1736 if (optname && optname[0] == x[0] && strcmp(optname, x))
1737 continue;
1738 if (ca_xor)
1739 addlinknode(ca_xor, x);
1740 set = 0;
1741 if (sl > 0) {
1742 if (strpfx(d->set, x)) {
1743 x += sl;
1744 set = 1;
1745 } else if (!strncmp(d->set, x, sl - 1)) {
1746 Caopt p;
1748 for (p = d->opts; p; p = p->next)
1749 if (p->set)
1750 p->active = 0;
1752 x = ":";
1753 set = 1;
1756 if (x[0] == ':' && !x[1]) {
1757 if (set) {
1758 Caarg a;
1760 for (a = d->args; a; a = a->next)
1761 if (a->set)
1762 a->active = 0;
1763 if (d->rest && (!set || d->rest->set))
1764 d->rest->active = 0;
1765 } else
1766 d->argsactive = 0;
1767 } else if (x[0] == '-' && !x[1]) {
1768 Caopt p;
1770 for (p = d->opts; p; p = p->next)
1771 if (!set || p->set)
1772 p->active = 0;
1773 } else if (x[0] == '*' && !x[1]) {
1774 if (d->rest && (!set || d->rest->set))
1775 d->rest->active = 0;
1776 } else if (idigit(x[0])) {
1777 int n = atoi(x);
1778 Caarg a = d->args;
1780 while (a && a->num < n)
1781 a = a->next;
1783 if (a && a->num == n && (!set || a->set))
1784 a->active = 0;
1785 } else if ((opt = ca_get_opt(d, x, 1, NULL)) && (!set || opt->set))
1786 opt->active = 0;
1788 if (opts)
1789 break;
1792 return 0;
1795 /* State when parsing a command line. */
1797 typedef struct castate *Castate;
1800 * **** DOCUMENT ME ****
1802 * This structure and its use are a nightmare.
1805 struct castate {
1806 Castate snext;
1807 Cadef d;
1808 int nopts;
1809 Caarg def, ddef;
1810 Caopt curopt, dopt;
1811 int opt, arg, argbeg, optbeg, nargbeg, restbeg, curpos, argend;
1812 int inopt, inrest, inarg, nth, doff, singles, oopt, actopts;
1813 LinkList args;
1814 LinkList *oargs;
1817 static struct castate ca_laststate;
1818 static int ca_parsed = 0, ca_alloced = 0;
1820 static void
1821 freecastate(Castate s)
1823 int i;
1824 LinkList *p;
1826 freelinklist(s->args, freestr);
1827 for (i = s->nopts, p = s->oargs; i--; p++)
1828 if (*p)
1829 freelinklist(*p, freestr);
1830 zfree(s->oargs, s->d->nopts * sizeof(LinkList));
1833 /* Return a copy of an option's argument, ignoring possible quoting
1834 * in the option name. */
1836 static char *
1837 ca_opt_arg(Caopt opt, char *line)
1839 char *o = opt->name;
1841 while (1) {
1842 if (*o == '\\')
1843 o++;
1844 if (*line == '\\' || *line == '\'' || *line == '"')
1845 line++;
1846 if (!*o || *o != *line)
1847 break;
1848 o++;
1849 line++;
1851 if (*line && (opt->type == CAO_EQUAL || opt->type == CAO_OEQUAL)) {
1852 if (*line == '\\')
1853 line++;
1854 if (*line == '=')
1855 line++;
1857 return ztrdup(line);
1860 /* Parse a command line. */
1862 static int
1863 ca_parse_line(Cadef d, int multi, int first)
1865 Caarg adef, ddef;
1866 Caopt ptr, wasopt = NULL, dopt;
1867 struct castate state;
1868 char *line, *oline, *pe, **argxor = NULL;
1869 int cur, doff, argend, arglast, ne;
1870 Patprog endpat = NULL, napat = NULL;
1871 LinkList sopts = NULL;
1873 /* Free old state. */
1875 if (first && ca_alloced) {
1876 Castate s = &ca_laststate, ss;
1878 while (s) {
1879 ss = s->snext;
1880 freecastate(s);
1881 s = ss;
1884 /* Mark everything as active. */
1886 for (ptr = d->opts; ptr; ptr = ptr->next)
1887 ptr->active = 1;
1888 d->argsactive = 1;
1889 if (d->rest)
1890 d->rest->active = 1;
1891 for (adef = d->args; adef; adef = adef->next)
1892 adef->active = 1;
1894 /* Default values for the state. */
1896 state.snext = NULL;
1897 state.d = d;
1898 state.nopts = d->nopts;
1899 state.def = state.ddef = NULL;
1900 state.curopt = state.dopt = NULL;
1901 state.argbeg = state.optbeg = state.nargbeg = state.restbeg = state.actopts =
1902 state.nth = state.inopt = state.inarg = state.opt = state.arg = 1;
1903 state.argend = argend = arrlen(compwords) - 1;
1904 state.inrest = state.doff = state.singles = state.doff = state.oopt = 0;
1905 state.curpos = compcurrent;
1906 state.args = znewlinklist();
1907 state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
1908 memset(state.oargs, 0, d->nopts * sizeof(LinkList));
1910 ca_alloced = 1;
1912 memcpy(&ca_laststate, &state, sizeof(state));
1914 if (!compwords[1]) {
1915 ca_laststate.opt = ca_laststate.arg = 0;
1917 goto end;
1919 if (d->nonarg)
1920 napat = patcompile(d->nonarg, 0, NULL);
1922 /* Loop over the words from the line. */
1924 for (line = compwords[1], cur = 2, state.curopt = NULL, state.def = NULL;
1925 line; line = compwords[cur++]) {
1926 ddef = adef = NULL;
1927 dopt = NULL;
1928 doff = state.singles = arglast = 0;
1930 /* remove quotes */
1931 oline = line;
1932 line = dupstring(line);
1933 ne = noerrs;
1934 noerrs = 2;
1935 parse_subst_string(line);
1936 noerrs = ne;
1937 remnulargs(line);
1938 untokenize(line);
1940 if (ca_inactive(d, argxor, cur, 0, NULL) ||
1941 ((d->flags & CDF_SEP) && cur != compcurrent && !strcmp(line, "--"))) {
1942 if (ca_inactive(d, NULL, cur, 1, NULL))
1943 return 1;
1944 continue;
1946 /* We've got a definition for an argument, skip to the next. */
1948 if (state.def) {
1949 state.arg = 0;
1950 if (state.curopt)
1951 zaddlinknode(state.oargs[state.curopt->num], ztrdup(oline));
1953 if ((state.opt = (state.def->type == CAA_OPT)) && state.def->opt)
1954 state.oopt++;
1956 if (state.def->type == CAA_REST || state.def->type == CAA_RARGS ||
1957 state.def->type == CAA_RREST) {
1958 if (state.def->end && pattry(endpat, line)) {
1959 state.def = NULL;
1960 state.curopt = NULL;
1961 state.opt = state.arg = 1;
1962 state.argend = ca_laststate.argend = cur - 1;
1963 goto cont;
1965 } else if ((state.def = state.def->next)) {
1966 state.argbeg = cur;
1967 state.argend = argend;
1968 } else if (sopts && nonempty(sopts)) {
1969 state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
1970 state.def = state.curopt->args;
1971 state.opt = 0;
1972 state.argbeg = state.optbeg = state.inopt = cur;
1973 state.argend = argend;
1974 doff = state.doff = 0;
1975 state.singles = 1;
1976 if (!state.oargs[state.curopt->num])
1977 state.oargs[state.curopt->num] = znewlinklist();
1978 goto cont;
1979 } else {
1980 state.curopt = NULL;
1981 state.opt = 1;
1983 } else {
1984 state.opt = state.arg = 1;
1985 state.curopt = NULL;
1987 if (state.opt)
1988 state.opt = (line[0] ? (line[1] ? 2 : 1) : 0);
1990 pe = NULL;
1992 wasopt = NULL;
1994 /* See if it's an option. */
1996 if (state.opt == 2 && (state.curopt = ca_get_opt(d, line, 0, &pe)) &&
1997 (state.curopt->type == CAO_OEQUAL ?
1998 (compwords[cur] || pe[-1] == '=') :
1999 (state.curopt->type == CAO_EQUAL ?
2000 (pe[-1] == '=' || !pe[0]) : 1))) {
2002 if ((ddef = state.def = ((state.curopt->type != CAO_EQUAL ||
2003 pe[-1] == '=') ?
2004 state.curopt->args : NULL)))
2005 dopt = state.curopt;
2007 doff = pe - line;
2008 state.optbeg = state.argbeg = state.inopt = cur;
2009 state.argend = argend;
2010 state.singles = (d->single && (!pe || !*pe) &&
2011 state.curopt->name[1] && !state.curopt->name[2]);
2013 if (!state.oargs[state.curopt->num])
2014 state.oargs[state.curopt->num] = znewlinklist();
2016 if (ca_inactive(d, state.curopt->xor, cur, 0,
2017 (cur == compcurrent ? state.curopt->name : NULL)))
2018 return 1;
2020 /* Collect the argument strings. Maybe. */
2022 if (state.def &&
2023 (state.curopt->type == CAO_DIRECT ||
2024 state.curopt->type == CAO_EQUAL ||
2025 (state.curopt->type == CAO_ODIRECT && pe[0]) ||
2026 (state.curopt->type == CAO_OEQUAL &&
2027 (pe[0] || pe[-1] == '=')))) {
2028 if (state.def->type != CAA_REST &&
2029 state.def->type != CAA_RARGS &&
2030 state.def->type != CAA_RREST)
2031 state.def = state.def->next;
2033 zaddlinknode(state.oargs[state.curopt->num],
2034 ca_opt_arg(state.curopt, oline));
2036 if (state.def)
2037 state.opt = 0;
2038 else {
2039 if (!d->single || (state.curopt->name[1] && state.curopt->name[2]))
2040 wasopt = state.curopt;
2041 state.curopt = NULL;
2043 } else if (state.opt == 2 && d->single &&
2044 ((state.curopt = ca_get_sopt(d, line, &pe, &sopts)) ||
2045 (cur != compcurrent && sopts && nonempty(sopts)))) {
2046 /* Or maybe it's a single-letter option? */
2048 char *p;
2049 Caopt tmpopt;
2051 if (cur != compcurrent && sopts && nonempty(sopts))
2052 state.curopt = (Caopt) uremnode(sopts, firstnode(sopts));
2054 if (!state.oargs[state.curopt->num])
2055 state.oargs[state.curopt->num] = znewlinklist();
2057 state.def = state.curopt->args;
2058 ddef = (state.curopt->type == CAO_NEXT && cur == compcurrent ?
2059 NULL : state.def);
2060 dopt = state.curopt;
2061 doff = pe - line;
2062 state.optbeg = state.argbeg = state.inopt = cur;
2063 state.argend = argend;
2064 state.singles = (!pe || !*pe);
2066 for (p = line + 1; p < pe; p++) {
2067 if ((tmpopt = d->single[STOUC(*p)])) {
2068 if (!state.oargs[tmpopt->num])
2069 state.oargs[tmpopt->num] = znewlinklist();
2071 if (ca_inactive(d, tmpopt->xor, cur, 0,
2072 (cur == compcurrent ? tmpopt->name : NULL)))
2073 return 1;
2076 if (state.def &&
2077 (state.curopt->type == CAO_DIRECT ||
2078 state.curopt->type == CAO_EQUAL ||
2079 (state.curopt->type == CAO_ODIRECT && pe[0]) ||
2080 (state.curopt->type == CAO_OEQUAL &&
2081 (pe[0] || pe[-1] == '=')))) {
2082 if (state.def->type != CAA_REST &&
2083 state.def->type != CAA_RARGS &&
2084 state.def->type != CAA_RREST)
2085 state.def = state.def->next;
2087 zaddlinknode(state.oargs[state.curopt->num],
2088 ca_opt_arg(state.curopt, line));
2090 if (state.def)
2091 state.opt = 0;
2092 else
2093 state.curopt = NULL;
2094 } else if (multi && (*line == '-' || *line == '+') && cur != compcurrent
2095 #if 0
2096 /**** Ouch. Using this will disable the mutual exclusion
2097 of different sets. Not using it will make the -A
2098 pattern be effectively ignored with multiple sets. */
2099 && (!napat || !pattry(napat, line))
2100 #endif
2102 return 1;
2103 else if (state.arg && (!napat || !pattry(napat, line))) {
2104 /* Otherwise it's a normal argument. */
2105 if (napat && ca_inactive(d, NULL, cur + 1, 1, NULL))
2106 return 1;
2108 arglast = 1;
2109 if (state.inopt) {
2110 state.inopt = 0;
2111 state.nargbeg = cur - 1;
2112 state.argend = argend;
2114 if (!d->args && !d->rest && *line && *line != '-' && *line != '+') {
2115 if (!multi && cur > compcurrent)
2116 break;
2117 return 1;
2119 if ((adef = state.def = ca_get_arg(d, state.nth)) &&
2120 (state.def->type == CAA_RREST ||
2121 state.def->type == CAA_RARGS)) {
2122 state.inrest = 0;
2123 state.opt = (cur == state.nargbeg + 1 &&
2124 (!multi || !*line ||
2125 *line == '-' || *line == '+'));
2126 state.optbeg = state.nargbeg;
2127 state.argbeg = cur - 1;
2128 state.argend = argend;
2130 for (; line; line = compwords[cur++])
2131 zaddlinknode(state.args, ztrdup(line));
2133 memcpy(&ca_laststate, &state, sizeof(state));
2134 ca_laststate.ddef = NULL;
2135 ca_laststate.dopt = NULL;
2136 ca_laststate.doff = 0;
2137 break;
2139 zaddlinknode(state.args, ztrdup(line));
2140 if (adef)
2141 state.oopt = adef->num - state.nth;
2143 if (state.def)
2144 argxor = state.def->xor;
2146 if (state.def && state.def->type != CAA_NORMAL &&
2147 state.def->type != CAA_OPT && state.inarg) {
2148 state.restbeg = cur;
2149 state.inarg = 0;
2150 } else if (!state.def || state.def->type == CAA_NORMAL ||
2151 state.def->type == CAA_OPT)
2152 state.inarg = 1;
2153 state.nth++;
2154 state.def = NULL;
2156 /* Do the end-pattern test if needed. */
2158 if (state.def && state.curopt &&
2159 (state.def->type == CAA_RREST || state.def->type == CAA_RARGS)) {
2160 if (state.def->end)
2161 endpat = patcompile(state.def->end, 0, NULL);
2162 else {
2163 LinkList l = state.oargs[state.curopt->num];
2165 if (cur < compcurrent)
2166 memcpy(&ca_laststate, &state, sizeof(state));
2168 for (; line; line = compwords[cur++])
2169 zaddlinknode(l, ztrdup(line));
2171 ca_laststate.ddef = NULL;
2172 ca_laststate.dopt = NULL;
2173 ca_laststate.doff = 0;
2174 break;
2176 } else if (state.def && state.def->end)
2177 endpat = patcompile(state.def->end, 0, NULL);
2179 /* Copy the state into the global one. */
2181 cont:
2183 if (cur + 1 == compcurrent) {
2184 memcpy(&ca_laststate, &state, sizeof(state));
2185 ca_laststate.ddef = NULL;
2186 ca_laststate.dopt = NULL;
2187 ca_laststate.doff = 0;
2188 } else if (cur == compcurrent && !ca_laststate.def) {
2189 if ((ca_laststate.def = ddef)) {
2190 ca_laststate.singles = state.singles;
2191 if (state.curopt && state.curopt->type == CAO_NEXT) {
2192 ca_laststate.ddef = ddef;
2193 ca_laststate.dopt = dopt;
2194 ca_laststate.def = NULL;
2195 ca_laststate.opt = 1;
2196 state.curopt->active = 1;
2197 } else {
2198 ca_laststate.doff = doff;
2199 ca_laststate.opt = 0;
2201 } else {
2202 ca_laststate.def = adef;
2203 ca_laststate.opt = (!arglast || !multi || !*line ||
2204 *line == '-' || *line == '+');
2205 ca_laststate.ddef = NULL;
2206 ca_laststate.dopt = NULL;
2207 ca_laststate.optbeg = state.nargbeg;
2208 ca_laststate.argbeg = state.restbeg;
2209 ca_laststate.argend = state.argend;
2210 ca_laststate.singles = state.singles;
2211 ca_laststate.oopt = state.oopt;
2212 if (wasopt)
2213 wasopt->active = 1;
2217 end:
2219 ca_laststate.actopts = 0;
2220 for (ptr = d->opts; ptr; ptr = ptr->next)
2221 if (ptr->active)
2222 ca_laststate.actopts++;
2224 return 0;
2227 /* Build a colon-list from a list. */
2229 static char *
2230 ca_colonlist(LinkList l)
2232 if (l) {
2233 LinkNode n;
2234 int len = 0;
2235 char *p, *ret, *q;
2237 for (n = firstnode(l); n; incnode(n)) {
2238 len++;
2239 for (p = (char *) getdata(n); *p; p++)
2240 len += (*p == ':' ? 2 : 1);
2242 ret = q = (char *) zalloc(len);
2244 for (n = firstnode(l); n;) {
2245 for (p = (char *) getdata(n); *p; p++) {
2246 if (*p == ':')
2247 *q++ = '\\';
2248 *q++ = *p;
2250 incnode(n);
2251 if (n)
2252 *q++ = ':';
2254 *q = '\0';
2256 return ret;
2257 } else
2258 return ztrdup("");
2262 * This function adds the current set of descriptions, actions,
2263 * and subcontext descriptions to the given linked list for passing
2264 * up in comparguments -D and comparguments -L. opt is the
2265 * option string (may be NULL if this isn't an option argument) and arg the
2266 * argument structure (either an option argument or a normal argument
2267 * as determined by arg->type).
2270 static void
2271 ca_set_data(LinkList descr, LinkList act, LinkList subc,
2272 char *opt, Caarg arg, Caopt optdef, int single)
2274 LinkNode dnode, anode;
2275 char nbuf[40], *buf;
2276 int restr = 0, onum, miss = 0, rest, oopt = 1, lopt = 0, addopt;
2278 rec:
2280 addopt = (opt ? 0 : ca_laststate.oopt);
2282 for (; arg && (opt || (arg->num < 0 ||
2283 (arg->min <= ca_laststate.nth + addopt &&
2284 arg->num >= ca_laststate.nth)));) {
2285 lopt = (arg->type == CAA_OPT);
2286 if (!opt && !lopt && oopt > 0)
2287 oopt = 0;
2289 for (dnode = firstnode(descr), anode = firstnode(act);
2290 dnode; incnode(dnode), incnode(anode))
2291 if (!strcmp((char *) getdata(dnode), arg->descr) &&
2292 !strcmp((char *) getdata(anode), arg->action))
2293 break;
2295 if (!dnode) {
2296 addlinknode(descr, arg->descr);
2297 addlinknode(act, arg->action);
2299 if (!restr) {
2300 if ((restr = (arg->type == CAA_RARGS)))
2301 restrict_range(ca_laststate.optbeg, ca_laststate.argend);
2302 else if ((restr = (arg->type == CAA_RREST)))
2303 restrict_range(ca_laststate.argbeg, ca_laststate.argend);
2305 if (arg->opt) {
2306 buf = (char *) zhalloc((arg->set ? strlen(arg->set) : 0) +
2307 strlen(arg->opt) + 40);
2308 if (arg->num > 0 && arg->type < CAA_REST)
2309 sprintf(buf, "%soption%s-%d",
2310 (arg->set ? arg->set : ""), arg->opt, arg->num);
2311 else
2312 sprintf(buf, "%soption%s-rest",
2313 (arg->set ? arg->set : ""), arg->opt);
2314 } else if (arg->num > 0) {
2315 sprintf(nbuf, "argument-%d", arg->num);
2316 buf = (arg->set ? dyncat(arg->set, nbuf) : dupstring(nbuf));
2317 } else
2318 buf = (arg->set ? dyncat(arg->set, "argument-rest") :
2319 dupstring("argument-rest"));
2321 addlinknode(subc, buf);
2324 * If this is an argument to an option, and the option definition says
2325 * the argument to the option is required and in the following
2326 * (i.e. this) word, then it must match what we've just told it to
2327 * match---don't try to match normal arguments.
2329 * This test may be too stringent for what we need, or it
2330 * may be too loose; I've simply tweaked it until it gets
2331 * the case above right.
2333 if (arg->type == CAA_NORMAL &&
2334 opt && optdef && optdef->type == CAO_NEXT)
2335 return;
2336 if (single)
2337 break;
2339 if (!opt) {
2340 if (arg->num >= 0 && !arg->next && miss)
2341 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ?
2342 ca_laststate.d->rest : NULL);
2343 else {
2344 onum = arg->num;
2345 rest = (onum != arg->min && onum == ca_laststate.nth);
2346 if ((arg = arg->next)) {
2347 if (arg->num != onum + 1)
2348 miss = 1;
2349 } else if (rest || (oopt > 0 && !opt)) {
2350 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ?
2351 ca_laststate.d->rest : NULL);
2352 oopt = -1;
2355 } else {
2356 if (!lopt)
2357 break;
2358 arg = arg->next;
2361 if (!single && opt && (lopt || ca_laststate.oopt)) {
2362 opt = NULL;
2363 arg = ca_get_arg(ca_laststate.d, ca_laststate.nth);
2365 goto rec;
2367 if (!opt && oopt > 0) {
2368 oopt = -1;
2369 arg = (ca_laststate.d->rest && ca_laststate.d->rest->active ?
2370 ca_laststate.d->rest : NULL);
2372 goto rec;
2376 static int
2377 bin_comparguments(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
2379 int min, max, n;
2380 Castate lstate = &ca_laststate;
2382 if (incompfunc != 1) {
2383 zwarnnam(nam, "can only be called from completion function");
2384 return 1;
2386 if (args[0][0] != '-' || !args[0][1] || args[0][2]) {
2387 zwarnnam(nam, "invalid argument: %s", args[0]);
2388 return 1;
2390 if (args[0][1] != 'i' && args[0][1] != 'I' && !ca_parsed) {
2391 zwarnnam(nam, "no parsed state");
2392 return 1;
2394 switch (args[0][1]) {
2395 case 'i': min = 2; max = -1; break;
2396 case 'D': min = 3; max = 3; break;
2397 case 'O': min = 4; max = 4; break;
2398 case 'L': min = 3; max = 4; break;
2399 case 's': min = 1; max = 1; break;
2400 case 'M': min = 1; max = 1; break;
2401 case 'a': min = 0; max = 0; break;
2402 case 'W': min = 2; max = 2; break;
2403 case 'n': min = 1; max = 1; break;
2404 default:
2405 zwarnnam(nam, "invalid option: %s", args[0]);
2406 return 1;
2408 n = arrlen(args) - 1;
2409 if (n < min) {
2410 zwarnnam(nam, "not enough arguments");
2411 return 1;
2412 } else if (max >= 0 && n > max) {
2413 zwarnnam(nam, "too many arguments");
2414 return 1;
2416 switch (args[0][1]) {
2417 case 'i':
2418 /* This initialises the internal data structures. Arguments are the
2419 * auto-description string, the optional -s, -S, -A and -M options
2420 * given to _arguments and the specs. */
2421 if (compcurrent > 1 && compwords[0]) {
2422 Cadef def;
2423 int cap = ca_parsed, multi, first = 1, use, ret = 0;
2424 LinkList cax = ca_xor, nx;
2425 LinkNode node;
2426 Castate states = NULL, sp;
2427 char *xor[2];
2429 ca_parsed = 0;
2430 xor[1] = NULL;
2432 if (!(def = get_cadef(nam, args + 1)))
2433 return 1;
2435 multi = !!def->snext;
2436 ca_parsed = cap;
2437 ca_xor = (multi ? newlinklist() : NULL);
2439 while (def) {
2440 use = !ca_parse_line(def, multi, first);
2441 nx = ca_xor;
2442 ca_xor = NULL;
2443 while ((def = def->snext)) {
2444 if (nx) {
2445 for (node = firstnode(nx); node; incnode(node)) {
2446 xor[0] = (char *) getdata(node);
2447 if (!strcmp(xor[0], def->sname) ||
2448 ca_inactive(def, xor, compcurrent, 0, NULL))
2449 break;
2451 if (!node)
2452 break;
2455 ca_xor = nx;
2456 if (use && def) {
2457 sp = (Castate) zalloc(sizeof(*sp));
2458 memcpy(sp, &ca_laststate, sizeof(*sp));
2459 sp->snext = states;
2460 states = sp;
2461 } else if (!use && !def) {
2462 if (states) {
2463 freecastate(&ca_laststate);
2464 memcpy(&ca_laststate, states, sizeof(*sp));
2465 sp = states->snext;
2466 zfree(states, sizeof(*states));
2467 states = sp;
2468 } else
2469 ret = 1;
2471 first = 0;
2473 ca_xor = cax;
2474 ca_parsed = 1;
2475 ca_laststate.snext = states;
2477 return ret;
2479 return 1;
2481 case 'D':
2482 /* This returns the descriptions, actions and sub-contexts for the
2483 * things _arguments has to execute at this place on the line (the
2484 * sub-contexts are used as tags).
2485 * The return value is particularly important here, it says if
2486 * there are arguments to completely at all. */
2488 LinkList descr, act, subc;
2489 Caarg arg;
2490 int ign = 0, ret = 1;
2492 descr = newlinklist();
2493 act = newlinklist();
2494 subc = newlinklist();
2496 while (lstate) {
2497 arg = lstate->def;
2499 if (arg) {
2500 ret = 0;
2501 if (!ign && lstate->doff > 0) {
2502 ign = 1;
2503 ignore_prefix(lstate->doff);
2505 ca_set_data(descr, act, subc, arg->opt, arg,
2506 lstate->curopt, (lstate->doff > 0));
2508 lstate = lstate->snext;
2510 if (!ret) {
2511 set_list_array(args[1], descr);
2512 set_list_array(args[2], act);
2513 set_list_array(args[3], subc);
2515 return ret;
2517 case 'O':
2518 /* This returns the descriptions for the options in the arrays whose
2519 * names are given as arguments. The descriptions are strings in a
2520 * form usable by _describe. The return value says if there are any
2521 * options to be completed. */
2523 LinkList next = newlinklist();
2524 LinkList direct = newlinklist();
2525 LinkList odirect = newlinklist();
2526 LinkList equal = newlinklist(), l;
2527 LinkNode node;
2528 Caopt p;
2529 char *str;
2530 int ret = 1;
2532 for (; lstate; lstate = lstate->snext) {
2533 if (lstate->actopts &&
2534 (lstate->opt || (lstate->doff && lstate->def) ||
2535 (lstate->def && lstate->def->opt &&
2536 (lstate->def->type == CAA_OPT ||
2537 (lstate->def->type >= CAA_RARGS &&
2538 lstate->def->num < 0)))) &&
2539 (!lstate->def || lstate->def->type < CAA_RARGS ||
2540 (lstate->def->type == CAA_RARGS ?
2541 (lstate->curpos == lstate->argbeg + 1) :
2542 (compcurrent == 1)))) {
2543 ret = 0;
2544 for (p = lstate->d->opts; p; p = p->next) {
2545 if (p->active && !p->not) {
2546 switch (p->type) {
2547 case CAO_NEXT: l = next; break;
2548 case CAO_DIRECT: l = direct; break;
2549 case CAO_ODIRECT: l = odirect; break;
2550 default: l = equal; break;
2552 if (p->descr) {
2553 char *n = bslashcolon(p->name);
2554 int len = strlen(n) + strlen(p->descr) + 2;
2556 str = (char *) zhalloc(len);
2557 strcpy(str, n);
2558 strcat(str, ":");
2559 strcat(str, p->descr);
2560 } else
2561 str = bslashcolon(p->name);
2563 for (node = firstnode(l); node; incnode(node))
2564 if (!strcmp(str, (char *) getdata(node)))
2565 break;
2567 if (!node)
2568 addlinknode(l, str);
2573 if (!ret) {
2574 set_list_array(args[1], next);
2575 set_list_array(args[2], direct);
2576 set_list_array(args[3], odirect);
2577 set_list_array(args[4], equal);
2579 return 0;
2581 return (ca_laststate.singles ? 2 : 1);
2583 case 'L':
2584 /* This tests if the beginning of the current word matches an option.
2585 * It is for cases like `./configure --pre=/<TAB>' which should
2586 * complete to `--prefix=/...'. The options name isn't fully typed
2587 * and _arguments finds out that there is no option `--pre' and that
2588 * it should complete some argument to an option. It then uses -L
2589 * to find the option the argument is for. */
2591 LinkList descr, act, subc;
2592 Caopt opt;
2593 int ret = 1;
2595 descr = newlinklist();
2596 act = newlinklist();
2597 subc = newlinklist();
2599 while (lstate) {
2600 opt = ca_get_opt(lstate->d, args[1], 1, NULL);
2602 if (opt && opt->args) {
2603 ret = 0;
2604 ca_set_data(descr, act, subc, opt->name, opt->args, opt, 1);
2606 lstate = lstate->snext;
2608 if (!ret) {
2609 set_list_array(args[2], descr);
2610 set_list_array(args[3], act);
2611 set_list_array(args[4], subc);
2613 return ret;
2615 case 's':
2616 /* This returns zero if we are completing single letter options.
2617 * It also uses its argument as the name of a parameter and sets
2618 * that to a string describing the argument behaviour of the last
2619 * option in the current word so that we can get the auto-suffix
2620 * right. */
2621 for (; lstate; lstate = lstate->snext)
2622 if (lstate->d->single && lstate->singles &&
2623 lstate->actopts
2624 #if 0
2625 /* let's try without, for the -W option of _arguments */
2626 && lstate->opt
2627 #endif
2629 setsparam(args[1],
2630 ztrdup((lstate->ddef && lstate->dopt) ?
2631 (lstate->dopt->type == CAO_DIRECT ?
2632 "direct" :
2633 ((lstate->dopt->type == CAO_OEQUAL ||
2634 lstate->dopt->type == CAO_EQUAL) ?
2635 "equal" : "next")) : ""));
2636 return 0;
2638 return 1;
2639 case 'M':
2640 /* This returns the match specs defined for the set of specs we are
2641 * using. Returned, as usual in a parameter whose name is given as
2642 * the argument. */
2643 setsparam(args[1], ztrdup(ca_laststate.d->match));
2644 return 0;
2645 case 'a':
2646 /* This just sets the return value. To zero if there would be or
2647 * were any normal arguments to be completed. Used to decide if
2648 * _arguments should say `no arguments' or `no more arguments'. */
2649 for (; lstate; lstate = lstate->snext)
2650 if (lstate->d->args || lstate->d->rest)
2651 return 0;
2652 return 1;
2653 case 'W':
2654 /* This gets two parameter names as arguments. The first is set to
2655 * the current word sans any option prefixes handled by comparguments.
2656 * The second parameter is set to an array containing the options on
2657 * the line and their arguments. I.e. the stuff _arguments returns
2658 * to its caller in the `line' and `opt_args' parameters. */
2660 Castate s;
2661 char **ret, **p;
2662 LinkNode n;
2663 LinkList *a;
2664 Caopt o;
2665 int num;
2667 for (num = 0, s = lstate; s; s = s->snext)
2668 num += countlinknodes(s->args);
2670 ret = p = zalloc((num + 1) * sizeof(char *));
2672 for (s = lstate; s; s = s->snext)
2673 for (n = firstnode(s->args); n; incnode(n))
2674 *p++ = ztrdup((char *) getdata(n));
2675 *p = NULL;
2677 setaparam(args[1], ret);
2679 for (num = 0, s = lstate; s; s = s->snext)
2680 for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
2681 if (*a)
2682 num += 2;
2684 ret = p = zalloc((num + 1) * sizeof(char *));
2686 for (s = lstate; s; s = s->snext)
2687 for (o = s->d->opts, a = s->oargs; o; o = o->next, a++)
2688 if (*a) {
2689 *p++ = (o->set ? tricat(o->set, o->name, "") :
2690 ztrdup(o->name));
2691 *p++ = ca_colonlist(*a);
2693 *p = NULL;
2695 sethparam(args[2], ret);
2697 return 0;
2698 case 'n':
2700 * This returns the array index of the word where normal
2701 * arguments began. It uses optbeg rather than nargbeg
2702 * (the value used when parsing) because nargbeg is assigned
2703 * to optbeg in the returned value and nargbeg isn't
2704 * used.
2706 * -->PLEASE DON'T ASK<--
2708 * Thank you.
2710 setiparam(args[1], (zlong)ca_laststate.optbeg + !isset(KSHARRAYS));
2711 return 0;
2713 return 1;
2716 /* Help for `_values'. */
2718 typedef struct cvdef *Cvdef;
2719 typedef struct cvval *Cvval;
2721 /* Definitions for _values. */
2723 struct cvdef {
2724 char *descr; /* global description */
2725 int hassep; /* multiple values allowed */
2726 char sep; /* separator character */
2727 char argsep; /* argument separator */
2728 Cvdef next; /* next in cache */
2729 Cvval vals; /* value definitions */
2730 char **defs; /* original strings */
2731 int ndefs; /* number of ... */
2732 int lastt; /* last time used */
2733 int words; /* if to look at other words */
2736 /* One value definition. */
2738 struct cvval {
2739 Cvval next;
2740 char *name; /* value name */
2741 char *descr; /* description */
2742 char **xor; /* xor-list */
2743 int type; /* CVV_* below */
2744 Caarg arg; /* argument definition */
2745 int active; /* still allowed */
2748 #define CVV_NOARG 0
2749 #define CVV_ARG 1
2750 #define CVV_OPT 2
2752 /* Cache. */
2754 #define MAX_CVCACHE 8
2755 static Cvdef cvdef_cache[MAX_CVCACHE];
2757 /* Memory stuff. */
2759 static void
2760 freecvdef(Cvdef d)
2762 if (d) {
2763 Cvval p, n;
2765 zsfree(d->descr);
2766 if (d->defs)
2767 freearray(d->defs);
2769 for (p = d->vals; p; p = n) {
2770 n = p->next;
2771 zsfree(p->name);
2772 zsfree(p->descr);
2773 if (p->xor)
2774 freearray(p->xor);
2775 freecaargs(p->arg);
2776 zfree(p, sizeof(*p));
2778 zfree(d, sizeof(*d));
2782 /* Parse option definitions. */
2784 static Cvdef
2785 parse_cvdef(char *nam, char **args)
2787 Cvdef ret;
2788 Cvval val, *valp;
2789 Caarg arg;
2790 char **oargs = args, sep = '\0', asep = '=', *name, *descr, *p, *q, **xor, c;
2791 int xnum, multi, vtype, hassep = 0, words = 0;
2793 while (args && args[0] && args[1] &&
2794 args[0][0] == '-' &&
2795 (args[0][1] == 's' || args[0][1] == 'S' || args[0][1] == 'w') &&
2796 !args[0][2]) {
2798 if (args[0][1] == 's') {
2799 hassep = 1;
2800 sep = args[1][0];
2801 args += 2;
2802 } else if (args[0][1] == 'S') {
2803 asep = args[1][0];
2804 args += 2;
2805 } else {
2806 words = 1;
2807 args++;
2810 if (!args[0] || !args[1]) {
2811 zwarnnam(nam, "not enough arguments");
2812 return NULL;
2814 descr = *args++;
2816 ret = (Cvdef) zalloc(sizeof(*ret));
2817 ret->descr = ztrdup(descr);
2818 ret->hassep = hassep;
2819 ret->sep = sep;
2820 ret->argsep = asep;
2821 ret->next = NULL;
2822 ret->vals = NULL;
2823 ret->defs = zarrdup(oargs);
2824 ret->ndefs = arrlen(oargs);
2825 ret->lastt = time(0);
2826 ret->words = words;
2828 for (valp = &(ret->vals); *args; args++) {
2829 int bs = 0;
2830 p = dupstring(*args);
2831 xnum = 0;
2833 /* xor list? */
2834 if (*p == '(') {
2835 LinkList list = newlinklist();
2836 LinkNode node;
2837 char **xp, sav;
2839 while (*p && *p != ')') {
2840 for (p++; inblank(*p); p++);
2842 if (*p == ')')
2843 break;
2844 for (q = p++; *p && *p != ')' && !inblank(*p); p++);
2846 if (!*p)
2847 break;
2849 sav = *p;
2850 *p = '\0';
2851 addlinknode(list, dupstring(q));
2852 xnum++;
2853 *p = sav;
2855 if (*p != ')') {
2856 freecvdef(ret);
2857 zwarnnam(nam, "invalid argument: %s", *args);
2858 return NULL;
2860 xor = (char **) zalloc((xnum + 2) * sizeof(char *));
2861 for (node = firstnode(list), xp = xor; node; incnode(node), xp++)
2862 *xp = ztrdup((char *) getdata(node));
2863 xp[0] = xp[1] = NULL;
2865 p++;
2866 } else
2867 xor = NULL;
2869 /* More than once allowed? */
2870 if ((multi = (*p == '*')))
2871 p++;
2873 /* Skip option name. */
2875 for (name = p; *p && *p != ':' && *p != '['; p++)
2876 if (*p == '\\' && p[1])
2877 p++, bs = 1;
2879 if (hassep && !sep && name + bs + 1 < p) {
2880 freecvdef(ret);
2881 zwarnnam(nam, "no multi-letter values with empty separator allowed");
2882 return NULL;
2884 /* Optional description? */
2886 if ((c = *p) == '[') {
2887 *p = '\0';
2888 for (descr = ++p; *p && *p != ']'; p++)
2889 if (*p == '\\' && p[1])
2890 p++;
2892 if (!*p) {
2893 freecvdef(ret);
2894 zwarnnam(nam, "invalid value definition: %s", *args);
2895 return NULL;
2897 *p++ = '\0';
2898 c = *p;
2899 } else {
2900 *p = '\0';
2901 descr = NULL;
2903 if (c && c != ':') {
2904 freecvdef(ret);
2905 zwarnnam(nam, "invalid value definition: %s", *args);
2906 return NULL;
2908 /* Get argument? */
2910 if (c == ':') {
2911 if (hassep && !sep) {
2912 freecvdef(ret);
2913 zwarnnam(nam, "no value with argument with empty separator allowed");
2914 return NULL;
2916 if (*++p == ':') {
2917 p++;
2918 vtype = CVV_OPT;
2919 } else
2920 vtype = CVV_ARG;
2921 arg = parse_caarg(0, 0, 0, 0, name, &p, NULL);
2922 } else {
2923 vtype = CVV_NOARG;
2924 arg = NULL;
2926 if (!multi) {
2927 if (!xor) {
2928 xor = (char **) zalloc(2 * sizeof(char *));
2929 xor[1] = NULL;
2931 xor[xnum] = ztrdup(name);
2933 *valp = val = (Cvval) zalloc(sizeof(*val));
2934 valp = &((*valp)->next);
2936 val->next = NULL;
2937 val->name = ztrdup(name);
2938 val->descr = ztrdup(descr);
2939 val->xor = xor;
2940 val->type = vtype;
2941 val->arg = arg;
2943 return ret;
2946 /* Get the definition from the cache or newly built. */
2948 static Cvdef
2949 get_cvdef(char *nam, char **args)
2951 Cvdef *p, *min, new;
2952 int i, na = arrlen(args);
2954 for (i = MAX_CVCACHE, p = cvdef_cache, min = NULL; *p && i--; p++)
2955 if (*p && na == (*p)->ndefs && arrcmp(args, (*p)->defs)) {
2956 (*p)->lastt = time(0);
2958 return *p;
2959 } else if (!min || !*p || (*p)->lastt < (*min)->lastt)
2960 min = p;
2961 if (i)
2962 min = p;
2963 if ((new = parse_cvdef(nam, args))) {
2964 freecvdef(*min);
2965 *min = new;
2967 return new;
2970 /* Get the definition for a value. */
2972 static Cvval
2973 cv_get_val(Cvdef d, char *name)
2975 Cvval p;
2977 for (p = d->vals; p; p = p->next)
2978 if (!strcmp(name, p->name))
2979 return p;
2981 return NULL;
2984 static Cvval
2985 cv_quote_get_val(Cvdef d, char *name)
2987 int ne;
2989 /* remove quotes */
2990 name = dupstring(name);
2991 ne = noerrs;
2992 noerrs = 2;
2993 parse_subst_string(name);
2994 noerrs = ne;
2995 remnulargs(name);
2996 untokenize(name);
2998 return cv_get_val(d, name);
3001 /* Handle a xor list. */
3003 static void
3004 cv_inactive(Cvdef d, char **xor)
3006 if (xor) {
3007 Cvval val;
3009 for (; *xor; xor++)
3010 if ((val = cv_get_val(d, *xor)))
3011 val->active = 0;
3015 /* Parse state. */
3017 struct cvstate {
3018 Cvdef d;
3019 Caarg def;
3020 Cvval val;
3021 LinkList vals;
3024 static struct cvstate cv_laststate;
3025 static int cv_parsed = 0, cv_alloced = 0;
3027 /* Get the next value in the string. Return it's definition and update the
3028 * sp pointer to point to the end of the value (plus argument, if any).
3029 * If there is no next value, the string pointer is set to null. In any
3030 * case ap will point to the beginning of the argument or will be a null
3031 * pointer if there is no argument.
3034 static Cvval
3035 cv_next(Cvdef d, char **sp, char **ap)
3037 Cvval r = NULL;
3038 char *s = *sp;
3040 if (!*s) {
3041 *sp = *ap = NULL;
3043 return NULL;
3045 if ((d->hassep && !d->sep) || !d->argsep) {
3046 char sav, ec, *v = s, *os;
3048 ec = ((d->hassep && d->sep) ? d->sep : d->argsep);
3050 do {
3051 sav = *++s;
3052 *s = '\0';
3053 if ((r = cv_quote_get_val(d, v))) {
3054 *s = sav;
3056 break;
3058 *s = sav;
3059 } while (*s && *s != ec);
3061 os = s;
3063 if (d->hassep && d->sep) {
3064 if ((s = strchr(s, d->sep)))
3065 *sp = s + 1;
3066 else
3067 *sp = NULL;
3068 } else
3069 *sp = s;
3070 if (d->argsep && *os == d->argsep) {
3071 *ap = os + 1;
3072 *sp = NULL;
3073 } else if (r && r->type != CVV_NOARG)
3074 *ap = os;
3075 else
3076 *ap = NULL;
3078 return r;
3080 } else if (d->hassep) {
3081 char *ns = strchr(s, d->sep), *as = 0, *sap, sav = 0;
3082 int skip = 0;
3084 if (d->argsep && (as = strchr(s, d->argsep)) && (!ns || as <= ns)) {
3085 *ap = as + 1;
3086 ns = strchr(as + 1, d->sep);
3087 skip = 1;
3088 sap = as;
3089 } else {
3090 *ap = NULL;
3091 sap = ns;
3093 if (sap) {
3094 sav = *sap;
3095 *sap = '\0';
3097 if ((!(r = cv_quote_get_val(d, s)) || r->type == CVV_NOARG) && skip)
3098 ns = as;
3100 if (sap)
3101 *sap = sav;
3103 *sp = ((!ns || (ns == as && r && r->type != CVV_NOARG)) ? NULL : ns + 1);
3105 return r;
3106 } else {
3107 char *as = strchr(s, d->argsep), *sap, sav = 0;
3109 *sp = NULL;
3111 if (as) {
3112 *ap = as + 1;
3113 sap = as;
3114 sav = *as;
3115 *sap = '\0';
3116 } else
3117 *ap = sap = NULL;
3119 r = cv_quote_get_val(d, s);
3121 if (sap)
3122 *sap = sav;
3124 return r;
3128 /* Parse the current word. */
3130 static void
3131 cv_parse_word(Cvdef d)
3133 Cvval val;
3134 struct cvstate state;
3135 char *str, *arg = NULL, *pign = compprefix;
3136 int nosfx = 0;
3138 if (cv_alloced)
3139 freelinklist(cv_laststate.vals, freestr);
3141 for (val = d->vals; val; val = val->next)
3142 val->active = 1;
3144 state.d = d;
3145 state.def = NULL;
3146 state.val = NULL;
3147 state.vals = (LinkList) znewlinklist();
3149 cv_alloced = 1;
3151 if (d->words && compwords[0]) {
3152 int i;
3154 for (i = 1; compwords[i]; i++)
3155 if (i != compcurrent - 1)
3156 for (str = compwords[i]; str && *str; ) {
3157 if ((val = cv_next(d, &str, &arg))) {
3158 zaddlinknode(state.vals, ztrdup(val->name));
3159 if (arg) {
3160 char sav = '\0';
3162 if (str) {
3163 sav = str[-1];
3164 str[-1] = '\0';
3166 zaddlinknode(state.vals, ztrdup(arg));
3167 if (str)
3168 str[-1] = sav;
3169 } else
3170 zaddlinknode(state.vals, ztrdup(""));
3172 if (i + 1 < compcurrent)
3173 cv_inactive(d, val->xor);
3177 val = NULL;
3178 arg = NULL;
3180 for (str = compprefix; str && *str; ) {
3181 if ((val = cv_next(d, &str, &arg))) {
3182 zaddlinknode(state.vals, ztrdup(val->name));
3183 if (arg) {
3184 if (str) {
3185 char sav = str[-1];
3187 str[-1] = '\0';
3188 zaddlinknode(state.vals, ztrdup(arg));
3189 str[-1] = sav;
3190 } else {
3191 zaddlinknode(state.vals, tricat(arg, compsuffix, ""));
3192 nosfx = 1;
3194 } else
3195 zaddlinknode(state.vals, ztrdup(""));
3197 cv_inactive(d, val->xor);
3199 if (str)
3200 pign = str;
3201 else
3202 val->active = 1;
3205 state.val = val;
3206 if (val && arg && !str)
3207 state.def = val->arg;
3209 if (!nosfx && d->hassep) {
3210 int ign = 0;
3211 char *more = NULL;
3213 ignore_prefix(pign - compprefix);
3215 if (!d->sep && (!val || val->type == CVV_NOARG)) {
3216 ign = strlen(compsuffix);
3217 more = compsuffix;
3218 } else {
3219 if (d->sep) {
3220 char *ns = strchr(compsuffix, d->sep), *as;
3222 if (d->argsep && (as = strchr(compsuffix, d->argsep)) &&
3223 (!ns || as <= ns)) {
3224 ign = strlen(as);
3225 } else
3226 ign = (ns ? strlen(ns) : 0);
3228 more = (ns ? ns + 1 : NULL);
3229 } else if (d->argsep) {
3230 char *as;
3232 if ((as = strchr(compsuffix, d->argsep)))
3233 ign = strlen(as);
3236 more = dupstring(more);
3238 if (ign)
3239 ignore_suffix(ign);
3241 while (more && *more) {
3242 if ((val = cv_next(d, &more, &arg))) {
3243 zaddlinknode(state.vals, ztrdup(val->name));
3244 if (arg) {
3245 if (more) {
3246 char sav = more[-1];
3248 more[-1] = '\0';
3249 zaddlinknode(state.vals, ztrdup(arg));
3250 more[-1] = sav;
3251 } else {
3252 zaddlinknode(state.vals, tricat(arg, compsuffix, ""));
3253 nosfx = 1;
3255 } else
3256 zaddlinknode(state.vals, ztrdup(""));
3258 cv_inactive(d, val->xor);
3261 } else if (arg)
3262 ignore_prefix(arg - compprefix);
3263 else
3264 ignore_prefix(pign - compprefix);
3266 memcpy(&cv_laststate, &state, sizeof(state));
3269 static int
3270 bin_compvalues(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
3272 int min, max, n;
3274 if (incompfunc != 1) {
3275 zwarnnam(nam, "can only be called from completion function");
3276 return 1;
3278 if (args[0][0] != '-' || !args[0][1] || args[0][2]) {
3279 zwarnnam(nam, "invalid argument: %s", args[0]);
3280 return 1;
3282 if (args[0][1] != 'i' && !cv_parsed) {
3283 zwarnnam(nam, "no parsed state");
3284 return 1;
3286 switch (args[0][1]) {
3287 case 'i': min = 2; max = -1; break;
3288 case 'D': min = 2; max = 2; break;
3289 case 'C': min = 1; max = 1; break;
3290 case 'V': min = 3; max = 3; break;
3291 case 's': min = 1; max = 1; break;
3292 case 'S': min = 1; max = 1; break;
3293 case 'd': min = 1; max = 1; break;
3294 case 'L': min = 3; max = 4; break;
3295 case 'v': min = 1; max = 1; break;
3296 default:
3297 zwarnnam(nam, "invalid option: %s", args[0]);
3298 return 1;
3300 n = arrlen(args) - 1;
3301 if (n < min) {
3302 zwarnnam(nam, "not enough arguments");
3303 return 1;
3304 } else if (max >= 0 && n > max) {
3305 zwarnnam(nam, "too many arguments");
3306 return 1;
3308 switch (args[0][1]) {
3309 case 'i':
3310 /* This initialises the internal data structures. The arguments are
3311 * just the arguments that were given to _values itself. */
3313 Cvdef def = get_cvdef(nam, args + 1);
3314 int cvp = cv_parsed;
3316 cv_parsed = 0;
3318 if (!def)
3319 return 1;
3321 cv_parsed = cvp;
3322 cv_parse_word(def);
3323 cv_parsed = 1;
3325 return 0;
3327 return 1;
3329 case 'D':
3330 /* This returns the description and action to use if we are at
3331 * a place where some action has to be used at all. In that case
3332 * zero is returned and non-zero otherwise. */
3334 Caarg arg = cv_laststate.def;
3336 if (arg) {
3337 setsparam(args[1], ztrdup(arg->descr));
3338 setsparam(args[2], ztrdup(arg->action));
3340 return 0;
3342 return 1;
3344 case 'C':
3345 /* This returns the sub-context (i.e.: the tag) to use when executing
3346 * an action. */
3348 Caarg arg = cv_laststate.def;
3350 if (arg) {
3351 setsparam(args[1], ztrdup(arg->opt));
3353 return 0;
3355 return 1;
3357 case 'V':
3358 /* This is what -O is for comparguments: it returns (in three arrays)
3359 * the values for values without arguments, with arguments and with
3360 * optional arguments (so that we can get the auto-suffixes right).
3361 * As for comparguments, the strings returned are usable for _describe. */
3363 LinkList noarg = newlinklist();
3364 LinkList arg = newlinklist();
3365 LinkList opt = newlinklist(), l;
3366 Cvval p;
3367 char *str;
3369 for (p = cv_laststate.d->vals; p; p = p->next) {
3370 if (p->active) {
3371 switch (p->type) {
3372 case CVV_NOARG: l = noarg; break;
3373 case CVV_ARG: l = arg; break;
3374 default: l = opt; break;
3376 if (p->descr) {
3377 int len = strlen(p->name) + strlen(p->descr) + 2;
3379 str = (char *) zhalloc(len);
3380 strcpy(str, p->name);
3381 strcat(str, ":");
3382 strcat(str, p->descr);
3383 } else
3384 str = p->name;
3385 addlinknode(l, str);
3388 set_list_array(args[1], noarg);
3389 set_list_array(args[2], arg);
3390 set_list_array(args[3], opt);
3392 return 0;
3394 case 's':
3395 /* This returns the value separator, if any, and sets the return
3396 * value to say if there is such a separator. */
3397 if (cv_laststate.d->hassep) {
3398 char tmp[2];
3400 tmp[0] = cv_laststate.d->sep;
3401 tmp[1] = '\0';
3402 setsparam(args[1], ztrdup(tmp));
3404 return 0;
3406 return 1;
3407 case 'S':
3408 /* Like -s, but for the separator between values and their arguments. */
3410 char tmp[2];
3412 tmp[0] = cv_laststate.d->argsep;
3413 tmp[1] = '\0';
3414 setsparam(args[1], ztrdup(tmp));
3416 return 0;
3417 case 'd':
3418 /* This returns the description string (first argument to _values)
3419 * which is passed down to _describe. */
3420 setsparam(args[1], ztrdup(cv_laststate.d->descr));
3421 return 0;
3422 case 'L':
3423 /* Almost the same as for comparguments. This gets a value name
3424 * and returns the description and action of its first argument, if
3425 * any. The rest (prefix matching) is in _values. Return non-zero
3426 * if there is no such option. */
3428 Cvval val = cv_get_val(cv_laststate.d, args[1]);
3430 if (val && val->arg) {
3431 setsparam(args[2], val->arg->descr);
3432 setsparam(args[3], val->arg->action);
3434 if (args[4])
3435 setsparam(args[4], ztrdup(val->name));
3437 return 0;
3439 return 1;
3441 case 'v':
3442 /* Again, as for comparguments. This returns the values and their
3443 * arguments as an array which will be stored in val_args in _values. */
3444 if (cv_laststate.vals) {
3445 char **ret;
3447 ret = zlinklist2array(cv_laststate.vals);
3448 sethparam(args[1], ret);
3450 return 0;
3452 return 1;
3454 return 1;
3457 static char *
3458 comp_quote(char *str, int prefix)
3460 int x;
3461 char *ret;
3463 if ((x = (prefix && *str == '=')))
3464 *str = 'x';
3466 ret = quotestring(str, NULL, *compqstack);
3468 if (x)
3469 *str = *ret = '=';
3471 return ret;
3474 static int
3475 bin_compquote(char *nam, char **args, Options ops, UNUSED(int func))
3477 char *name;
3478 struct value vbuf;
3479 Value v;
3481 if (incompfunc != 1) {
3482 zwarnnam(nam, "can only be called from completion function");
3483 return 1;
3485 /* Anything to do? */
3487 if (!compqstack || !*compqstack)
3488 return 0;
3490 /* For all parameters given... */
3492 while ((name = *args++)) {
3493 name = dupstring(name);
3494 queue_signals();
3495 if ((v = getvalue(&vbuf, &name, 0))) {
3496 switch (PM_TYPE(v->pm->node.flags)) {
3497 case PM_SCALAR:
3498 setstrvalue(v, ztrdup(comp_quote(getstrvalue(v),
3499 OPT_ISSET(ops,'p'))));
3500 break;
3501 case PM_ARRAY:
3503 char **val = v->pm->gsu.a->getfn(v->pm);
3504 char **new = (char **) zalloc((arrlen(val) + 1) *
3505 sizeof(char *));
3506 char **p = new;
3508 for (; *val; val++, p++)
3509 *p = ztrdup(comp_quote(*val, OPT_ISSET(ops,'p')));
3510 *p = NULL;
3512 setarrvalue(v, new);
3514 break;
3515 default:
3516 zwarnnam(nam, "invalid parameter type: %s", args[-1]);
3518 } else
3519 zwarnnam(nam, "unknown parameter: %s", args[-1]);
3520 unqueue_signals();
3522 return 0;
3525 /* Tags stuff. */
3527 typedef struct ctags *Ctags;
3528 typedef struct ctset *Ctset;
3530 /* A bunch of tag sets. */
3532 struct ctags {
3533 char **all; /* all tags offered */
3534 char *context; /* the current context */
3535 int init; /* not yet used */
3536 Ctset sets; /* the tag sets */
3539 /* A tag set. */
3541 struct ctset {
3542 Ctset next;
3543 char **tags; /* the tags */
3544 char *tag; /* last tag checked for -A */
3545 char **ptr; /* ptr into tags for -A */
3548 /* Array of tag-set infos. Index is the locallevel. */
3550 #define MAX_TAGS 256
3551 static Ctags comptags[MAX_TAGS];
3553 /* locallevel at last comptags -i */
3555 static int lasttaglevel;
3557 static void
3558 freectset(Ctset s)
3560 Ctset n;
3562 while (s) {
3563 n = s->next;
3565 if (s->tags)
3566 freearray(s->tags);
3567 zsfree(s->tag);
3568 zfree(s, sizeof(*s));
3570 s = n;
3574 static void
3575 freectags(Ctags t)
3577 if (t) {
3578 if (t->all)
3579 freearray(t->all);
3580 zsfree(t->context);
3581 freectset(t->sets);
3582 zfree(t, sizeof(*t));
3586 /* Set the tags for the current local level. */
3588 static void
3589 settags(int level, char **tags)
3591 Ctags t;
3593 if (comptags[level])
3594 freectags(comptags[level]);
3596 comptags[level] = t = (Ctags) zalloc(sizeof(*t));
3598 t->all = zarrdup(tags + 1);
3599 t->context = ztrdup(*tags);
3600 t->sets = NULL;
3601 t->init = 1;
3604 /* Check if an array contains a string. */
3606 /**/
3607 static int
3608 arrcontains(char **a, char *s, int colon)
3610 char *p, *q;
3612 while (*a) {
3613 if (colon) {
3614 for (p = s, q = *a++; *p && *q && *p != ':' && *q != ':'; p++, q++)
3615 if (*p != *q)
3616 break;
3617 if ((!*p || *p == ':') && (!*q || *q == ':'))
3618 return 1;
3619 } else if (!strcmp(*a++, s))
3620 return 1;
3622 return 0;
3625 static int
3626 bin_comptags(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
3628 int min, max, n, level;
3630 if (incompfunc != 1) {
3631 zwarnnam(nam, "can only be called from completion function");
3632 return 1;
3634 if (args[0][0] != '-' || !args[0][1] ||
3635 (args[0][2] && (args[0][2] != '-' || args[0][3]))) {
3636 zwarnnam(nam, "invalid argument: %s", args[0]);
3637 return 1;
3639 level = locallevel - (args[0][2] ? 1 : 0);
3640 if (level >= MAX_TAGS) {
3641 zwarnnam(nam, "nesting level too deep");
3642 return 1;
3644 if (args[0][1] != 'i' && args[0][1] != 'I' && !comptags[level]) {
3645 zwarnnam(nam, "no tags registered");
3646 return 1;
3648 switch (args[0][1]) {
3649 case 'i': min = 2; max = -1; break;
3650 case 'C': min = 1; max = 1; break;
3651 case 'T': min = 0; max = 0; break;
3652 case 'N': min = 0; max = 0; break;
3653 case 'R': min = 1; max = 1; break;
3654 case 'S': min = 1; max = 1; break;
3655 case 'A': min = 2; max = 3; break;
3656 default:
3657 zwarnnam(nam, "invalid option: %s", args[0]);
3658 return 1;
3660 n = arrlen(args) - 1;
3661 if (n < min) {
3662 zwarnnam(nam, "not enough arguments");
3663 return 1;
3664 } else if (max >= 0 && n > max) {
3665 zwarnnam(nam, "too many arguments");
3666 return 1;
3668 switch (args[0][1]) {
3669 case 'i':
3670 settags(level, args + 1);
3671 lasttaglevel = level;
3672 break;
3673 case 'C':
3674 setsparam(args[1], ztrdup(comptags[level]->context));
3675 break;
3676 case 'T':
3677 return !comptags[level]->sets;
3678 case 'N':
3680 Ctset s;
3682 if (comptags[level]->init)
3683 comptags[level]->init = 0;
3684 else if ((s = comptags[level]->sets)) {
3685 comptags[level]->sets = s->next;
3686 s->next = NULL;
3687 freectset(s);
3689 return !comptags[level]->sets;
3691 case 'R':
3693 Ctset s;
3695 return !((s = comptags[level]->sets) &&
3696 arrcontains(s->tags, args[1], 1));
3698 case 'A':
3700 Ctset s;
3702 if (comptags[level] && (s = comptags[level]->sets)) {
3703 char **q, *v = NULL;
3704 int l = strlen(args[1]);
3706 if (!s->tag || strcmp(s->tag, args[1])) {
3707 zsfree(s->tag);
3708 s->tag = ztrdup(args[1]);
3709 s->ptr = s->tags;
3711 for (q = s->ptr; *q; q++) {
3712 if (strpfx(args[1], *q)) {
3713 if (!(*q)[l]) {
3714 v = *q;
3715 break;
3716 } else if ((*q)[l] == ':') {
3717 v = (*q) + l + 1;
3718 break;
3722 if (!v) {
3723 zsfree(s->tag);
3724 s->tag = NULL;
3725 return 1;
3727 s->ptr = q + 1;
3728 setsparam(args[2], ztrdup(*v == '-' ? dyncat(args[1], v) : v));
3729 if (args[3]) {
3730 char *r = dupstring(*q), *p;
3732 for (p = r + (v - *q); *p && *p != ':'; p++);
3733 *p = '\0';
3735 setsparam(args[3], ztrdup(r));
3737 return 0;
3739 return 1;
3741 case 'S':
3742 if (comptags[level]->sets) {
3743 char **ret;
3745 ret = zarrdup(comptags[level]->sets->tags);
3746 setaparam(args[1], ret);
3747 } else
3748 return 1;
3750 break;
3752 return 0;
3755 static int
3756 bin_comptry(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
3758 if (incompfunc != 1) {
3759 zwarnnam(nam, "can only be called from completion function");
3760 return 1;
3762 if (!lasttaglevel || !comptags[lasttaglevel]) {
3763 zwarnnam(nam, "no tags registered");
3764 return 1;
3766 if (*args) {
3767 if (!strcmp(*args, "-m")) {
3768 char *s, *p, *q, *c, **all = comptags[lasttaglevel]->all;
3769 LinkList list = newlinklist();
3770 int num = 0;
3771 Ctset set;
3773 while ((s = *++args)) {
3774 while (*s) {
3775 while (*s && iblank(*s))
3776 s++;
3777 for (p = q = s, c = NULL; *s && !inblank(*s); s++) {
3778 if (!c && *s == ':')
3779 c = p;
3780 if (*s == '\\' && s[1])
3781 s++;
3782 *p++ = *s;
3784 if (*s)
3785 s++;
3786 *p = '\0';
3787 if (*q) {
3788 char *qq, *qqq;
3790 if (c)
3791 *c = '\0';
3793 qqq = qq = dupstring(q);
3794 while (*qqq) {
3795 if (*qqq == '\\' && qqq[1])
3796 qqq++;
3797 else if (*qqq == '{')
3798 *qqq = Inbrace;
3799 else if (*qqq == '}')
3800 *qqq = Outbrace;
3801 else if (*qqq == ',')
3802 *qqq = Comma;
3803 qqq++;
3805 tokenize(qq);
3806 if (haswilds(qq) || hasbraces(qq)) {
3807 Patprog prog;
3808 LinkNode bnode, node;
3809 LinkList blist = newlinklist();
3811 addlinknode(blist, qq);
3812 for (bnode = firstnode(blist); bnode; incnode(bnode))
3813 while (hasbraces(getdata(bnode)))
3814 xpandbraces(blist, &bnode);
3816 for (bnode = firstnode(blist); bnode; incnode(bnode)) {
3817 qq = (char *) getdata(bnode);
3818 if ((prog = patcompile(qq, PAT_STATIC, NULL))) {
3819 char **a, *n;
3820 int l = (c ? strlen(c + 1) + 2 : 1), al;
3822 for (a = all; *a; a++) {
3823 for (node = firstnode(list); node;
3824 incnode(node)) {
3825 char *as, *ls;
3827 for (as = *a, ls = (char *) getdata(node);
3828 *as && *ls && *ls != ':'; as++, ls++)
3829 if (*as != *ls)
3830 break;
3831 if (!*as && (!*ls || *ls == ':'))
3832 break;
3834 if (node)
3835 continue;
3836 if (pattry(prog, *a)) {
3837 n = (char *) zhalloc((al = strlen(*a)) + l);
3838 strcpy(n, *a);
3839 if (c) {
3840 n[al] = ':';
3841 strcpy(n + al + 1, c + 1);
3843 addlinknode(list, n);
3844 num++;
3849 } else if (arrcontains(all, q, 0)) {
3850 for (set = comptags[lasttaglevel]->sets; set;
3851 set = set->next)
3852 if (arrcontains(set->tags, q, 0))
3853 break;
3854 if (!set) {
3855 addlinknode(list, q);
3856 num++;
3859 if (c)
3860 *c = ':';
3863 if (num) {
3864 Ctset l;
3866 set = (Ctset) zalloc(sizeof(*set));
3868 set->tags = zlinklist2array(list);
3869 set->next = NULL;
3870 set->ptr = NULL;
3871 set->tag = NULL;
3873 if ((l = comptags[lasttaglevel]->sets)) {
3874 while (l->next)
3875 l = l->next;
3877 l->next = set;
3878 } else
3879 comptags[lasttaglevel]->sets = set;
3882 } else {
3883 char **p, **q, **all;
3884 int sep = 0;
3886 if ((sep = !strcmp(*args, "-s")))
3887 args++;
3889 for (p = q = args, all = comptags[lasttaglevel]->all; *p; p++)
3890 if (arrcontains(all, *p, 1)) {
3891 Ctset s;
3893 for (s = comptags[lasttaglevel]->sets; s; s = s->next)
3894 if (arrcontains(s->tags, *p, 0))
3895 break;
3897 if (!s)
3898 *q++ = *p;
3900 *q = NULL;
3902 if (*args) {
3903 char *dummy[2];
3905 do {
3906 Ctset s = (Ctset) zalloc(sizeof(*s)), l;
3908 if (sep) {
3909 dummy[0] = *args++;
3910 dummy[1] = NULL;
3911 s->tags = zarrdup(dummy);
3912 } else
3913 s->tags = zarrdup(args);
3914 s->next = NULL;
3915 s->ptr = NULL;
3916 s->tag = NULL;
3918 if ((l = comptags[lasttaglevel]->sets)) {
3919 while (l->next)
3920 l = l->next;
3922 l->next = s;
3923 } else
3924 comptags[lasttaglevel]->sets = s;
3925 } while (sep && *args);
3929 return 0;
3932 #define PATH_MAX2 (PATH_MAX * 2)
3934 static LinkList
3935 cfp_test_exact(LinkList names, char **accept, char *skipped)
3937 char buf[PATH_MAX2 + 1], *suf, *p;
3938 int l, sl, found = 0;
3939 struct stat st;
3940 LinkNode node;
3941 LinkList ret = newlinklist(), alist = NULL;
3943 if ((!(compprefix && *compprefix) && !(compsuffix && *compsuffix)) ||
3944 (!accept || !*accept ||
3945 ((!strcmp(*accept, "false") || !strcmp(*accept, "no") ||
3946 !strcmp(*accept, "off") || !strcmp(*accept, "0")) && !accept[1])))
3947 return NULL;
3949 if (accept[1] ||
3950 (strcmp(*accept, "true") && strcmp(*accept, "yes") &&
3951 strcmp(*accept, "on") && strcmp(*accept, "1"))) {
3952 Patprog prog;
3954 alist = newlinklist();
3956 for (; (p = *accept); accept++) {
3957 if (*p == '*' && !p[1]) {
3958 alist = NULL;
3959 break;
3961 tokenize(p = dupstring(p));
3962 if ((prog = patcompile(p, 0, NULL)))
3963 addlinknode(alist, prog);
3966 sl = strlen(skipped) + (compprefix ? strlen(compprefix) : 0) +
3967 (compsuffix ? strlen(compsuffix) : 0);
3969 if (sl > PATH_MAX2)
3970 return NULL;
3972 suf = dyncat(skipped, rembslash(dyncat(compprefix, compsuffix)));
3974 for (node = firstnode(names); node; incnode(node)) {
3975 l = strlen(p = (char *) getdata(node));
3976 if (l + sl < PATH_MAX2) {
3977 strcpy(buf, p);
3978 strcpy(buf + l, suf);
3980 if (!ztat(buf, &st, 0)) {
3981 if (alist) {
3982 LinkNode anode;
3984 for (anode = firstnode(alist); anode; incnode(anode))
3985 if (pattry((Patprog) getdata(anode), buf))
3986 break;
3988 if (!anode)
3989 continue;
3991 found = 1;
3992 addlinknode(ret, dupstring(buf));
3996 return (found ? ret : NULL);
4001 * This code constructs (from heap) and returns a string that
4002 * corresponds to a series of matches; when compiled as a pattern, at
4003 * each position it matches either the character from the string "add"
4004 * or the corresponding single-character match from the set of matchers.
4005 * To take a simple case, if add is "a" and the single matcher for the
4006 * character position matches "[0-9]", the pattern returned is "[0-9a]".
4007 * We take account of equivalences between the word and line, too.
4009 * As there are virtually no comments in this file, I don't really
4010 * know why we're doing this, but it's to do with a matcher which
4011 * is passed as an argument to the utility compfiles -p/-P.
4013 static char *
4014 cfp_matcher_range(Cmatcher *ms, char *add)
4016 Cmatcher *mp, m;
4017 int len = 0, mt;
4018 char *ret = NULL, *p = NULL, *adds = add;
4021 * Do this twice: once to work out the length of the
4022 * string in len, the second time to build it in ret.
4023 * This is probably worthwhile because otherwise memory
4024 * management is difficult.
4026 for (;;) {
4027 MB_METACHARINIT();
4028 for (mp = ms; *add; ) {
4029 convchar_t addc;
4030 int addlen;
4032 addlen = MB_METACHARLENCONV(add, &addc);
4033 #ifdef MULTIBYTE_SUPPORT
4034 if (addc == WEOF)
4035 addc = (wchar_t)(*p == Meta ? p[1] ^ 32 : *p);
4036 #endif
4038 if (!(m = *mp)) {
4040 * No matcher, so just match the character
4041 * itself.
4043 * TODO: surely this needs quoting if it's a
4044 * metacharacter?
4046 if (ret) {
4047 memcpy(p, add, addlen);
4048 p += addlen;
4049 } else
4050 len += addlen;
4051 } else if (m->flags & CMF_RIGHT) {
4053 * Right-anchored: match anything followed
4054 * by the character itself.
4056 if (ret) {
4057 *p++ = '*';
4058 /* TODO: quote again? */
4059 memcpy(p, add, addlen);
4060 p += addlen;
4061 } else
4062 len += addlen + 1;
4063 } else {
4064 /* The usual set of matcher possibilities. */
4065 convchar_t ind;
4066 if (m->line->tp == CPAT_EQUIV &&
4067 m->word->tp == CPAT_EQUIV) {
4069 * Genuine equivalence. Add the character to match
4070 * and the equivalent character from the word
4071 * pattern.
4073 * TODO: we could be more careful here with special
4074 * cases as we are in the basic character class
4075 * code below.
4077 if (ret) {
4078 *p++ = '[';
4079 memcpy(p, add, addlen);
4080 p += addlen;
4081 } else
4082 len += addlen + 1;
4083 if (PATMATCHRANGE(m->line->u.str, addc, &ind, &mt)) {
4085 * Find the equivalent match for ind in the
4086 * word pattern.
4088 if ((ind = pattern_match_equivalence
4089 (m->word, ind, mt, addc)) != CHR_INVALID) {
4090 if (ret) {
4091 if (imeta(ind)) {
4092 *p++ = Meta;
4093 *p++ = ind ^ 32;
4094 } else
4095 *p++ = ind;
4096 } else
4097 len += imeta(ind) ? 2 : 1;
4100 if (ret)
4101 *p++ = ']';
4102 else
4103 len++;
4104 } else {
4105 int newlen, addadd;
4107 switch (m->word->tp) {
4108 case CPAT_NCLASS:
4110 * TODO: the old logic implies that we need to
4111 * match *add, i.e. it should be deleted from
4112 * the set of character's we're not allowed to
4113 * match. That's too much like hard work for
4114 * now. Indeed, in general it's impossible
4115 * without trickery. Consider *add == 'A',
4116 * range == "[^[:upper:]]": we would have to
4117 * resort to something like "(A|[^[:upper:]])";
4118 * and in an expression like that *add may or
4119 * may not need backslashing. So we're deep
4120 * into see-if-we-can-get-away-without
4121 * territory.
4123 if (ret) {
4124 *p++ = '[';
4125 *p++ = '^';
4126 } else
4127 len += 2;
4129 * Convert the compiled range string back
4130 * to an ordinary string.
4132 newlen =
4133 pattern_range_to_string(m->word->u.str, p);
4134 DPUTS(!newlen, "empty character range");
4135 if (ret) {
4136 p += newlen;
4137 *p++ = ']';
4138 } else
4139 len += newlen + 1;
4140 break;
4142 case CPAT_CCLASS:
4144 * If there is an equivalence only on one
4145 * side it's not equivalent to anything.
4146 * Treat it as an ordinary character class.
4148 case CPAT_EQUIV:
4149 case CPAT_CHAR:
4150 if (ret)
4151 *p++ = '[';
4152 else
4153 len++;
4155 * We needed to add *add specially only if
4156 * it is not covered by the range. This
4157 * is necessary for correct syntax---consider
4158 * if *add is ] and ] is also the first
4159 * character in the range.
4161 addadd = !pattern_match1(m->word, addc, &mt);
4162 if (addadd && *add == ']') {
4163 if (ret)
4164 *p++ = *add;
4165 else
4166 len++;
4168 if (m->word->tp == CPAT_CHAR) {
4170 * The matcher just matches a single
4171 * character, but we need to be able
4172 * to match *add, too, hence we do
4173 * this as a [...].
4175 if (ret) {
4176 if (imeta(m->word->u.chr)) {
4177 *p++ = Meta;
4178 *p++ = m->word->u.chr ^ 32;
4179 } else
4180 *p++ = m->word->u.chr;
4181 } else
4182 len += imeta(m->word->u.chr) ? 2 : 1;
4183 } else {
4185 * Convert the compiled range string back
4186 * to an ordinary string.
4188 newlen =
4189 pattern_range_to_string(m->word->u.str, p);
4190 DPUTS(!newlen, "empty character range");
4191 if (ret)
4192 p += newlen;
4193 else
4194 len += newlen;
4196 if (addadd && *add != ']') {
4197 if (ret) {
4198 memcpy(p, add, addlen);
4199 p += addlen;
4200 } else
4201 len += addlen;
4203 if (ret)
4204 *p++ = ']';
4205 else
4206 len++;
4207 break;
4209 case CPAT_ANY:
4210 if (ret)
4211 *p++ = '?';
4212 else
4213 len++;
4214 break;
4218 add += addlen;
4219 mp++;
4221 if (ret) {
4222 *p = '\0';
4223 return ret;
4225 p = ret = zhalloc(len + 1);
4226 add = adds;
4231 static char *
4232 cfp_matcher_pats(char *matcher, char *add)
4234 Cmatcher m = parse_cmatcher(NULL, matcher);
4236 if (m && m != pcm_err) {
4237 char *tmp;
4238 int al = strlen(add), zl = ztrlen(add), tl, cl;
4239 VARARR(Cmatcher, ms, zl);
4240 Cmatcher *mp;
4241 Cpattern stopp;
4242 int stopl = 0;
4244 memset(ms, 0, zl * sizeof(Cmatcher));
4246 for (; m && *add; m = m->next) {
4247 stopp = NULL;
4248 if (!(m->flags & (CMF_LEFT|CMF_RIGHT))) {
4249 if (m->llen == 1 && m->wlen == 1) {
4250 for (tmp = add, tl = al, mp = ms; tl; ) {
4251 if (pattern_match(m->line, tmp, NULL, NULL)) {
4252 if (*mp) {
4253 *tmp = '\0';
4254 al = tmp - add;
4255 break;
4256 } else
4257 *mp = m;
4259 cl = (*tmp == Meta) ? 2 : 1;
4260 tl -= cl;
4261 tmp += cl;
4262 mp += cl;
4264 } else {
4265 stopp = m->line;
4266 stopl = m->llen;
4268 } else if (m->flags & CMF_RIGHT) {
4269 if (m->wlen < 0 && !m->llen && m->ralen == 1) {
4270 for (tmp = add, tl = al, mp = ms; tl; ) {
4271 if (pattern_match(m->right, tmp, NULL, NULL)) {
4272 if (*mp || (tmp == add && *tmp == '.')) {
4273 *tmp = '\0';
4274 al = tmp - add;
4275 break;
4276 } else
4277 *mp = m;
4279 cl = (*tmp == Meta) ? 2 : 1;
4280 tl -= cl;
4281 tmp += cl;
4282 mp += cl;
4284 } else if (m->llen) {
4285 stopp = m->line;
4286 stopl = m->llen;
4287 } else {
4288 stopp = m->right;
4289 stopl = m->ralen;
4291 } else {
4292 if (!m->lalen)
4293 return "";
4295 stopp = m->left;
4296 stopl = m->lalen;
4298 if (stopp)
4299 for (tmp = add, tl = al; tl >= stopl; ) {
4300 if (pattern_match(stopp, tmp, NULL, NULL)) {
4301 *tmp = '\0';
4302 al = tmp - add;
4303 break;
4305 cl = (*tmp == Meta) ? 2 : 1;
4306 tl -= cl;
4307 tmp += cl;
4310 if (*add)
4311 return cfp_matcher_range(ms, add);
4313 return add;
4316 static void
4317 cfp_opt_pats(char **pats, char *matcher)
4319 char *add, **p, *q, *t, *s;
4321 if (!compprefix || !*compprefix)
4322 return;
4324 if (comppatmatch && *comppatmatch) {
4325 tokenize(t = rembslash(dyncat(compprefix, compsuffix)));
4326 remnulargs(t);
4327 if (haswilds(t))
4328 return;
4330 add = (char *) zhalloc(strlen(compprefix) * 2 + 1);
4331 for (s = compprefix, t = add; *s; s++) {
4332 if (*s != '\\' || !s[1] || s[1] == '*' || s[1] == '?' ||
4333 s[1] == '<' || s[1] == '>' || s[1] == '(' || s[1] == ')' ||
4334 s[1] == '[' || s[1] == ']' || s[1] == '|' || s[1] == '#' ||
4335 s[1] == '^' || s[1] == '~' || s[1] == '=') {
4336 if ((s == compprefix || s[-1] != '\\') &&
4337 (*s == '*' || *s == '?' || *s == '<' || *s == '>' ||
4338 *s == '(' || *s == ')' || *s == '[' || *s == ']' ||
4339 *s == '|' || *s == '#' || *s == '^' || *s == '~' ||
4340 *s == '='))
4341 *t++ = '\\';
4342 *t++ = *s;
4345 *t = '\0';
4346 for (p = pats; *add && (q = *p); p++) {
4347 if (*q) {
4348 q = dupstring(q);
4349 t = q + strlen(q) - 1;
4350 if (*t == ')') {
4351 for (s = t--; t > q; t--)
4352 if (*t == ')' || *t == '|' || *t == '~' || *t == '(')
4353 break;
4354 if (t != q && *t == '(')
4355 *t = '\0';
4357 for (; *q && *add; q++) {
4358 if (*q == '\\' && q[1]) {
4359 for (s = add, q++; *s && *s != *q; s++);
4360 *s = '\0';
4361 } else if (*q == '<') {
4362 for (s = add; *s && !idigit(*s); s++);
4363 *s = '\0';
4364 } else if (*q == '[') {
4365 int not;
4366 char *x = ++q;
4368 if ((not = (*x == '!' || *x == '^')))
4369 x++;
4370 for (; *x; x++) {
4371 if (x[1] == '-' && x[2]) {
4372 char c1 = *x, c2 = x[2];
4374 for (s = add; *s && (*x < c1 || *x > c2); s++);
4375 *s = '\0';
4376 } else {
4377 for (s = add; *s && *s != *x; s++);
4378 *s = '\0';
4381 } else if (*q != '?' && *q != '*' && *q != '(' && *q != ')' &&
4382 *q != '|' && *q != '~' && *q != '#') {
4383 for (s = add; *s && *s != *q; s++);
4384 *s = '\0';
4389 if (*add) {
4390 if (*matcher && !(add = cfp_matcher_pats(matcher, add)))
4391 return;
4393 for (p = pats; *p; p++)
4394 if (**p == '*')
4395 *p = dyncat(add, *p);
4399 static LinkList
4400 cfp_bld_pats(UNUSED(int dirs), LinkList names, char *skipped, char **pats)
4402 LinkList ret = newlinklist();
4403 LinkNode node;
4404 int ol, sl = strlen(skipped), pl, dot;
4405 char **p, *o, *str;
4407 dot = (unset(GLOBDOTS) && compprefix && *compprefix == '.');
4408 for (node = firstnode(names); node; incnode(node)) {
4409 ol = strlen(o = (char *) getdata(node));
4410 for (p = pats; *p; p++) {
4411 pl = strlen(*p);
4412 str = (char *) zhalloc(ol + sl + pl + 1);
4413 strcpy(str, o);
4414 strcpy(str + ol, skipped);
4415 strcpy(str + ol + sl, *p);
4416 addlinknode(ret, str);
4417 if (dot && **p != '.') {
4418 str = (char *) zhalloc(ol + sl + pl + 2);
4419 strcpy(str, o);
4420 strcpy(str + ol, skipped);
4421 str[ol + sl] = '.';
4422 strcpy(str + ol + sl + 1, *p);
4423 addlinknode(ret, str);
4427 return ret;
4430 static LinkList
4431 cfp_add_sdirs(LinkList final, LinkList orig, char *skipped,
4432 char *sdirs, char **fake)
4434 int add = 0;
4436 if (*sdirs && (isset(GLOBDOTS) || (compprefix && *compprefix == '.'))) {
4437 if (!strcmp(sdirs, "yes") || !strcmp(sdirs, "true") ||
4438 !strcmp(sdirs, "on") || !strcmp(sdirs, "1"))
4439 add = 2;
4440 else if (!strcmp(sdirs, ".."))
4441 add = 1;
4443 if (add) {
4444 LinkNode node;
4445 char *s1 = dyncat(skipped, "..");
4446 char *s2 = (add == 2 ? dyncat(skipped, ".") : NULL), *m;
4448 for (node = firstnode(orig); node; incnode(node)) {
4449 if ((m = (char *) getdata(node))) {
4450 addlinknode(final, dyncat(m, s1));
4451 if (s2)
4452 addlinknode(final, dyncat(m, s2));
4456 if (fake && *fake) {
4457 LinkNode node;
4458 char *m, *f, *p, *t, *a, c;
4459 int sl = strlen(skipped) + 1;
4460 struct stat st1, st2;
4461 Patprog pprog;
4463 for (; (f = *fake); fake++) {
4464 f = dupstring(f);
4465 for (p = t = f; *p; p++) {
4466 if (*p == ':')
4467 break;
4468 else if (*p == '\\' && p[1] == ':') {
4470 * strip quoted colons here; rely
4471 * on tokenization to strip other backslashes
4473 p++;
4475 *t++ = *p;
4477 if (*p) {
4478 *t = *p++ = '\0';
4479 if (!*p)
4480 continue;
4482 tokenize(f);
4483 pprog = patcompile(f, PAT_STATIC, NULL);
4484 untokenize(f);
4485 for (node = firstnode(orig); node; incnode(node)) {
4486 if ((m = (char *) getdata(node)) &&
4487 ((pprog ? pattry(pprog, m) : !strcmp(f, m)) ||
4488 (!stat(f, &st1) && !stat((*m ? m : "."), &st2) &&
4489 st1.st_dev == st2.st_dev &&
4490 st1.st_ino == st2.st_ino))) {
4491 while (*p) {
4492 while (*p && inblank(*p))
4493 p++;
4494 if (!*p)
4495 break;
4496 for (f = t = p; *p; p++) {
4497 if (inblank(*p))
4498 break;
4499 else if (*p == '\\' && p[1])
4500 p++;
4501 *t++ = *p;
4503 c = *t;
4504 *t = '\0';
4505 a = (char *) zhalloc(strlen(m) + sl + strlen(f));
4506 strcpy(a, m);
4507 strcat(a, skipped);
4508 strcat(a, f);
4509 addlinknode(final, a);
4510 *t = c;
4517 return final;
4520 static LinkList
4521 cf_pats(int dirs, int noopt, LinkList names, char **accept, char *skipped,
4522 char *matcher, char *sdirs, char **fake, char **pats)
4524 LinkList ret;
4525 char *dpats[2];
4527 if ((ret = cfp_test_exact(names, accept, skipped)))
4528 return cfp_add_sdirs(ret, names, skipped, sdirs, fake);
4530 if (dirs) {
4531 dpats[0] = "*(-/)";
4532 dpats[1] = NULL;
4533 pats = dpats;
4535 if (!noopt)
4536 cfp_opt_pats(pats, matcher);
4538 return cfp_add_sdirs(cfp_bld_pats(dirs, names, skipped, pats),
4539 names, skipped, sdirs, fake);
4542 static void
4543 cf_ignore(char **names, LinkList ign, char *style, char *path)
4545 int pl = strlen(path), tpar, tpwd, found;
4546 struct stat nst, est, st;
4547 char *n, *c, *e;
4549 tpar = !!strstr(style, "parent");
4550 if ((tpwd = !!strstr(style, "pwd")) && stat(pwd, &est))
4551 tpwd = 0;
4553 if (!tpar && !tpwd)
4554 return;
4556 for (; (n = *names); names++) {
4557 if (!ztat(n, &nst, 0) && S_ISDIR(nst.st_mode)) {
4558 if (tpwd && nst.st_dev == est.st_dev && nst.st_ino == est.st_ino) {
4559 addlinknode(ign, quotestring(n, NULL, QT_BACKSLASH));
4560 continue;
4562 if (tpar && !strncmp((c = dupstring(n)), path, pl)) {
4563 found = 0;
4564 while ((e = strrchr(c, '/')) && e > c + pl) {
4565 *e = '\0';
4566 if (!ztat(c, &st, 0) &&
4567 st.st_dev == nst.st_dev && st.st_ino == nst.st_ino) {
4568 found = 1;
4569 break;
4572 if (found || ((e = strrchr(c, '/')) && e > c + pl &&
4573 !ztat(c, &st, 0) && st.st_dev == nst.st_dev &&
4574 st.st_ino == nst.st_ino))
4575 addlinknode(ign, quotestring(n, NULL, QT_BACKSLASH));
4581 static LinkList
4582 cf_remove_other(char **names, char *pre, int *amb)
4584 char *p;
4586 if ((p = strchr(pre, '/'))) {
4587 char **n;
4589 *p = '\0';
4590 pre = dyncat(pre, "/");
4591 *p = '/';
4593 for (n = names; *n; n++)
4594 if (strpfx(pre, *n))
4595 break;
4597 if (*n) {
4598 LinkList ret = newlinklist();
4600 for (; *names; names++)
4601 if (strpfx(pre, *names))
4602 addlinknode(ret, dupstring(*names));
4604 *amb = 0;
4606 return ret;
4607 } else {
4608 if (!(p = *names++))
4609 *amb = 0;
4610 else {
4611 char *q;
4613 if ((q = strchr((p = dupstring(p)), '/')))
4614 *q = '\0';
4616 p = dyncat(p, "/");
4618 for (; *names; names++)
4619 if (!strpfx(p, *names)) {
4620 *amb = 1;
4621 return NULL;
4625 } else {
4626 if (!(p = *names++))
4627 *amb = 0;
4628 else
4629 for (; *names; names++)
4630 if (strcmp(p, *names)) {
4631 *amb = 1;
4632 return NULL;
4635 return NULL;
4638 static int
4639 bin_compfiles(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
4641 if (incompfunc != 1) {
4642 zwarnnam(nam, "can only be called from completion function");
4643 return 1;
4645 if (**args != '-') {
4646 zwarnnam(nam, "missing option: %s", *args);
4647 return 1;
4649 switch (args[0][1]) {
4650 case 'p':
4651 case 'P':
4652 if (args[0][2] && (args[0][2] != '-' || args[0][3])) {
4653 zwarnnam(nam, "invalid option: %s", *args);
4654 return 1;
4655 } else {
4656 char **tmp;
4657 LinkList l;
4659 if (!args[1] || !args[2] || !args[3] || !args[4] || !args[5] ||
4660 !args[6] || (args[0][1] == 'p' && !args[7])) {
4661 zwarnnam(nam, "too few arguments");
4662 return 1;
4664 queue_signals();
4665 if (!(tmp = getaparam(args[1]))) {
4666 zwarnnam(nam, "unknown parameter: %s", args[1]);
4667 return 0;
4669 for (l = newlinklist(); *tmp; tmp++)
4670 addlinknode(l, *tmp);
4671 set_list_array(args[1], cf_pats((args[0][1] == 'P'), !!args[0][2],
4672 l, getaparam(args[2]), args[3],
4673 args[4], args[5],
4674 getaparam(args[6]), args + 7));
4675 unqueue_signals();
4676 return 0;
4678 case 'i':
4679 if (args[0][2]) {
4680 zwarnnam(nam, "invalid option: %s", *args);
4681 return 1;
4682 } else {
4683 char **tmp;
4684 LinkList l;
4686 if (!args[1] || !args[2] || !args[3] || !args[4]) {
4687 zwarnnam(nam, "too few arguments");
4688 return 1;
4690 if (args[5]) {
4691 zwarnnam(nam, "too many arguments");
4692 return 1;
4694 queue_signals();
4695 tmp = getaparam(args[2]);
4696 l = newlinklist();
4697 if (tmp)
4698 for (; *tmp; tmp++)
4699 addlinknode(l, *tmp);
4700 if (!(tmp = getaparam(args[1]))) {
4701 unqueue_signals();
4702 zwarnnam(nam, "unknown parameter: %s", args[1]);
4703 return 0;
4705 cf_ignore(tmp, l, args[3], args[4]);
4706 unqueue_signals();
4707 set_list_array(args[2], l);
4708 return 0;
4710 case 'r':
4712 char **tmp;
4713 LinkList l;
4714 int ret = 0;
4716 if (!args[1] || !args[2]) {
4717 zwarnnam(nam, "too few arguments");
4718 return 1;
4720 if (args[3]) {
4721 zwarnnam(nam, "too many arguments");
4722 return 1;
4724 queue_signals();
4725 if (!(tmp = getaparam(args[1]))) {
4726 unqueue_signals();
4727 zwarnnam(nam, "unknown parameter: %s", args[1]);
4728 return 0;
4730 if ((l = cf_remove_other(tmp, args[2], &ret)))
4731 set_list_array(args[1], l);
4732 unqueue_signals();
4733 return ret;
4736 zwarnnam(nam, "invalid option: %s", *args);
4737 return 1;
4740 static int
4741 bin_compgroups(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
4743 Heap oldheap;
4744 char *n;
4746 if (incompfunc != 1) {
4747 zwarnnam(nam, "can only be called from completion function");
4748 return 1;
4750 SWITCHHEAPS(oldheap, compheap) {
4751 while ((n = *args++)) {
4752 endcmgroup(NULL);
4753 begcmgroup(n, CGF_NOSORT|CGF_UNIQCON);
4754 endcmgroup(NULL);
4755 begcmgroup(n, CGF_UNIQALL);
4756 endcmgroup(NULL);
4757 begcmgroup(n, CGF_NOSORT|CGF_UNIQCON);
4758 endcmgroup(NULL);
4759 begcmgroup(n, CGF_UNIQALL);
4760 endcmgroup(NULL);
4761 begcmgroup(n, CGF_NOSORT);
4762 endcmgroup(NULL);
4763 begcmgroup(n, 0);
4765 } SWITCHBACKHEAPS(oldheap);
4767 return 0;
4770 static struct builtin bintab[] = {
4771 BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL),
4772 BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
4773 BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL),
4774 BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL),
4775 BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, "p", NULL),
4776 BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL),
4777 BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL),
4778 BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL)
4781 static struct features module_features = {
4782 bintab, sizeof(bintab)/sizeof(*bintab),
4783 NULL, 0,
4784 NULL, 0,
4785 NULL, 0,
4790 /**/
4792 setup_(UNUSED(Module m))
4794 memset(cadef_cache, 0, sizeof(cadef_cache));
4795 memset(cvdef_cache, 0, sizeof(cvdef_cache));
4797 memset(comptags, 0, sizeof(comptags));
4799 lasttaglevel = 0;
4801 return 0;
4804 /**/
4806 features_(Module m, char ***features)
4808 *features = featuresarray(m, &module_features);
4809 return 0;
4812 /**/
4814 enables_(Module m, int **enables)
4816 return handlefeatures(m, &module_features, enables);
4819 /**/
4821 boot_(Module m)
4823 return 0;
4826 /**/
4828 cleanup_(Module m)
4830 return setfeatureenables(m, &module_features, NULL);
4833 /**/
4835 finish_(UNUSED(Module m))
4837 int i;
4839 for (i = 0; i < MAX_CACACHE; i++)
4840 freecadef(cadef_cache[i]);
4841 for (i = 0; i < MAX_CVCACHE; i++)
4842 freecvdef(cvdef_cache[i]);
4844 for (i = 0; i < MAX_TAGS; i++)
4845 freectags(comptags[i]);
4847 return 0;