1/*
2 * compctl.c - the compctl builtin
3 *
4 * This file is part of zsh, the Z shell.
5 *
6 * Copyright (c) 1992-1997 Paul Falstad
7 * All rights reserved.
8 *
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.
14 *
15 * In no event shall Paul Falstad 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 Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
20 *
21 * Paul Falstad 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 Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
27 *
28 */
29
30#include "compctl.mdh"
31#include "compctl.pro"
32
33/* Global matcher. */
34
35/**/
36static Cmlist cmatcher;
37
38/* Default completion infos */
39
40/**/
41struct compctl cc_compos, cc_default, cc_first, cc_dummy;
42
43/* Hash table for completion info for commands */
44
45/**/
46HashTable compctltab;
47
48/* List of pattern compctls */
49
50/**/
51Patcomp patcomps;
52
53#define COMP_LIST	(1<<0)	/* -L */
54#define COMP_COMMAND	(1<<1)	/* -C */
55#define COMP_DEFAULT	(1<<2)	/* -D */
56#define COMP_FIRST	(1<<3)	/* -T */
57#define COMP_REMOVE	(1<<4)
58#define COMP_LISTMATCH	(1<<5)	/* -L and -M */
59
60#define COMP_SPECIAL (COMP_COMMAND|COMP_DEFAULT|COMP_FIRST)
61
62/* Flag for listing, command, default, or first completion */
63static int cclist;
64
65/* Mask for determining what to print */
66static unsigned long showmask = 0;
67
68/**/
69static void
70createcompctltable(void)
71{
72    compctltab = newhashtable(23, "compctltab", NULL);
73
74    compctltab->hash        = hasher;
75    compctltab->emptytable  = emptyhashtable;
76    compctltab->filltable   = NULL;
77    compctltab->cmpnodes    = strcmp;
78    compctltab->addnode     = addhashnode;
79    compctltab->getnode     = gethashnode2;
80    compctltab->getnode2    = gethashnode2;
81    compctltab->removenode  = removehashnode;
82    compctltab->disablenode = NULL;
83    compctltab->enablenode  = NULL;
84    compctltab->freenode    = freecompctlp;
85    compctltab->printnode   = printcompctlp;
86
87    patcomps = NULL;
88}
89
90/**/
91static void
92freecompctlp(HashNode hn)
93{
94    Compctlp ccp = (Compctlp) hn;
95
96    zsfree(ccp->node.nam);
97    freecompctl(ccp->cc);
98    zfree(ccp, sizeof(struct compctlp));
99}
100
101/**/
102void
103freecompctl(Compctl cc)
104{
105    if (cc == &cc_default ||
106 	cc == &cc_first ||
107	cc == &cc_compos ||
108	--cc->refc > 0)
109	return;
110
111    zsfree(cc->keyvar);
112    zsfree(cc->glob);
113    zsfree(cc->str);
114    zsfree(cc->func);
115    zsfree(cc->explain);
116    zsfree(cc->ylist);
117    zsfree(cc->prefix);
118    zsfree(cc->suffix);
119    zsfree(cc->hpat);
120    zsfree(cc->gname);
121    zsfree(cc->subcmd);
122    zsfree(cc->substr);
123    if (cc->cond)
124	freecompcond(cc->cond);
125    if (cc->ext) {
126	Compctl n, m;
127
128	n = cc->ext;
129	do {
130	    m = (Compctl) (n->next);
131	    freecompctl(n);
132	    n = m;
133	}
134	while (n);
135    }
136    if (cc->xor && cc->xor != &cc_default)
137	freecompctl(cc->xor);
138    if (cc->matcher)
139	freecmatcher(cc->matcher);
140    zsfree(cc->mstr);
141    zfree(cc, sizeof(struct compctl));
142}
143
144/**/
145void
146freecompcond(void *a)
147{
148    Compcond cc = (Compcond) a;
149    Compcond and, or, c;
150    int n;
151
152    for (c = cc; c; c = or) {
153	or = c->or;
154	for (; c; c = and) {
155	    and = c->and;
156	    if (c->type == CCT_POS ||
157		c->type == CCT_NUMWORDS) {
158		free(c->u.r.a);
159		free(c->u.r.b);
160	    } else if (c->type == CCT_CURSUF ||
161		       c->type == CCT_CURPRE) {
162		for (n = 0; n < c->n; n++)
163		    if (c->u.s.s[n])
164			zsfree(c->u.s.s[n]);
165		free(c->u.s.s);
166	    } else if (c->type == CCT_RANGESTR ||
167		       c->type == CCT_RANGEPAT) {
168		for (n = 0; n < c->n; n++)
169		    if (c->u.l.a[n])
170			zsfree(c->u.l.a[n]);
171		free(c->u.l.a);
172		for (n = 0; n < c->n; n++)
173		    if (c->u.l.b[n])
174			zsfree(c->u.l.b[n]);
175		free(c->u.l.b);
176	    } else {
177		for (n = 0; n < c->n; n++)
178		    if (c->u.s.s[n])
179			zsfree(c->u.s.s[n]);
180		free(c->u.s.p);
181		free(c->u.s.s);
182	    }
183	    zfree(c, sizeof(struct compcond));
184	}
185    }
186}
187
188/**/
189int
190compctlread(char *name, char **args, Options ops, char *reply)
191{
192    char *buf, *bptr;
193
194    /* only allowed to be called for completion */
195    if (!incompctlfunc) {
196	zwarnnam(name, "option valid only in functions called for completion");
197	return 1;
198    }
199
200    METACHECK();
201
202    if (OPT_ISSET(ops,'l')) {
203	/*
204	 * -ln gives the index of the word the cursor is currently on, which
205	 * is available in zlemetacs (but remember that Zsh counts from one,
206	 * not zero!)
207	 */
208	if (OPT_ISSET(ops,'n')) {
209	    char nbuf[14];
210
211	    if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E'))
212		printf("%d\n", zlemetacs + 1);
213	    if (!OPT_ISSET(ops,'e')) {
214		sprintf(nbuf, "%d", zlemetacs + 1);
215		setsparam(reply, ztrdup(nbuf));
216	    }
217	    return 0;
218	}
219	/* without -n, the current line is assigned to the given parameter as a
220	scalar */
221	if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E')) {
222	    zputs(zlemetaline, stdout);
223	    putchar('\n');
224	}
225	if (!OPT_ISSET(ops,'e'))
226	    setsparam(reply, ztrdup(zlemetaline));
227    } else {
228	int i;
229
230	/* -cn gives the current cursor position within the current word, which
231	is available in clwpos (but remember that Zsh counts from one, not
232	zero!) */
233	if (OPT_ISSET(ops,'n')) {
234	    char nbuf[14];
235
236	    if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E'))
237		printf("%d\n", clwpos + 1);
238	    if (!OPT_ISSET(ops,'e')) {
239		sprintf(nbuf, "%d", clwpos + 1);
240		setsparam(reply, ztrdup(nbuf));
241	    }
242	    return 0;
243	}
244	/* without -n, the words of the current line are assigned to the given
245	parameters separately */
246	if (OPT_ISSET(ops,'A') && !OPT_ISSET(ops,'e')) {
247	    /* the -A option means that one array is specified, instead of
248	    many parameters */
249	    char **p, **b = (char **)zshcalloc((clwnum + 1) * sizeof(char *));
250
251	    for (i = 0, p = b; i < clwnum; p++, i++)
252		*p = ztrdup(clwords[i]);
253
254	    setaparam(reply, b);
255	    return 0;
256	}
257	if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E')) {
258	    for (i = 0; i < clwnum; i++) {
259		zputs(clwords[i], stdout);
260		putchar('\n');
261	    }
262
263	    if (OPT_ISSET(ops,'e'))
264		return 0;
265	}
266
267	for (i = 0; i < clwnum && *args; reply = *args++, i++)
268	    setsparam(reply, ztrdup(clwords[i]));
269
270	if (i < clwnum) {
271	    int j, len;
272
273	    for (j = i, len = 0; j < clwnum; len += strlen(clwords[j++]));
274	    bptr = buf = zalloc(len + j - i);
275	    while (i < clwnum) {
276		strucpy(&bptr, clwords[i++]);
277		*bptr++ = ' ';
278	    }
279	    bptr[-1] = '\0';
280	} else
281	    buf = ztrdup("");
282	setsparam(reply, buf);
283    }
284    return 0;
285}
286
287/* Copy a list of completion matchers. */
288
289/**/
290static Cmlist
291cpcmlist(Cmlist l)
292{
293    Cmlist r = NULL, *p = &r, n;
294
295    while (l) {
296	*p = n = (Cmlist) zalloc(sizeof(struct cmlist));
297	n->next = NULL;
298	n->matcher = cpcmatcher(l->matcher);
299	n->str = ztrdup(l->str);
300
301	p = &(n->next);
302	l = l->next;
303    }
304    return r;
305}
306
307/* Set the global match specs. */
308
309/**/
310static int
311set_gmatcher(char *name, char **argv)
312{
313    Cmlist l = NULL, *q = &l, n;
314    Cmatcher m;
315
316    while (*argv) {
317	if ((m = parse_cmatcher(name, *argv)) == pcm_err)
318	    return 1;
319	*q = n = (Cmlist) zhalloc(sizeof(struct cmlist));
320	n->next = NULL;
321	n->matcher = m;
322	n->str = *argv++;
323
324	q = &(n->next);
325    }
326    freecmlist(cmatcher);
327    cmatcher = cpcmlist(l);
328
329    return 1;
330}
331
332/* Try to get the global matcher from the given compctl. */
333
334/**/
335static int
336get_gmatcher(char *name, char **argv)
337{
338    if (!strcmp(*argv, "-M")) {
339	char **p = ++argv;
340
341	while (*p) {
342	    if (**p++ == '-')
343		return 0;
344	}
345	if (set_gmatcher(name, argv))
346	    return 2;
347
348	return 1;
349    }
350    return 0;
351}
352
353/* This prints the global matcher definitions. */
354
355/**/
356static void
357print_gmatcher(int ac)
358{
359    Cmlist p;
360
361    if ((p = cmatcher)) {
362	printf((ac ? "compctl -M" : "MATCH"));
363
364	while (p) {
365	    printf(" \'%s\'", p->str);
366
367	    p = p->next;
368	}
369	putchar('\n');
370    }
371}
372
373/* Parse the basic flags for `compctl' */
374
375/**/
376static int
377get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
378{
379    /* Parse the basic flags for completion:
380     * first is a flag that we are not in extended completion,
381     * while hx indicates or (+) completion (need to know for
382     * default and command completion as the initial compctl is special).
383     * cct is a temporary just to hold flags; it never needs freeing.
384     */
385    struct compctl cct;
386    char **argv = *av;
387    int ready = 0, hx = 0;
388
389    /* Handle `compctl + foo ...' specially:  turn it into
390     * a default compctl by removing it from the hash table.
391     */
392    if (first && argv[0][0] == '+' && !argv[0][1] &&
393	!(argv[1] && argv[1][0] == '-' && argv[1][1])) {
394	argv++;
395	if(argv[0] && argv[0][0] == '-')
396	    argv++;
397	*av = argv;
398	if (cl)
399	    return 1;
400	else {
401	    freecompctl(cc);
402	    cclist = COMP_REMOVE;
403	    return 0;
404	}
405    }
406
407    memset((void *)&cct, 0, sizeof(cct));
408    cct.mask2 = CC_CCCONT;
409
410    /* Loop through the flags until we have no more:        *
411     * those with arguments are not properly allocated yet, *
412     * we just hang on to the argument that was passed.     */
413    for (; !ready && argv[0] && argv[0][0] == '-' && (argv[0][1] || !first);) {
414	if (!argv[0][1])
415	    *argv = "-+";
416	while (!ready && *++(*argv)) {
417	    if(**argv == Meta)
418		*++*argv ^= 32;
419	    switch (**argv) {
420	    case 'f':
421		cct.mask |= CC_FILES;
422		break;
423	    case 'c':
424		cct.mask |= CC_COMMPATH;
425		break;
426	    case 'm':
427		cct.mask |= CC_EXTCMDS;
428		break;
429	    case 'w':
430		cct.mask |= CC_RESWDS;
431		break;
432	    case 'o':
433		cct.mask |= CC_OPTIONS;
434		break;
435	    case 'v':
436		cct.mask |= CC_VARS;
437		break;
438	    case 'b':
439		cct.mask |= CC_BINDINGS;
440		break;
441	    case 'A':
442		cct.mask |= CC_ARRAYS;
443		break;
444	    case 'I':
445		cct.mask |= CC_INTVARS;
446		break;
447	    case 'F':
448		cct.mask |= CC_SHFUNCS;
449		break;
450	    case 'p':
451		cct.mask |= CC_PARAMS;
452		break;
453	    case 'E':
454		cct.mask |= CC_ENVVARS;
455		break;
456	    case 'j':
457		cct.mask |= CC_JOBS;
458		break;
459	    case 'r':
460		cct.mask |= CC_RUNNING;
461		break;
462	    case 'z':
463		cct.mask |= CC_STOPPED;
464		break;
465	    case 'B':
466		cct.mask |= CC_BUILTINS;
467		break;
468	    case 'a':
469		cct.mask |= CC_ALREG | CC_ALGLOB;
470		break;
471	    case 'R':
472		cct.mask |= CC_ALREG;
473		break;
474	    case 'G':
475		cct.mask |= CC_ALGLOB;
476		break;
477	    case 'u':
478		cct.mask |= CC_USERS;
479		break;
480	    case 'd':
481		cct.mask |= CC_DISCMDS;
482		break;
483	    case 'e':
484		cct.mask |= CC_EXCMDS;
485		break;
486	    case 'N':
487		cct.mask |= CC_SCALARS;
488		break;
489	    case 'O':
490		cct.mask |= CC_READONLYS;
491		break;
492	    case 'Z':
493		cct.mask |= CC_SPECIALS;
494		break;
495	    case 'q':
496		cct.mask |= CC_REMOVE;
497		break;
498	    case 'U':
499		cct.mask |= CC_DELETE;
500		break;
501	    case 'n':
502		cct.mask |= CC_NAMED;
503		break;
504	    case 'Q':
505		cct.mask |= CC_QUOTEFLAG;
506		break;
507	    case '/':
508		cct.mask |= CC_DIRS;
509		break;
510	    case 't':
511		{
512		    char *p;
513
514		    if (cl) {
515			zwarnnam(name, "illegal option -%c", **argv);
516			return 1;
517		    }
518		    if ((*argv)[1]) {
519			p = (*argv) + 1;
520			*argv = "" - 1;
521		    } else if (!argv[1]) {
522			zwarnnam(name, "retry specification expected after -%c",
523				 **argv);
524			return 1;
525		    } else {
526			p = *++argv;
527			*argv = "" - 1;
528		    }
529		    switch (*p) {
530		    case '+':
531			cct.mask2 = CC_XORCONT;
532			break;
533		    case 'n':
534			cct.mask2 = 0;
535			break;
536		    case '-':
537			cct.mask2 = CC_PATCONT;
538			break;
539		    case 'x':
540			cct.mask2 = CC_DEFCONT;
541			break;
542		    default:
543			zwarnnam(name, "invalid retry specification character `%c'",
544				 *p);
545			return 1;
546		    }
547		    if (p[1]) {
548			zwarnnam(name, "too many retry specification characters: `%s'",
549				 p + 1);
550			return 1;
551		    }
552		}
553		break;
554	    case 'k':
555		if ((*argv)[1]) {
556		    cct.keyvar = (*argv) + 1;
557		    *argv = "" - 1;
558		} else if (!argv[1]) {
559		    zwarnnam(name, "variable name expected after -%c", **argv);
560		    return 1;
561		} else {
562		    cct.keyvar = *++argv;
563		    *argv = "" - 1;
564		}
565		break;
566	    case 'K':
567		if ((*argv)[1]) {
568		    cct.func = (*argv) + 1;
569		    *argv = "" - 1;
570		} else if (!argv[1]) {
571		    zwarnnam(name, "function name expected after -%c", **argv);
572		    return 1;
573		} else {
574		    cct.func = *++argv;
575		    *argv = "" - 1;
576		}
577		break;
578	    case 'Y':
579		cct.mask |= CC_EXPANDEXPL;
580		goto expl;
581	    case 'X':
582		cct.mask &= ~CC_EXPANDEXPL;
583	    expl:
584		if ((*argv)[1]) {
585		    cct.explain = (*argv) + 1;
586		    *argv = "" - 1;
587		} else if (!argv[1]) {
588		    zwarnnam(name, "string expected after -%c", **argv);
589		    return 1;
590		} else {
591		    cct.explain = *++argv;
592		    *argv = "" - 1;
593		}
594		break;
595	    case 'y':
596		if ((*argv)[1]) {
597		    cct.ylist = (*argv) + 1;
598		    *argv = "" - 1;
599		} else if (!argv[1]) {
600		    zwarnnam(name, "function/variable expected after -%c",
601			     **argv);
602		} else {
603		    cct.ylist = *++argv;
604		    *argv = "" - 1;
605		}
606		break;
607	    case 'P':
608		if ((*argv)[1]) {
609		    cct.prefix = (*argv) + 1;
610		    *argv = "" - 1;
611		} else if (!argv[1]) {
612		    zwarnnam(name, "string expected after -%c", **argv);
613		    return 1;
614		} else {
615		    cct.prefix = *++argv;
616		    *argv = "" - 1;
617		}
618		break;
619	    case 'S':
620		if ((*argv)[1]) {
621		    cct.suffix = (*argv) + 1;
622		    *argv = "" - 1;
623		} else if (!argv[1]) {
624		    zwarnnam(name, "string expected after -%c", **argv);
625		    return 1;
626		} else {
627		    cct.suffix = *++argv;
628		    *argv = "" - 1;
629		}
630		break;
631	    case 'g':
632		if ((*argv)[1]) {
633		    cct.glob = (*argv) + 1;
634		    *argv = "" - 1;
635		} else if (!argv[1]) {
636		    zwarnnam(name, "glob pattern expected after -%c", **argv);
637		    return 1;
638		} else {
639		    cct.glob = *++argv;
640		    *argv = "" - 1;
641		}
642		break;
643	    case 's':
644		if ((*argv)[1]) {
645		    cct.str = (*argv) + 1;
646		    *argv = "" - 1;
647		} else if (!argv[1]) {
648		    zwarnnam(name, "command string expected after -%c",
649			     **argv);
650		    return 1;
651		} else {
652		    cct.str = *++argv;
653		    *argv = "" - 1;
654		}
655		break;
656	    case 'l':
657		if (cl) {
658		    zwarnnam(name, "illegal option -%c", **argv);
659		    return 1;
660		} else if ((*argv)[1]) {
661		    cct.subcmd = (*argv) + 1;
662		    *argv = "" - 1;
663		} else if (!argv[1]) {
664		    zwarnnam(name, "command name expected after -%c", **argv);
665		    return 1;
666		} else {
667		    cct.subcmd = *++argv;
668		    *argv = "" - 1;
669		}
670		break;
671	    case 'h':
672		if (cl) {
673		    zwarnnam(name, "illegal option -%c", **argv);
674		    return 1;
675		} else if ((*argv)[1]) {
676		    cct.substr = (*argv) + 1;
677		    *argv = "" - 1;
678		} else if (!argv[1]) {
679		    zwarnnam(name, "command name expected after -%c", **argv);
680		    return 1;
681		} else {
682		    cct.substr = *++argv;
683		    *argv = "" - 1;
684		}
685		break;
686	    case 'W':
687		if ((*argv)[1]) {
688		    cct.withd = (*argv) + 1;
689		    *argv = "" - 1;
690		} else if (!argv[1]) {
691		    zwarnnam(name, "path expected after -%c", **argv);
692		    return 1;
693		} else {
694		    cct.withd = *++argv;
695		    *argv = "" - 1;
696		}
697		break;
698	    case 'J':
699		if ((*argv)[1]) {
700		    cct.gname = (*argv) + 1;
701		    *argv = "" - 1;
702		} else if (!argv[1]) {
703		    zwarnnam(name, "group name expected after -%c", **argv);
704		    return 1;
705		} else {
706		    cct.gname = *++argv;
707		    *argv = "" - 1;
708		}
709		break;
710	    case 'V':
711		if ((*argv)[1]) {
712		    cct.gname = (*argv) + 1;
713		    *argv = "" - 1;
714		} else if (!argv[1]) {
715		    zwarnnam(name, "group name expected after -%c", **argv);
716		    return 1;
717		} else {
718		    cct.gname = *++argv;
719		    *argv = "" - 1;
720		}
721		cct.mask2 |= CC_NOSORT;
722		break;
723	    case '1':
724		cct.mask2 |= CC_UNIQALL;
725		cct.mask2 &= ~CC_UNIQCON;
726		break;
727	    case '2':
728		cct.mask2 |= CC_UNIQCON;
729		cct.mask2 &= ~CC_UNIQALL;
730		break;
731	    case 'M':
732		if (cclist & COMP_LIST) {
733		    cclist |= COMP_LISTMATCH;
734		} else if ((*argv)[1]) {
735		    if ((cct.matcher =
736			 parse_cmatcher(name, (cct.mstr = (*argv) + 1))) ==
737			pcm_err) {
738			cct.matcher = NULL;
739			cct.mstr = NULL;
740			return 1;
741		    }
742		    *argv = "" - 1;
743		} else if (!argv[1]) {
744		    zwarnnam(name, "matching specification expected after -%c",
745			     **argv);
746		    return 1;
747		} else {
748		    if ((cct.matcher =
749			 parse_cmatcher(name, (cct.mstr = *++argv))) ==
750			pcm_err) {
751			cct.matcher = NULL;
752			cct.mstr = NULL;
753			return 1;
754		    }
755		    *argv = "" - 1;
756		}
757		break;
758	    case 'H':
759		if ((*argv)[1])
760		    cct.hnum = atoi((*argv) + 1);
761		else if (argv[1])
762		    cct.hnum = atoi(*++argv);
763		else {
764		    zwarnnam(name, "number expected after -%c", **argv);
765		    return 1;
766		}
767		if (!argv[1]) {
768		    zwarnnam(name, "missing pattern after -%c", **argv);
769		    return 1;
770		}
771		cct.hpat = *++argv;
772		if (cct.hnum < 1)
773		    cct.hnum = 0;
774		if (*cct.hpat == '*' && !cct.hpat[1])
775		    cct.hpat = "";
776		*argv = "" - 1;
777		break;
778	    case 'C':
779		if (cl) {
780		    zwarnnam(name, "illegal option -%c", **argv);
781		    return 1;
782		}
783		if (first && !hx) {
784		    cclist |= COMP_COMMAND;
785		} else {
786		    zwarnnam(name, "misplaced command completion (-C) flag");
787		    return 1;
788		}
789		break;
790	    case 'D':
791		if (cl) {
792		    zwarnnam(name, "illegal option -%c", **argv);
793		    return 1;
794		}
795		if (first && !hx) {
796		    isdef = 1;
797		    cclist |= COMP_DEFAULT;
798		} else {
799		    zwarnnam(name, "misplaced default completion (-D) flag");
800		    return 1;
801		}
802		break;
803 	    case 'T':
804		if (cl) {
805		    zwarnnam(name, "illegal option -%c", **argv);
806		    return 1;
807		}
808		if (first && !hx) {
809 		    cclist |= COMP_FIRST;
810 		} else {
811 		    zwarnnam(name, "misplaced first completion (-T) flag");
812 		    return 1;
813 		}
814 		break;
815	    case 'L':
816		if (cl) {
817		    zwarnnam(name, "illegal option -%c", **argv);
818		    return 1;
819		}
820		if (!first || hx) {
821		    zwarnnam(name, "illegal use of -L flag");
822		    return 1;
823		}
824		cclist |= COMP_LIST;
825		break;
826	    case 'x':
827		if (cl) {
828		    zwarnnam(name, "extended completion not allowed");
829		    return 1;
830		}
831		if (!argv[1]) {
832		    zwarnnam(name, "condition expected after -%c", **argv);
833		    return 1;
834		}
835		if (first) {
836		    argv++;
837		    if (get_xcompctl(name, &argv, &cct, isdef)) {
838			if (cct.ext)
839			    freecompctl(cct.ext);
840			return 1;
841		    }
842		    ready = 2;
843		} else {
844		    zwarnnam(name, "recursive extended completion not allowed");
845		    return 1;
846		}
847		break;
848	    default:
849		if (!first && (**argv == '-' || **argv == '+') && !argv[0][1])
850		    (*argv)--, argv--, ready = 1;
851		else {
852		    zwarnnam(name, "bad option: -%c", **argv);
853		    return 1;
854		}
855	    }
856	}
857
858	if (*++argv && (!ready || ready == 2) &&
859	    **argv == '+' && !argv[0][1]) {
860	    if (cl) {
861		zwarnnam(name, "xor'ed completion illegal");
862		return 1;
863	    }
864	    /* There's an alternative (+) completion:  assign
865	     * what we have so far before moving on to that.
866	     */
867	    if (cc_assign(name, &cc, &cct, first && !hx))
868		return 1;
869
870	    hx = 1;
871	    ready = 0;
872
873	    if (!*++argv || **argv != '-' ||
874		(**argv == '-' && (!argv[0][1] ||
875				   (argv[0][1] == '-' && !argv[0][2])))) {
876		/* No argument to +, which means do default completion */
877		if (isdef)
878		    zwarnnam(name,
879			    "recursive xor'd default completions not allowed");
880		else
881		    cc->xor = &cc_default;
882	    } else {
883		/* more flags follow:  prepare to loop again */
884		cc->xor = (Compctl) zshcalloc(sizeof(*cc));
885		cc = cc->xor;
886		memset((void *)&cct, 0, sizeof(cct));
887		cct.mask2 = CC_CCCONT;
888	    }
889	}
890    }
891    if (!ready && *argv && **argv == '-')
892	argv++;
893
894    if (! (cct.mask & (CC_EXCMDS | CC_DISCMDS)))
895	cct.mask |= CC_EXCMDS;
896
897    /* assign the last set of flags we parsed */
898    if (cc_assign(name, &cc, &cct, first && !hx))
899	return 1;
900
901    *av = argv;
902
903    return 0;
904}
905
906/* Handle the -x ... -- part of compctl. */
907
908/**/
909static int
910get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
911{
912    char **argv = *av, *t, *tt, sav;
913    int n, l = 0, ready = 0;
914    Compcond m, c, o;
915    Compctl *next = &(cc->ext);
916
917    while (!ready) {
918	/* o keeps track of or's, m remembers the starting condition,
919	 * c is the current condition being parsed
920	 */
921	o = m = c = (Compcond) zshcalloc(sizeof(*c));
922	/* Loop over each condition:  something like 's[...][...], p[...]' */
923	for (t = *argv; *t;) {
924	    while (*t == ' ')
925		t++;
926	    /* First get the condition code */
927	    switch (*t) {
928	    case 'q':
929		c->type = CCT_QUOTE;
930		break;
931	    case 's':
932		c->type = CCT_CURSUF;
933		break;
934	    case 'S':
935		c->type = CCT_CURPRE;
936		break;
937	    case 'p':
938		c->type = CCT_POS;
939		break;
940	    case 'c':
941		c->type = CCT_CURSTR;
942		break;
943	    case 'C':
944		c->type = CCT_CURPAT;
945		break;
946	    case 'w':
947		c->type = CCT_WORDSTR;
948		break;
949	    case 'W':
950		c->type = CCT_WORDPAT;
951		break;
952	    case 'n':
953		c->type = CCT_CURSUB;
954		break;
955	    case 'N':
956		c->type = CCT_CURSUBC;
957		break;
958	    case 'm':
959		c->type = CCT_NUMWORDS;
960		break;
961	    case 'r':
962		c->type = CCT_RANGESTR;
963		break;
964	    case 'R':
965		c->type = CCT_RANGEPAT;
966		break;
967	    default:
968		t[1] = '\0';
969		zwarnnam(name, "unknown condition code: %s", t);
970		zfree(m, sizeof(struct compcond));
971
972		return 1;
973	    }
974	    /* Now get the arguments in square brackets */
975	    if (t[1] != '[') {
976		t[1] = '\0';
977		zwarnnam(name, "expected condition after condition code: %s", t);
978		zfree(m, sizeof(struct compcond));
979
980		return 1;
981	    }
982	    t++;
983	    /* First count how many or'd arguments there are,
984	     * marking the active ]'s and ,'s with unprintable characters.
985	     */
986	    for (n = 0, tt = t; *tt == '['; n++) {
987		for (l = 1, tt++; *tt && l; tt++)
988		    if (*tt == '\\' && tt[1])
989			tt++;
990		    else if (*tt == '[')
991			l++;
992		    else if (*tt == ']')
993			l--;
994		    else if (l == 1 && *tt == ',')
995			*tt = '\201';
996		if (tt[-1] == ']')
997		    tt[-1] = '\200';
998	    }
999
1000	    if (l) {
1001		t[1] = '\0';
1002		zwarnnam(name, "error after condition code: %s", t);
1003		zfree(m, sizeof(struct compcond));
1004
1005		return 1;
1006	    }
1007	    c->n = n;
1008
1009	    /* Allocate space for all the arguments of the conditions */
1010	    if (c->type == CCT_POS ||
1011		c->type == CCT_NUMWORDS) {
1012		c->u.r.a = (int *)zshcalloc(n * sizeof(int));
1013		c->u.r.b = (int *)zshcalloc(n * sizeof(int));
1014	    } else if (c->type == CCT_CURSUF ||
1015		       c->type == CCT_CURPRE ||
1016		       c->type == CCT_QUOTE)
1017		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
1018
1019	    else if (c->type == CCT_RANGESTR ||
1020		     c->type == CCT_RANGEPAT) {
1021		c->u.l.a = (char **)zshcalloc(n * sizeof(char *));
1022		c->u.l.b = (char **)zshcalloc(n * sizeof(char *));
1023	    } else {
1024		c->u.s.p = (int *)zshcalloc(n * sizeof(int));
1025		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
1026	    }
1027	    /* Now loop over the actual arguments */
1028	    for (l = 0; *t == '['; l++, t++) {
1029		for (t++; *t && *t == ' '; t++);
1030		tt = t;
1031		if (c->type == CCT_POS ||
1032		    c->type == CCT_NUMWORDS) {
1033		    /* p[...] or m[...]:  one or two numbers expected */
1034		    for (; *t && *t != '\201' && *t != '\200'; t++);
1035		    if (!(sav = *t)) {
1036			zwarnnam(name, "error in condition");
1037			freecompcond(m);
1038			return 1;
1039		    }
1040		    *t = '\0';
1041		    c->u.r.a[l] = atoi(tt);
1042		    /* Second argument is optional:  see if it's there */
1043		    if (sav == '\200')
1044			/* no:  copy first argument */
1045			c->u.r.b[l] = c->u.r.a[l];
1046		    else {
1047			tt = ++t;
1048			for (; *t && *t != '\200'; t++);
1049			if (!*t) {
1050			    zwarnnam(name, "error in condition");
1051			    freecompcond(m);
1052			    return 1;
1053			}
1054			*t = '\0';
1055			c->u.r.b[l] = atoi(tt);
1056		    }
1057		} else if (c->type == CCT_CURSUF ||
1058			   c->type == CCT_CURPRE ||
1059			   c->type == CCT_QUOTE) {
1060		    /* -s[..] or -S[..]:  single string expected */
1061		    for (; *t && *t != '\200'; t++)
1062			if (*t == '\201')
1063			    *t = ',';
1064		    if (!*t) {
1065			zwarnnam(name, "error in condition");
1066			freecompcond(m);
1067			return 1;
1068		    }
1069		    *t = '\0';
1070		    c->u.s.s[l] = ztrdup(tt);
1071		} else if (c->type == CCT_RANGESTR ||
1072			   c->type == CCT_RANGEPAT) {
1073		    int hc;
1074
1075		    /* -r[..,..] or -R[..,..]:  two strings expected */
1076		    for (; *t && *t != '\201' && *t != '\200'; t++);
1077		    if (!*t) {
1078			zwarnnam(name, "error in condition");
1079			freecompcond(m);
1080			return 1;
1081		    }
1082		    hc = (*t == '\201');
1083		    *t = '\0';
1084		    c->u.l.a[l] = ztrdup(tt);
1085		    if (hc) {
1086			tt = ++t;
1087			/* any more commas are text, not active */
1088			for (; *t && *t != '\200'; t++)
1089			    if (*t == '\201')
1090				*t = ',';
1091			if (!*t) {
1092			    zwarnnam(name, "error in condition");
1093			    freecompcond(m);
1094			    return 1;
1095			}
1096			*t = '\0';
1097			c->u.l.b[l] = ztrdup(tt);
1098		    }
1099		    else
1100			c->u.l.b[l] = NULL;
1101		} else {
1102		    /* remaining patterns are number followed by string */
1103		    for (; *t && *t != '\200' && *t != '\201'; t++);
1104		    if (!*t || *t == '\200') {
1105			zwarnnam(name, "error in condition");
1106			freecompcond(m);
1107			return 1;
1108		    }
1109		    *t = '\0';
1110		    c->u.s.p[l] = atoi(tt);
1111		    tt = ++t;
1112		    for (; *t && *t != '\200'; t++)
1113			if (*t == '\201')
1114			    *t = ',';
1115		    if (!*t) {
1116			zwarnnam(name, "error in condition");
1117			freecompcond(m);
1118			return 1;
1119		    }
1120		    *t = '\0';
1121		    c->u.s.s[l] = ztrdup(tt);
1122		}
1123	    }
1124	    while (*t == ' ')
1125		t++;
1126	    if (*t == ',') {
1127		/* Another condition to `or' */
1128		o->or = c = (Compcond) zshcalloc(sizeof(*c));
1129		o = c;
1130		t++;
1131	    } else if (*t) {
1132		/* Another condition to `and' */
1133		c->and = (Compcond) zshcalloc(sizeof(*c));
1134		c = c->and;
1135	    }
1136	}
1137	/* Assign condition to current compctl */
1138	*next = (Compctl) zshcalloc(sizeof(*cc));
1139	(*next)->cond = m;
1140	argv++;
1141	/* End of the condition; get the flags that go with it. */
1142	if (get_compctl(name, &argv, *next, 0, isdef, 0))
1143	    return 1;
1144 	if ((!argv || !*argv) && (cclist & COMP_SPECIAL))
1145 	    /* default, first, or command completion finished */
1146	    ready = 1;
1147	else {
1148	    /* see if we are looking for more conditions or are
1149	     * ready to return (ready = 1)
1150	     */
1151	    if (!argv || !*argv || **argv != '-' ||
1152		((!argv[0][1] || argv[0][1] == '+') && !argv[1])) {
1153		zwarnnam(name, "missing command names");
1154		return 1;
1155	    }
1156	    if (!strcmp(*argv, "--"))
1157		ready = 1;
1158	    else if (!strcmp(*argv, "-+") && argv[1] &&
1159		     !strcmp(argv[1], "--")) {
1160		ready = 1;
1161		argv++;
1162	    }
1163	    argv++;
1164	    /* prepare to put the next lot of conditions on the end */
1165	    next = &((*next)->next);
1166	}
1167    }
1168    /* save position at end of parsing */
1169    *av = argv - 1;
1170    return 0;
1171}
1172
1173/**/
1174static int
1175cc_assign(char *name, Compctl *ccptr, Compctl cct, int reass)
1176{
1177    /* Copy over the details from the values in cct to those in *ccptr */
1178    Compctl cc;
1179
1180    /* Handle assignment of new default or command completion */
1181    if (reass && !(cclist & COMP_LIST)) {
1182	/* if not listing */
1183	if (cclist == (COMP_COMMAND|COMP_DEFAULT)
1184	    || cclist == (COMP_COMMAND|COMP_FIRST)
1185	    || cclist == (COMP_DEFAULT|COMP_FIRST)
1186	    || cclist == COMP_SPECIAL) {
1187 	    zwarnnam(name, "can't set -D, -T, and -C simultaneously");
1188	    /* ... because the following code wouldn't work. */
1189	    return 1;
1190	}
1191	if (cclist & COMP_COMMAND) {
1192	    /* command */
1193	    *ccptr = &cc_compos;
1194	    cc_reassign(*ccptr);
1195	} else if (cclist & COMP_DEFAULT) {
1196	    /* default */
1197	    *ccptr = &cc_default;
1198	    cc_reassign(*ccptr);
1199 	} else if (cclist & COMP_FIRST) {
1200 	    /* first */
1201 	    *ccptr = &cc_first;
1202 	    cc_reassign(*ccptr);
1203	}
1204    }
1205
1206    /* Free the old compctl */
1207    cc = *ccptr;
1208    zsfree(cc->keyvar);
1209    zsfree(cc->glob);
1210    zsfree(cc->str);
1211    zsfree(cc->func);
1212    zsfree(cc->explain);
1213    zsfree(cc->ylist);
1214    zsfree(cc->prefix);
1215    zsfree(cc->suffix);
1216    zsfree(cc->subcmd);
1217    zsfree(cc->substr);
1218    zsfree(cc->withd);
1219    zsfree(cc->hpat);
1220    zsfree(cc->gname);
1221    zsfree(cc->mstr);
1222    freecmatcher(cc->matcher);
1223
1224    /* and copy over the new stuff, (permanently) allocating
1225     * space for strings.
1226     */
1227    cc->mask = cct->mask;
1228    cc->mask2 = cct->mask2;
1229    cc->keyvar = ztrdup(cct->keyvar);
1230    cc->glob = ztrdup(cct->glob);
1231    cc->str = ztrdup(cct->str);
1232    cc->func = ztrdup(cct->func);
1233    cc->explain = ztrdup(cct->explain);
1234    cc->ylist = ztrdup(cct->ylist);
1235    cc->prefix = ztrdup(cct->prefix);
1236    cc->suffix = ztrdup(cct->suffix);
1237    cc->subcmd = ztrdup(cct->subcmd);
1238    cc->substr = ztrdup(cct->substr);
1239    cc->withd = ztrdup(cct->withd);
1240    cc->gname = ztrdup(cct->gname);
1241    cc->hpat = ztrdup(cct->hpat);
1242    cc->hnum = cct->hnum;
1243    cc->matcher = cpcmatcher(cct->matcher);
1244    cc->mstr = ztrdup(cct->mstr);
1245
1246    /* careful with extended completion:  it's already allocated */
1247    cc->ext = cct->ext;
1248
1249    return 0;
1250}
1251
1252/**/
1253static void
1254cc_reassign(Compctl cc)
1255{
1256    /* Free up a new default or command completion:
1257     * this is a hack to free up the parts which should be deleted,
1258     * without removing the basic variable which is statically allocated
1259     */
1260    Compctl c2;
1261
1262    c2 = (Compctl) zshcalloc(sizeof *cc);
1263    c2->xor = cc->xor;
1264    c2->ext = cc->ext;
1265    c2->refc = 1;
1266
1267    freecompctl(c2);
1268
1269    cc->ext = cc->xor = NULL;
1270}
1271
1272/* Check if the given string is a pattern. If so, return one and tokenize *
1273 * it. If not, we just remove the backslashes. */
1274
1275static int
1276compctl_name_pat(char **p)
1277{
1278    char *s = *p;
1279
1280    tokenize(s = dupstring(s));
1281    remnulargs(s);
1282
1283    if (haswilds(s)) {
1284	*p = s;
1285	return 1;
1286    } else
1287	*p = rembslash(*p);
1288
1289    return 0;
1290}
1291
1292/* Delete the pattern compctl with the given name. */
1293
1294static void
1295delpatcomp(char *n)
1296{
1297    Patcomp p, q;
1298
1299    for (q = 0, p = patcomps; p; q = p, p = p->next) {
1300	if (!strcmp(n, p->pat)) {
1301	    if (q)
1302		q->next = p->next;
1303	    else
1304		patcomps = p->next;
1305	    zsfree(p->pat);
1306	    freecompctl(p->cc);
1307	    free(p);
1308
1309	    break;
1310	}
1311    }
1312}
1313
1314/**/
1315static void
1316compctl_process_cc(char **s, Compctl cc)
1317{
1318    Compctlp ccp;
1319    char *n;
1320
1321    if (cclist & COMP_REMOVE) {
1322	/* Delete entries for the commands listed */
1323	for (; *s; s++) {
1324	    n = *s;
1325	    if (compctl_name_pat(&n))
1326		delpatcomp(n);
1327	    else if ((ccp = (Compctlp) compctltab->removenode(compctltab, n)))
1328		compctltab->freenode(&ccp->node);
1329	}
1330    } else {
1331	/* Add the compctl just read to the hash table */
1332
1333	cc->refc = 0;
1334	for (; *s; s++) {
1335	    n = *s;
1336
1337	    cc->refc++;
1338	    if (compctl_name_pat(&n)) {
1339		Patcomp pc;
1340
1341		delpatcomp(n);
1342		pc = zalloc(sizeof *pc);
1343		pc->pat = ztrdup(n);
1344		pc->cc = cc;
1345		pc->next = patcomps;
1346		patcomps = pc;
1347	    } else {
1348		ccp = (Compctlp) zalloc(sizeof *ccp);
1349		ccp->cc = cc;
1350		compctltab->addnode(compctltab, ztrdup(n), ccp);
1351	    }
1352	}
1353    }
1354}
1355
1356/* Print a `compctl' */
1357
1358/**/
1359static void
1360printcompctl(char *s, Compctl cc, int printflags, int ispat)
1361{
1362    Compctl cc2;
1363    char *css = "fcqovbAIFpEjrzBRGudeNOZUnQmw/";
1364    char *mss = " pcCwWsSnNmrRq";
1365    unsigned long t = 0x7fffffff;
1366    unsigned long flags = cc->mask, flags2 = cc->mask2;
1367    unsigned long oldshowmask;
1368
1369    /* Printflags is used outside the standard compctl commands*/
1370    if (printflags & PRINT_LIST)
1371	cclist |= COMP_LIST;
1372    else if (printflags & PRINT_TYPE)
1373	cclist &= ~COMP_LIST;
1374
1375    if ((flags & CC_EXCMDS) && !(flags & CC_DISCMDS))
1376	flags &= ~CC_EXCMDS;
1377
1378    /* If showmask is non-zero, then print only those *
1379     * commands with that flag set.                   */
1380    if (showmask && !(flags & showmask))
1381	return;
1382
1383    /* Temporarily clear showmask in case we make *
1384     * recursive calls to printcompctl.           */
1385    oldshowmask = showmask;
1386    showmask = 0;
1387
1388    /* print either command name or start of compctl command itself */
1389    if (s) {
1390	if (cclist & COMP_LIST) {
1391	    printf("compctl");
1392	    if (cc == &cc_compos)
1393		printf(" -C");
1394	    if (cc == &cc_default)
1395		printf(" -D");
1396	    if (cc == &cc_first)
1397		printf(" -T");
1398	} else if (ispat) {
1399	    char *p = dupstring(s);
1400
1401	    untokenize(p);
1402	    quotedzputs(p, stdout);
1403	} else
1404	    quotedzputs(quotestring(s, NULL, QT_BACKSLASH), stdout);
1405    }
1406
1407    /* loop through flags w/o args that are set, printing them if so */
1408    if ((flags & t) || (flags2 & (CC_UNIQALL | CC_UNIQCON))) {
1409	printf(" -");
1410	if ((flags & (CC_ALREG | CC_ALGLOB)) == (CC_ALREG | CC_ALGLOB))
1411	    putchar('a'), flags &= ~(CC_ALREG | CC_ALGLOB);
1412	while (*css) {
1413	    if (flags & t & 1)
1414		putchar(*css);
1415	    css++;
1416	    flags >>= 1;
1417	    t >>= 1;
1418	}
1419	if (flags2 & CC_UNIQALL)
1420	    putchar('1');
1421	else if (flags2 & CC_UNIQCON)
1422	    putchar('2');
1423    }
1424    if (flags2 & (CC_XORCONT | CC_PATCONT | CC_DEFCONT)) {
1425	printf(" -t");
1426	if (flags2 & CC_XORCONT)
1427	    putchar('+');
1428	if (flags2 & CC_PATCONT)
1429	    putchar('-');
1430	if (flags2 & CC_DEFCONT)
1431	    putchar('x');
1432    } else if (!(flags2 & CC_CCCONT))
1433	printf(" -tn");
1434    /* now flags with arguments */
1435    printif(cc->mstr, 'M');
1436    if (flags2 & CC_NOSORT)
1437	printif(cc->gname, 'V');
1438    else
1439	printif(cc->gname, 'J');
1440    printif(cc->keyvar, 'k');
1441    printif(cc->func, 'K');
1442    printif(cc->explain, (cc->mask & CC_EXPANDEXPL) ? 'Y' : 'X');
1443    printif(cc->ylist, 'y');
1444    printif(cc->prefix, 'P');
1445    printif(cc->suffix, 'S');
1446    printif(cc->glob, 'g');
1447    printif(cc->str, 's');
1448    printif(cc->subcmd, 'l');
1449    printif(cc->substr, 'h');
1450    printif(cc->withd, 'W');
1451    if (cc->hpat) {
1452	printf(" -H %d ", cc->hnum);
1453	quotedzputs(cc->hpat, stdout);
1454    }
1455
1456    /* now the -x ... -- extended completion part */
1457    if (cc->ext) {
1458	Compcond c, o;
1459	int i;
1460
1461	cc2 = cc->ext;
1462	printf(" -x");
1463
1464	while (cc2) {
1465	    /* loop over conditions */
1466	    c = cc2->cond;
1467
1468	    printf(" '");
1469	    for (c = cc2->cond; c;) {
1470		/* loop over or's */
1471		o = c->or;
1472		while (c) {
1473		    /* loop over and's */
1474		    putchar(mss[c->type]);
1475
1476		    for (i = 0; i < c->n; i++) {
1477			/* for all [...]'s of a given condition */
1478			putchar('[');
1479			switch (c->type) {
1480			case CCT_POS:
1481			case CCT_NUMWORDS:
1482			    printf("%d,%d", c->u.r.a[i], c->u.r.b[i]);
1483			    break;
1484			case CCT_CURSUF:
1485			case CCT_CURPRE:
1486			case CCT_QUOTE:
1487			    printqt(c->u.s.s[i]);
1488			    break;
1489			case CCT_RANGESTR:
1490			case CCT_RANGEPAT:
1491			    printqt(c->u.l.a[i]);
1492			    putchar(',');
1493			    printqt(c->u.l.b[i]);
1494			    break;
1495			default:
1496			    printf("%d,", c->u.s.p[i]);
1497			    printqt(c->u.s.s[i]);
1498			}
1499			putchar(']');
1500		    }
1501		    if ((c = c->and))
1502			putchar(' ');
1503		}
1504		if ((c = o))
1505		    printf(" , ");
1506	    }
1507	    putchar('\'');
1508	    c = cc2->cond;
1509	    cc2->cond = NULL;
1510	    /* now print the flags for the current condition */
1511	    printcompctl(NULL, cc2, 0, 0);
1512	    cc2->cond = c;
1513	    if ((cc2 = (Compctl) (cc2->next)))
1514		printf(" -");
1515	}
1516	if (cclist & COMP_LIST)
1517	    printf(" --");
1518    }
1519    if (cc && cc->xor) {
1520	/* print xor'd (+) completions */
1521	printf(" +");
1522	if (cc->xor != &cc_default)
1523	    printcompctl(NULL, cc->xor, 0, 0);
1524    }
1525    if (s) {
1526	if ((cclist & COMP_LIST) && (cc != &cc_compos)
1527	    && (cc != &cc_default) && (cc != &cc_first)) {
1528	    if(s[0] == '-' || s[0] == '+')
1529		printf(" -");
1530	    putchar(' ');
1531	    if (ispat) {
1532		char *p = dupstring(s);
1533
1534		untokenize(p);
1535		quotedzputs(p, stdout);
1536	    } else {
1537		char *p = dupstring(s);
1538
1539		untokenize(p);
1540		quotedzputs(quotestring(p, NULL, QT_BACKSLASH), stdout);
1541	    }
1542	}
1543	putchar('\n');
1544    }
1545
1546    showmask = oldshowmask;
1547}
1548
1549/**/
1550static void
1551printcompctlp(HashNode hn, int printflags)
1552{
1553    Compctlp ccp = (Compctlp) hn;
1554
1555    /* Function needed for use by scanhashtable() */
1556    printcompctl(ccp->node.nam, ccp->cc, printflags, 0);
1557}
1558
1559/* Main entry point for the `compctl' builtin */
1560
1561/**/
1562static int
1563bin_compctl(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
1564{
1565    Compctl cc = NULL;
1566    int ret = 0;
1567
1568    /* clear static flags */
1569    cclist = 0;
1570    showmask = 0;
1571
1572    /* Parse all the arguments */
1573    if (*argv) {
1574	/* Let's see if this is a global matcher definition. */
1575	if ((ret = get_gmatcher(name, argv)))
1576	    return ret - 1;
1577
1578	cc = (Compctl) zshcalloc(sizeof(*cc));
1579	if (get_compctl(name, &argv, cc, 1, 0, 0)) {
1580	    freecompctl(cc);
1581	    return 1;
1582	}
1583
1584	/* remember flags for printing */
1585	showmask = cc->mask;
1586	if ((showmask & CC_EXCMDS) && !(showmask & CC_DISCMDS))
1587	    showmask &= ~CC_EXCMDS;
1588
1589	/* if no command arguments or just listing, we don't want cc */
1590	if (!*argv || (cclist & COMP_LIST))
1591	    freecompctl(cc);
1592    }
1593
1594    /* If no commands and no -C, -T, or -D, print all the compctl's *
1595     * If some flags (other than -C, -T, or -D) were given, then    *
1596     * only print compctl containing those flags.                   */
1597    if (!*argv && !(cclist & (COMP_SPECIAL|COMP_LISTMATCH))) {
1598	Patcomp pc;
1599
1600	for (pc = patcomps; pc; pc = pc->next)
1601	    printcompctl(pc->pat, pc->cc, 0, 1);
1602
1603	scanhashtable(compctltab, 1, 0, 0, compctltab->printnode, 0);
1604	printcompctl((cclist & COMP_LIST) ? "" : "COMMAND", &cc_compos, 0, 0);
1605	printcompctl((cclist & COMP_LIST) ? "" : "DEFAULT", &cc_default, 0, 0);
1606 	printcompctl((cclist & COMP_LIST) ? "" : "FIRST", &cc_first, 0, 0);
1607	print_gmatcher((cclist & COMP_LIST));
1608	return ret;
1609    }
1610
1611    /* If we're listing and we've made it to here, then there are arguments *
1612     * or a COMP_SPECIAL flag (-D, -C, -T), so print only those.            */
1613    if (cclist & COMP_LIST) {
1614	HashNode hn;
1615	char **ptr, *n;
1616
1617	showmask = 0;
1618	for (ptr = argv; *ptr; ptr++) {
1619	    n = *ptr;
1620	    if (compctl_name_pat(&n)) {
1621		Patcomp pc;
1622
1623		for (pc = patcomps; pc; pc = pc->next)
1624		    if (!strcmp(n, pc->pat)) {
1625			printcompctl(pc->pat, pc->cc, 0, 1);
1626			n = NULL;
1627			break;
1628		    }
1629	    } else if ((hn = compctltab->getnode(compctltab, n))) {
1630		compctltab->printnode(hn, 0);
1631		n = NULL;
1632	    }
1633	    if (n) {
1634		zwarnnam(name, "no compctl defined for %s", n);
1635		ret = 1;
1636	    }
1637	}
1638	if (cclist & COMP_COMMAND)
1639	    printcompctl("", &cc_compos, 0, 0);
1640	if (cclist & COMP_DEFAULT)
1641	    printcompctl("", &cc_default, 0, 0);
1642	if (cclist & COMP_FIRST)
1643	    printcompctl("", &cc_first, 0, 0);
1644	if (cclist & COMP_LISTMATCH)
1645	    print_gmatcher(COMP_LIST);
1646	return ret;
1647    }
1648
1649    /* Assign the compctl to the commands given */
1650    if (*argv) {
1651	if(cclist & COMP_SPECIAL)
1652	    /* Ideally we'd handle this properly, setting both the *
1653	     * special and normal completions.  For the moment,    *
1654	     * this is better than silently failing.               */
1655	    zwarnnam(name, "extraneous commands ignored");
1656	else
1657	    compctl_process_cc(argv, cc);
1658    }
1659
1660    return ret;
1661}
1662
1663/* Flags for makecomplist*(). Things not to do. */
1664
1665#define CFN_FIRST   1
1666#define CFN_DEFAULT 2
1667
1668static int
1669bin_compcall(char *name, UNUSED(char **argv), Options ops, UNUSED(int func))
1670{
1671    if (incompfunc != 1) {
1672	zwarnnam(name, "can only be called from completion function");
1673	return 1;
1674    }
1675    return makecomplistctl((OPT_ISSET(ops,'T') ? 0 : CFN_FIRST) |
1676			   (OPT_ISSET(ops,'D') ? 0 : CFN_DEFAULT));
1677}
1678
1679/*
1680 * Functions to generate matches.
1681 */
1682
1683/* A pointer to the compctl we are using. */
1684
1685static Compctl curcc;
1686
1687/* A list of all compctls we have already used. */
1688
1689static LinkList ccused, lastccused;
1690
1691/* A stack of currently used compctls. */
1692
1693static LinkList ccstack;
1694
1695/* The beginning and end of a word range to be used by -l. */
1696
1697static int brange, erange;
1698
1699/* This is used to detect when and what to continue. */
1700
1701static unsigned long ccont;
1702
1703/* Two patterns used when doing glob-completion.  The first one is built *
1704 * from the whole word we are completing and the second one from that    *
1705 * part of the word that was identified as a possible filename.          */
1706
1707static Patprog patcomp, filecomp;
1708
1709/* We store the following prefixes/suffixes:                               *
1710 * lpre/lsuf -- what's on the line                                         *
1711 * rpre/rsuf -- same as lpre/lsuf, but expanded                            *
1712 * ppre/psuf   -- the path prefix/suffix                                   *
1713 * lppre/lpsuf -- the path prefix/suffix, unexpanded                       *
1714 * fpre/fsuf   -- prefix/suffix of the pathname component the cursor is in *
1715 * prpre       -- ppre in expanded form usable for opendir                 *
1716 * qipre, qisuf-- ingnored quoted string                                   *
1717 *                                                                         *
1718 * The integer variables hold the lengths of lpre, lsuf, rpre, rsuf,       *
1719 * fpre, fsuf, lppre, and lpsuf.  noreal is non-zero if we have rpre/rsuf. */
1720
1721static char *lpre, *lsuf;
1722static char *rpre, *rsuf;
1723static char *ppre, *psuf, *lppre, *lpsuf, *prpre;
1724static char *fpre, *fsuf;
1725static char *qfpre, *qfsuf, *qrpre, *qrsuf, *qlpre, *qlsuf;
1726static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl;
1727static int noreal;
1728
1729/* This is either zero or equal to the special character the word we are *
1730 * trying to complete starts with (e.g. Tilde or Equals).                */
1731
1732static char ic;
1733
1734/* This variable says what we are currently adding to the list of matches. */
1735
1736static int addwhat;
1737
1738/*
1739 * Convenience macro for calling quotestring (formerly bslashquote()
1740 * (formerly quotename())).
1741 * This uses the instring variable exported from zle_tricky.c.
1742 */
1743
1744#define quotename(s, e) \
1745quotestring(s, e, instring == QT_NONE ? QT_BACKSLASH : instring)
1746
1747/* Hook functions */
1748
1749static int
1750ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat)
1751{
1752    char *s = dat->str;
1753    int incmd = dat->incmd, lst = dat->lst;
1754    struct cmlist ms;
1755    Cmlist m;
1756    char *os = s;
1757    int onm = nmatches, odm = diffmatches, osi = movefd(0);
1758    LinkNode n;
1759
1760    /* We build a copy of the list of matchers to use to make sure that this
1761     * works even if a shell function called from the completion code changes
1762     * the global matchers. */
1763
1764    if ((m = cmatcher)) {
1765	Cmlist mm, *mp = &mm;
1766	int n;
1767
1768	for (n = 0; m; m = m->next, n++) {
1769	    *mp = (Cmlist) zhalloc(sizeof(struct cmlist));
1770	    (*mp)->matcher = m->matcher;
1771	    (*mp)->next = NULL;
1772	    (*mp)->str = dupstring(m->str);
1773	    mp = &((*mp)->next);
1774	    addlinknode(matchers, m->matcher);
1775	    if (m->matcher)
1776		m->matcher->refc++;
1777	}
1778	m = mm;
1779    }
1780
1781    /* Walk through the global matchers. */
1782    for (;;) {
1783	bmatchers = NULL;
1784	if (m) {
1785	    ms.next = NULL;
1786	    ms.matcher = m->matcher;
1787	    mstack = &ms;
1788
1789	    /* Store the matchers used in the bmatchers list which is used
1790	     * when building new parts for the string to insert into the
1791	     * line. */
1792	    add_bmatchers(m->matcher);
1793	} else
1794	    mstack = NULL;
1795
1796	ainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
1797	fainfo = (Aminfo) hcalloc(sizeof(struct aminfo));
1798
1799	freecl = NULL;
1800
1801	if (!validlist)
1802	    lastambig = 0;
1803	amatches = NULL;
1804	mnum = 0;
1805	unambig_mnum = -1;
1806	isuf = NULL;
1807	insmnum = 1;
1808#if 0
1809	/* group-numbers in compstate[insert] */
1810	insgnum = 1;
1811	insgroup = 0;
1812#endif
1813	oldlist = oldins = 0;
1814	begcmgroup("default", 0);
1815	menucmp = menuacc = newmatches = onlyexpl = 0;
1816
1817	ccused = newlinklist();
1818	ccstack = newlinklist();
1819
1820	s = dupstring(os);
1821	makecomplistglobal(s, incmd, lst, 0);
1822	endcmgroup(NULL);
1823
1824	if (amatches && !oldlist) {
1825	    if (lastccused)
1826		freelinklist(lastccused, (FreeFunc) freecompctl);
1827
1828	    lastccused = znewlinklist();
1829	    for (n = firstnode(ccused); n; incnode(n))
1830		zaddlinknode(lastccused, getdata(n));
1831	} else if (ccused)
1832	    for (n = firstnode(ccused); n; incnode(n))
1833		if (((Compctl) getdata(n)) != &cc_dummy)
1834		    freecompctl((Compctl) getdata(n));
1835
1836	if (oldlist) {
1837	    nmatches = onm;
1838	    diffmatches = odm;
1839	    validlist = 1;
1840	    amatches = lastmatches;
1841#ifdef ZSH_HEAP_DEBUG
1842	    if (memory_validate(amatches->heap_id)) {
1843		HEAP_ERROR(amatches->heap_id);
1844	    }
1845#endif
1846	    lmatches = lastlmatches;
1847	    if (pmatches) {
1848		freematches(pmatches, 1);
1849		pmatches = NULL;
1850		hasperm = 0;
1851	    }
1852	    redup(osi, 0);
1853
1854	    dat->lst = 0;
1855	    return 0;
1856	}
1857	if (lastmatches) {
1858	    freematches(lastmatches, 1);
1859	    lastmatches = NULL;
1860	}
1861	permmatches(1);
1862	amatches = pmatches;
1863	lastpermmnum = permmnum;
1864	lastpermgnum = permgnum;
1865
1866	lastmatches = pmatches;
1867	lastlmatches = lmatches;
1868	pmatches = NULL;
1869	hasperm = 0;
1870	hasoldlist = 1;
1871
1872	if (nmatches && !errflag) {
1873	    validlist = 1;
1874
1875	    redup(osi, 0);
1876
1877	    dat->lst = 0;
1878	    return 0;
1879	}
1880	if (!m || !(m = m->next))
1881	    break;
1882
1883	errflag = 0;
1884    }
1885    redup(osi, 0);
1886    dat->lst = 1;
1887    return 0;
1888}
1889
1890static int
1891cccleanuphookfn(UNUSED(Hookdef dummy), UNUSED(void *dat))
1892{
1893    ccused = ccstack = NULL;
1894    return 0;
1895}
1896
1897/* This adds a match to the list of matches.  The string to add is given   *
1898 * in s, the type of match is given in the global variable addwhat and     *
1899 * the parameter t (if not NULL) is a pointer to a hash node which         *
1900 * may be used to give other information to this function.                 *
1901 *                                                                         *
1902 * addwhat contains either one of the special values (negative, see below) *
1903 * or the inclusive OR of some of the CC_* flags used for compctls.        */
1904
1905/**/
1906static void
1907addmatch(char *s, char *t)
1908{
1909    int isfile = 0, isalt = 0, isexact;
1910    char *ms = NULL, *tt;
1911    HashNode hn;
1912    Param pm;
1913    Cline lc = NULL;
1914    Brinfo bp, bpl = brbeg, bsl = brend, bpt, bst;
1915
1916    for (bp = brbeg; bp; bp = bp->next)
1917	bp->curpos = ((addwhat == CC_QUOTEFLAG) ? bp->qpos : bp->pos);
1918    for (bp = brend; bp; bp = bp->next)
1919	bp->curpos = ((addwhat == CC_QUOTEFLAG) ? bp->qpos : bp->pos);
1920
1921    /*
1922     * addwhat: -5 is for files,
1923     *          -6 is for glob expansions,
1924     *          -8 is for executable files (e.g. command paths),
1925     *          -9 is for parameters
1926     *          -7 is for command names (from cmdnamtab)
1927     *          -4 is for a cdable parameter
1928     *          -3 is for executable command names.
1929     *          -2 is for anything unquoted
1930     *          -1 is for other file specifications
1931     *          (things with `~' or `=' at the beginning, ...).
1932     */
1933
1934    /* Just to make the code cleaner */
1935    hn = (HashNode) t;
1936    pm = (Param) t;
1937
1938    if (addwhat == -1 || addwhat == -5 || addwhat == -6 ||
1939	addwhat == CC_FILES || addwhat == -7 || addwhat == -8) {
1940	int ppl = (ppre ? strlen(ppre) : 0), psl = (psuf ? strlen(psuf) : 0);
1941
1942	while (bpl && bpl->curpos < ppl)
1943	    bpl = bpl->next;
1944	while (bsl && bsl->curpos < psl)
1945	    bsl = bsl->next;
1946
1947	if ((addwhat == CC_FILES ||
1948	     addwhat == -5) && !*psuf) {
1949	    /* If this is a filename, do the fignore check. */
1950	    char **pt = fignore;
1951	    int filell, sl = strlen(s);
1952
1953	    for (isalt = 0; !isalt && *pt; pt++)
1954		if ((filell = strlen(*pt)) < sl &&
1955		    !strcmp(*pt, s + sl - filell))
1956		    isalt = 1;
1957	}
1958	ms = ((addwhat == CC_FILES || addwhat == -6 ||
1959	       addwhat == -5 || addwhat == -8) ?
1960	      comp_match(tildequote(qfpre, 1), multiquote(qfsuf, 1),
1961			 s, filecomp, &lc, (ppre && *ppre ? 1 : 2),
1962			 &bpl, ppl ,&bsl, psl, &isexact) :
1963	      comp_match(multiquote(fpre, 1), multiquote(fsuf, 1),
1964			 s, filecomp, &lc, 0,
1965			 &bpl, ppl, &bsl, psl, &isexact));
1966	if (!ms)
1967	    return;
1968
1969	if (addwhat == -7 && !findcmd(s, 0))
1970	    return;
1971	isfile = CMF_FILE;
1972    } else if (addwhat == CC_QUOTEFLAG || addwhat == -2  ||
1973	      (addwhat == -3 && !(hn->flags & DISABLED)) ||
1974	      (addwhat == -4 && (PM_TYPE(pm->node.flags) == PM_SCALAR) &&
1975	       !pm->level && (tt = pm->gsu.s->getfn(pm)) && *tt == '/') ||
1976	      (addwhat == -9 && !(hn->flags & PM_UNSET) && !pm->level) ||
1977	      (addwhat > 0 &&
1978	       ((!(hn->flags & PM_UNSET) &&
1979		 (((addwhat & CC_ARRAYS)    &&  (hn->flags & PM_ARRAY))    ||
1980		  ((addwhat & CC_INTVARS)   &&  (hn->flags & PM_INTEGER))  ||
1981		  ((addwhat & CC_ENVVARS)   &&  (hn->flags & PM_EXPORTED)) ||
1982		  ((addwhat & CC_SCALARS)   &&  (hn->flags & PM_SCALAR))   ||
1983		  ((addwhat & CC_READONLYS) &&  (hn->flags & PM_READONLY)) ||
1984		  ((addwhat & CC_SPECIALS)  &&  (hn->flags & PM_SPECIAL))  ||
1985		  ((addwhat & CC_PARAMS)    && !(hn->flags & PM_EXPORTED))) &&
1986		 !pm->level) ||
1987		((( addwhat & CC_SHFUNCS)				  ||
1988		  ( addwhat & CC_BUILTINS)				  ||
1989		  ( addwhat & CC_EXTCMDS)				  ||
1990		  ( addwhat & CC_RESWDS)				  ||
1991		  ((addwhat & CC_ALREG)   && !(hn->flags & ALIAS_GLOBAL)) ||
1992		  ((addwhat & CC_ALGLOB)  &&  (hn->flags & ALIAS_GLOBAL))) &&
1993		 (((addwhat & CC_DISCMDS) && (hn->flags & DISABLED)) ||
1994		  ((addwhat & CC_EXCMDS)  && !(hn->flags & DISABLED)))) ||
1995		((addwhat & CC_BINDINGS) && !(hn->flags & DISABLED))))) {
1996	char *p1, *s1, *p2, *s2;
1997
1998	if (addwhat == CC_QUOTEFLAG) {
1999	    p1 = qrpre; s1 = qrsuf;
2000	    p2 = rpre;  s2 = rsuf;
2001	} else {
2002	    p1 = qlpre; s1 = qlsuf;
2003	    p2 = lpre;  s2 = lsuf;
2004	}
2005	p1 = multiquote(p1, 1); s1 = multiquote(s1, 1);
2006	p2 = multiquote(p2, 1); s2 = multiquote(s2, 1);
2007	bpt = bpl;
2008	bst = bsl;
2009
2010	if (!(ms = comp_match(p1, s1, s, patcomp, &lc,
2011			      (addwhat == CC_QUOTEFLAG),
2012			      &bpl, strlen(p1), &bsl, strlen(s1),
2013			      &isexact))) {
2014	    bpl = bpt;
2015	    bsl = bst;
2016	    if (!(ms = comp_match(p2, s2, s, NULL, &lc,
2017				  (addwhat == CC_QUOTEFLAG),
2018				  &bpl, strlen(p2), &bsl, strlen(s2),
2019				  &isexact)))
2020		return;
2021	}
2022    }
2023    if (!ms)
2024	return;
2025    add_match_data(isalt, ms, s, lc, ipre, ripre, isuf,
2026		   (incompfunc ? dupstring(curcc->prefix) : curcc->prefix),
2027		   prpre,
2028		   (isfile ? lppre : NULL), NULL,
2029		   (isfile ? lpsuf : NULL), NULL,
2030		   (incompfunc ? dupstring(curcc->suffix) : curcc->suffix),
2031		   (mflags | isfile), isexact);
2032}
2033
2034/**/
2035static void
2036maketildelist(void)
2037{
2038    /* add all the usernames to the named directory table */
2039    nameddirtab->filltable(nameddirtab);
2040
2041    scanhashtable(nameddirtab, 0, (addwhat==-1) ? 0 : ND_USERNAME, 0,
2042		  addhnmatch, 0);
2043}
2044
2045/* This does the check for compctl -x `n' and `N' patterns. */
2046
2047/**/
2048int
2049getcpat(char *str, int cpatindex, char *cpat, int class)
2050{
2051    char *s, *t, *p;
2052    int d = 0;
2053
2054    if (!str || !*str)
2055	return -1;
2056
2057    cpat = rembslash(cpat);
2058
2059    if (!cpatindex)
2060	cpatindex++, d = 0;
2061    else if ((d = (cpatindex < 0)))
2062	cpatindex = -cpatindex;
2063
2064    for (s = d ? str + strlen(str) - 1 : str;
2065	 d ? (s >= str) : *s;
2066	 d ? s-- : s++) {
2067	for (t = s, p = cpat; *t && *p; p++) {
2068	    if (class) {
2069		if (*p == *s && !--cpatindex)
2070		    return (int)(s - str + 1);
2071	    } else if (*t++ != *p)
2072		break;
2073	}
2074	if (!class && !*p && !--cpatindex)
2075	    return t - str;
2076    }
2077    return -1;
2078}
2079
2080/* Dump a hash table (without sorting).  For each element the addmatch  *
2081 * function is called and at the beginning the addwhat variable is set. *
2082 * This could be done using scanhashtable(), but this is easy and much  *
2083 * more efficient.                                                      */
2084
2085/**/
2086static void
2087dumphashtable(HashTable ht, int what)
2088{
2089    HashNode hn;
2090    int i;
2091
2092    addwhat = what;
2093
2094    for (i = 0; i < ht->hsize; i++)
2095	for (hn = ht->nodes[i]; hn; hn = hn->next)
2096	    addmatch(dupstring(hn->nam), (char *) hn);
2097}
2098
2099/* ScanFunc used by maketildelist() et al. */
2100
2101/**/
2102static void
2103addhnmatch(HashNode hn, UNUSED(int flags))
2104{
2105    addmatch(hn->nam, NULL);
2106}
2107
2108/* Perform expansion on the given string and return the result. *
2109 * During this errors are not reported.                         */
2110
2111/**/
2112static char *
2113getreal(char *str)
2114{
2115    LinkList l = newlinklist();
2116    int ne = noerrs;
2117
2118    noerrs = 1;
2119    addlinknode(l, dupstring(str));
2120    prefork(l, 0);
2121    noerrs = ne;
2122    if (!errflag && nonempty(l) &&
2123	((char *) peekfirst(l)) && ((char *) peekfirst(l))[0])
2124	return dupstring(peekfirst(l));
2125    errflag = 0;
2126
2127    return dupstring(str);
2128}
2129
2130/* This reads a directory and adds the files to the list of  *
2131 * matches.  The parameters say which files should be added. */
2132
2133/**/
2134static void
2135gen_matches_files(int dirs, int execs, int all)
2136{
2137    DIR *d;
2138    struct stat buf;
2139    char *n, p[PATH_MAX], *q = NULL, *e, *pathpref;
2140    LinkList l = NULL;
2141    int ns = 0, ng = opts[NULLGLOB], test, aw = addwhat, pathpreflen;
2142
2143    opts[NULLGLOB] = 1;
2144
2145    if (*psuf) {
2146	/* If there is a path suffix, check if it doesn't have a `*' or *
2147	 * `)' at the end (this is used to determine if we should use   *
2148	 * globbing).                                                   */
2149	q = psuf + strlen(psuf) - 1;
2150	ns = !(*q == Star || *q == Outpar);
2151	l = newlinklist();
2152	/* And generate only directory names. */
2153	dirs = 1;
2154	all = execs = 0;
2155    }
2156    /* Open directory. */
2157    if (prpre && *prpre) {
2158	pathpref = dupstring(prpre);
2159	unmetafy(pathpref, &pathpreflen);
2160	/* system needs NULL termination, not provided by unmetafy */
2161	pathpref[pathpreflen] = '\0';
2162    } else {
2163	pathpref = NULL;
2164	pathpreflen = 0;
2165    }
2166    if ((d = opendir(pathpref ? pathpref : "."))) {
2167	/* If we search only special files, prepare a path buffer for stat. */
2168	if (!all && pathpreflen) {
2169	    /* include null byte we carefully added */
2170	    memcpy(p, pathpref, pathpreflen+1);
2171	}
2172	q = p + pathpreflen;
2173	/* Fine, now read the directory. */
2174	while ((n = zreaddir(d, 1)) && !errflag) {
2175	    /* Ignore files beginning with `.' unless the thing we found on *
2176	     * the command line also starts with a dot or GLOBDOTS is set.  */
2177	    if (*n != '.' || *fpre == '.' || isset(GLOBDOTS)) {
2178		addwhat = execs ? -8 : -5;
2179		if (filecomp)
2180		    /* If we have a pattern for the filename check, use it. */
2181		    test = pattry(filecomp, n);
2182		else {
2183		    /* Otherwise use the prefix and suffix strings directly. */
2184		    e = n + strlen(n) - fsl;
2185		    if ((test = !strncmp(n, fpre, fpl)))
2186			test = !strcmp(e, fsuf);
2187		    if (!test && mstack) {
2188			test = 1;
2189			addwhat = CC_FILES;
2190		    }
2191		}
2192		/* Filename didn't match? */
2193		if (!test)
2194		    continue;
2195		if (!all) {
2196		    char *ums;
2197		    int umlen;
2198		    /* We still have to check the file type, so prepare *
2199		     * the path buffer by appending the filename.       */
2200		    ums = dupstring(n);
2201		    unmetafy(ums, &umlen);
2202		    memcpy(q, ums, umlen);
2203		    q[umlen] = '\0';
2204		    /* And do the stat. */
2205		    if (stat(p, &buf) < 0)
2206			continue;
2207		}
2208		if (all ||
2209		    (dirs && S_ISDIR(buf.st_mode)) ||
2210		    (execs && S_ISREG(buf.st_mode) && (buf.st_mode&S_IXUGO))) {
2211		    /* If we want all files or the file has the right type... */
2212		    if (*psuf) {
2213			/* We have to test for a path suffix. */
2214			int o = strlen(p), tt;
2215
2216			/* Append it to the path buffer. */
2217			strcpy(p + o, psuf);
2218
2219			/* Do we have to use globbing? */
2220			if (ispattern ||
2221			    (ns && comppatmatch && *comppatmatch)) {
2222			    /* Yes, so append a `*' if needed. */
2223			    if (ns && comppatmatch && *comppatmatch == '*') {
2224				int tl = strlen(p);
2225
2226				p[tl] = Star;
2227				p[tl + 1] = '\0';
2228			    }
2229			    /* Do the globbing... */
2230			    remnulargs(p);
2231			    addlinknode(l, p);
2232			    globlist(l, 0);
2233			    /* And see if that produced a filename. */
2234			    tt = nonempty(l);
2235			    while (ugetnode(l));
2236			} else
2237			    /* Otherwise just check, if we have access *
2238			     * to the file.                            */
2239			    tt = !access(p, F_OK);
2240
2241			p[o] = '\0';
2242			if (tt)
2243			    /* Ok, we can add the filename to the *
2244			     * list of matches.                   */
2245			    addmatch(dupstring(n), NULL);
2246		    } else
2247			/* We want all files, so just add the name *
2248			 * to the matches.                         */
2249			addmatch(dupstring(n), NULL);
2250		}
2251	    }
2252	}
2253	closedir(d);
2254    }
2255    opts[NULLGLOB] = ng;
2256    addwhat = aw;
2257}
2258
2259/* This returns the node with the given data. */
2260/* ...should probably be moved to linklist.c. */
2261
2262static LinkNode
2263findnode(LinkList list, void *dat)
2264{
2265    LinkNode tmp = firstnode(list);
2266
2267    while (tmp && getdata(tmp) != dat) incnode(tmp);
2268
2269    return tmp;
2270}
2271
2272/* A simple counter to avoid endless recursion between old and new style *
2273 * completion. */
2274
2275static int cdepth = 0;
2276
2277#define MAX_CDEPTH 16
2278
2279/**/
2280static int
2281makecomplistctl(int flags)
2282{
2283    Heap oldheap;
2284    int ret;
2285
2286    if (cdepth == MAX_CDEPTH)
2287	return 0;
2288
2289    cdepth++;
2290    SWITCHHEAPS(oldheap, compheap) {
2291	int ooffs = offs, lip, lp;
2292	char *str = comp_str(&lip, &lp, 0), *t;
2293	char *os = cmdstr, **ow = clwords, **p, **q, qc;
2294	int on = clwnum, op = clwpos, ois =  instring, oib = inbackt;
2295	char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, *oaq = autoq;
2296	char buf[3];
2297
2298	if (compquote && (qc = *compquote)) {
2299	    if (qc == '`') {
2300		instring = QT_NONE;
2301		/*
2302		 * Yes, inbackt has always been set to zero here.  I'm
2303		 * sure there's a simple explanation.
2304		 */
2305		inbackt = 0;
2306		autoq = "";
2307	    } else {
2308		switch (qc) {
2309		case '\'':
2310		    instring = QT_SINGLE;
2311		    break;
2312
2313		case '"':
2314		    instring = QT_DOUBLE;
2315		    break;
2316
2317		case '$':
2318		    instring = QT_DOLLARS;
2319		    break;
2320		}
2321		inbackt = 0;
2322		strcpy(buf, *compquote == '$' ? compquote+1 : compquote);
2323		autoq = buf;
2324	    }
2325	} else {
2326	    instring = QT_NONE;
2327	    inbackt = 0;
2328	    autoq = "";
2329	}
2330	qipre = ztrdup(compqiprefix ? compqiprefix : "");
2331	qisuf = ztrdup(compqisuffix ? compqisuffix : "");
2332	isuf = dupstring(compisuffix);
2333	ctokenize(isuf);
2334	remnulargs(isuf);
2335	clwnum = arrlen(compwords);
2336	clwpos = compcurrent - 1;
2337	cmdstr = ztrdup(compwords[0]);
2338	clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
2339	for (p = compwords, q = clwords; *p; p++, q++) {
2340	    t = dupstring(*p);
2341	    tokenize(t);
2342	    remnulargs(t);
2343	    *q = ztrdup(t);
2344	}
2345	*q = NULL;
2346	offs = lip + lp;
2347	incompfunc = 2;
2348	ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags);
2349	incompfunc = 1;
2350	isuf = oisuf;
2351	zsfree(qipre);
2352	zsfree(qisuf);
2353	qipre = oqp;
2354	qisuf = oqs;
2355	instring = ois;
2356	inbackt = oib;
2357	autoq = oaq;
2358	offs = ooffs;
2359	zsfree(cmdstr);
2360	freearray(clwords);
2361	cmdstr = os;
2362	clwords = ow;
2363	clwnum = on;
2364	clwpos = op;
2365    } SWITCHBACKHEAPS(oldheap);
2366    cdepth--;
2367
2368    return ret;
2369}
2370
2371/* This function gets the compctls for the given command line and *
2372 * adds all completions for them. */
2373
2374/**/
2375static int
2376makecomplistglobal(char *os, int incmd, UNUSED(int lst), int flags)
2377{
2378    Compctl cc = NULL;
2379    char *s;
2380
2381    ccont = CC_CCCONT;
2382    cc_dummy.suffix = NULL;
2383
2384    if (linwhat == IN_ENV) {
2385        /* Default completion for parameter values. */
2386	if (!(flags & CFN_DEFAULT)) {
2387	    cc = &cc_default;
2388	    keypm = NULL;
2389	}
2390    } else if (linwhat == IN_MATH) {
2391	if (!(flags & CFN_DEFAULT)) {
2392	    if (insubscr >= 2) {
2393		/* Inside subscript of assoc array, complete keys. */
2394		cc_dummy.mask = 0;
2395		cc_dummy.suffix = (insubscr == 2 ? "]" : "");
2396	    } else {
2397		/* Other math environment, complete paramete names. */
2398		keypm = NULL;
2399		cc_dummy.mask = CC_PARAMS;
2400	    }
2401	    cc = &cc_dummy;
2402	    cc_dummy.refc = 10000;
2403	}
2404    } else if (linwhat == IN_COND) {
2405	/* We try to be clever here: in conditions we complete option   *
2406	 * names after a `-o', file names after `-nt', `-ot', and `-ef' *
2407	 * and file names and parameter names elsewhere.                */
2408	if (!(flags & CFN_DEFAULT)) {
2409	    s = clwpos ? clwords[clwpos - 1] : "";
2410	    cc_dummy.mask = !strcmp("-o", s) ? CC_OPTIONS :
2411		((*s == '-' && s[1] && !s[2]) ||
2412		 !strcmp("-nt", s) ||
2413		 !strcmp("-ot", s) ||
2414		 !strcmp("-ef", s)) ? CC_FILES :
2415		(CC_FILES | CC_PARAMS);
2416	    cc = &cc_dummy;
2417	    cc_dummy.refc = 10000;
2418	    keypm = NULL;
2419	}
2420    } else if (linredir) {
2421	if (!(flags & CFN_DEFAULT)) {
2422	    /* In redirections use default completion. */
2423	    cc = &cc_default;
2424	    keypm = NULL;
2425	}
2426    } else {
2427	/* Otherwise get the matches for the command. */
2428	keypm = NULL;
2429	return makecomplistcmd(os, incmd, flags);
2430    }
2431    if (cc) {
2432	/* First, use the -T compctl. */
2433	if (!(flags & CFN_FIRST)) {
2434	    makecomplistcc(&cc_first, os, incmd);
2435
2436	    if (!(ccont & CC_CCCONT))
2437		return 0;
2438	}
2439	makecomplistcc(cc, os, incmd);
2440	return 1;
2441    }
2442    return 0;
2443}
2444
2445/* This produces the matches for a command. */
2446
2447/**/
2448static int
2449makecomplistcmd(char *os, int incmd, int flags)
2450{
2451    Compctl cc;
2452    Compctlp ccp;
2453    char *s;
2454    int ret = 0;
2455
2456    /* First, use the -T compctl. */
2457    if (!(flags & CFN_FIRST)) {
2458	makecomplistcc(&cc_first, os, incmd);
2459
2460	if (!(ccont & CC_CCCONT))
2461	    return 0;
2462    }
2463    /* Then search the pattern compctls, with the command name and the *
2464     * full pathname of the command. */
2465    if (cmdstr) {
2466	ret |= makecomplistpc(os, incmd);
2467	if (!(ccont & CC_CCCONT))
2468	    return ret;
2469    }
2470    /* If the command string starts with `=', try the path name of the *
2471     * command. */
2472    if (cmdstr && cmdstr[0] == Equals) {
2473	char *c = findcmd(cmdstr + 1, 1);
2474
2475	if (c) {
2476	    zsfree(cmdstr);
2477	    cmdstr = ztrdup(c);
2478	}
2479    }
2480
2481    /* Find the compctl for this command, trying the full name and then *
2482     * the trailing pathname component. If that doesn't yield anything, *
2483     * use default completion. */
2484    if (incmd)
2485	cc = &cc_compos;
2486    else if (!(cmdstr &&
2487	  (((ccp = (Compctlp) compctltab->getnode(compctltab, cmdstr)) &&
2488	    (cc = ccp->cc)) ||
2489	   ((s = dupstring(cmdstr)) && remlpaths(&s) &&
2490	    (ccp = (Compctlp) compctltab->getnode(compctltab, s)) &&
2491	    (cc = ccp->cc))))) {
2492	if (flags & CFN_DEFAULT)
2493	    return ret;
2494	cc = &cc_default;
2495    } else
2496	ret|= 1;
2497    makecomplistcc(cc, os, incmd);
2498    return ret;
2499}
2500
2501/* This adds the matches for the pattern compctls. */
2502
2503/**/
2504static int
2505makecomplistpc(char *os, int incmd)
2506{
2507    Patcomp pc;
2508    Patprog pat;
2509    char *s;
2510    int ret = 0;
2511
2512    s = ((shfunctab->getnode(shfunctab, cmdstr) ||
2513	  builtintab->getnode(builtintab, cmdstr)) ? NULL : findcmd(cmdstr, 1));
2514
2515    for (pc = patcomps; pc; pc = pc->next) {
2516	if ((pat = patcompile(pc->pat, PAT_STATIC, NULL)) &&
2517	    (pattry(pat, cmdstr) ||
2518	     (s && pattry(pat, s)))) {
2519	    makecomplistcc(pc->cc, os, incmd);
2520	    ret |= 2;
2521	    if (!(ccont & CC_CCCONT))
2522		return ret;
2523	}
2524    }
2525    return ret;
2526}
2527
2528/* This produces the matches for one compctl. */
2529
2530/**/
2531static void
2532makecomplistcc(Compctl cc, char *s, int incmd)
2533{
2534    cc->refc++;
2535    if (!ccused)
2536	ccused = newlinklist();
2537    addlinknode(ccused, cc);
2538
2539    ccont = 0;
2540
2541    makecomplistor(cc, s, incmd, 0, 0);
2542}
2543
2544/* This adds the completions for one run of [x]or'ed completions. */
2545
2546/**/
2547static void
2548makecomplistor(Compctl cc, char *s, int incmd, int compadd, int sub)
2549{
2550    int mn, ct, um = usemenu;
2551
2552    /* Loop over xors. */
2553    do {
2554	mn = mnum;
2555
2556	/* Loop over ors. */
2557	do {
2558	    /* Reset the range information if we are not in a sub-list. */
2559	    if (!sub) {
2560		brange = 0;
2561		erange = clwnum - 1;
2562	    }
2563	    usemenu = 0;
2564	    makecomplistlist(cc, s, incmd, compadd);
2565	    um |= usemenu;
2566
2567	    ct = cc->mask2 & CC_XORCONT;
2568
2569	    cc = cc->xor;
2570	} while (cc && ct);
2571
2572	/* Stop if we got some matches. */
2573	if (mn != mnum)
2574	    break;
2575	if (cc) {
2576	    ccont &= ~(CC_DEFCONT | CC_PATCONT);
2577	    if (!sub)
2578		ccont &= ~CC_CCCONT;
2579	}
2580    } while (cc);
2581
2582    usemenu = um;
2583}
2584
2585/* This dispatches for simple and extended completion. */
2586
2587/**/
2588static void
2589makecomplistlist(Compctl cc, char *s, int incmd, int compadd)
2590{
2591    int oloffs = offs, owe = we, owb = wb, ocs = zlemetacs;
2592
2593    METACHECK();
2594
2595    if (cc->ext)
2596	/* Handle extended completion. */
2597	makecomplistext(cc, s, incmd);
2598    else
2599	/* Only normal flags. */
2600	makecomplistflags(cc, s, incmd, compadd);
2601
2602    /* Reset some information variables for the next try. */
2603    errflag = 0;
2604    offs = oloffs;
2605    wb = owb;
2606    we = owe;
2607    zlemetacs = ocs;
2608}
2609
2610/* This add matches for extended completion patterns */
2611
2612/**/
2613static void
2614makecomplistext(Compctl occ, char *os, int incmd)
2615{
2616    Compctl compc;
2617    Compcond or, cc;
2618    Patprog pprog;
2619    int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins;
2620    char *sc = NULL, *s, *ss;
2621
2622    ins = (instring != QT_NONE ? instring : (inbackt ? QT_BACKTICK : 0));
2623
2624    /* This loops over the patterns separated by `-'s. */
2625    for (compc = occ->ext; compc; compc = compc->next) {
2626	compadd = t = brange = 0;
2627	erange = clwnum - 1;
2628	/* This loops over OR'ed patterns. */
2629	for (cc = compc->cond; cc && !t; cc = or) {
2630	    or = cc->or;
2631	    /* This loops over AND'ed patterns. */
2632	    for (t = 1; cc && t; cc = cc->and) {
2633		/* And this loops over [...] pairs. */
2634		for (t = i = 0; i < cc->n && !t; i++) {
2635		    s = NULL;
2636		    brange = 0;
2637		    erange = clwnum - 1;
2638		    switch (cc->type) {
2639		    case CCT_QUOTE:
2640			t = ((cc->u.s.s[i][0] == 's' && ins == QT_SINGLE) ||
2641			     (cc->u.s.s[i][0] == 'd' && ins == QT_DOUBLE) ||
2642			     (cc->u.s.s[i][0] == 'b' && ins == QT_BACKTICK));
2643			break;
2644		    case CCT_POS:
2645			tt = clwpos;
2646			goto cct_num;
2647		    case CCT_NUMWORDS:
2648			tt = clwnum;
2649		    cct_num:
2650			if ((a = cc->u.r.a[i]) < 0)
2651			    a += clwnum;
2652			if ((b = cc->u.r.b[i]) < 0)
2653			    b += clwnum;
2654			if (cc->type == CCT_POS)
2655			    brange = a, erange = b;
2656			t = (tt >= a && tt <= b);
2657			break;
2658		    case CCT_CURSUF:
2659		    case CCT_CURPRE:
2660			s = ztrdup(clwpos < clwnum ? os : "");
2661			untokenize(s);
2662			if (isset(COMPLETEINWORD)) s[offs] = '\0';
2663			sc = rembslash(cc->u.s.s[i]);
2664			a = strlen(sc);
2665			if (!strncmp(s, sc, a)) {
2666			    compadd = (cc->type == CCT_CURSUF ? a : 0);
2667			    t = 1;
2668			}
2669			break;
2670		    case CCT_CURSUB:
2671		    case CCT_CURSUBC:
2672			if (clwpos < 0 || clwpos >= clwnum)
2673			    t = 0;
2674			else {
2675			    s = ztrdup(os);
2676			    untokenize(s);
2677			    if (isset(COMPLETEINWORD)) s[offs] = '\0';
2678			    a = getcpat(s,
2679					cc->u.s.p[i],
2680					cc->u.s.s[i],
2681					cc->type == CCT_CURSUBC);
2682			    if (a != -1)
2683				compadd = a, t = 1;
2684			}
2685			break;
2686
2687		    case CCT_CURPAT:
2688		    case CCT_CURSTR:
2689			tt = clwpos;
2690			goto cct_str;
2691		    case CCT_WORDPAT:
2692		    case CCT_WORDSTR:
2693			tt = 0;
2694		    cct_str:
2695			if ((a = tt + cc->u.s.p[i]) < 0)
2696			    a += clwnum;
2697			s = ztrdup((a < 0 || a >= clwnum) ? "" :
2698				   clwords[a]);
2699			untokenize(s);
2700
2701			if (cc->type == CCT_CURPAT ||
2702			    cc->type == CCT_WORDPAT) {
2703			    tokenize(ss = dupstring(cc->u.s.s[i]));
2704			    t = ((pprog = patcompile(ss, PAT_STATIC, NULL)) &&
2705				 pattry(pprog, s));
2706			} else
2707			    t = (!strcmp(s, rembslash(cc->u.s.s[i])));
2708			break;
2709		    case CCT_RANGESTR:
2710		    case CCT_RANGEPAT:
2711			if (cc->type == CCT_RANGEPAT)
2712			    tokenize(sc = dupstring(cc->u.l.a[i]));
2713			for (j = clwpos - 1; j > 0; j--) {
2714			    untokenize(s = ztrdup(clwords[j]));
2715			    if (cc->type == CCT_RANGESTR)
2716				sc = rembslash(cc->u.l.a[i]);
2717			    if (cc->type == CCT_RANGESTR ?
2718				!strncmp(s, sc, strlen(sc)) :
2719				((pprog = patcompile(sc, PAT_STATIC, 0)) &&
2720				 pattry(pprog, s))) {
2721				zsfree(s);
2722				brange = j + 1;
2723				t = 1;
2724				break;
2725			    }
2726			    zsfree(s);
2727			}
2728			if (t && cc->u.l.b[i]) {
2729			    if (cc->type == CCT_RANGEPAT)
2730				tokenize(sc = dupstring(cc->u.l.b[i]));
2731			    for (j++; j < clwnum; j++) {
2732				untokenize(s = ztrdup(clwords[j]));
2733				if (cc->type == CCT_RANGESTR)
2734				    sc = rembslash(cc->u.l.b[i]);
2735				if (cc->type == CCT_RANGESTR ?
2736				    !strncmp(s, sc, strlen(sc)) :
2737				    ((pprog = patcompile(sc, PAT_STATIC, 0)) &&
2738				     pattry(pprog, s))) {
2739				    zsfree(s);
2740				    erange = j - 1;
2741				    t = clwpos <= erange;
2742				    break;
2743				}
2744				zsfree(s);
2745			    }
2746			}
2747			s = NULL;
2748		    }
2749		    zsfree(s);
2750		}
2751	    }
2752	}
2753	if (t) {
2754	    /* The patterns matched, use the flags. */
2755	    m = 1;
2756	    ccont &= ~(CC_PATCONT | CC_DEFCONT);
2757	    makecomplistor(compc, os, incmd, compadd, 1);
2758	    if (!d && (ccont & CC_DEFCONT)) {
2759		d = 1;
2760		compadd = 0;
2761		brange = 0;
2762		erange = clwnum - 1;
2763		makecomplistflags(occ, os, incmd, 0);
2764	    }
2765	    if (!(ccont & CC_PATCONT))
2766		break;
2767	}
2768    }
2769    /* If no pattern matched, use the standard flags. */
2770    if (!m) {
2771	compadd = 0;
2772	brange = 0;
2773	erange = clwnum - 1;
2774	makecomplistflags(occ, os, incmd, 0);
2775    }
2776}
2777
2778/**/
2779static int
2780sep_comp_string(char *ss, char *s, int noffs)
2781{
2782    LinkList foo = newlinklist();
2783    LinkNode n;
2784    int owe = we, owb = wb, ocs = zlemetacs, swb, swe, scs, soffs, ne = noerrs;
2785    int sl = strlen(ss), tl, got = 0, i = 0, cur = -1, oll = zlemetall, remq;
2786    int ois = instring, oib = inbackt, ona = noaliases;
2787    char *tmp, *p, *ns, *ol = zlemetaline, sav, *oaq = autoq;
2788    char *qp, *qs, *ts;
2789
2790    swb = swe = soffs = 0;
2791    ns = NULL;
2792
2793    METACHECK();
2794
2795    /* Put the string in the lexer buffer and call the lexer to *
2796     * get the words we have to expand.                        */
2797    addedx = 1;
2798    noerrs = 1;
2799    lexsave();
2800    lexflags = LEXFLAGS_ZLE;
2801    tmp = (char *) zhalloc(tl = sl + 3 + strlen(s));
2802    strcpy(tmp, ss);
2803    tmp[sl] = ' ';
2804    memcpy(tmp + sl + 1, s, noffs);
2805    tmp[(scs = zlemetacs = sl + 1 + noffs)] = 'x';
2806    strcpy(tmp + sl + 2 + noffs, s + noffs);
2807    if ((remq = (*compqstack == QT_BACKSLASH)))
2808	tmp = rembslash(tmp);
2809    inpush(dupstrspace(tmp), 0, NULL);
2810    zlemetaline = tmp;
2811    zlemetall = tl - 1;
2812    strinbeg(0);
2813    noaliases = 1;
2814    do {
2815	ctxtlex();
2816	if (tok == LEXERR) {
2817	    int j;
2818
2819	    if (!tokstr)
2820		break;
2821	    for (j = 0, p = tokstr; *p; p++)
2822		if (*p == Snull || *p == Dnull)
2823		    j++;
2824	    if (j & 1) {
2825		tok = STRING;
2826		if (p > tokstr && p[-1] == ' ')
2827		    p[-1] = '\0';
2828	    }
2829	}
2830	if (tok == ENDINPUT || tok == LEXERR)
2831	    break;
2832	if (tokstr && *tokstr)
2833	    addlinknode(foo, (p = ztrdup(tokstr)));
2834	else
2835	    p = NULL;
2836	if (!got && !lexflags) {
2837	    DPUTS(!p, "no current word in substr");
2838	    got = 1;
2839	    cur = i;
2840	    swb = wb - 1;
2841	    swe = we - 1;
2842	    soffs = zlemetacs - swb;
2843	    chuck(p + soffs);
2844	    ns = dupstring(p);
2845	}
2846	i++;
2847    } while (tok != ENDINPUT && tok != LEXERR);
2848    noaliases = ona;
2849    strinend();
2850    inpop();
2851    errflag = 0;
2852    noerrs = ne;
2853    lexrestore();
2854    wb = owb;
2855    we = owe;
2856    zlemetacs = ocs;
2857    zlemetaline = ol;
2858    zlemetall = oll;
2859    if (cur < 0 || i < 1)
2860	return 1;
2861    owb = offs;
2862    offs = soffs;
2863    if ((p = check_param(ns, 0, 1))) {
2864	for (p = ns; *p; p++)
2865	    if (*p == Dnull)
2866		*p = '"';
2867	    else if (*p == Snull)
2868		*p = '\'';
2869    }
2870    offs = owb;
2871
2872    untokenize(ts = dupstring(ns));
2873
2874    if (*ns == Snull || *ns == Dnull ||
2875	((*ns == String || *ns == Qstring) && ns[1] == Snull)) {
2876	char *tsptr = ts, *nsptr = ns, sav;
2877	switch (*ns) {
2878	case Snull:
2879	    instring = QT_SINGLE;
2880	    break;
2881
2882	case Dnull:
2883	    instring = QT_DOUBLE;
2884	    break;
2885
2886	default:
2887	    instring = QT_DOLLARS;
2888	    nsptr++;
2889	    tsptr++;
2890	    break;
2891	}
2892
2893	inbackt = 0;
2894	swb++;
2895	if (nsptr[strlen(nsptr) - 1] == *nsptr && nsptr[1])
2896	    swe--;
2897	sav = *++tsptr;
2898	*tsptr = '\0';
2899	autoq = compqstack[1] ? "" : multiquote(ts, 1);
2900	*(ts = tsptr) = sav;
2901    } else {
2902	instring = QT_NONE;
2903	autoq = "";
2904    }
2905    for (p = ns, i = swb; *p; p++, i++) {
2906	if (inull(*p)) {
2907	    if (i < scs) {
2908		soffs--;
2909		if (remq && *p == Bnull && p[1])
2910		    swb -= 2;
2911	    }
2912	    if (p[1] || *p != Bnull) {
2913		if (*p == Bnull) {
2914		    if (scs == i + 1)
2915			scs++, soffs++;
2916		} else {
2917		    if (scs > i--)
2918			scs--;
2919		}
2920	    } else {
2921		if (scs == swe)
2922		    scs--;
2923	    }
2924	    chuck(p--);
2925	}
2926    }
2927    ns = ts;
2928
2929    if (instring != QT_NONE && strchr(compqstack, QT_BACKSLASH)) {
2930	int rl = strlen(ns), ql = strlen(multiquote(ns, !!compqstack[1]));
2931
2932	if (ql > rl)
2933	    swb -= ql - rl;
2934    }
2935    sav = s[(i = swb - sl - 1)];
2936    s[i] = '\0';
2937    qp = tricat(qipre, multiquote(s, 0), "");
2938    s[i] = sav;
2939    if (swe < swb)
2940	swe = swb;
2941    swe -= sl + 1;
2942    sl = strlen(s);
2943    if (swe > sl) {
2944	swe = sl;
2945	if ((int)strlen(ns) > swe - swb + 1)
2946	    ns[swe - swb + 1] = '\0';
2947    }
2948    qs = tricat(multiquote(s + swe, 0), qisuf, "");
2949    sl = strlen(ns);
2950    if (soffs > sl)
2951	soffs = sl;
2952
2953    {
2954	char **ow = clwords, *os = cmdstr, *oqp = qipre, *oqs = qisuf;
2955	char *oqst = compqstack, compnewchar[2];
2956	int olws = clwsize, olwn = clwnum, olwp = clwpos;
2957	int obr = brange, oer = erange, oof = offs;
2958	unsigned long occ = ccont;
2959
2960	compnewchar[0] = (char)(instring != QT_NONE ? (char)instring :
2961				QT_BACKSLASH);
2962	compnewchar[1] = '\0';
2963	compqstack = tricat(compnewchar, compqstack, "");
2964
2965	clwsize = clwnum = countlinknodes(foo);
2966	clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
2967	for (n = firstnode(foo), i = 0; n; incnode(n), i++) {
2968	    p = clwords[i] = (char *) getdata(n);
2969	    untokenize(p);
2970	}
2971	clwords[i] = NULL;
2972	clwpos = cur;
2973	cmdstr = ztrdup(clwords[0]);
2974	brange = 0;
2975	erange = clwnum - 1;
2976	qipre = qp;
2977	qisuf = qs;
2978	offs = soffs;
2979	ccont = CC_CCCONT;
2980	makecomplistcmd(ns, !clwpos, CFN_FIRST);
2981	ccont = occ;
2982	offs = oof;
2983	zsfree(cmdstr);
2984	cmdstr = os;
2985	freearray(clwords);
2986	clwords = ow;
2987	clwsize = olws;
2988	clwnum = olwn;
2989	clwpos = olwp;
2990	brange = obr;
2991	erange = oer;
2992	zsfree(qipre);
2993	qipre = oqp;
2994	zsfree(qisuf);
2995	qisuf = oqs;
2996	zsfree(compqstack);
2997	compqstack = oqst;
2998    }
2999    autoq = oaq;
3000    instring = ois;
3001    inbackt = oib;
3002
3003    return 0;
3004}
3005
3006/* This adds the completions for the flags in the given compctl. */
3007
3008/**/
3009static void
3010makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
3011{
3012    int t, sf1, sf2, ooffs, um = usemenu, delit, oaw, gflags;
3013    int mn = mnum, ohp = haspattern;
3014    char *p, *sd = NULL, *tt, *s1, *s2, *os =  dupstring(s);
3015    struct cmlist ms;
3016
3017    ccont |= (cc->mask2 & (CC_CCCONT | CC_DEFCONT | CC_PATCONT));
3018
3019    if (incompfunc != 1 && ccstack && findnode(ccstack, cc))
3020	return;
3021
3022    if (!ccstack)
3023	ccstack = newlinklist();
3024    addlinknode(ccstack, cc);
3025
3026    if (incompfunc != 1 && allccs) {
3027	if (findnode(allccs, cc)) {
3028	    uremnode(ccstack, firstnode(ccstack));
3029	    return;
3030	}
3031	addlinknode(allccs, cc);
3032    }
3033    /* Go to the end of the word if complete_in_word is not set. */
3034    if (unset(COMPLETEINWORD) && zlemetacs != we)
3035	zlemetacs = we, offs = strlen(s);
3036
3037    s = dupstring(s);
3038    delit = ispattern = 0;
3039    usemenu = um;
3040    patcomp = filecomp = NULL;
3041    rpre = rsuf = lpre = lsuf = ppre = psuf = lppre = lpsuf =
3042	fpre = fsuf = ipre = ripre = prpre =
3043	qfpre = qfsuf = qrpre = qrsuf = qlpre = qlsuf = NULL;
3044
3045    curcc = cc;
3046
3047    mflags = 0;
3048    gflags = (((cc->mask2 & CC_NOSORT ) ? CGF_NOSORT  : 0) |
3049	      ((cc->mask2 & CC_UNIQALL) ? CGF_UNIQALL : 0) |
3050	      ((cc->mask2 & CC_UNIQCON) ? CGF_UNIQCON : 0));
3051    if (cc->gname) {
3052	endcmgroup(NULL);
3053	begcmgroup(cc->gname, gflags);
3054    }
3055    if (cc->ylist) {
3056	endcmgroup(NULL);
3057	begcmgroup(NULL, gflags);
3058    }
3059    if (cc->mask & CC_REMOVE)
3060	mflags |= CMF_REMOVE;
3061    if (cc->explain) {
3062	curexpl = (Cexpl) zhalloc(sizeof(struct cexpl));
3063	curexpl->count = curexpl->fcount = 0;
3064    } else
3065	curexpl = NULL;
3066    /* compadd is the number of characters we have to ignore at the  *
3067     * beginning of the word.                                        */
3068    if (compadd) {
3069	ipre = dupstring(s);
3070	ipre[compadd] = '\0';
3071	untokenize(ipre);
3072	wb += compadd;
3073	s += compadd;
3074	if ((offs -= compadd) < 0) {
3075	    /* It's bigger than our word prefix, so we can't help here... */
3076	    uremnode(ccstack, firstnode(ccstack));
3077	    return;
3078	}
3079    } else
3080	ipre = NULL;
3081
3082    if (cc->matcher) {
3083	ms.next = mstack;
3084	ms.matcher = cc->matcher;
3085	mstack = &ms;
3086
3087	if (!mnum)
3088	    add_bmatchers(cc->matcher);
3089
3090	addlinknode(matchers, cc->matcher);
3091	cc->matcher->refc++;
3092    }
3093    if (mnum && (mstack || bmatchers))
3094	update_bmatchers();
3095
3096    /* Insert the prefix (compctl -P), if any. */
3097    if (cc->prefix) {
3098	int pl = 0;
3099
3100	if (*s) {
3101	    char *dp = rembslash(cc->prefix);
3102	    /* First find out how much of the prefix is already on the line. */
3103	    sd = dupstring(s);
3104	    untokenize(sd);
3105	    pl = pfxlen(dp, sd);
3106	    s += pl;
3107	    sd += pl;
3108	    offs -= pl;
3109	}
3110    }
3111    /* Does this compctl have a suffix (compctl -S)? */
3112    if (cc->suffix) {
3113	char *sdup = rembslash(cc->suffix);
3114	int sl = strlen(sdup), suffixll;
3115
3116	/* Ignore trailing spaces. */
3117	for (p = sdup + sl - 1; p >= sdup && *p == ' '; p--, sl--);
3118	p[1] = '\0';
3119
3120	if (!sd) {
3121	    sd = dupstring(s);
3122	    untokenize(sd);
3123	}
3124	/* If the suffix is already there, ignore it (and don't add *
3125	 * it again).                                               */
3126	if (*sd && (suffixll = strlen(sd)) >= sl &&
3127	    offs <= suffixll - sl && !strcmp(sdup, sd + suffixll - sl))
3128	    s[suffixll - sl] = '\0';
3129    }
3130    /* Do we have one of the special characters `~' and `=' at the beginning? */
3131    if (incompfunc || ((ic = *s) != Tilde && ic != Equals))
3132	ic = 0;
3133
3134    /* Check if we have to complete a parameter name... */
3135    if (!incompfunc && (p = check_param(s, 1, 0))) {
3136	s = p;
3137	/* And now make sure that we complete parameter names. */
3138	cc = &cc_dummy;
3139	cc_dummy.refc = 10000;
3140	cc_dummy.mask = CC_PARAMS | CC_ENVVARS;
3141    }
3142    ooffs = offs;
3143    /* If we have to ignore the word, do that. */
3144    if (cc->mask & CC_DELETE) {
3145	delit = 1;
3146	*s = '\0';
3147	offs = 0;
3148	if (isset(AUTOMENU))
3149	    usemenu = 1;
3150    }
3151
3152    /* Compute line prefix/suffix. */
3153    lpl = offs;
3154    lpre = zhalloc(lpl + 1);
3155    memcpy(lpre, s, lpl);
3156    lpre[lpl] = '\0';
3157    qlpre = quotename(lpre, NULL);
3158    lsuf = dupstring(s + offs);
3159    lsl = strlen(lsuf);
3160    qlsuf = quotename(lsuf, NULL);
3161
3162    /* First check for ~.../... */
3163    if (ic == Tilde) {
3164	for (p = lpre + lpl; p > lpre; p--)
3165	    if (*p == '/')
3166		break;
3167
3168	if (*p == '/')
3169	    ic = 0;
3170    }
3171    /* Compute real prefix/suffix. */
3172
3173    noreal = !delit;
3174    for (p = lpre; *p && *p != String && *p != Tick; p++);
3175    tt = ic && !ispar ? lpre + 1 : lpre;
3176    rpre = (*p || *lpre == Tilde || *lpre == Equals) ?
3177	(noreal = 0, getreal(tt)) :
3178	dupstring(tt);
3179    qrpre = quotename(rpre, NULL);
3180
3181    for (p = lsuf; *p && *p != String && *p != Tick; p++);
3182    rsuf = *p ? (noreal = 0, getreal(lsuf)) : dupstring(lsuf);
3183    qrsuf = quotename(rsuf, NULL);
3184
3185    /* Check if word is a pattern. */
3186
3187    for (s1 = NULL, sf1 = 0, p = rpre + (rpl = strlen(rpre)) - 1;
3188	 p >= rpre && (ispattern != 3 || !sf1);
3189	 p--)
3190	if (itok(*p) && (p > rpre || (*p != Equals && *p != Tilde)))
3191	    ispattern |= sf1 ? 1 : 2;
3192	else if (*p == '/') {
3193	    sf1++;
3194	    if (!s1)
3195		s1 = p;
3196	}
3197    rsl = strlen(rsuf);
3198    for (s2 = NULL, sf2 = t = 0, p = rsuf; *p && (!t || !sf2); p++)
3199	if (itok(*p))
3200	    t |= sf2 ? 4 : 2;
3201	else if (*p == '/') {
3202	    sf2++;
3203	    if (!s2)
3204		s2 = p;
3205	}
3206    ispattern = ispattern | t;
3207
3208    /* But if we were asked not to do glob completion, we never treat the *
3209     * thing as a pattern.                                                */
3210    if (!comppatmatch || !*comppatmatch)
3211	ispattern = 0;
3212
3213    if (ispattern) {
3214	/* The word should be treated as a pattern, so compute the matcher. */
3215	p = (char *) zhalloc(rpl + rsl + 2);
3216	strcpy(p, rpre);
3217	if (rpl && p[rpl - 1] != Star &&
3218	    (!comppatmatch || *comppatmatch == '*')) {
3219	    p[rpl] = Star;
3220	    strcpy(p + rpl + 1, rsuf);
3221	} else
3222	    strcpy(p + rpl, rsuf);
3223	patcomp = patcompile(p, 0, NULL);
3224	haspattern = 1;
3225    }
3226    if (!patcomp) {
3227	untokenize(rpre);
3228	untokenize(rsuf);
3229
3230	rpl = strlen(rpre);
3231	rsl = strlen(rsuf);
3232    }
3233    untokenize(lpre);
3234    untokenize(lsuf);
3235
3236    if (!(cc->mask & CC_DELETE))
3237	hasmatched = 1;
3238
3239    /* Handle completion of files specially (of course). */
3240
3241    if ((cc->mask & (CC_FILES | CC_DIRS | CC_COMMPATH)) || cc->glob) {
3242	/* s1 and s2 point to the last/first slash in the prefix/suffix. */
3243	if (!s1)
3244	    s1 = rpre;
3245	if (!s2)
3246	    s2 = rsuf + rsl;
3247
3248	/* Compute the path prefix/suffix. */
3249	if (*s1 != '/')
3250	    ppre = "";
3251	else
3252	    ppre = dupstrpfx(rpre, s1 - rpre + 1);
3253	psuf = dupstring(s2);
3254
3255	if (zlemetacs != wb) {
3256	    char save = zlemetaline[zlemetacs];
3257
3258	    zlemetaline[zlemetacs] = 0;
3259	    lppre = dupstring(zlemetaline + wb +
3260			      (qipre && *qipre ?
3261			       (strlen(qipre) -
3262				(*qipre == '\'' || *qipre == '\"')) : 0));
3263	    zlemetaline[zlemetacs] = save;
3264	    if (brbeg) {
3265		Brinfo bp;
3266
3267		for (bp = brbeg; bp; bp = bp->next)
3268		    strcpy(lppre + bp->qpos,
3269			   lppre + bp->qpos + strlen(bp->str));
3270	    }
3271	    if ((p = strrchr(lppre, '/'))) {
3272		p[1] = '\0';
3273		lppl = strlen(lppre);
3274	    } else if (!sf1) {
3275		lppre = NULL;
3276		lppl = 0;
3277	    } else {
3278		lppre = ppre;
3279		lppl = strlen(lppre);
3280	    }
3281	} else {
3282	    lppre = NULL;
3283	    lppl = 0;
3284	}
3285	if (zlemetacs != we) {
3286	    int end = we;
3287	    char save = zlemetaline[end];
3288
3289	    if (qisuf && *qisuf) {
3290		int ql = strlen(qisuf);
3291
3292		end -= ql - (qisuf[ql-1] == '\'' || qisuf[ql-1] == '"');
3293	    }
3294	    zlemetaline[end] = 0;
3295	    lpsuf = dupstring(zlemetaline + zlemetacs);
3296	    zlemetaline[end] = save;
3297	    if (brend) {
3298		Brinfo bp;
3299		char *p;
3300		int bl;
3301
3302		for (bp = brend; bp; bp = bp->next) {
3303		    p = lpsuf + (we - zlemetacs) - bp->qpos -
3304			(bl = strlen(bp->str));
3305		    strcpy(p, p + bl);
3306		}
3307	    }
3308	    if (!(lpsuf = strchr(lpsuf, '/')) && sf2)
3309		lpsuf = psuf;
3310	    lpsl = (lpsuf ? strlen(lpsuf) : 0);
3311	} else {
3312	    lpsuf = NULL;
3313	    lpsl = 0;
3314	}
3315
3316	/* And get the file prefix. */
3317	fpre = dupstring(((s1 == s || s1 == rpre || ic) &&
3318			  (*s != '/' || zlemetacs == wb)) ? s1 : s1 + 1);
3319	qfpre = quotename(fpre, NULL);
3320	/* And the suffix. */
3321	fsuf = dupstrpfx(rsuf, s2 - rsuf);
3322	qfsuf = quotename(fsuf, NULL);
3323
3324	if (comppatmatch && *comppatmatch && (ispattern & 2)) {
3325	    int t2;
3326
3327	    /* We have to use globbing, so compute the pattern from *
3328	     * the file prefix and suffix with a `*' between them.  */
3329	    p = (char *) zhalloc((t2 = strlen(fpre)) + strlen(fsuf) + 2);
3330	    strcpy(p, fpre);
3331	    if ((!t2 || p[t2 - 1] != Star) && *fsuf != Star &&
3332		(!comppatmatch || *comppatmatch == '*'))
3333		p[t2++] = Star;
3334	    strcpy(p + t2, fsuf);
3335	    filecomp = patcompile(p, 0, NULL);
3336	}
3337	if (!filecomp) {
3338	    untokenize(fpre);
3339	    untokenize(fsuf);
3340
3341	    fpl = strlen(fpre);
3342	    fsl = strlen(fsuf);
3343	}
3344	addwhat = -1;
3345
3346	/* Completion after `~', maketildelist adds the usernames *
3347	 * and named directories.                                 */
3348	if (ic == Tilde) {
3349	    char *oi = ipre;
3350
3351	    ipre = (ipre ? dyncat("~", ipre) : "~");
3352	    maketildelist();
3353	    ipre = oi;
3354	} else if (ic == Equals) {
3355	    /* Completion after `=', get the command names from *
3356	     * the cmdnamtab and aliases from aliastab.         */
3357	    char *oi = ipre;
3358
3359	    ipre = (ipre ? dyncat("=", ipre) : "=");
3360	    if (isset(HASHLISTALL))
3361		cmdnamtab->filltable(cmdnamtab);
3362	    dumphashtable(cmdnamtab, -7);
3363	    dumphashtable(aliastab, -2);
3364	    ipre = oi;
3365	} else {
3366	    /* Normal file completion... */
3367	    if (ispattern & 1) {
3368		/* But with pattern matching. */
3369		LinkList l = newlinklist();
3370		LinkNode n;
3371		int ng = opts[NULLGLOB];
3372
3373		opts[NULLGLOB] = 1;
3374
3375		addwhat = 0;
3376		p = (char *) zhalloc(lpl + lsl + 3);
3377		strcpy(p, lpre);
3378		if (*lsuf != '*' && *lpre && lpre[lpl - 1] != '*')
3379		    strcat(p, "*");
3380		strcat(p, lsuf);
3381		if (*lsuf && lsuf[lsl - 1] != '*' && lsuf[lsl - 1] != ')')
3382		    strcat(p, "*");
3383
3384		/* Do the globbing. */
3385		tokenize(p);
3386		remnulargs(p);
3387		addlinknode(l, p);
3388		globlist(l, 0);
3389
3390		if (nonempty(l)) {
3391		    /* And add the resulting words. */
3392		    mflags |= CMF_FILE;
3393		    for (n = firstnode(l); n; incnode(n))
3394			addmatch(getdata(n), NULL);
3395		    mflags &= !CMF_FILE;
3396		}
3397		opts[NULLGLOB] = ng;
3398	    } else {
3399		char **dirs = 0, *ta[2];
3400
3401		/* No pattern matching. */
3402		addwhat = CC_FILES;
3403
3404		if (cc->withd) {
3405		    char **pp, **npp, *tp;
3406		    int tl = strlen(ppre) + 2, pl;
3407
3408		    if ((pp = get_user_var(cc->withd))) {
3409			dirs = npp =
3410			    (char**) zhalloc(sizeof(char *)*(arrlen(pp)+1));
3411			while (*pp) {
3412			    pl = strlen(*pp);
3413			    tp = (char *) zhalloc(strlen(*pp) + tl);
3414			    strcpy(tp, *pp);
3415			    tp[pl] = '/';
3416			    strcpy(tp + pl + 1, ppre);
3417			    *npp++ = tp;
3418			    pp++;
3419			}
3420			*npp = '\0';
3421		    }
3422		}
3423		if (!dirs) {
3424		    dirs = ta;
3425		    if (cc->withd) {
3426			char *tp;
3427			int pl = strlen(cc->withd);
3428
3429			ta[0] = tp = (char *) zhalloc(strlen(ppre) + pl + 2);
3430			strcpy(tp, cc->withd);
3431			tp[pl] = '/';
3432			strcpy(tp + pl + 1, ppre);
3433		    } else
3434			ta[0] = ppre;
3435		    ta[1] = NULL;
3436		}
3437		while (*dirs) {
3438		    prpre = *dirs;
3439
3440		    if (sf2)
3441			/* We are in the path, so add only directories. */
3442			gen_matches_files(1, 0, 0);
3443		    else {
3444			if (cc->mask & CC_FILES)
3445			    /* Add all files. */
3446			    gen_matches_files(0, 0, 1);
3447			else if (cc->mask & CC_COMMPATH) {
3448			    /* Completion of command paths. */
3449			    if (sf1 || cc->withd)
3450				/* There is a path prefix, so add *
3451				 * directories and executables.   */
3452				gen_matches_files(1, 1, 0);
3453			    else {
3454				/* No path prefix, so add the things *
3455				 * reachable via the PATH variable.  */
3456				char **pc = path, *pp = prpre;
3457
3458				for (; *pc; pc++)
3459				    if (!**pc || (pc[0][0] == '.' && !pc[0][1]))
3460					break;
3461				if (*pc) {
3462				    prpre = "./";
3463				    gen_matches_files(1, 1, 0);
3464				    prpre = pp;
3465				}
3466			    }
3467			} else if (cc->mask & CC_DIRS)
3468			    gen_matches_files(1, 0, 0);
3469			/* The compctl has a glob pattern (compctl -g). */
3470			if (cc->glob) {
3471			    int ns, pl = strlen(prpre), o, paalloc;
3472			    char *g = dupstring(cc->glob), *pa;
3473			    char *p2, *p3;
3474			    int ne = noerrs, md = opts[MARKDIRS];
3475
3476			    /* These are used in the globbing code to make *
3477			     * things a bit faster.                        */
3478			    if (ispattern || mstack)
3479				glob_pre = glob_suf = NULL;
3480			    else {
3481				glob_pre = fpre;
3482				glob_suf = fsuf;
3483			    }
3484			    noerrs = 1;
3485			    addwhat = -6;
3486			    o = strlen(prpre);
3487			    pa = (char *)zalloc(paalloc = o + PATH_MAX);
3488			    strcpy(pa, prpre);
3489			    opts[MARKDIRS] = 0;
3490
3491			    /* The compctl -g string may contain more than *
3492			     * one pattern, so we need a loop.             */
3493			    while (*g) {
3494				LinkList l = newlinklist();
3495				int ng;
3496
3497				/* Find the blank terminating the pattern. */
3498				while (*g && inblank(*g))
3499				    g++;
3500				/* Oops, we already reached the end of the
3501				   string. */
3502				if (!*g)
3503				    break;
3504				for (p = g + 1; *p && !inblank(*p); p++)
3505				    if (*p == '\\' && p[1])
3506					p++;
3507				/* Get the pattern string. */
3508				tokenize(g = dupstrpfx(g, p - g));
3509				if (*g == '=' && isset(EQUALS))
3510				    *g = Equals;
3511				if (*g == '~')
3512				    *g = Tilde;
3513				remnulargs(g);
3514				if ((*g == Equals || *g == Tilde) && !cc->withd) {
3515				/* The pattern has a `~' or `=' at the  *
3516				 * beginning, so we expand this and use *
3517				 * the result.                          */
3518				    filesub(&g, 0);
3519				    addlinknode(l, dupstring(g));
3520				} else if (*g == '/' && !cc->withd)
3521				/* The pattern is a full path (starting *
3522				 * with '/'), so add it unchanged.      */
3523				    addlinknode(l, dupstring(g));
3524				else {
3525				/* It's a simple pattern, so append it to *
3526				 * the path we have on the command line.  */
3527				    int minlen = o + strlen(g);
3528				    if (minlen >= paalloc)
3529					pa = (char *)
3530					    zrealloc(pa, paalloc = minlen+1);
3531				    strcpy(pa + o, g);
3532				    addlinknode(l, dupstring(pa));
3533				}
3534				/* Do the globbing. */
3535				ng = opts[NULLGLOB];
3536				opts[NULLGLOB] = 1;
3537				globlist(l, 0);
3538				opts[NULLGLOB] = ng;
3539				/* Get the results. */
3540				if (nonempty(l) && peekfirst(l)) {
3541				    for (p2 = (char *)peekfirst(l); *p2; p2++)
3542					if (itok(*p2))
3543					    break;
3544				    if (!*p2) {
3545					if ((*g == Equals || *g == Tilde ||
3546					     *g == '/') || cc->withd) {
3547					    /* IF the pattern started with `~',  *
3548					     * `=', or `/', add the result only, *
3549					     * if it really matches what we have *
3550					     * on the line.                      *
3551					     * Do this if an initial directory   *
3552					     * was specified, too.               */
3553					    while ((p2 = (char *)ugetnode(l)))
3554						if (strpfx(prpre, p2))
3555						    addmatch(p2 + pl, NULL);
3556					} else {
3557					    /* Otherwise ignore the path we *
3558					     * prepended to the pattern.    */
3559					    while ((p2 = p3 =
3560						    (char *)ugetnode(l))) {
3561						for (ns = sf1; *p3 && ns; p3++)
3562						    if (*p3 == '/')
3563							ns--;
3564
3565						addmatch(p3, NULL);
3566					    }
3567					}
3568				    }
3569				}
3570				pa[o] = '\0';
3571				g = p;
3572			    }
3573			    glob_pre = glob_suf = NULL;
3574			    noerrs = ne;
3575			    opts[MARKDIRS] = md;
3576
3577			    zfree(pa, paalloc);
3578			}
3579		    }
3580		    dirs++;
3581		}
3582		prpre = NULL;
3583	    }
3584	}
3585	lppre = lpsuf = NULL;
3586	lppl = lpsl = 0;
3587    }
3588    if (ic) {
3589	/* Now change the `~' and `=' tokens to the real characters so *
3590	 * that things starting with these characters will be added.   */
3591	rpre = dyncat((ic == Tilde) ? "~" : "=", rpre);
3592	rpl++;
3593	qrpre = dyncat((ic == Tilde) ? "~" : "=", qrpre);
3594    }
3595    if (!ic && (cc->mask & CC_COMMPATH) && !*ppre && !*psuf) {
3596	/* If we have to complete commands, add alias names, *
3597	 * shell functions and builtins too.                 */
3598	dumphashtable(aliastab, -3);
3599	dumphashtable(reswdtab, -3);
3600	dumphashtable(shfunctab, -3);
3601	dumphashtable(builtintab, -3);
3602	if (isset(HASHLISTALL))
3603	    cmdnamtab->filltable(cmdnamtab);
3604	dumphashtable(cmdnamtab, -3);
3605	/* And parameter names if autocd and cdablevars are set. */
3606	if (isset(AUTOCD) && isset(CDABLEVARS))
3607	    dumphashtable(paramtab, -4);
3608    }
3609    oaw = addwhat = (cc->mask & CC_QUOTEFLAG) ? -2 : CC_QUOTEFLAG;
3610
3611    if (cc->mask & CC_NAMED)
3612	/* Add named directories. */
3613	dumphashtable(nameddirtab, addwhat);
3614    if (cc->mask & CC_OPTIONS)
3615	/* Add option names. */
3616	dumphashtable(optiontab, addwhat);
3617    if (cc->mask & CC_VARS) {
3618	/* And parameter names. */
3619	dumphashtable(paramtab, -9);
3620	addwhat = oaw;
3621    }
3622    if (cc->mask & CC_BINDINGS) {
3623	/* And zle function names... */
3624	dumphashtable(thingytab, CC_BINDINGS);
3625	addwhat = oaw;
3626    }
3627    if (cc->keyvar) {
3628	/* This adds things given to the compctl -k flag *
3629	 * (from a parameter or a list of words).        */
3630	char **usr = get_user_var(cc->keyvar);
3631
3632	if (usr)
3633	    while (*usr)
3634		addmatch(*usr++, NULL);
3635    }
3636    if (cc->mask & CC_USERS) {
3637	/* Add user names. */
3638	maketildelist();
3639	addwhat = oaw;
3640    }
3641    if (cc->func) {
3642	/* This handles the compctl -K flag. */
3643	Shfunc shfunc;
3644	char **r;
3645	int lv = lastval;
3646
3647	/* Get the function. */
3648	if ((shfunc = getshfunc(cc->func))) {
3649	    /* We have it, so build a argument list. */
3650	    LinkList args = newlinklist();
3651	    int osc = sfcontext;
3652
3653	    addlinknode(args, cc->func);
3654
3655	    if (delit) {
3656		p = dupstrpfx(os, ooffs);
3657		untokenize(p);
3658		addlinknode(args, p);
3659		p = dupstring(os + ooffs);
3660		untokenize(p);
3661		addlinknode(args, p);
3662	    } else {
3663		addlinknode(args, lpre);
3664		addlinknode(args, lsuf);
3665	    }
3666
3667	    /* This flag allows us to use read -l and -c. */
3668	    if (incompfunc != 1)
3669		incompctlfunc = 1;
3670	    sfcontext = SFC_COMPLETE;
3671	    /* Call the function. */
3672	    doshfunc(shfunc, args, 1);
3673	    sfcontext = osc;
3674	    incompctlfunc = 0;
3675	    /* And get the result from the reply parameter. */
3676	    if ((r = get_user_var("reply")))
3677		while (*r)
3678		    addmatch(*r++, NULL);
3679	}
3680	lastval = lv;
3681    }
3682    if (cc->mask & (CC_JOBS | CC_RUNNING | CC_STOPPED)) {
3683	/* Get job names. */
3684	int i;
3685	char *j;
3686
3687	for (i = 0; i <= maxjob; i++)
3688	    if ((jobtab[i].stat & STAT_INUSE) &&
3689		jobtab[i].procs && jobtab[i].procs->text) {
3690		int stopped = jobtab[i].stat & STAT_STOPPED;
3691
3692		j = dupstring(jobtab[i].procs->text);
3693		if ((cc->mask & CC_JOBS) ||
3694		    (stopped && (cc->mask & CC_STOPPED)) ||
3695		    (!stopped && (cc->mask & CC_RUNNING)))
3696		    addmatch(j, NULL);
3697	    }
3698    }
3699    if (cc->str) {
3700	/* Get the stuff from a compctl -s. */
3701	LinkList foo = newlinklist();
3702	LinkNode n;
3703	int first = 1, ng = opts[NULLGLOB], oowe = we, oowb = wb;
3704	int ona = noaliases;
3705	char *tmpbuf;
3706
3707	opts[NULLGLOB] = 1;
3708
3709	/* Put the string in the lexer buffer and call the lexer to *
3710	 * get the words we have to expand.                        */
3711	lexsave();
3712	lexflags = LEXFLAGS_ZLE;
3713	tmpbuf = (char *)zhalloc(strlen(cc->str) + 5);
3714	sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */
3715	inpush(tmpbuf, 0, NULL);
3716	strinbeg(0);
3717	noaliases = 1;
3718	do {
3719	    ctxtlex();
3720	    if (tok == ENDINPUT || tok == LEXERR)
3721		break;
3722	    if (!first && tokstr && *tokstr)
3723		addlinknode(foo, ztrdup(tokstr));
3724	    first = 0;
3725	} while (tok != ENDINPUT && tok != LEXERR);
3726	noaliases = ona;
3727	strinend();
3728	inpop();
3729	errflag = 0;
3730	lexrestore();
3731	/* Fine, now do full expansion. */
3732	prefork(foo, 0);
3733	if (!errflag) {
3734	    globlist(foo, 0);
3735	    if (!errflag)
3736		/* And add the resulting words as matches. */
3737		for (n = firstnode(foo); n; incnode(n))
3738		    addmatch(getdata(n), NULL);
3739	}
3740	opts[NULLGLOB] = ng;
3741	we = oowe;
3742	wb = oowb;
3743    }
3744    if (cc->hpat) {
3745	/* We have a pattern to take things from the history. */
3746	Patprog pprogc = NULL;
3747	char *e, *h, hpatsav;
3748	zlong i = addhistnum(curhist,-1,HIST_FOREIGN), n = cc->hnum;
3749	Histent he = gethistent(i, GETHIST_UPWARD);
3750
3751	/* Parse the pattern, if it isn't the null string. */
3752	if (*(cc->hpat)) {
3753	    char *thpat = dupstring(cc->hpat);
3754
3755	    tokenize(thpat);
3756	    pprogc = patcompile(thpat, 0, NULL);
3757	}
3758	/* n holds the number of history line we have to search. */
3759	if (!n)
3760	    n = -1;
3761
3762	/* Now search the history. */
3763	while (n-- && he) {
3764	    int iwords;
3765	    for (iwords = he->nwords - 1; iwords >= 0; iwords--) {
3766		h = he->node.nam + he->words[iwords*2];
3767		e = he->node.nam + he->words[iwords*2+1];
3768		hpatsav = *e;
3769		*e = '\0';
3770		/* We now have a word from the history, ignore it *
3771		 * if it begins with a quote or `$'.              */
3772		if (*h != '\'' && *h != '"' && *h != '`' && *h != '$' &&
3773		    (!pprogc || pattry(pprogc, h)))
3774		    /* Otherwise add it if it was matched. */
3775		    addmatch(dupstring(h), NULL);
3776		if (hpatsav)
3777		    *e = hpatsav;
3778	    }
3779	    he = up_histent(he);
3780	}
3781	freepatprog(pprogc);
3782    }
3783    if ((t = cc->mask & (CC_ARRAYS | CC_INTVARS | CC_ENVVARS | CC_SCALARS |
3784			 CC_READONLYS | CC_SPECIALS | CC_PARAMS)))
3785	/* Add various flavours of parameters. */
3786	dumphashtable(paramtab, t);
3787    if ((t = cc->mask & CC_SHFUNCS))
3788	/* Add shell functions. */
3789	dumphashtable(shfunctab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
3790    if ((t = cc->mask & CC_BUILTINS))
3791	/* Add builtins. */
3792	dumphashtable(builtintab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
3793    if ((t = cc->mask & CC_EXTCMDS)) {
3794	/* Add external commands */
3795	if (isset(HASHLISTALL))
3796	    cmdnamtab->filltable(cmdnamtab);
3797	dumphashtable(cmdnamtab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
3798    }
3799    if ((t = cc->mask & CC_RESWDS))
3800	/* Add reserved words */
3801	dumphashtable(reswdtab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
3802    if ((t = cc->mask & (CC_ALREG | CC_ALGLOB)))
3803	/* Add the two types of aliases. */
3804	dumphashtable(aliastab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
3805    if (keypm && cc == &cc_dummy) {
3806	/* Add the keys of the parameter in keypm. */
3807	HashTable t = keypm->gsu.h->getfn(keypm);
3808
3809	if (t)
3810	    scanhashtable(t, 0, 0, PM_UNSET, addhnmatch, 0);
3811	keypm = NULL;
3812	cc_dummy.suffix = NULL;
3813    }
3814    if (!errflag && cc->ylist) {
3815	/* generate the user-defined display list: if anything fails, *
3816	 * we silently allow the normal completion list to be used.   */
3817	char **yaptr = NULL, *uv = NULL;
3818	Shfunc shfunc;
3819
3820	if (cc->ylist[0] == '$' || cc->ylist[0] == '(') {
3821	    /* from variable */
3822	    uv = cc->ylist + (cc->ylist[0] == '$');
3823	} else if ((shfunc = getshfunc(cc->ylist))) {
3824	    /* from function:  pass completions as arg list */
3825	    LinkList args = newlinklist();
3826	    LinkNode ln;
3827	    Cmatch m;
3828	    int osc = sfcontext;
3829
3830	    addlinknode(args, cc->ylist);
3831	    for (ln = firstnode(matches); ln; ln = nextnode(ln)) {
3832		m = (Cmatch) getdata(ln);
3833		if (m->ppre) {
3834		    char *s = (m->psuf ? m->psuf : "");
3835		    char *p = (char *) zhalloc(strlen(m->ppre) + strlen(m->str) +
3836					      strlen(s) + 1);
3837
3838		    sprintf(p, "%s%s%s", m->ppre, m->str, s);
3839		    addlinknode(args, dupstring(p));
3840		} else
3841		    addlinknode(args, dupstring(m->str));
3842	    }
3843
3844	    /* No harm in allowing read -l and -c here, too */
3845	    if (incompfunc != 1)
3846		incompctlfunc = 1;
3847	    sfcontext = SFC_COMPLETE;
3848	    doshfunc(shfunc, args, 1);
3849	    sfcontext = osc;
3850	    incompctlfunc = 0;
3851	    uv = "reply";
3852	}
3853	if (uv)
3854	    yaptr = get_user_var(uv);
3855	if ((tt = cc->explain)) {
3856	    tt = dupstring(tt);
3857	    if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
3858		singsub(&tt);
3859		untokenize(tt);
3860	    }
3861	    curexpl->str = tt;
3862	    if (cc->gname) {
3863		endcmgroup(yaptr);
3864		begcmgroup(cc->gname, gflags);
3865		addexpl(0);
3866	    } else {
3867		addexpl(0);
3868		endcmgroup(yaptr);
3869		begcmgroup("default", 0);
3870	    }
3871	} else {
3872	    endcmgroup(yaptr);
3873	    begcmgroup("default", 0);
3874	}
3875    } else if ((tt = cc->explain)) {
3876	tt = dupstring(tt);
3877	if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
3878	    singsub(&tt);
3879	    untokenize(tt);
3880	}
3881	curexpl->str = tt;
3882	addexpl(0);
3883    }
3884    if (cc->subcmd) {
3885	/* Handle -l sub-completion. */
3886	char **ow = clwords, *os = cmdstr, *ops = NULL;
3887	int oldn = clwnum, oldp = clwpos, br;
3888	unsigned long occ = ccont;
3889
3890	ccont = CC_CCCONT;
3891
3892	/* So we restrict the words-array. */
3893	if (brange >= clwnum)
3894	    brange = clwnum - 1;
3895	if (brange < 1)
3896	    brange = 1;
3897	if (erange >= clwnum)
3898	    erange = clwnum - 1;
3899	if (erange < 1)
3900	    erange = 1;
3901	clwnum = erange - brange + 1;
3902	clwpos = clwpos - brange;
3903	br = brange;
3904
3905	if (cc->subcmd[0]) {
3906	    /* And probably put the command name given to the flag *
3907	     * in the array.                                       */
3908	    clwpos++;
3909	    clwnum++;
3910	    incmd = 0;
3911	    ops = clwords[br - 1];
3912	    clwords[br - 1] = ztrdup(cc->subcmd);
3913	    cmdstr = ztrdup(cc->subcmd);
3914	    clwords += br - 1;
3915	} else {
3916	    cmdstr = ztrdup(clwords[br]);
3917	    incmd = !clwpos;
3918	    clwords += br;
3919	}
3920	/* Produce the matches. */
3921	makecomplistcmd(s, incmd, CFN_FIRST);
3922
3923	/* And restore the things we changed. */
3924	clwords = ow;
3925	zsfree(cmdstr);
3926	cmdstr = os;
3927	clwnum = oldn;
3928	clwpos = oldp;
3929	if (ops) {
3930	    zsfree(clwords[br - 1]);
3931	    clwords[br - 1] = ops;
3932	}
3933	ccont = occ;
3934    }
3935    if (cc->substr)
3936	sep_comp_string(cc->substr, s, offs);
3937    uremnode(ccstack, firstnode(ccstack));
3938    if (cc->matcher)
3939	mstack = mstack->next;
3940
3941    if (mn == mnum)
3942	haspattern = ohp;
3943}
3944
3945
3946static struct builtin bintab[] = {
3947    BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
3948    BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
3949};
3950
3951static struct features module_features = {
3952    bintab, sizeof(bintab)/sizeof(*bintab),
3953    NULL, 0,
3954    NULL, 0,
3955    NULL, 0,
3956    0
3957};
3958
3959/**/
3960int
3961setup_(UNUSED(Module m))
3962{
3963    compctlreadptr = compctlread;
3964    createcompctltable();
3965    cc_compos.mask = CC_COMMPATH;
3966    cc_compos.mask2 = 0;
3967    cc_default.refc = 10000;
3968    cc_default.mask = CC_FILES;
3969    cc_default.mask2 = 0;
3970    cc_first.refc = 10000;
3971    cc_first.mask = 0;
3972    cc_first.mask2 = CC_CCCONT;
3973
3974    lastccused = NULL;
3975
3976    return 0;
3977}
3978
3979/**/
3980int
3981features_(Module m, char ***features)
3982{
3983    *features = featuresarray(m, &module_features);
3984    return 0;
3985}
3986
3987/**/
3988int
3989enables_(Module m, int **enables)
3990{
3991    return handlefeatures(m, &module_features, enables);
3992}
3993
3994/**/
3995int
3996boot_(Module m)
3997{
3998    addhookfunc("compctl_make", (Hookfn) ccmakehookfn);
3999    addhookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn);
4000    return 0;
4001}
4002
4003/**/
4004int
4005cleanup_(Module m)
4006{
4007    deletehookfunc("compctl_make", (Hookfn) ccmakehookfn);
4008    deletehookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn);
4009    return setfeatureenables(m, &module_features, NULL);
4010}
4011
4012/**/
4013int
4014finish_(UNUSED(Module m))
4015{
4016    deletehashtable(compctltab);
4017
4018    if (lastccused)
4019	freelinklist(lastccused, (FreeFunc) freecompctl);
4020
4021    compctlreadptr = fallback_compctlread;
4022    return 0;
4023}
4024