1/*
2 * module.c - deal with dynamic modules
3 *
4 * This file is part of zsh, the Z shell.
5 *
6 * Copyright (c) 1996-1997 Zoltán Hidvégi
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 Zoltán Hidvégi 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 Zoltán Hidvégi and the Zsh Development Group have been advised of
19 * the possibility of such damage.
20 *
21 * Zoltán Hidvégi 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 Zoltán Hidvégi and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
27 */
28
29#include "zsh.mdh"
30#include "module.pro"
31
32/*
33 * List of linked-in modules.
34 * This is set up at boot and remains for the life of the shell;
35 * entries do not appear in "zmodload" listings.
36 */
37
38/**/
39LinkList linkedmodules;
40
41/* $module_path ($MODULE_PATH) */
42
43/**/
44char **module_path;
45
46/* Hash of modules */
47
48/**/
49mod_export HashTable modulestab;
50
51/*
52 * Bit flags passed as the "flags" argument of a autofeaturefn_t.
53 * Used in other places, such as the final argument to
54 * do_module_features().
55 */
56enum {
57    /*
58     * `-i' option: ignore errors pertaining to redefinitions,
59     * or indicate to do_module_features() that it should be
60     * silent.
61     */
62    FEAT_IGNORE = 0x0001,
63    /* If a condition, condition is infix rather than prefix */
64    FEAT_INFIX = 0x0002,
65    /*
66     * Enable all features in the module when autoloading.
67     * This is the traditional zmodload -a behaviour;
68     * zmodload -Fa only enables features explicitly marked for
69     * autoloading.
70     */
71    FEAT_AUTOALL = 0x0004,
72    /*
73     * Remove feature:  alternative to "-X:NAME" used if
74     * X is passed separately from NAME.
75     */
76    FEAT_REMOVE = 0x0008,
77    /*
78     * For do_module_features().  Check that any autoloads
79     * for the module are actually provided.
80     */
81    FEAT_CHECKAUTO = 0x0010
82};
83
84/*
85 * All functions to add or remove autoloadable features fit
86 * the following prototype.
87 *
88 * "module" is the name of the module.
89 *
90 * "feature" is the name of the feature, minus any type prefix.
91 *
92 * "flags" is a set of the bits above.
93 *
94 * The return value is 0 for success, -1 for failure with no
95 * message needed, and one of the following to indicate the calling
96 * function should print a message:
97 *
98 * 1:  failed to add [type] `[feature]'
99 * 2:  [feature]: no such [type]
100 * 3:  [feature]: [type] is already defined
101 */
102typedef int (*autofeaturefn_t)(const char *module, const char *feature,
103			       int flags);
104
105/* Bits in the second argument to find_module. */
106enum {
107    /*
108     * Resolve any aliases to the underlying module.
109     */
110    FINDMOD_ALIASP = 0x0001,
111    /*
112     * Create an element for the module in the list if
113     * it is not found.
114     */
115    FINDMOD_CREATE = 0x0002,
116};
117
118static void
119freemodulenode(HashNode hn)
120{
121    Module m = (Module) hn;
122
123    if (m->node.flags & MOD_ALIAS)
124	zsfree(m->u.alias);
125    zsfree(m->node.nam);
126    if (m->autoloads)
127	freelinklist(m->autoloads, freestr);
128    if (m->deps)
129	freelinklist(m->deps, freestr);
130    zfree(m, sizeof(*m));
131}
132
133/* flags argument to printmodulenode */
134enum {
135    /* -L flag, output zmodload commands */
136    PRINTMOD_LIST = 0x0001,
137    /* -e flag */
138    PRINTMOD_EXIST = 0x0002,
139    /* -A flag */
140    PRINTMOD_ALIAS = 0x0004,
141    /* -d flag */
142    PRINTMOD_DEPS = 0x0008,
143    /* -F flag */
144    PRINTMOD_FEATURES = 0x0010,
145    /* -l flag in combination with -L flag */
146    PRINTMOD_LISTALL = 0x0020,
147    /* -a flag */
148    PRINTMOD_AUTO = 0x0040
149};
150
151/* Scan function for printing module details */
152
153static void
154printmodulenode(HashNode hn, int flags)
155{
156    Module m = (Module)hn;
157    /*
158     * If we check for a module loaded under an alias, we
159     * need the name of the alias.  We can use it in other
160     * cases, too.
161     */
162    const char *modname = m->node.nam;
163
164    if (flags & PRINTMOD_DEPS) {
165	/*
166	 * Print the module's dependencies.
167	 */
168	LinkNode n;
169
170	if (!m->deps)
171	    return;
172
173	if (flags & PRINTMOD_LIST) {
174	    printf("zmodload -d ");
175	    if (modname[0] == '-')
176		fputs("-- ", stdout);
177	    quotedzputs(modname, stdout);
178	} else {
179	    nicezputs(modname, stdout);
180	    putchar(':');
181	}
182	for (n = firstnode(m->deps); n; incnode(n)) {
183	    putchar(' ');
184	    if (flags & PRINTMOD_LIST)
185		quotedzputs((char *) getdata(n), stdout);
186	    else
187		nicezputs((char *) getdata(n), stdout);
188	}
189    } else if (flags & PRINTMOD_EXIST) {
190	/*
191	 * Just print the module name, provided the module is
192	 * present under an alias or otherwise.
193	 */
194	if (m->node.flags & MOD_ALIAS) {
195	    if (!(flags & PRINTMOD_ALIAS) ||
196		!(m = find_module(m->u.alias, FINDMOD_ALIASP, NULL)))
197		return;
198	}
199	if (!m->u.handle || (m->node.flags & MOD_UNLOAD))
200	    return;
201	nicezputs(modname, stdout);
202   } else if (m->node.flags & MOD_ALIAS) {
203	/*
204	 * Normal listing, but for aliases.
205	 */
206	if (flags & PRINTMOD_LIST) {
207	    printf("zmodload -A ");
208	    if (modname[0] == '-')
209		fputs("-- ", stdout);
210	    quotedzputs(modname, stdout);
211	    putchar('=');
212	    quotedzputs(m->u.alias, stdout);
213	} else {
214	    nicezputs(modname, stdout);
215	    fputs(" -> ", stdout);
216	    nicezputs(m->u.alias, stdout);
217	}
218    } else if (m->u.handle || (flags & PRINTMOD_AUTO)) {
219	/*
220	 * Loaded module.
221	 */
222	if (flags & PRINTMOD_LIST) {
223	    /*
224	     * List with -L format.  Possibly we are printing
225	     * features, either enables or autoloads.
226	     */
227	    char **features = NULL;
228	    int *enables = NULL;
229	    if (flags & PRINTMOD_AUTO) {
230		if (!m->autoloads || !firstnode(m->autoloads))
231		    return;
232	    } else if (flags & PRINTMOD_FEATURES) {
233		if (features_module(m, &features) ||
234		    enables_module(m, &enables) ||
235		    !*features)
236		    return;
237	    }
238	    printf("zmodload ");
239	    if (flags & PRINTMOD_AUTO) {
240		fputs("-Fa ", stdout);
241	    } else if (features)
242		fputs("-F ", stdout);
243	    if(modname[0] == '-')
244		fputs("-- ", stdout);
245	    quotedzputs(modname, stdout);
246	    if (flags & PRINTMOD_AUTO) {
247		LinkNode an;
248		for (an = firstnode(m->autoloads); an; incnode(an)) {
249		    putchar(' ');
250		    quotedzputs((char *)getdata(an), stdout);
251		}
252	    } else if (features) {
253		const char *f;
254		while ((f = *features++)) {
255		    int on = *enables++;
256		    if (flags & PRINTMOD_LISTALL)
257			printf(" %s", on ? "+" : "-");
258		    else if (!on)
259			continue;
260		    else
261			putchar(' ');
262		    quotedzputs(f, stdout);
263		}
264	    }
265	} else /* -l */
266	    nicezputs(modname, stdout);
267    } else
268	return;
269    putchar('\n');
270}
271
272/**/
273HashTable
274newmoduletable(int size, char const *name)
275{
276    HashTable ht;
277    ht = newhashtable(size, name, NULL);
278
279    ht->hash        = hasher;
280    ht->emptytable  = emptyhashtable;
281    ht->filltable   = NULL;
282    ht->cmpnodes    = strcmp;
283    ht->addnode     = addhashnode;
284    /* DISABLED is not supported */
285    ht->getnode     = gethashnode2;
286    ht->getnode2    = gethashnode2;
287    ht->removenode  = removehashnode;
288    ht->disablenode = NULL;
289    ht->enablenode  = NULL;
290    ht->freenode    = freemodulenode;
291    ht->printnode   = printmodulenode;
292
293    return ht;
294}
295
296/************************************************************************
297 * zsh/main standard module functions
298 ************************************************************************/
299
300/* The `zsh/main' module contains all the base code that can't actually be *
301 * built as a separate module.  It is initialised by main(), so there's    *
302 * nothing for the boot function to do.                                    */
303
304/**/
305int
306setup_(UNUSED(Module m))
307{
308    return 0;
309}
310
311/**/
312int
313features_(UNUSED(Module m), UNUSED(char ***features))
314{
315    /*
316     * There are lots and lots of features, but they're not
317     * handled here.
318     */
319    return 1;
320}
321
322/**/
323int
324enables_(UNUSED(Module m), UNUSED(int **enables))
325{
326    return 1;
327}
328
329/**/
330int
331boot_(UNUSED(Module m))
332{
333    return 0;
334}
335
336/**/
337int
338cleanup_(UNUSED(Module m))
339{
340    return 0;
341}
342
343/**/
344int
345finish_(UNUSED(Module m))
346{
347    return 0;
348}
349
350
351/************************************************************************
352 * Module utility functions
353 ************************************************************************/
354
355/* This registers a builtin module.                                   */
356
357/**/
358void
359register_module(char *n, Module_void_func setup,
360		Module_features_func features,
361		Module_enables_func enables,
362		Module_void_func boot,
363		Module_void_func cleanup,
364		Module_void_func finish)
365{
366    Linkedmod m;
367
368    m = (Linkedmod) zalloc(sizeof(*m));
369
370    m->name = ztrdup(n);
371    m->setup = setup;
372    m->features = features;
373    m->enables = enables;
374    m->boot = boot;
375    m->cleanup = cleanup;
376    m->finish = finish;
377
378    zaddlinknode(linkedmodules, m);
379}
380
381/* Check if a module is linked in. */
382
383/**/
384Linkedmod
385module_linked(char const *name)
386{
387    LinkNode node;
388
389    for (node = firstnode(linkedmodules); node; incnode(node))
390	if (!strcmp(((Linkedmod) getdata(node))->name, name))
391	    return (Linkedmod) getdata(node);
392
393    return NULL;
394}
395
396
397/************************************************************************
398 * Support for the various feature types.
399 * First, builtins.
400 ************************************************************************/
401
402/* addbuiltin() can be used to add a new builtin.  It returns zero on *
403 * success, 1 on failure.  The only possible type of failure is that  *
404 * a builtin with the specified name already exists.  An autoloaded   *
405 * builtin can be replaced using this function.                       */
406
407/**/
408static int
409addbuiltin(Builtin b)
410{
411    Builtin bn = (Builtin) builtintab->getnode2(builtintab, b->node.nam);
412    if (bn && (bn->node.flags & BINF_ADDED))
413	return 1;
414    if (bn)
415	builtintab->freenode(builtintab->removenode(builtintab, b->node.nam));
416    builtintab->addnode(builtintab, b->node.nam, b);
417    return 0;
418}
419
420/* Define an autoloadable builtin.  It returns 0 on success, or 1 on *
421 * failure.  The only possible cause of failure is that a builtin    *
422 * with the specified name already exists.                           */
423
424/**/
425static int
426add_autobin(const char *module, const char *bnam, int flags)
427{
428    Builtin bn;
429    int ret;
430
431    bn = zshcalloc(sizeof(*bn));
432    bn->node.nam = ztrdup(bnam);
433    bn->optstr = ztrdup(module);
434    if (flags & FEAT_AUTOALL)
435	bn->node.flags |= BINF_AUTOALL;
436    if ((ret = addbuiltin(bn))) {
437	builtintab->freenode(&bn->node);
438	if (!(flags & FEAT_IGNORE))
439	    return 1;
440    }
441    return 0;
442}
443
444/* Remove the builtin added previously by addbuiltin().  Returns *
445 * zero on succes and -1 if there is no builtin with that name.  */
446
447/**/
448int
449deletebuiltin(const char *nam)
450{
451    Builtin bn;
452
453    bn = (Builtin) builtintab->removenode(builtintab, nam);
454    if (!bn)
455	return -1;
456    builtintab->freenode(&bn->node);
457    return 0;
458}
459
460/* Remove an autoloaded added by add_autobin */
461
462/**/
463static int
464del_autobin(UNUSED(const char *module), const char *bnam, int flags)
465{
466    Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam);
467    if (!bn) {
468	if(!(flags & FEAT_IGNORE))
469	    return 2;
470    } else if (bn->node.flags & BINF_ADDED) {
471	if (!(flags & FEAT_IGNORE))
472	    return 3;
473    } else
474	deletebuiltin(bnam);
475
476    return 0;
477}
478
479/*
480 * Manipulate a set of builtins.  This should be called
481 * via setfeatureenables() (or, usually, via the next level up,
482 * handlefeatures()).
483 *
484 * "nam" is the name of the calling code builtin, probably "zmodload".
485 *
486 * "binl" is the builtin table containing an array of "size" builtins.
487 *
488 * "e" is either NULL, in which case all builtins in the
489 * table are removed, or else an array corresponding to "binl"
490 * with a 1 for builtins that are to be added and a 0 for builtins
491 * that are to be removed.  Any builtin already in the appropriate
492 * state is left alone.
493 *
494 * Returns 1 on any error, 0 for success.  The recommended way
495 * of handling errors is to compare the enables passed down
496 * with the set retrieved after the error to find what failed.
497 */
498
499/**/
500static int
501setbuiltins(char const *nam, Builtin binl, int size, int *e)
502{
503    int ret = 0, n;
504
505    for(n = 0; n < size; n++) {
506	Builtin b = &binl[n];
507	if (e && *e++) {
508	    if (b->node.flags & BINF_ADDED)
509		continue;
510	    if (addbuiltin(b)) {
511		zwarnnam(nam,
512			 "name clash when adding builtin `%s'", b->node.nam);
513		ret = 1;
514	    } else {
515		b->node.flags |= BINF_ADDED;
516	    }
517	} else {
518	    if (!(b->node.flags & BINF_ADDED))
519		continue;
520	    if (deletebuiltin(b->node.nam)) {
521		zwarnnam(nam, "builtin `%s' already deleted", b->node.nam);
522		ret = 1;
523	    } else {
524		b->node.flags &= ~BINF_ADDED;
525	    }
526	}
527    }
528    return ret;
529}
530
531/*
532 * Add multiple builtins.  binl points to a table of `size' builtin
533 * structures.  Those for which (.flags & BINF_ADDED) is false are to be
534 * added; that flag is set if they succeed.
535 *
536 * If any fail, an error message is printed, using nam as the leading name.
537 * Returns 0 on success, 1 for any failure.
538 *
539 * This should not be used from a module; instead, use handlefeatures().
540 */
541
542/**/
543mod_export int
544addbuiltins(char const *nam, Builtin binl, int size)
545{
546    int ret = 0, n;
547
548    for(n = 0; n < size; n++) {
549	Builtin b = &binl[n];
550	if(b->node.flags & BINF_ADDED)
551	    continue;
552	if(addbuiltin(b)) {
553	    zwarnnam(nam, "name clash when adding builtin `%s'", b->node.nam);
554	    ret = 1;
555	} else {
556	    b->node.flags |= BINF_ADDED;
557	}
558    }
559    return ret;
560}
561
562
563/************************************************************************
564 * Function wrappers.
565 ************************************************************************/
566
567/* The list of function wrappers defined. */
568
569/**/
570FuncWrap wrappers;
571
572/* This adds a definition for a wrapper. Return value is one in case of *
573 * error and zero if all went fine. */
574
575/**/
576mod_export int
577addwrapper(Module m, FuncWrap w)
578{
579    FuncWrap p, q;
580
581    /*
582     * We can't add a wrapper to an alias, since it's supposed
583     * to behave identically to the resolved module.  This shouldn't
584     * happen since we usually add wrappers when a real module is
585     * loaded.
586     */
587    if (m->node.flags & MOD_ALIAS)
588	return 1;
589
590    if (w->flags & WRAPF_ADDED)
591	return 1;
592    for (p = wrappers, q = NULL; p; q = p, p = p->next);
593    if (q)
594	q->next = w;
595    else
596	wrappers = w;
597    w->next = NULL;
598    w->flags |= WRAPF_ADDED;
599    w->module = m;
600
601    return 0;
602}
603
604/* This removes the given wrapper definition from the list. Returned is *
605 * one in case of error and zero otherwise. */
606
607/**/
608mod_export int
609deletewrapper(Module m, FuncWrap w)
610{
611    FuncWrap p, q;
612
613    if (m->node.flags & MOD_ALIAS)
614	return 1;
615
616    if (w->flags & WRAPF_ADDED) {
617	for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next);
618
619	if (p) {
620	    if (q)
621		q->next = p->next;
622	    else
623		wrappers = p->next;
624	    p->flags &= ~WRAPF_ADDED;
625
626	    return 0;
627	}
628    }
629    return 1;
630}
631
632
633/************************************************************************
634 * Conditions.
635 ************************************************************************/
636
637/* The list of module-defined conditions. */
638
639/**/
640mod_export Conddef condtab;
641
642/* This gets a condition definition with the given name. The first        *
643 * argument says if we have to look for an infix condition. The last      *
644 * argument is non-zero if we should autoload modules if needed. */
645
646/**/
647Conddef
648getconddef(int inf, const char *name, int autol)
649{
650    Conddef p;
651    int f = 1;
652
653    do {
654	for (p = condtab; p; p = p->next) {
655	    if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
656		!strcmp(name, p->name))
657		break;
658	}
659	if (autol && p && p->module) {
660	    /*
661	     * This is a definition for an autoloaded condition; load the
662	     * module if we haven't tried that already.
663	     */
664	    if (f) {
665		(void)ensurefeature(p->module,
666				    (p->flags & CONDF_INFIX) ? "C:" : "c:",
667				    (p->flags & CONDF_AUTOALL) ? NULL : name);
668		f = 0;
669		p = NULL;
670	    } else {
671		deleteconddef(p);
672		return NULL;
673	    }
674	} else
675	    break;
676    } while (!p);
677    return p;
678}
679
680/*
681 * This adds the given condition definition. The return value is zero on *
682 * success and 1 on failure. If there is a matching definition for an    *
683 * autoloaded condition, it is removed.
684 *
685 * This is used for adding both an autoload definition or
686 * a real condition.  In the latter case the caller is responsible
687 * for setting the CONDF_ADDED flag.
688 */
689
690/**/
691static int
692addconddef(Conddef c)
693{
694    Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0);
695
696    if (p) {
697	if (!p->module || (p->flags & CONDF_ADDED))
698	    return 1;
699	/* There is an autoload definition. */
700
701	deleteconddef(p);
702    }
703    c->next = condtab;
704    condtab = c;
705    return 0;
706}
707
708/* This removes the given condition definition from the list(s). If this *
709 * is a definition for a autoloaded condition, the memory is freed. */
710
711/**/
712int
713deleteconddef(Conddef c)
714{
715    Conddef p, q;
716
717    for (p = condtab, q = NULL; p && p != c; q = p, p = p->next);
718
719    if (p) {
720	if (q)
721	    q->next = p->next;
722	else
723	    condtab = p->next;
724
725	if (p->module) {
726	    /* autoloaded, free it */
727	    zsfree(p->name);
728	    zsfree(p->module);
729	    zfree(p, sizeof(*p));
730	}
731	return 0;
732    }
733    return -1;
734}
735
736/*
737 * Add or remove sets of conditions.  The interface is
738 * identical to setbuiltins().
739 */
740
741/**/
742static int
743setconddefs(char const *nam, Conddef c, int size, int *e)
744{
745    int ret = 0;
746
747    while (size--) {
748	if (e && *e++) {
749	    if (c->flags & CONDF_ADDED) {
750		c++;
751		continue;
752	    }
753	    if (addconddef(c)) {
754		zwarnnam(nam, "name clash when adding condition `%s'",
755			 c->name);
756		ret = 1;
757	    } else {
758		c->flags |= CONDF_ADDED;
759	    }
760	} else {
761	    if (!(c->flags & CONDF_ADDED)) {
762		c++;
763		continue;
764	    }
765	    if (deleteconddef(c)) {
766		zwarnnam(nam, "condition `%s' already deleted", c->name);
767		ret = 1;
768	    } else {
769		c->flags &= ~CONDF_ADDED;
770	    }
771	}
772	c++;
773    }
774    return ret;
775}
776
777/* This adds a definition for autoloading a module for a condition. */
778
779/**/
780static int
781add_autocond(const char *module, const char *cnam, int flags)
782{
783    Conddef c;
784
785    c = (Conddef) zalloc(sizeof(*c));
786
787    c->name = ztrdup(cnam);
788    c->flags = ((flags & FEAT_INFIX) ? CONDF_INFIX : 0);
789    if (flags & FEAT_AUTOALL)
790	c->flags |= CONDF_AUTOALL;
791    c->module = ztrdup(module);
792
793    if (addconddef(c)) {
794	zsfree(c->name);
795	zsfree(c->module);
796	zfree(c, sizeof(*c));
797
798	if (!(flags & FEAT_IGNORE))
799	    return 1;
800    }
801    return 0;
802}
803
804/* Remove a condition added with add_autocond */
805
806/**/
807static int
808del_autocond(UNUSED(const char *modnam), const char *cnam, int flags)
809{
810    Conddef cd = getconddef((flags & FEAT_INFIX) ? 1 : 0, cnam, 0);
811
812    if (!cd) {
813	if (!(flags & FEAT_IGNORE)) {
814	    return 2;
815	}
816    } else if (cd->flags & CONDF_ADDED) {
817	if (!(flags & FEAT_IGNORE))
818	    return 3;
819    } else
820	deleteconddef(cd);
821
822    return 0;
823}
824
825/************************************************************************
826 * Hook functions.
827 ************************************************************************/
828
829/* This list of hook functions defined. */
830
831/**/
832Hookdef hooktab;
833
834/* Find a hook definition given the name. */
835
836/**/
837Hookdef
838gethookdef(char *n)
839{
840    Hookdef p;
841
842    for (p = hooktab; p; p = p->next)
843	if (!strcmp(n, p->name))
844	    return p;
845    return NULL;
846}
847
848/* This adds the given hook definition. The return value is zero on      *
849 * success and 1 on failure.                                             */
850
851/**/
852int
853addhookdef(Hookdef h)
854{
855    if (gethookdef(h->name))
856	return 1;
857
858    h->next = hooktab;
859    hooktab = h;
860    h->funcs = znewlinklist();
861
862    return 0;
863}
864
865/*
866 * This adds multiple hook definitions. This is like addbuiltins().
867 * This allows a NULL module because we call it from init.c.
868 */
869
870/**/
871mod_export int
872addhookdefs(Module m, Hookdef h, int size)
873{
874    int ret = 0;
875
876    while (size--) {
877	if (addhookdef(h)) {
878	    zwarnnam(m ? m->node.nam : NULL,
879		     "name clash when adding hook `%s'", h->name);
880	    ret = 1;
881	}
882	h++;
883    }
884    return ret;
885}
886
887/* Delete hook definitions. */
888
889/**/
890int
891deletehookdef(Hookdef h)
892{
893    Hookdef p, q;
894
895    for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next);
896
897    if (!p)
898	return 1;
899
900    if (q)
901	q->next = p->next;
902    else
903	hooktab = p->next;
904    freelinklist(p->funcs, NULL);
905    return 0;
906}
907
908/* Remove multiple hook definitions. */
909
910/**/
911mod_export int
912deletehookdefs(UNUSED(Module m), Hookdef h, int size)
913{
914    int ret = 0;
915
916    while (size--) {
917	if (deletehookdef(h))
918	    ret = 1;
919	h++;
920    }
921    return ret;
922}
923
924/* Add a function to a hook. */
925
926/**/
927int
928addhookdeffunc(Hookdef h, Hookfn f)
929{
930    zaddlinknode(h->funcs, (void *) f);
931
932    return 0;
933}
934
935/**/
936mod_export int
937addhookfunc(char *n, Hookfn f)
938{
939    Hookdef h = gethookdef(n);
940
941    if (h)
942	return addhookdeffunc(h, f);
943    return 1;
944}
945
946/* Delete a function from a hook. */
947
948/**/
949int
950deletehookdeffunc(Hookdef h, Hookfn f)
951{
952    LinkNode p;
953
954    for (p = firstnode(h->funcs); p; incnode(p))
955	if (f == (Hookfn) getdata(p)) {
956	    remnode(h->funcs, p);
957	    return 0;
958	}
959    return 1;
960}
961
962/* Delete a hook. */
963
964/**/
965mod_export int
966deletehookfunc(char *n, Hookfn f)
967{
968    Hookdef h = gethookdef(n);
969
970    if (h)
971	return deletehookdeffunc(h, f);
972    return 1;
973}
974
975/* Run the function(s) for a hook. */
976
977/**/
978mod_export int
979runhookdef(Hookdef h, void *d)
980{
981    if (empty(h->funcs)) {
982	if (h->def)
983	    return h->def(h, d);
984	return 0;
985    } else if (h->flags & HOOKF_ALL) {
986	LinkNode p;
987	int r;
988
989	for (p = firstnode(h->funcs); p; incnode(p))
990	    if ((r = ((Hookfn) getdata(p))(h, d)))
991		return r;
992	if (h->def)
993	    return h->def(h, d);
994	return 0;
995    } else
996	return ((Hookfn) getdata(lastnode(h->funcs)))(h, d);
997}
998
999
1000
1001/************************************************************************
1002 * Shell parameters.
1003 ************************************************************************/
1004
1005/*
1006 * Check that it's possible to add a parameter.  This
1007 * requires that either there's no parameter already present,
1008 * or it's a global parameter marked for autoloading.
1009 *
1010 * The special status 2 is to indicate it didn't work but
1011 * -i was in use so we didn't print a warning.
1012 */
1013
1014static int
1015checkaddparam(const char *nam, int opt_i)
1016{
1017    Param pm;
1018
1019    if (!(pm = (Param) gethashnode2(paramtab, nam)))
1020	return 0;
1021
1022    if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) {
1023	/*
1024	 * -i suppresses "it's already that way" warnings,
1025	 * but not "this can't possibly work" warnings, so we print
1026	 * the message anyway if there's a local parameter blocking
1027	 * the parameter we want to add, not if there's a
1028	 * non-autoloadable parameter already there.  This
1029	 * is consistent with the way add_auto* functions work.
1030	 */
1031	if (!opt_i || !pm->level) {
1032	    zwarn("Can't add module parameter `%s': %s",
1033		  nam, pm->level ?
1034		  "local parameter exists" :
1035		  "parameter already exists");
1036	    return 1;
1037	}
1038	return 2;
1039    }
1040
1041    unsetparam_pm(pm, 0, 1);
1042    return 0;
1043}
1044
1045/* This adds the given parameter definition. The return value is zero on *
1046 * success and 1 on failure. */
1047
1048/**/
1049int
1050addparamdef(Paramdef d)
1051{
1052    Param pm;
1053
1054    if (checkaddparam(d->name, 0))
1055	return 1;
1056
1057    if (d->getnfn) {
1058	if (!(pm = createspecialhash(d->name, d->getnfn,
1059				     d->scantfn, d->flags)))
1060	    return 1;
1061    }
1062    else if (!(pm = createparam(d->name, d->flags)) &&
1063	!(pm = (Param) paramtab->getnode(paramtab, d->name)))
1064	return 1;
1065
1066    d->pm = pm;
1067    pm->level = 0;
1068    if (d->var)
1069	pm->u.data = d->var;
1070    if (d->var || d->gsu) {
1071	/*
1072	 * If no get/set/unset class, use the appropriate
1073	 * variable type, else use the one supplied.
1074	 */
1075	switch (PM_TYPE(pm->node.flags)) {
1076	case PM_SCALAR:
1077	    pm->gsu.s = d->gsu ? (GsuScalar)d->gsu : &varscalar_gsu;
1078	    break;
1079
1080	case PM_INTEGER:
1081	    pm->gsu.i = d->gsu ? (GsuInteger)d->gsu : &varinteger_gsu;
1082	    break;
1083
1084	case PM_FFLOAT:
1085	case PM_EFLOAT:
1086	    pm->gsu.f = d->gsu;
1087	    break;
1088
1089	case PM_ARRAY:
1090	    pm->gsu.a = d->gsu ? (GsuArray)d->gsu : &vararray_gsu;
1091	    break;
1092
1093	case PM_HASHED:
1094	    /* hashes may behave like standard hashes */
1095	    if (d->gsu)
1096		pm->gsu.h = (GsuHash)d->gsu;
1097	    break;
1098
1099	default:
1100	    unsetparam_pm(pm, 0, 1);
1101	    return 1;
1102	}
1103    }
1104
1105    return 0;
1106}
1107
1108/* Delete parameters defined. No error checking yet. */
1109
1110/**/
1111int
1112deleteparamdef(Paramdef d)
1113{
1114    Param pm = (Param) paramtab->getnode(paramtab, d->name);
1115
1116    if (!pm)
1117	return 1;
1118    if (pm != d->pm) {
1119	/*
1120	 * See if the parameter has been hidden.  If so,
1121	 * bring it to the front to unset it.
1122	 */
1123	Param prevpm, searchpm;
1124	for (prevpm = pm, searchpm = pm->old;
1125	     searchpm;
1126	     prevpm = searchpm, searchpm = searchpm->old)
1127	    if (searchpm == d->pm)
1128		break;
1129
1130	if (!searchpm)
1131	    return 1;
1132
1133	paramtab->removenode(paramtab, pm->node.nam);
1134	prevpm->old = searchpm->old;
1135	searchpm->old = pm;
1136	paramtab->addnode(paramtab, searchpm->node.nam, searchpm);
1137
1138	pm = searchpm;
1139    }
1140    pm->node.flags = (pm->node.flags & ~PM_READONLY) | PM_REMOVABLE;
1141    unsetparam_pm(pm, 0, 1);
1142    d->pm = NULL;
1143    return 0;
1144}
1145
1146/*
1147 * Add or remove sets of parameters.  The interface is
1148 * identical to setbuiltins().
1149 */
1150
1151/**/
1152static int
1153setparamdefs(char const *nam, Paramdef d, int size, int *e)
1154{
1155    int ret = 0;
1156
1157    while (size--) {
1158	if (e && *e++) {
1159	    if (d->pm) {
1160		d++;
1161		continue;
1162	    }
1163	    if (addparamdef(d)) {
1164		zwarnnam(nam, "error when adding parameter `%s'", d->name);
1165		ret = 1;
1166	    }
1167	} else {
1168	    if (!d->pm) {
1169		d++;
1170		continue;
1171	    }
1172	    if (deleteparamdef(d)) {
1173		zwarnnam(nam, "parameter `%s' already deleted", d->name);
1174		ret = 1;
1175	    }
1176	}
1177	d++;
1178    }
1179    return ret;
1180}
1181
1182/* This adds a definition for autoloading a module for a parameter. */
1183
1184/**/
1185static int
1186add_autoparam(const char *module, const char *pnam, int flags)
1187{
1188    Param pm;
1189    int ret;
1190
1191    queue_signals();
1192    if ((ret = checkaddparam(pnam, (flags & FEAT_IGNORE)))) {
1193	unqueue_signals();
1194	/*
1195	 * checkaddparam() has already printed a message if one was
1196	 * needed.  If it wasn't owing to the presence of -i, ret is 2;
1197	 * for consistency with other add_auto* functions we return
1198	 * status 0 to indicate there's already such a parameter and
1199	 * we've been told not to worry if so.
1200	 */
1201	return ret == 2 ? 0 : -1;
1202    }
1203
1204    pm = setsparam(dupstring(pnam), ztrdup(module));
1205
1206    pm->node.flags |= PM_AUTOLOAD;
1207    if (flags & FEAT_AUTOALL)
1208	pm->node.flags |= PM_AUTOALL;
1209    unqueue_signals();
1210
1211    return 0;
1212}
1213
1214/* Remove a parameter added with add_autoparam() */
1215
1216/**/
1217static int
1218del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags)
1219{
1220    Param pm = (Param) gethashnode2(paramtab, pnam);
1221
1222    if (!pm) {
1223	if (!(flags & FEAT_IGNORE))
1224	    return 2;
1225    } else if (!(pm->node.flags & PM_AUTOLOAD)) {
1226	if (!(flags & FEAT_IGNORE))
1227	    return 3;
1228    } else
1229	unsetparam_pm(pm, 0, 1);
1230
1231    return 0;
1232}
1233
1234/************************************************************************
1235 * Math functions.
1236 ************************************************************************/
1237
1238/* List of math functions. */
1239
1240/**/
1241MathFunc mathfuncs;
1242
1243/*
1244 * Remove a single math function form the list (utility function).
1245 * This does not delete a module math function, that's deletemathfunc().
1246 */
1247
1248/**/
1249void
1250removemathfunc(MathFunc previous, MathFunc current)
1251{
1252    if (previous)
1253	previous->next = current->next;
1254    else
1255	mathfuncs = current->next;
1256
1257    zsfree(current->name);
1258    zsfree(current->module);
1259    zfree(current, sizeof(*current));
1260}
1261
1262/* Find a math function in the list, handling autoload if necessary. */
1263
1264/**/
1265MathFunc
1266getmathfunc(const char *name, int autol)
1267{
1268    MathFunc p, q = NULL;
1269
1270    for (p = mathfuncs; p; q = p, p = p->next)
1271	if (!strcmp(name, p->name)) {
1272	    if (autol && p->module && !(p->flags & MFF_USERFUNC)) {
1273		char *n = dupstring(p->module);
1274		int flags = p->flags;
1275
1276		removemathfunc(q, p);
1277
1278		(void)ensurefeature(n, "f:", (flags & MFF_AUTOALL) ? NULL :
1279				    name);
1280
1281	       p = getmathfunc(name, 0);
1282	       if (!p) {
1283		   zerr("autoloading module %s failed to define math function: %s", n, name);
1284	       }
1285	    }
1286	    return p;
1287	}
1288
1289    return NULL;
1290}
1291
1292/* Add a single math function */
1293
1294/**/
1295static int
1296addmathfunc(MathFunc f)
1297{
1298    MathFunc p, q = NULL;
1299
1300    if (f->flags & MFF_ADDED)
1301	return 1;
1302
1303    for (p = mathfuncs; p; q = p, p = p->next)
1304	if (!strcmp(f->name, p->name)) {
1305	    if (p->module && !(p->flags & MFF_USERFUNC)) {
1306		/*
1307		 * Autoloadable, replace.
1308		 */
1309		removemathfunc(q, p);
1310		break;
1311	    }
1312	    return 1;
1313	}
1314
1315    f->next = mathfuncs;
1316    mathfuncs = f;
1317
1318    return 0;
1319}
1320
1321/* Delete a single math function */
1322
1323/**/
1324mod_export int
1325deletemathfunc(MathFunc f)
1326{
1327    MathFunc p, q;
1328
1329    for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next);
1330
1331    if (p) {
1332	if (q)
1333	    q->next = f->next;
1334	else
1335	    mathfuncs = f->next;
1336
1337	/* the following applies to both unloaded and user-defined functions */
1338	if (f->module) {
1339	    zsfree(f->name);
1340	    zsfree(f->module);
1341	    zfree(f, sizeof(*f));
1342	} else
1343	    f->flags &= ~MFF_ADDED;
1344
1345	return 0;
1346    }
1347    return -1;
1348}
1349
1350/*
1351 * Add or remove sets of math functions.  The interface is
1352 * identical to setbuiltins().
1353 */
1354
1355/**/
1356static int
1357setmathfuncs(char const *nam, MathFunc f, int size, int *e)
1358{
1359    int ret = 0;
1360
1361    while (size--) {
1362	if (e && *e++) {
1363	    if (f->flags & MFF_ADDED) {
1364		f++;
1365		continue;
1366	    }
1367	    if (addmathfunc(f)) {
1368		zwarnnam(nam, "name clash when adding math function `%s'",
1369			 f->name);
1370		ret = 1;
1371	    } else {
1372		f->flags |= MFF_ADDED;
1373	    }
1374	} else {
1375	    if (!(f->flags & MFF_ADDED)) {
1376		f++;
1377		continue;
1378	    }
1379	    if (deletemathfunc(f)) {
1380		zwarnnam(nam, "math function `%s' already deleted", f->name);
1381		ret = 1;
1382	    } else {
1383		f->flags &= ~MFF_ADDED;
1384	    }
1385	}
1386	f++;
1387    }
1388    return ret;
1389}
1390
1391/* Add an autoload definition for a math function. */
1392
1393/**/
1394static int
1395add_automathfunc(const char *module, const char *fnam, int flags)
1396{
1397    MathFunc f;
1398
1399    f = (MathFunc) zalloc(sizeof(*f));
1400
1401    f->name = ztrdup(fnam);
1402    f->module = ztrdup(module);
1403    f->flags = 0;
1404
1405    if (addmathfunc(f)) {
1406	zsfree(f->name);
1407	zsfree(f->module);
1408	zfree(f, sizeof(*f));
1409
1410	if (!(flags & FEAT_IGNORE))
1411	    return 1;
1412    }
1413
1414    return 0;
1415}
1416
1417/* Remove a math function added with add_automathfunc() */
1418
1419/**/
1420static int
1421del_automathfunc(UNUSED(const char *modnam), const char *fnam, int flags)
1422{
1423    MathFunc f = getmathfunc(fnam, 0);
1424
1425    if (!f) {
1426	if (!(flags & FEAT_IGNORE))
1427	    return 2;
1428    } else if (f->flags & MFF_ADDED) {
1429	if (!(flags & FEAT_IGNORE))
1430	    return 3;
1431    } else
1432	deletemathfunc(f);
1433
1434    return 0;
1435}
1436
1437/************************************************************************
1438 * Now support for dynamical loading and the fallback functions
1439 * we use for loading if dynamical loading is not available.
1440 ************************************************************************/
1441
1442/**/
1443#ifdef DYNAMIC
1444
1445/**/
1446#ifdef AIXDYNAMIC
1447
1448#include <sys/ldr.h>
1449
1450static char *dlerrstr[256];
1451
1452static void *
1453load_and_bind(const char *fn)
1454{
1455    void *ret = (void *) load((char *) fn, L_NOAUTODEFER, NULL);
1456
1457    if (ret) {
1458	Module m;
1459	int i, err = loadbind(0, (void *) addbuiltin, ret);
1460	for (i = 0; i < modulestab->hsize && !err; i++) {
1461	    for (m = (Module)modulestab->nodes[i]; m && !err;
1462		 m = (Module)m->node.next) {
1463		if (!(m->node.flags & MOD_ALIAS) &&
1464		    m->u.handle && !(m->node.flags & MOD_LINKED))
1465		    err |= loadbind(0, m->u.handle, ret);
1466	    }
1467	}
1468
1469	if (err) {
1470	    loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr));
1471	    unload(ret);
1472	    ret = NULL;
1473	}
1474    } else
1475	loadquery(L_GETMESSAGES, dlerrstr, sizeof(dlerrstr));
1476
1477    return ret;
1478}
1479
1480#define dlopen(X,Y) load_and_bind(X)
1481#define dlclose(X)  unload(X)
1482#define dlerror()   (dlerrstr[0])
1483#ifndef HAVE_DLERROR
1484# define HAVE_DLERROR 1
1485#endif
1486
1487/**/
1488#else
1489
1490#ifdef HAVE_DLFCN_H
1491# if defined(HAVE_DL_H) && defined(HPUX10DYNAMIC)
1492#  include <dl.h>
1493# else
1494#  include <dlfcn.h>
1495# endif
1496#else
1497# ifdef HAVE_DL_H
1498#  include <dl.h>
1499#  define RTLD_LAZY BIND_DEFERRED
1500#  define RTLD_GLOBAL DYNAMIC_PATH
1501# else
1502#  include <sys/types.h>
1503#  include <nlist.h>
1504#  include <link.h>
1505# endif
1506#endif
1507
1508/**/
1509#ifdef HPUX10DYNAMIC
1510# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
1511# define dlclose(handle) shl_unload((shl_t)(handle))
1512
1513static
1514void *
1515hpux_dlsym(void *handle, char *name)
1516{
1517    void *sym_addr;
1518    if (!shl_findsym((shl_t *)&handle, name, TYPE_UNDEFINED, &sym_addr))
1519	return sym_addr;
1520    return NULL;
1521}
1522
1523# define dlsym(handle,name) hpux_dlsym(handle,name)
1524# ifdef HAVE_DLERROR		/* paranoia */
1525#  undef HAVE_DLERROR
1526# endif
1527#else
1528# ifndef HAVE_DLCLOSE
1529#  define dlclose(X) ((X), 0)
1530# endif
1531/**/
1532#endif
1533
1534#ifdef DLSYM_NEEDS_UNDERSCORE
1535# define STR_SETUP     "_setup_"
1536# define STR_FEATURES  "_features_"
1537# define STR_ENABLES   "_enables_"
1538# define STR_BOOT      "_boot_"
1539# define STR_CLEANUP   "_cleanup_"
1540# define STR_FINISH    "_finish_"
1541#else /* !DLSYM_NEEDS_UNDERSCORE */
1542# define STR_SETUP     "setup_"
1543# define STR_FEATURES  "features_"
1544# define STR_ENABLES   "enables_"
1545# define STR_BOOT      "boot_"
1546# define STR_CLEANUP   "cleanup_"
1547# define STR_FINISH    "finish_"
1548#endif /* !DLSYM_NEEDS_UNDERSCORE */
1549
1550/**/
1551#endif /* !AIXDYNAMIC */
1552
1553#ifndef RTLD_LAZY
1554# define RTLD_LAZY 1
1555#endif
1556#ifndef RTLD_GLOBAL
1557# define RTLD_GLOBAL 0
1558#endif
1559
1560/*
1561 * Attempt to load a module.  This is the lowest level of
1562 * zsh function for dynamical modules.  Returns the handle
1563 * from the dynamic loader.
1564 */
1565
1566/**/
1567static void *
1568try_load_module(char const *name)
1569{
1570    char buf[PATH_MAX + 1];
1571    char **pp;
1572    void *ret = NULL;
1573    int l;
1574
1575    l = 1 + strlen(name) + 1 + strlen(DL_EXT);
1576    for (pp = module_path; !ret && *pp; pp++) {
1577	if (l + (**pp ? strlen(*pp) : 1) > PATH_MAX)
1578	    continue;
1579	sprintf(buf, "%s/%s.%s", **pp ? *pp : ".", name, DL_EXT);
1580	ret = dlopen(unmeta(buf), RTLD_LAZY | RTLD_GLOBAL);
1581    }
1582
1583    return ret;
1584}
1585
1586/*
1587 * Load a module, with option to complain or not.
1588 * Returns the handle from the dynamic loader.
1589 */
1590
1591/**/
1592static void *
1593do_load_module(char const *name, int silent)
1594{
1595    void *ret;
1596
1597    ret = try_load_module(name);
1598    if (!ret && !silent) {
1599#ifdef HAVE_DLERROR
1600	zwarn("failed to load module `%s': %s", name,
1601	      metafy(dlerror(), -1, META_USEHEAP));
1602#else
1603	zwarn("failed to load module: %s", name);
1604#endif
1605    }
1606    return ret;
1607}
1608
1609/**/
1610#else /* !DYNAMIC */
1611
1612/*
1613 * Dummy loader when no dynamic loading available; always fails.
1614 */
1615
1616/**/
1617static void *
1618do_load_module(char const *name, int silent)
1619{
1620    if (!silent)
1621	zwarn("failed to load module: %s", name);
1622
1623    return NULL;
1624}
1625
1626/**/
1627#endif /* !DYNAMIC */
1628
1629/*
1630 * Find a module in the list.
1631 * flags is a set of bits defined in the enum above.
1632 * If namep is set, this is set to point to the last alias value resolved,
1633 *   even if that module was not loaded. or the module name if no aliases.
1634 *   Hence this is always the physical module to load in a chain of aliases.
1635 * Return NULL if the module named is not stored as a structure, or if we were
1636 * resolving aliases and the final module named is not stored as a
1637 * structure.
1638 */
1639/**/
1640static Module
1641find_module(const char *name, int flags, const char **namep)
1642{
1643    Module m;
1644
1645    m = (Module)modulestab->getnode2(modulestab, name);
1646    if (m) {
1647	if ((flags & FINDMOD_ALIASP) && (m->node.flags & MOD_ALIAS)) {
1648	    if (namep)
1649		*namep = m->u.alias;
1650	    return find_module(m->u.alias, flags, namep);
1651	}
1652	if (namep)
1653	    *namep = m->node.nam;
1654	return m;
1655    }
1656    if (!(flags & FINDMOD_CREATE))
1657	return NULL;
1658    m = zshcalloc(sizeof(*m));
1659    modulestab->addnode(modulestab, ztrdup(name), m);
1660    return m;
1661}
1662
1663/*
1664 * Unlink and free a module node from the linked list.
1665 */
1666
1667/**/
1668static void
1669delete_module(Module m)
1670{
1671    modulestab->removenode(modulestab, m->node.nam);
1672
1673    modulestab->freenode(&m->node);
1674}
1675
1676/*
1677 * Return 1 if a module is fully loaded else zero.
1678 * A linked module may be marked as unloaded even though
1679 * we can't fully unload it; this returns 0 to try to
1680 * make that state transparently like an unloaded module.
1681 */
1682
1683/**/
1684mod_export int
1685module_loaded(const char *name)
1686{
1687    Module m;
1688
1689    return ((m = find_module(name, FINDMOD_ALIASP, NULL)) &&
1690	    m->u.handle &&
1691	    !(m->node.flags & MOD_UNLOAD));
1692}
1693
1694/*
1695 * Setup and cleanup functions:  we don't search for aliases here,
1696 * since they should have been resolved before we try to load or unload
1697 * the module.
1698 */
1699
1700/**/
1701#ifdef DYNAMIC
1702
1703/**/
1704#ifdef AIXDYNAMIC
1705
1706/**/
1707static int
1708dyn_setup_module(Module m)
1709{
1710    return ((int (*)_((int,Module, void*))) m->u.handle)(0, m, NULL);
1711}
1712
1713/**/
1714static int
1715dyn_features_module(Module m, char ***features)
1716{
1717    return ((int (*)_((int,Module, void*))) m->u.handle)(4, m, features);
1718}
1719
1720/**/
1721static int
1722dyn_enables_module(Module m, int **enables)
1723{
1724    return ((int (*)_((int,Module, void*))) m->u.handle)(5, m, enables);
1725}
1726
1727/**/
1728static int
1729dyn_boot_module(Module m)
1730{
1731    return ((int (*)_((int,Module, void*))) m->u.handle)(1, m, NULL);
1732}
1733
1734/**/
1735static int
1736dyn_cleanup_module(Module m)
1737{
1738    return ((int (*)_((int,Module, void*))) m->u.handle)(2, m, NULL);
1739}
1740
1741/**/
1742static int
1743dyn_finish_module(Module m)
1744{
1745    return ((int (*)_((int,Module,void *))) m->u.handle)(3, m, NULL);
1746}
1747
1748/**/
1749#else
1750
1751static Module_generic_func
1752module_func(Module m, char *name)
1753{
1754#ifdef DYNAMIC_NAME_CLASH_OK
1755    return (Module_generic_func) dlsym(m->u.handle, name);
1756#else /* !DYNAMIC_NAME_CLASH_OK */
1757    VARARR(char, buf, strlen(name) + strlen(m->node.nam)*2 + 1);
1758    char const *p;
1759    char *q;
1760    strcpy(buf, name);
1761    q = strchr(buf, 0);
1762    for(p = m->node.nam; *p; p++) {
1763	if(*p == '/') {
1764	    *q++ = 'Q';
1765	    *q++ = 's';
1766	} else if(*p == '_') {
1767	    *q++ = 'Q';
1768	    *q++ = 'u';
1769	} else if(*p == 'Q') {
1770	    *q++ = 'Q';
1771	    *q++ = 'q';
1772	} else
1773	    *q++ = *p;
1774    }
1775    *q = 0;
1776    return (Module_generic_func) dlsym(m->u.handle, buf);
1777#endif /* !DYNAMIC_NAME_CLASH_OK */
1778}
1779
1780/**/
1781static int
1782dyn_setup_module(Module m)
1783{
1784    Module_void_func fn = (Module_void_func)module_func(m, STR_SETUP);
1785
1786    if (fn)
1787	return fn(m);
1788    zwarnnam(m->node.nam, "no setup function");
1789    return 1;
1790}
1791
1792/**/
1793static int
1794dyn_features_module(Module m, char ***features)
1795{
1796    Module_features_func fn =
1797	(Module_features_func)module_func(m, STR_FEATURES);
1798
1799    if (fn)
1800	return fn(m, features);
1801    /* not a user-visible error if no features function */
1802    return 1;
1803}
1804
1805/**/
1806static int
1807dyn_enables_module(Module m, int **enables)
1808{
1809    Module_enables_func fn = (Module_enables_func)module_func(m, STR_ENABLES);
1810
1811    if (fn)
1812	return fn(m, enables);
1813    /* not a user-visible error if no enables function */
1814    return 1;
1815}
1816
1817/**/
1818static int
1819dyn_boot_module(Module m)
1820{
1821    Module_void_func fn = (Module_void_func)module_func(m, STR_BOOT);
1822
1823    if(fn)
1824	return fn(m);
1825    zwarnnam(m->node.nam, "no boot function");
1826    return 1;
1827}
1828
1829/**/
1830static int
1831dyn_cleanup_module(Module m)
1832{
1833    Module_void_func fn = (Module_void_func)module_func(m, STR_CLEANUP);
1834
1835    if(fn)
1836	return fn(m);
1837    zwarnnam(m->node.nam, "no cleanup function");
1838    return 1;
1839}
1840
1841/* Note that this function does more than just calling finish_foo(), *
1842 * it really unloads the module. */
1843
1844/**/
1845static int
1846dyn_finish_module(Module m)
1847{
1848    Module_void_func fn = (Module_void_func)module_func(m, STR_FINISH);
1849    int r;
1850
1851    if (fn)
1852	r = fn(m);
1853    else {
1854	zwarnnam(m->node.nam, "no finish function");
1855	r = 1;
1856    }
1857    dlclose(m->u.handle);
1858    return r;
1859}
1860
1861/**/
1862#endif /* !AIXDYNAMIC */
1863
1864/**/
1865static int
1866setup_module(Module m)
1867{
1868    return ((m->node.flags & MOD_LINKED) ?
1869	    (m->u.linked->setup)(m) : dyn_setup_module(m));
1870}
1871
1872/**/
1873static int
1874features_module(Module m, char ***features)
1875{
1876    return ((m->node.flags & MOD_LINKED) ?
1877	    (m->u.linked->features)(m, features) :
1878	    dyn_features_module(m, features));
1879}
1880
1881/**/
1882static int
1883enables_module(Module m, int **enables)
1884{
1885    return ((m->node.flags & MOD_LINKED) ?
1886	    (m->u.linked->enables)(m, enables) :
1887	    dyn_enables_module(m, enables));
1888}
1889
1890/**/
1891static int
1892boot_module(Module m)
1893{
1894    return ((m->node.flags & MOD_LINKED) ?
1895	    (m->u.linked->boot)(m) : dyn_boot_module(m));
1896}
1897
1898/**/
1899static int
1900cleanup_module(Module m)
1901{
1902    return ((m->node.flags & MOD_LINKED) ?
1903	    (m->u.linked->cleanup)(m) : dyn_cleanup_module(m));
1904}
1905
1906/**/
1907static int
1908finish_module(Module m)
1909{
1910    return ((m->node.flags & MOD_LINKED) ?
1911	    (m->u.linked->finish)(m) : dyn_finish_module(m));
1912}
1913
1914/**/
1915#else /* !DYNAMIC */
1916
1917/**/
1918static int
1919setup_module(Module m)
1920{
1921    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1);
1922}
1923
1924/**/
1925static int
1926features_module(Module m, char ***features)
1927{
1928    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features)
1929	    : 1);
1930}
1931
1932/**/
1933static int
1934enables_module(Module m, int **enables)
1935{
1936    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables)
1937	    : 1);
1938}
1939
1940/**/
1941static int
1942boot_module(Module m)
1943{
1944    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1);
1945}
1946
1947/**/
1948static int
1949cleanup_module(Module m)
1950{
1951    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1);
1952}
1953
1954/**/
1955static int
1956finish_module(Module m)
1957{
1958    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1);
1959}
1960
1961/**/
1962#endif /* !DYNAMIC */
1963
1964
1965/************************************************************************
1966 * Functions called when manipulating modules
1967 ************************************************************************/
1968
1969/*
1970 * Set the features for the module, which must be loaded
1971 * by now (though may not be fully set up).
1972 *
1973 * Return 0 for success, 1 for failure, 2 if some features
1974 * couldn't be set by the module itself (non-existent features
1975 * are tested here and cause 1 to be returned).
1976 */
1977
1978/**/
1979static int
1980do_module_features(Module m, Feature_enables enablesarr, int flags)
1981{
1982    char **features;
1983    int ret = 0;
1984
1985    if (features_module(m, &features) == 0) {
1986	/*
1987	 * Features are supported.  If we were passed
1988	 * a NULL array, enable all features, else
1989	 * enable only the features listed.
1990	 * (This may in principle be an empty array,
1991	 * although that's not very pointful.)
1992	 */
1993	int *enables = NULL;
1994	if (enables_module(m, &enables)) {
1995	    /* If features are supported, enables should be, too */
1996	    if (!(flags & FEAT_IGNORE))
1997		zwarn("error getting enabled features for module `%s'",
1998		      m->node.nam);
1999	    return 1;
2000	}
2001
2002	if ((flags & FEAT_CHECKAUTO) && m->autoloads) {
2003	    /*
2004	     * Check autoloads are available.  Since these
2005	     * have been requested at some other point, they
2006	     * don't affect the return status unless something
2007	     * in enablesstr doesn't work.
2008	     */
2009	    LinkNode an, nextn;
2010	    for (an = firstnode(m->autoloads); an; an = nextn) {
2011		char *al = (char *)getdata(an), **ptr;
2012		/* careful, we can delete the current node */
2013		nextn = nextnode(an);
2014		for (ptr = features; *ptr; ptr++)
2015		    if (!strcmp(al, *ptr))
2016			break;
2017		if (!*ptr) {
2018		    char *arg[2];
2019		    if (!(flags & FEAT_IGNORE))
2020			zwarn(
2021		    "module `%s' has no such feature: `%s': autoload cancelled",
2022		    m->node.nam, al);
2023		    /*
2024		     * This shouldn't happen, so it's not worth optimising
2025		     * the call to autofeatures...
2026		     */
2027		    arg[0] = al = dupstring(al);
2028		    arg[1] = NULL;
2029		    (void)autofeatures(NULL, m->node.nam, arg, 0,
2030				       FEAT_IGNORE|FEAT_REMOVE);
2031		    /*
2032		     * don't want to try to enable *that*...
2033		     * expunge it from the enable string.
2034		     */
2035		    if (enablesarr) {
2036			Feature_enables fep;
2037			for (fep = enablesarr; fep->str; fep++) {
2038			    char *str = fep->str;
2039			    if (*str == '+' || *str == '-')
2040				str++;
2041			    if (fep->pat ? pattry(fep->pat, al) :
2042				!strcmp(al, str)) {
2043				/* can't enable it after all, so return 1 */
2044				ret = 1;
2045				while (fep->str) {
2046				    fep->str = fep[1].str;
2047				    fep->pat = fep[1].pat;
2048				    fep++;
2049				}
2050				if (!fep->pat)
2051				    break;
2052			    }
2053			}
2054		    }
2055		}
2056	    }
2057	}
2058
2059	if (enablesarr) {
2060	    Feature_enables fep;
2061	    for (fep = enablesarr; fep->str; fep++) {
2062		char **fp, *esp = fep->str;
2063		int on = 1, found = 0;
2064		if (*esp == '+')
2065		    esp++;
2066		else if (*esp == '-') {
2067		    on = 0;
2068		    esp++;
2069		}
2070		for (fp = features; *fp; fp++)
2071		    if (fep->pat ? pattry(fep->pat, *fp) : !strcmp(*fp, esp)) {
2072			enables[fp - features] = on;
2073			found++;
2074			if (!fep->pat)
2075			    break;
2076		    }
2077		if (!found) {
2078		    if (!(flags & FEAT_IGNORE))
2079			zwarn(fep->pat ?
2080			      "module `%s' has no feature matching: `%s'" :
2081			      "module `%s' has no such feature: `%s'",
2082			      m->node.nam, esp);
2083		    return 1;
2084		}
2085	    }
2086	} else {
2087	    /*
2088	     * Enable all features.  This is used when loading
2089	     * without using zmodload -F.
2090	     */
2091	    int n_features = arrlen(features);
2092	    int *ep;
2093	    for (ep = enables; n_features--; ep++)
2094		*ep = 1;
2095	}
2096
2097	if (enables_module(m, &enables))
2098	    return 2;
2099    } else if (enablesarr) {
2100	if (!(flags & FEAT_IGNORE))
2101	    zwarn("module `%s' does not support features", m->node.nam);
2102	return 1;
2103    }
2104    /* Else it doesn't support features but we don't care. */
2105
2106    return ret;
2107}
2108
2109/*
2110 * Boot the module, including setting up features.
2111 * As we've only just loaded the module, we don't yet
2112 * know what features it supports, so we get them passed
2113 * as a string.
2114 *
2115 * Returns 0 if OK, 1 if completely failed, 2 if some features
2116 * couldn't be set up.
2117 */
2118
2119/**/
2120static int
2121do_boot_module(Module m, Feature_enables enablesarr, int silent)
2122{
2123    int ret = do_module_features(m, enablesarr,
2124				 silent ? FEAT_IGNORE|FEAT_CHECKAUTO :
2125				 FEAT_CHECKAUTO);
2126
2127    if (ret == 1)
2128	return 1;
2129
2130    if (boot_module(m))
2131	return 1;
2132    return ret;
2133}
2134
2135/*
2136 * Cleanup the module.
2137 */
2138
2139/**/
2140static int
2141do_cleanup_module(Module m)
2142{
2143    return (m->node.flags & MOD_LINKED) ?
2144	(m->u.linked && m->u.linked->cleanup(m)) :
2145	(m->u.handle && cleanup_module(m));
2146}
2147
2148/*
2149 * Test a module name contains only valid characters: those
2150 * allowed in a shell identifier plus slash.  Return 1 if so.
2151 */
2152
2153/**/
2154static int
2155modname_ok(char const *p)
2156{
2157    do {
2158	p = itype_end(p, IIDENT, 0);
2159	if (!*p)
2160	    return 1;
2161    } while(*p++ == '/');
2162    return 0;
2163}
2164
2165/*
2166 * High level function to load a module, encapsulating
2167 * all the handling of module functions.
2168 *
2169 * "*enablesstr" is NULL if the caller is not feature-aware;
2170 * then the module should turn on all features.  If it
2171 * is not NULL it points to an array of features to be
2172 * turned on.  This function is responsible for testing whether
2173 * the module supports those features.
2174 *
2175 * If "silent" is 1, don't issue warnings for errors.
2176 *
2177 * Now returns 0 for success (changed post-4.3.4),
2178 * 1 for complete failure, 2 if some features couldn't be set.
2179 */
2180
2181/**/
2182mod_export int
2183load_module(char const *name, Feature_enables enablesarr, int silent)
2184{
2185    Module m;
2186    void *handle = NULL;
2187    Linkedmod linked;
2188    int set, bootret;
2189
2190    if (!modname_ok(name)) {
2191	if (!silent)
2192	    zerr("invalid module name `%s'", name);
2193	return 1;
2194    }
2195    /*
2196     * The following function call may alter name to the final name in a
2197     * chain of aliases.  This makes sure the actual module loaded
2198     * is the right one.
2199     */
2200    queue_signals();
2201    if (!(m = find_module(name, FINDMOD_ALIASP, &name))) {
2202	if (!(linked = module_linked(name)) &&
2203	    !(handle = do_load_module(name, silent))) {
2204	    unqueue_signals();
2205	    return 1;
2206	}
2207	m = zshcalloc(sizeof(*m));
2208	if (handle) {
2209	    m->u.handle = handle;
2210	    m->node.flags |= MOD_SETUP;
2211	} else {
2212	    m->u.linked = linked;
2213	    m->node.flags |= MOD_SETUP | MOD_LINKED;
2214	}
2215	modulestab->addnode(modulestab, ztrdup(name), m);
2216
2217	if ((set = setup_module(m)) ||
2218	    (bootret = do_boot_module(m, enablesarr, silent)) == 1) {
2219	    if (!set)
2220		do_cleanup_module(m);
2221	    finish_module(m);
2222	    delete_module(m);
2223	    unqueue_signals();
2224	    return 1;
2225	}
2226	m->node.flags |= MOD_INIT_S | MOD_INIT_B;
2227	m->node.flags &= ~MOD_SETUP;
2228	unqueue_signals();
2229	return bootret;
2230    }
2231    if (m->node.flags & MOD_SETUP) {
2232	unqueue_signals();
2233	return 0;
2234    }
2235    if (m->node.flags & MOD_UNLOAD)
2236	m->node.flags &= ~MOD_UNLOAD;
2237    else if ((m->node.flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
2238	unqueue_signals();
2239	return 0;
2240    }
2241    if (m->node.flags & MOD_BUSY) {
2242	zerr("circular dependencies for module ;%s", name);
2243	return 1;
2244    }
2245    m->node.flags |= MOD_BUSY;
2246    /*
2247     * TODO: shouldn't we unload the module if one of
2248     * its dependencies fails?
2249     */
2250    if (m->deps) {
2251	LinkNode n;
2252	for (n = firstnode(m->deps); n; incnode(n))
2253	    if (load_module((char *) getdata(n), NULL, silent) == 1) {
2254		m->node.flags &= ~MOD_BUSY;
2255		unqueue_signals();
2256		return 1;
2257	    }
2258    }
2259    m->node.flags &= ~MOD_BUSY;
2260    if (!m->u.handle) {
2261	handle = NULL;
2262	if (!(linked = module_linked(name)) &&
2263	    !(handle = do_load_module(name, silent))) {
2264	    unqueue_signals();
2265	    return 1;
2266	}
2267	if (handle) {
2268	    m->u.handle = handle;
2269	    m->node.flags |= MOD_SETUP;
2270	} else {
2271	    m->u.linked = linked;
2272	    m->node.flags |= MOD_SETUP | MOD_LINKED;
2273	}
2274	if (setup_module(m)) {
2275	    finish_module(m);
2276	    if (handle)
2277		m->u.handle = NULL;
2278	    else
2279		m->u.linked = NULL;
2280	    m->node.flags &= ~MOD_SETUP;
2281	    unqueue_signals();
2282	    return 1;
2283	}
2284	m->node.flags |= MOD_INIT_S;
2285    }
2286    m->node.flags |= MOD_SETUP;
2287    if ((bootret = do_boot_module(m, enablesarr, silent)) == 1) {
2288	do_cleanup_module(m);
2289	finish_module(m);
2290	if (m->node.flags & MOD_LINKED)
2291	    m->u.linked = NULL;
2292	else
2293	    m->u.handle = NULL;
2294	m->node.flags &= ~MOD_SETUP;
2295	unqueue_signals();
2296	return 1;
2297    }
2298    m->node.flags |= MOD_INIT_B;
2299    m->node.flags &= ~MOD_SETUP;
2300    unqueue_signals();
2301    return bootret;
2302}
2303
2304/* This ensures that the module with the name given as the first argument
2305 * is loaded.
2306 * The other argument is the array of features to set.  If this is NULL
2307 * all features are enabled (even if the module was already loaded).
2308 *
2309 * If this is non-NULL the module features are set accordingly
2310 * whether or not the module is loaded; it is an error if the
2311 * module does not support the features passed (even if the feature
2312 * is to be turned off) or if the module does not support features
2313 * at all.
2314 * The return value is 0 if the module was found or loaded
2315 * (this changed post-4.3.4, because I got so confused---pws),
2316 * 1 if loading failed completely, 2 if some features couldn't be set.
2317 *
2318 * This function behaves like load_module() except that it
2319 * handles the case where the module was already loaded, and
2320 * sets features accordingly.
2321 */
2322
2323/**/
2324mod_export int
2325require_module(const char *module, Feature_enables features)
2326{
2327    Module m = NULL;
2328    int ret = 0;
2329
2330    /* Resolve aliases and actual loadable module as for load_module */
2331    queue_signals();
2332    m = find_module(module, FINDMOD_ALIASP, &module);
2333    if (!m || !m->u.handle ||
2334	(m->node.flags & MOD_UNLOAD))
2335	ret = load_module(module, features, 0);
2336    else
2337	ret = do_module_features(m, features, 0);
2338    unqueue_signals();
2339
2340    return ret;
2341}
2342
2343/*
2344 * Indicate that the module named "name" depends on the module
2345 * named "from".
2346 */
2347
2348/**/
2349void
2350add_dep(const char *name, char *from)
2351{
2352    LinkNode node;
2353    Module m;
2354
2355    /*
2356     * If we were passed an alias, we must resolve it to a final
2357     * module name (and maybe add the corresponding struct), since otherwise
2358     * we would need to check all modules to see if they happen
2359     * to be aliased to the same thing to implement dependencies properly.
2360     *
2361     * This should mean that an attempt to add an alias which would
2362     * have the same name as a module which has dependencies is correctly
2363     * rejected, because then the module named already exists as a non-alias.
2364     * Better make sure.  (There's no problem making a an alias which
2365     * *points* to a module with dependencies, of course.)
2366     */
2367    m = find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name);
2368    if (!m->deps)
2369	m->deps = znewlinklist();
2370    for (node = firstnode(m->deps);
2371	 node && strcmp((char *) getdata(node), from);
2372	 incnode(node));
2373    if (!node)
2374	zaddlinknode(m->deps, ztrdup(from));
2375}
2376
2377/*
2378 * Function to be used when scanning the builtins table to
2379 * find and print autoloadable builtins.
2380 */
2381
2382/**/
2383static void
2384autoloadscan(HashNode hn, int printflags)
2385{
2386    Builtin bn = (Builtin) hn;
2387
2388    if(bn->node.flags & BINF_ADDED)
2389	return;
2390    if(printflags & PRINT_LIST) {
2391	fputs("zmodload -ab ", stdout);
2392	if(bn->optstr[0] == '-')
2393	    fputs("-- ", stdout);
2394	quotedzputs(bn->optstr, stdout);
2395	if(strcmp(bn->node.nam, bn->optstr)) {
2396	    putchar(' ');
2397	    quotedzputs(bn->node.nam, stdout);
2398	}
2399    } else {
2400	nicezputs(bn->node.nam, stdout);
2401	if(strcmp(bn->node.nam, bn->optstr)) {
2402	    fputs(" (", stdout);
2403	    nicezputs(bn->optstr, stdout);
2404	    putchar(')');
2405	}
2406    }
2407    putchar('\n');
2408}
2409
2410
2411/************************************************************************
2412 * Handling for the zmodload builtin and its various options.
2413 ************************************************************************/
2414
2415/*
2416 * Main builtin entry point for zmodload.
2417 */
2418
2419/**/
2420int
2421bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
2422{
2423    int ops_bcpf = OPT_ISSET(ops,'b') || OPT_ISSET(ops,'c') ||
2424	OPT_ISSET(ops,'p') || OPT_ISSET(ops,'f');
2425    int ops_au = OPT_ISSET(ops,'a') || OPT_ISSET(ops,'u');
2426    int ret = 1, autoopts;
2427    /* options only allowed with -F */
2428    char *fonly = "lP", *fp;
2429
2430    if (ops_bcpf && !ops_au) {
2431	zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
2432	return 1;
2433    }
2434    if (OPT_ISSET(ops,'F') && (ops_bcpf || OPT_ISSET(ops,'u'))) {
2435	zwarnnam(nam, "-b, -c, -f, -p and -u cannot be combined with -F");
2436	return 1;
2437    }
2438    if (OPT_ISSET(ops,'A') || OPT_ISSET(ops,'R')) {
2439	if (ops_bcpf || ops_au || OPT_ISSET(ops,'d') ||
2440	    (OPT_ISSET(ops,'R') && OPT_ISSET(ops,'e'))) {
2441	    zwarnnam(nam, "illegal flags combined with -A or -R");
2442	    return 1;
2443	}
2444	if (!OPT_ISSET(ops,'e'))
2445	    return bin_zmodload_alias(nam, args, ops);
2446    }
2447    if (OPT_ISSET(ops,'d') && OPT_ISSET(ops,'a')) {
2448	zwarnnam(nam, "-d cannot be combined with -a");
2449	return 1;
2450    }
2451    if (OPT_ISSET(ops,'u') && !*args) {
2452	zwarnnam(nam, "what do you want to unload?");
2453	return 1;
2454    }
2455    if (OPT_ISSET(ops,'e') && (OPT_ISSET(ops,'I') || OPT_ISSET(ops,'L') ||
2456			       (OPT_ISSET(ops,'a') && !OPT_ISSET(ops,'F'))
2457			       || OPT_ISSET(ops,'d') ||
2458			       OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) {
2459	zwarnnam(nam, "-e cannot be combined with other options");
2460	/* except -F ... */
2461	return 1;
2462    }
2463    for (fp = fonly; *fp; fp++) {
2464	if (OPT_ISSET(ops,STOUC(*fp)) && !OPT_ISSET(ops,'F')) {
2465	    zwarnnam(nam, "-%c is only allowed with -F", *fp);
2466	    return 1;
2467	}
2468    }
2469    queue_signals();
2470    if (OPT_ISSET(ops, 'F'))
2471	ret = bin_zmodload_features(nam, args, ops);
2472    else if (OPT_ISSET(ops,'e'))
2473	ret = bin_zmodload_exist(nam, args, ops);
2474    else if (OPT_ISSET(ops,'d'))
2475	ret = bin_zmodload_dep(nam, args, ops);
2476    else if ((autoopts = OPT_ISSET(ops, 'b') + OPT_ISSET(ops, 'c') +
2477	      OPT_ISSET(ops, 'p') + OPT_ISSET(ops, 'f')) ||
2478	     /* zmodload -a is equivalent to zmodload -ab, annoyingly */
2479	     OPT_ISSET(ops, 'a')) {
2480	if (autoopts > 1) {
2481	    zwarnnam(nam, "use only one of -b, -c, or -p");
2482	    ret = 1;
2483	} else
2484	    ret = bin_zmodload_auto(nam, args, ops);
2485    } else
2486	ret = bin_zmodload_load(nam, args, ops);
2487    unqueue_signals();
2488
2489    return ret;
2490}
2491
2492/* zmodload -A */
2493
2494/**/
2495static int
2496bin_zmodload_alias(char *nam, char **args, Options ops)
2497{
2498    /*
2499     * TODO: while it would be too nasty to have aliases, as opposed
2500     * to real loadable modules, with dependencies --- just what would
2501     * we need to load when, exactly? --- there is in principle no objection
2502     * to making it possible to force an alias onto an existing unloaded
2503     * module which has dependencies.  This would simply transfer
2504     * the dependencies down the line to the aliased-to module name.
2505     * This is actually useful, since then you can alias zsh/zle=mytestzle
2506     * to load another version of zle.  But then what happens when the
2507     * alias is removed?  Do you transfer the dependencies back? And
2508     * suppose other names are aliased to the same file?  It might be
2509     * kettle of fish best left unwormed.
2510     */
2511    Module m;
2512
2513    if (!*args) {
2514	if (OPT_ISSET(ops,'R')) {
2515	    zwarnnam(nam, "no module alias to remove");
2516	    return 1;
2517	}
2518	scanhashtable(modulestab, 1, MOD_ALIAS, 0,
2519		      modulestab->printnode,
2520		      OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
2521	return 0;
2522    }
2523
2524    for (; *args; args++) {
2525	char *eqpos = strchr(*args, '=');
2526	char *aliasname = eqpos ? eqpos+1 : NULL;
2527	if (eqpos)
2528	    *eqpos = '\0';
2529	if (!modname_ok(*args)) {
2530	    zwarnnam(nam, "invalid module name `%s'", *args);
2531	    return 1;
2532	}
2533	if (OPT_ISSET(ops,'R')) {
2534	    if (aliasname) {
2535		zwarnnam(nam, "bad syntax for removing module alias: %s",
2536			 *args);
2537		return 1;
2538	    }
2539	    m = find_module(*args, 0, NULL);
2540	    if (m) {
2541		if (!(m->node.flags & MOD_ALIAS)) {
2542		    zwarnnam(nam, "module is not an alias: %s", *args);
2543		    return 1;
2544		}
2545		delete_module(m);
2546	    } else {
2547		zwarnnam(nam, "no such module alias: %s", *args);
2548		return 1;
2549	    }
2550	} else {
2551	    if (aliasname) {
2552		const char *mname = aliasname;
2553		if (!modname_ok(aliasname)) {
2554		    zwarnnam(nam, "invalid module name `%s'", aliasname);
2555		    return 1;
2556		}
2557		do {
2558		    if (!strcmp(mname, *args)) {
2559			zwarnnam(nam, "module alias would refer to itself: %s",
2560				 *args);
2561			return 1;
2562		    }
2563		} while ((m = find_module(mname, 0, NULL))
2564			 && (m->node.flags & MOD_ALIAS)
2565			 && (mname = m->u.alias));
2566		m = find_module(*args, 0, NULL);
2567		if (m) {
2568		    if (!(m->node.flags & MOD_ALIAS)) {
2569			zwarnnam(nam, "module is not an alias: %s", *args);
2570			return 1;
2571		    }
2572		    zsfree(m->u.alias);
2573		} else {
2574		    m = (Module) zshcalloc(sizeof(*m));
2575		    m->node.flags = MOD_ALIAS;
2576		    modulestab->addnode(modulestab, ztrdup(*args), m);
2577		}
2578		m->u.alias = ztrdup(aliasname);
2579	    } else {
2580		if ((m = find_module(*args, 0, NULL))) {
2581		    if (m->node.flags & MOD_ALIAS)
2582			modulestab->printnode(&m->node,
2583					      OPT_ISSET(ops,'L') ?
2584					      PRINTMOD_LIST : 0);
2585		    else {
2586			zwarnnam(nam, "module is not an alias: %s", *args);
2587			return 1;
2588		    }
2589		} else {
2590		    zwarnnam(nam, "no such module alias: %s", *args);
2591		    return 1;
2592		}
2593	    }
2594	}
2595    }
2596
2597    return 0;
2598}
2599
2600/* zmodload -e (without -F) */
2601
2602/**/
2603static int
2604bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops)
2605{
2606    Module m;
2607
2608    if (!*args) {
2609	scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
2610		      OPT_ISSET(ops,'A') ? PRINTMOD_EXIST|PRINTMOD_ALIAS :
2611		      PRINTMOD_EXIST);
2612	return 0;
2613    } else {
2614	int ret = 0;
2615
2616	for (; !ret && *args; args++) {
2617	    if (!(m = find_module(*args, FINDMOD_ALIASP, NULL))
2618		|| !m->u.handle
2619		|| (m->node.flags & MOD_UNLOAD))
2620		ret = 1;
2621	}
2622	return ret;
2623    }
2624}
2625
2626/* zmodload -d */
2627
2628/**/
2629static int
2630bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops)
2631{
2632    Module m;
2633    if (OPT_ISSET(ops,'u')) {
2634	/* remove dependencies, which can't pertain to aliases */
2635	const char *tnam = *args++;
2636	m = find_module(tnam, FINDMOD_ALIASP, &tnam);
2637	if (!m)
2638	    return 0;
2639	if (*args && m->deps) {
2640	    do {
2641		LinkNode dnode;
2642		for (dnode = firstnode(m->deps); dnode; incnode(dnode))
2643		    if (!strcmp(*args, getdata(dnode))) {
2644			zsfree(getdata(dnode));
2645			remnode(m->deps, dnode);
2646			break;
2647		    }
2648	    } while(*++args);
2649	    if (empty(m->deps)) {
2650		freelinklist(m->deps, freestr);
2651		m->deps = NULL;
2652	    }
2653	} else {
2654	    if (m->deps) {
2655		freelinklist(m->deps, freestr);
2656		m->deps = NULL;
2657	    }
2658	}
2659	if (!m->deps && !m->u.handle)
2660	    delete_module(m);
2661	return 0;
2662    } else if (!args[0] || !args[1]) {
2663	/* list dependencies */
2664	int depflags = OPT_ISSET(ops,'L') ?
2665	    PRINTMOD_DEPS|PRINTMOD_LIST : PRINTMOD_DEPS;
2666	if (args[0]) {
2667	    if ((m = (Module)modulestab->getnode2(modulestab, args[0])))
2668		modulestab->printnode(&m->node, depflags);
2669	} else {
2670	    scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
2671			  depflags);
2672	}
2673	return 0;
2674    } else {
2675	/* add dependencies */
2676	int ret = 0;
2677	char *tnam = *args++;
2678
2679	for (; *args; args++)
2680	    add_dep(tnam, *args);
2681	return ret;
2682    }
2683}
2684
2685/*
2686 * Function for scanning the parameter table to find and print
2687 * out autoloadable parameters.
2688 */
2689
2690static void
2691printautoparams(HashNode hn, int lon)
2692{
2693    Param pm = (Param) hn;
2694
2695    if (pm->node.flags & PM_AUTOLOAD) {
2696	if (lon)
2697	    printf("zmodload -ap %s %s\n", pm->u.str, pm->node.nam);
2698	else
2699	    printf("%s (%s)\n", pm->node.nam, pm->u.str);
2700    }
2701}
2702
2703/* zmodload -a/u [bcpf] */
2704
2705/**/
2706static int
2707bin_zmodload_auto(char *nam, char **args, Options ops)
2708{
2709    int fchar, flags;
2710    char *modnam;
2711
2712    if (OPT_ISSET(ops,'c')) {
2713	if (!*args) {
2714	    /* list autoloaded conditions */
2715	    Conddef p;
2716
2717	    for (p = condtab; p; p = p->next) {
2718		if (p->module) {
2719		    if (OPT_ISSET(ops,'L')) {
2720			fputs("zmodload -ac", stdout);
2721			if (p->flags & CONDF_INFIX)
2722			    putchar('I');
2723			printf(" %s %s\n", p->module, p->name);
2724		    } else {
2725			if (p->flags & CONDF_INFIX)
2726			    fputs("infix ", stdout);
2727			else
2728			    fputs("post ", stdout);
2729			printf("%s (%s)\n",p->name, p->module);
2730		    }
2731		}
2732	    }
2733	    return 0;
2734	}
2735	fchar = OPT_ISSET(ops,'I') ? 'C' : 'c';
2736    } else if (OPT_ISSET(ops,'p')) {
2737	if (!*args) {
2738	    /* list autoloaded parameters */
2739	    scanhashtable(paramtab, 1, 0, 0, printautoparams,
2740			  OPT_ISSET(ops,'L'));
2741	    return 0;
2742	}
2743	fchar = 'p';
2744    } else if (OPT_ISSET(ops,'f')) {
2745	if (!*args) {
2746	    /* list autoloaded math functions */
2747	    MathFunc p;
2748
2749	    for (p = mathfuncs; p; p = p->next) {
2750		if (!(p->flags & MFF_USERFUNC) && p->module) {
2751		    if (OPT_ISSET(ops,'L')) {
2752			fputs("zmodload -af", stdout);
2753			printf(" %s %s\n", p->module, p->name);
2754		    } else
2755			printf("%s (%s)\n",p->name, p->module);
2756		}
2757	    }
2758	    return 0;
2759	}
2760	fchar = 'f';
2761    } else {
2762	/* builtins are the default; zmodload -ab or just zmodload -a */
2763	if (!*args) {
2764	    /* list autoloaded builtins */
2765	    scanhashtable(builtintab, 1, 0, 0,
2766			  autoloadscan, OPT_ISSET(ops,'L') ? PRINT_LIST : 0);
2767	    return 0;
2768	}
2769	fchar = 'b';
2770    }
2771
2772    flags = FEAT_AUTOALL;
2773    if (OPT_ISSET(ops,'i'))
2774	flags |= FEAT_IGNORE;
2775    if (OPT_ISSET(ops,'u')) {
2776	/* remove autoload */
2777	flags |= FEAT_REMOVE;
2778	modnam = NULL;
2779    } else {
2780	/* add autoload */
2781	modnam = *args;
2782
2783	if (args[1])
2784	    args++;
2785    }
2786    return autofeatures(nam, modnam, args, fchar, flags);
2787}
2788
2789/* Backend handler for zmodload -u */
2790
2791/**/
2792int
2793unload_module(Module m)
2794{
2795    int del;
2796
2797    /*
2798     * Only unload the real module, so resolve aliases.
2799     */
2800    if (m->node.flags & MOD_ALIAS) {
2801	m = find_module(m->u.alias, FINDMOD_ALIASP, NULL);
2802	if (!m)
2803	    return 1;
2804    }
2805    /*
2806     * We may need to clean up the module any time setup_ has been
2807     * called.  After cleanup_ is successful we are no longer in the
2808     * booted state (because features etc. are deregistered), so remove
2809     * MOD_INIT_B, and also MOD_INIT_S since we won't need to cleanup
2810     * again if this succeeded.
2811     */
2812    if ((m->node.flags & MOD_INIT_S) &&
2813	!(m->node.flags & MOD_UNLOAD) &&
2814	do_cleanup_module(m))
2815	return 1;
2816    m->node.flags &= ~(MOD_INIT_B|MOD_INIT_S);
2817
2818    del = (m->node.flags & MOD_UNLOAD);
2819
2820    if (m->wrapper) {
2821	m->node.flags |= MOD_UNLOAD;
2822	return 0;
2823    }
2824    m->node.flags &= ~MOD_UNLOAD;
2825
2826    /*
2827     * We always need to finish the module (and unload it)
2828     * if it is present.
2829     */
2830    if (m->node.flags & MOD_LINKED) {
2831	if (m->u.linked) {
2832	    m->u.linked->finish(m);
2833	    m->u.linked = NULL;
2834	}
2835    } else {
2836	if (m->u.handle) {
2837	    finish_module(m);
2838	    m->u.handle = NULL;
2839	}
2840    }
2841
2842    if (del && m->deps) {
2843	/* The module was unloaded delayed, unload all modules *
2844	 * on which it depended. */
2845	LinkNode n;
2846
2847	for (n = firstnode(m->deps); n; incnode(n)) {
2848	    Module dm = find_module((char *) getdata(n),
2849				    FINDMOD_ALIASP, NULL);
2850
2851	    if (dm &&
2852		(dm->node.flags & MOD_UNLOAD)) {
2853		/* See if this is the only module depending on it. */
2854		Module am;
2855		int du = 1, i;
2856		/* Scan hash table the hard way */
2857		for (i = 0; du && i < modulestab->hsize; i++) {
2858		    for (am = (Module)modulestab->nodes[i]; du && am;
2859			 am = (Module)am->node.next) {
2860			LinkNode sn;
2861			/*
2862			 * Don't scan the module we're unloading;
2863			 * ignore if no dependencies.
2864			 */
2865			if (am == m || !am->deps)
2866			    continue;
2867			/* Don't scan if not loaded nor linked */
2868			if ((am->node.flags & MOD_LINKED) ?
2869			    !am->u.linked : !am->u.handle)
2870			    continue;
2871			for (sn = firstnode(am->deps); du && sn;
2872			     incnode(sn)) {
2873			    if (!strcmp((char *) getdata(sn),
2874					dm->node.nam))
2875				du = 0;
2876			}
2877		    }
2878		}
2879		if (du)
2880		    unload_module(dm);
2881	    }
2882	}
2883    }
2884    if (m->autoloads && firstnode(m->autoloads)) {
2885	/*
2886	 * Module has autoloadable features.  Restore them
2887	 * so that the module will be reloaded when needed.
2888	 */
2889	autofeatures("zsh", m->node.nam,
2890		     hlinklist2array(m->autoloads, 0), 0, FEAT_IGNORE);
2891    } else if (!m->deps) {
2892	delete_module(m);
2893    }
2894    return 0;
2895}
2896
2897/*
2898 * Unload a module by name (modname); nam is the command name.
2899 * Optionally don't print some error messages (always print
2900 * dependency errors).
2901 */
2902
2903/**/
2904int
2905unload_named_module(char *modname, char *nam, int silent)
2906{
2907    const char *mname;
2908    Module m;
2909    int ret = 0;
2910
2911    m = find_module(modname, FINDMOD_ALIASP, &mname);
2912    if (m) {
2913	int i, del = 0;
2914	Module dm;
2915
2916	for (i = 0; i < modulestab->hsize; i++) {
2917	    for (dm = (Module)modulestab->nodes[i]; dm;
2918		 dm = (Module)dm->node.next) {
2919		LinkNode dn;
2920		if (!dm->deps || !dm->u.handle)
2921		    continue;
2922		for (dn = firstnode(dm->deps); dn; incnode(dn)) {
2923		    if (!strcmp((char *) getdata(dn), mname)) {
2924			if (dm->node.flags & MOD_UNLOAD)
2925			    del = 1;
2926			else {
2927			    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname);
2928			    return 1;
2929			}
2930		    }
2931		}
2932	    }
2933	}
2934	if (del)
2935	    m->wrapper++;
2936	if (unload_module(m))
2937	    ret = 1;
2938	if (del)
2939	    m->wrapper--;
2940    } else if (!silent) {
2941	zwarnnam(nam, "no such module %s", modname);
2942	ret = 1;
2943    }
2944
2945    return ret;
2946}
2947
2948/* zmodload -u without -d */
2949
2950/**/
2951static int
2952bin_zmodload_load(char *nam, char **args, Options ops)
2953{
2954    int ret = 0;
2955    if(OPT_ISSET(ops,'u')) {
2956	/* unload modules */
2957	for(; *args; args++) {
2958	    if (unload_named_module(*args, nam, OPT_ISSET(ops,'i')))
2959		ret = 1;
2960	}
2961	return ret;
2962    } else if(!*args) {
2963	/* list modules */
2964	scanhashtable(modulestab, 1, 0, MOD_UNLOAD|MOD_ALIAS,
2965		      modulestab->printnode,
2966		      OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
2967	return 0;
2968    } else {
2969	/* load modules */
2970	for (; *args; args++) {
2971	    int tmpret = require_module(*args, NULL);
2972	    if (tmpret && ret != 1)
2973		ret = tmpret;
2974	}
2975
2976	return ret;
2977    }
2978}
2979
2980/* zmodload -F */
2981
2982/**/
2983static int
2984bin_zmodload_features(const char *nam, char **args, Options ops)
2985{
2986    int iarg;
2987    char *modname = *args;
2988    Patprog *patprogs;
2989    Feature_enables features, fep;
2990
2991    if (modname)
2992	args++;
2993    else if (OPT_ISSET(ops,'L')) {
2994	int printflags = PRINTMOD_LIST|PRINTMOD_FEATURES;
2995	if (OPT_ISSET(ops,'P')) {
2996	    zwarnnam(nam, "-P is only allowed with a module name");
2997	    return 1;
2998	}
2999	if (OPT_ISSET(ops,'l'))
3000	    printflags |= PRINTMOD_LISTALL;
3001	if (OPT_ISSET(ops,'a'))
3002	    printflags |= PRINTMOD_AUTO;
3003	scanhashtable(modulestab, 1, 0, MOD_ALIAS,
3004		      modulestab->printnode, printflags);
3005	return 0;
3006    }
3007
3008    if (!modname) {
3009	zwarnnam(nam, "-F requires a module name");
3010	return 1;
3011    }
3012
3013    if (OPT_ISSET(ops,'m')) {
3014	char **argp;
3015	Patprog *patprogp;
3016
3017	/* not NULL terminated */
3018	patprogp = patprogs =
3019	    (Patprog *)zhalloc(arrlen(args)*sizeof(Patprog));
3020	for (argp = args; *argp; argp++, patprogp++) {
3021	    char *arg = *argp;
3022	    if (*arg == '+' || *arg == '-')
3023		arg++;
3024	    tokenize(arg);
3025	    *patprogp = patcompile(arg, 0, 0);
3026	}
3027    } else
3028	patprogs = NULL;
3029
3030    if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) {
3031	/*
3032	 * With option 'l', list all features one per line with + or -.
3033	 * With option 'L', list as zmodload statement showing
3034	 * only options turned on.
3035	 * With both options, list as zmodload showing options
3036	 * to be turned both on and off.
3037	 */
3038	Module m;
3039	char **features, **fp, **arrset = NULL, **arrp = NULL;
3040	int *enables = NULL, *ep;
3041	char *param = OPT_ARG_SAFE(ops,'P');
3042
3043	m = find_module(modname, FINDMOD_ALIASP, NULL);
3044	if (OPT_ISSET(ops,'a')) {
3045	    LinkNode ln;
3046	    /*
3047	     * If there are no autoloads defined, return status 1.
3048	     */
3049	    if (!m || !m->autoloads)
3050		return 1;
3051	    if (OPT_ISSET(ops,'e')) {
3052		for (fp = args; *fp; fp++) {
3053		    char *fstr = *fp;
3054		    int sense = 1;
3055		    if (*fstr == '+')
3056			fstr++;
3057		    else if (*fstr == '-') {
3058			fstr++;
3059			sense = 0;
3060		    }
3061		    if ((linknodebystring(m->autoloads, fstr) != NULL) !=
3062			sense)
3063			return 1;
3064		}
3065		return 0;
3066	    }
3067	    if (param) {
3068		arrp = arrset = (char **)zalloc(sizeof(char*) *
3069				 (countlinknodes(m->autoloads)+1));
3070	    } else if (OPT_ISSET(ops,'L')) {
3071		printf("zmodload -aF %s%c", m->node.nam,
3072		       m->autoloads && firstnode(m->autoloads) ? ' ' : '\n');
3073		arrp = NULL;
3074	    }
3075	    for (ln = firstnode(m->autoloads); ln; incnode(ln)) {
3076		char *al = (char *)getdata(ln);
3077		if (param)
3078		    *arrp++ = ztrdup(al);
3079		else
3080		    printf("%s%c", al,
3081			   OPT_ISSET(ops,'L') && nextnode(ln) ? ' ' : '\n');
3082	    }
3083	    if (param) {
3084		*arrp = NULL;
3085		if (!setaparam(param, arrset))
3086		    return 1;
3087	    }
3088	    return 0;
3089	}
3090	if (!m || !m->u.handle || (m->node.flags & MOD_UNLOAD)) {
3091	    if (!OPT_ISSET(ops,'e'))
3092		zwarnnam(nam, "module `%s' is not yet loaded", modname);
3093	    return 1;
3094	}
3095	if (features_module(m, &features)) {
3096	    if (!OPT_ISSET(ops,'e'))
3097		zwarnnam(nam, "module `%s' does not support features",
3098			 m->node.nam);
3099	    return 1;
3100	}
3101	if (enables_module(m, &enables)) {
3102	    /* this shouldn't ever happen, so don't silence this error */
3103	    zwarnnam(nam, "error getting enabled features for module `%s'",
3104		     m->node.nam);
3105	    return 1;
3106	}
3107	for (arrp = args, iarg = 0; *arrp; arrp++, iarg++) {
3108	    char *arg = *arrp;
3109	    int on, found = 0;
3110	    if (*arg == '-') {
3111		on = 0;
3112		arg++;
3113	    } else if (*arg == '+') {
3114		on = 1;
3115		arg++;
3116	    } else
3117		on = -1;
3118	    for (fp = features, ep = enables; *fp; fp++, ep++) {
3119		if (patprogs ? pattry(patprogs[iarg], *fp) :
3120		    !strcmp(arg, *fp)) {
3121		    /* for -e, check given state, if any */
3122		    if (OPT_ISSET(ops,'e') && on != -1 &&
3123			on != (*ep & 1))
3124			return 1;
3125		    found++;
3126		    if (!patprogs)
3127			break;
3128		}
3129	    }
3130	    if (!found) {
3131		if (!OPT_ISSET(ops,'e'))
3132		    zwarnnam(nam, patprogs ?
3133			     "module `%s' has no feature matching: `%s'" :
3134			     "module `%s' has no such feature: `%s'",
3135			     modname, *arrp);
3136		return 1;
3137	    }
3138	}
3139	if (OPT_ISSET(ops,'e'))		/* yep, everything we want exists */
3140	    return 0;
3141	if (param) {
3142	    int arrlen = 0;
3143	    for (fp = features, ep = enables; *fp; fp++, ep++) {
3144		if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') &&
3145		    !*ep)
3146		    continue;
3147		if (*args) {
3148		    char **argp;
3149		    for (argp = args, iarg = 0; *argp; argp++, iarg++) {
3150			char *arg = *argp;
3151			/* ignore +/- for consistency */
3152			if (*arg == '+' || *arg == '-')
3153			    arg++;
3154			if (patprogs ? pattry(patprogs[iarg], *fp) :
3155			    !strcmp(*fp, arg))
3156			    break;
3157		    }
3158		    if (!*argp)
3159			continue;
3160		}
3161		arrlen++;
3162	    }
3163	    arrp = arrset = zalloc(sizeof(char *) * (arrlen+1));
3164	} else if (OPT_ISSET(ops, 'L'))
3165	    printf("zmodload -F %s ", m->node.nam);
3166	for (fp = features, ep = enables; *fp; fp++, ep++) {
3167	    char *onoff;
3168	    int term;
3169	    if (*args) {
3170		char **argp;
3171		for (argp = args, iarg = 0; *argp; argp++, iarg++) {
3172		    char *arg = *argp;
3173		    if (*arg == '+' || *arg == '-')
3174			arg++;
3175		    if (patprogs ? pattry(patprogs[iarg], *fp) :
3176			!strcmp(*fp, *argp))
3177			break;
3178		}
3179		if (!*argp)
3180		    continue;
3181	    }
3182	    if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l')) {
3183		if (!*ep)
3184		    continue;
3185		onoff = "";
3186	    } else if (*ep) {
3187		onoff = "+";
3188	    } else {
3189		onoff = "-";
3190	    }
3191	    if (param) {
3192		*arrp++ = bicat(onoff, *fp);
3193	    } else {
3194		if (OPT_ISSET(ops, 'L') && fp[1]) {
3195		    term = ' ';
3196		} else {
3197		    term = '\n';
3198		}
3199		printf("%s%s%c", onoff, *fp, term);
3200	    }
3201	}
3202	if (param) {
3203	    *arrp = NULL;
3204	    if (!setaparam(param, arrset))
3205		return 1;
3206	}
3207	return 0;
3208    } else if (OPT_ISSET(ops,'P')) {
3209	zwarnnam(nam, "-P can only be used with -l or -L");
3210	return 1;
3211    } else if (OPT_ISSET(ops,'a')) {
3212	if (OPT_ISSET(ops,'m')) {
3213	    zwarnnam(nam, "-m cannot be used with -a");
3214	    return 1;
3215	}
3216	/*
3217	 * With zmodload -aF, we always use the effect of -i.
3218	 * The thinking is that marking a feature for
3219	 * autoload is separate from enabling or disabling it.
3220	 * Arguably we could do this with the zmodload -ab method
3221	 * but I've kept it there for old time's sake.
3222	 * The decoupling has meant FEAT_IGNORE/-i also
3223	 * suppresses an error for attempting to remove an
3224	 * autoload when the feature is enabled, which used
3225	 * to be a hard error before.
3226	 */
3227	return autofeatures(nam, modname, args, 0, FEAT_IGNORE);
3228    }
3229
3230    fep = features =
3231	(Feature_enables)zhalloc((arrlen(args)+1)*sizeof(*fep));
3232
3233    while (*args) {
3234	fep->str = *args++;
3235	fep->pat = patprogs ? *patprogs++ : NULL;
3236	fep++;
3237    }
3238    fep->str = NULL;
3239    fep->pat = NULL;
3240
3241    return require_module(modname, features);
3242}
3243
3244
3245/************************************************************************
3246 * Generic feature support.
3247 * These functions are designed to be called by modules.
3248 ************************************************************************/
3249
3250/*
3251 * Construct a features array out of the list of concrete
3252 * features given, leaving space for any abstract features
3253 * to be added by the module itself.
3254 *
3255 * Note the memory is from the heap.
3256 */
3257
3258/**/
3259mod_export char **
3260featuresarray(UNUSED(Module m), Features f)
3261{
3262    int bn_size = f->bn_size, cd_size = f->cd_size;
3263    int mf_size = f->mf_size, pd_size = f->pd_size;
3264    int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
3265    Builtin bnp = f->bn_list;
3266    Conddef cdp = f->cd_list;
3267    MathFunc mfp = f->mf_list;
3268    Paramdef pdp = f->pd_list;
3269    char **features = (char **)zhalloc((features_size + 1) * sizeof(char *));
3270    char **featurep = features;
3271
3272    while (bn_size--)
3273	*featurep++ = dyncat("b:", (bnp++)->node.nam);
3274    while (cd_size--) {
3275	*featurep++ = dyncat((cdp->flags & CONDF_INFIX) ? "C:" : "c:",
3276			     cdp->name);
3277	cdp++;
3278    }
3279    while (mf_size--)
3280	*featurep++ = dyncat("f:", (mfp++)->name);
3281    while (pd_size--)
3282	*featurep++ = dyncat("p:", (pdp++)->name);
3283
3284    features[features_size] = NULL;
3285    return features;
3286}
3287
3288/*
3289 * Return the current set of enables for the features in a
3290 * module using heap memory.  Leave space for abstract
3291 * features.  The array is not zero terminated.
3292 */
3293/**/
3294mod_export int *
3295getfeatureenables(UNUSED(Module m), Features f)
3296{
3297    int bn_size = f->bn_size, cd_size = f->cd_size;
3298    int mf_size = f->mf_size, pd_size = f->pd_size;
3299    int features_size = bn_size + cd_size + mf_size + pd_size + f->n_abstract;
3300    Builtin bnp = f->bn_list;
3301    Conddef cdp = f->cd_list;
3302    MathFunc mfp = f->mf_list;
3303    Paramdef pdp = f->pd_list;
3304    int *enables = zhalloc(sizeof(int) * features_size);
3305    int *enablep = enables;
3306
3307    while (bn_size--)
3308	*enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0;
3309    while (cd_size--)
3310	*enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0;
3311    while (mf_size--)
3312	*enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0;
3313    while (pd_size--)
3314	*enablep++ = (pdp++)->pm ? 1 : 0;
3315
3316    return enables;
3317}
3318
3319/*
3320 * Add or remove the concrete features passed in arguments,
3321 * depending on the corresponding element of the array e.
3322 * If e is NULL, disable everything.
3323 * Return 0 for success, 1 for failure; does not attempt
3324 * to imitate the return values of addbuiltins() etc.
3325 * Any failure in adding a requested feature is an
3326 * error.
3327 */
3328
3329/**/
3330mod_export int
3331setfeatureenables(Module m, Features f, int *e)
3332{
3333    int ret = 0;
3334
3335    if (f->bn_size) {
3336	if (setbuiltins(m->node.nam, f->bn_list, f->bn_size, e))
3337	    ret = 1;
3338	if (e)
3339	    e += f->bn_size;
3340    }
3341    if (f->cd_size) {
3342	if (setconddefs(m->node.nam, f->cd_list, f->cd_size, e))
3343	    ret = 1;
3344	if (e)
3345	    e += f->cd_size;
3346    }
3347    if (f->mf_size) {
3348	if (setmathfuncs(m->node.nam, f->mf_list, f->mf_size, e))
3349	    ret = 1;
3350    }
3351    if (f->pd_size) {
3352	if (setparamdefs(m->node.nam, f->pd_list, f->pd_size, e))
3353	    ret = 1;
3354	if (e)
3355	    e += f->pd_size;
3356    }
3357    return ret;
3358}
3359
3360/*
3361 * Convenient front-end to get or set features which
3362 * can be used in a module enables_() function.
3363 */
3364
3365/**/
3366mod_export int
3367handlefeatures(Module m, Features f, int **enables)
3368{
3369    if (!enables || *enables)
3370	return setfeatureenables(m, f, *enables);
3371    *enables = getfeatureenables(m, f);
3372    return 0;
3373}
3374
3375/*
3376 * Ensure module "modname" is providing feature with "prefix"
3377 * and "feature" (e.g. "b:", "limit").  If feature is NULL,
3378 * ensure all features are loaded (used for compatibility
3379 * with the pre-feature autoloading behaviour).
3380 *
3381 * This will usually be called from the main shell to handle
3382 * loading of an autoloadable feature.
3383 *
3384 * Returns 0 on success, 1 for error in module, 2 for error
3385 * setting the feature.  However, this isn't actually all
3386 * that useful for testing immediately on an autoload since
3387 * it could be a failure to autoload a different feature
3388 * from the one we want.  We could fix this but it's
3389 * possible to test other ways.
3390 */
3391
3392/**/
3393mod_export int
3394ensurefeature(const char *modname, const char *prefix, const char *feature)
3395{
3396    char *f;
3397    struct feature_enables features[2];
3398
3399    if (!feature)
3400	return require_module(modname, NULL);
3401    f = dyncat(prefix, feature);
3402
3403    features[0].str = f;
3404    features[0].pat = NULL;
3405    features[1].str = NULL;
3406    features[1].pat = NULL;
3407    return require_module(modname, features);
3408}
3409
3410/*
3411 * Add autoloadable features for a given module.
3412 */
3413
3414/**/
3415int
3416autofeatures(const char *cmdnam, const char *module, char **features,
3417	     int prefchar, int defflags)
3418{
3419    int ret = 0, subret;
3420    Module defm, m;
3421    char **modfeatures = NULL;
3422    int *modenables = NULL;
3423    if (module) {
3424	defm = (Module)find_module(module,
3425				   FINDMOD_ALIASP|FINDMOD_CREATE, NULL);
3426	if ((defm->node.flags & MOD_LINKED) ? defm->u.linked :
3427	    defm->u.handle) {
3428	    (void)features_module(defm, &modfeatures);
3429	    (void)enables_module(defm, &modenables);
3430	}
3431    } else
3432	defm = NULL;
3433
3434    for (; *features; features++) {
3435	char *fnam, *typnam, *feature;
3436	int add, fchar, flags = defflags;
3437	autofeaturefn_t fn;
3438
3439	if (prefchar) {
3440	    /*
3441	     * "features" is list of bare features with no
3442	     * type prefix; prefchar gives type character.
3443	     */
3444	    add = 1; 		/* unless overridden by flag */
3445	    fchar = prefchar;
3446	    fnam = *features;
3447	    feature = zhalloc(strlen(fnam) + 3);
3448	    sprintf(feature, "%c:%s", fchar, fnam);
3449	} else {
3450	    feature = *features;
3451	    if (*feature == '-') {
3452		add = 0;
3453		feature++;
3454	    } else {
3455		add = 1;
3456		if (*feature == '+')
3457		    feature++;
3458	    }
3459
3460	    if (!*feature || feature[1] != ':') {
3461		zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'",
3462			 feature);
3463		ret = 1;
3464		continue;
3465	    }
3466	    fnam = feature + 2;
3467	    fchar = feature[0];
3468	}
3469	if (flags & FEAT_REMOVE)
3470	    add = 0;
3471
3472	switch (fchar) {
3473	case 'b':
3474	    fn = add ? add_autobin : del_autobin;
3475	    typnam = "builtin";
3476	    break;
3477
3478	case 'C':
3479	    flags |= FEAT_INFIX;
3480	    /* FALLTHROUGH */
3481	case 'c':
3482	    fn = add ? add_autocond : del_autocond;
3483	    typnam = "condition";
3484	    break;
3485
3486	case 'f':
3487	    fn = add ? add_automathfunc : del_automathfunc;
3488	    typnam = "math function";
3489	    break;
3490
3491	case 'p':
3492	    fn = add ? add_autoparam : del_autoparam;
3493	    typnam = "parameter";
3494	    break;
3495
3496	default:
3497	    zwarnnam(cmdnam, "bad autoloadable feature type: `%c'",
3498		     fchar);
3499	    ret = 1;
3500	    continue;
3501	}
3502
3503	if (strchr(fnam, '/')) {
3504	    zwarnnam(cmdnam, "%s: `/' is illegal in a %s", fnam, typnam);
3505	    ret = 1;
3506	    continue;
3507	}
3508
3509	if (!module) {
3510	    /*
3511	     * Traditional un-autoload syntax doesn't tell us
3512	     * which module this came from.
3513	     */
3514	    int i;
3515	    for (i = 0, m = NULL; !m && i < modulestab->hsize; i++) {
3516		for (m = (Module)modulestab->nodes[i]; m;
3517		     m = (Module)m->node.next) {
3518		    if (m->autoloads &&
3519			linknodebystring(m->autoloads, feature))
3520			break;
3521		}
3522	    }
3523	    if (!m) {
3524		if (!(flags & FEAT_IGNORE)) {
3525		    ret = 1;
3526		    zwarnnam(cmdnam, "%s: no such %s", fnam, typnam);
3527		}
3528		continue;
3529	    }
3530	} else
3531	    m = defm;
3532
3533	subret = 0;
3534	if (add) {
3535	    char **ptr;
3536	    if (modfeatures) {
3537		/*
3538		 * If the module is already available, check that
3539		 * it does in fact provide the necessary feature.
3540		 */
3541		for (ptr = modfeatures; *ptr; ptr++)
3542		    if (!strcmp(*ptr, feature))
3543			break;
3544		if (!*ptr) {
3545		    zwarnnam(cmdnam, "module `%s' has no such feature: `%s'",
3546			     m->node.nam, feature);
3547		    ret = 1;
3548		    continue;
3549		}
3550		/*
3551		 * If the feature is already provided by the module, there's
3552		 * nothing more to do.
3553		 */
3554		if (modenables[ptr-modfeatures])
3555		    continue;
3556		/*
3557		 * Otherwise, marking it for autoload will do the
3558		 * right thing when the feature is eventually used.
3559		 */
3560	    }
3561	    if (!m->autoloads) {
3562		m->autoloads = znewlinklist();
3563		zaddlinknode(m->autoloads, ztrdup(feature));
3564	    } else {
3565		/* Insert in lexical order */
3566		LinkNode ln, prev = (LinkNode)m->autoloads;
3567		while ((ln = nextnode(prev))) {
3568		    int cmp = strcmp(feature, (char *)getdata(ln));
3569		    if (cmp == 0) {
3570			/* Already there.  Never an error. */
3571			break;
3572		    }
3573		    if (cmp < 0) {
3574			zinsertlinknode(m->autoloads, prev,
3575					ztrdup(feature));
3576			break;
3577		    }
3578		    prev = ln;
3579		}
3580		if (!ln)
3581		    zaddlinknode(m->autoloads, ztrdup(feature));
3582	    }
3583	} else if (m->autoloads) {
3584	    LinkNode ln;
3585	    if ((ln = linknodebystring(m->autoloads, feature)))
3586		zsfree((char *)remnode(m->autoloads, ln));
3587	    else {
3588		/*
3589		 * With -i (or zmodload -Fa), removing an autoload
3590		 * that's not there is not an error.
3591		 */
3592		subret = (flags & FEAT_IGNORE) ? -2 : 2;
3593	    }
3594	}
3595
3596	if (subret == 0)
3597	    subret = fn(module, fnam, flags);
3598
3599	if (subret != 0) {
3600	    /* -2 indicates not an error, just skip running fn() */
3601	    if (subret != -2)
3602		ret = 1;
3603	    switch (subret) {
3604	    case 1:
3605		zwarnnam(cmdnam, "failed to add %s `%s'", typnam, fnam);
3606		break;
3607
3608	    case 2:
3609		zwarnnam(cmdnam, "%s: no such %s", fnam, typnam);
3610		break;
3611
3612	    case 3:
3613		zwarnnam(cmdnam, "%s: %s is already defined", fnam, typnam);
3614		break;
3615
3616	    default:
3617		/* no (further) message needed */
3618		break;
3619	    }
3620	}
3621    }
3622
3623    return ret;
3624}
3625