Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: feature autoloading etc.



The main focus of this patch was to finish off autoloading of features
from modules, but it turned out to have a lot of other stuff in it.

I think this is the last of feature autoloading.  The only part I
haven't done any work on is dependencies.  However, there's currently
no requirement to have one module depending on another module's
modifiable features instead of the module itself.  The feature
facilities give plenty of scope for handling dependencies in shell
code.  So I'm not doing anything about that for now.

Among the changes here are:

General syntax:
- In the course of this I found out that the following code:
    [[ -nonexistentcondition foo ]]
  returns status 2, while
    [[ -nonexistentcondition foo ]] && stuff
  returns status 1, even though execution aborts at the non existent
  condition in both cases.  This is because the top-level loop for
  executing lists of commands doesn't abort on errors, although the
  functions it executes do.  I've noticed this before and not dared to
  change it because it apparently wasn't doing any harm.  Now it is,
  so I've changed it.  This didn't seem to cause any problems.

Features:
- Autoloading for features is persistent.  Hence if you
  unload a module the autoloads you previously set up will still
  be able to reload the module.
- The lists of autoloads and features allow better checking of
  autoload requests.  If an autoload is requested with the module
  already loaded, it's check immediately, otherwise when the
  module is loaded.  If a module is loaded and an autoload is found
  to be bogus, a warning is printed; however, the shell status is
  only affected if the autoload was the one that caused the module
  to be loaded.  This was the best compromise I could think of.
- I've also tried to sanitize error checking, error messages and
  the use of the -i flag for autoloads more generally.
- I've also tried to rationalize the behaviour when executing
  a module's boot or setup functions fails.  See descriptions in
  the code and Etc/zsh-development-guide.
- It was convenient to put modules in a hash table, which gives
  better features for manipulating them than a linked list.
- I've finally restored the behaviour of the old autoload syntax
  that it forced every feature in the module to be enabled.  Feature
  autoloads only cause the feature in question to be enabled on
  autoload.
- Previous patches left a bug that the wrong set of autoloads were
  compiled into the shell from some modules; I didn't unset
  autofeatures in the shell code before sourcing the module's
  .mdd file, which is now done.
- "zmodload -LF" and "zmodload -LFa" list all enabled features or
  all autoloaded features for all modules as zmodload statements.
- As features are listed in the order they're originally defined in the
  module, I've reordered them into alphabetical order and made a note
  in the development guide for people to ignore.

Other stuff
- Using modules in hash tables required either tightening up of
  the use of "const char *" in list/table utilities, or loosening it
  in modules.  I chose the former.  This hasn't spread much further
  than use of linked lists and hash tables.
- I've restored the use of dlerror() where available to module.c.
  I'm not sure how it escaped.

Maybe I'll finally get around to the horrible nested quotes in completion.

Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.96
diff -u -r1.96 builtins.yo
--- Doc/Zsh/builtins.yo	20 Jun 2007 20:59:17 -0000	1.96
+++ Doc/Zsh/builtins.yo	6 Jul 2007 20:57:44 -0000
@@ -1932,11 +1932,16 @@
 array of features, either features together with their state or (if
 tt(-L) alone is given) enabled features.
 
-A set of features may be provided together with tt(-l) or tt(-L); in
-that case only the state of features provided is considered.  Each
-feature may be preceded by tt(PLUS()) or tt(-) but the character
-has no effect.  If no set of features is provided, all features
-are considered.
+With the option tt(-L) the module name may be omitted; then a list
+of all enabled features for all modules providing features is printed
+in the form of tt(zmodload -F) commands.  If tt(-l) is also given,
+the state of both enabled and disabled features is output in that form.
+
+A set of features may be provided together with tt(-l) or tt(-L) and a
+module name; in that case only the state of those features is
+considered.  Each feature may be preceded by tt(PLUS()) or tt(-) but the
+character has no effect.  If no set of features is provided, all
+features are considered.
 
 With tt(-e), the command first tests that the module is loaded;
 if it is not, status 1 is returned.  If the module is loaded,
@@ -1947,11 +1952,31 @@
 in the list succeed, status 0 is returned, else status 1.
 
 With tt(-a), the given list of features is marked for autoload from
-the specified module, which may not be loaded.  An optional tt(PLUS())
+the specified module, which may not yet be loaded.  An optional tt(PLUS())
 may appear before the feature name.  If the feature is prefixed with
-tt(-), the existing autoload is deleted.  Note that only standard
-features as described above can be autoloaded; other features require
-the module to be loaded.
+tt(-), any existing autoload is removed.  The options tt(-l) and tt(-L)
+may be used to list autoloads.  Autoloading is specific to individual
+features; when the module is loaded only the requested feature is
+enabled.  Autoload requests are preserved if the module is
+subsequently unloaded until an explicit `tt(zmodload -Fa) var(module)
+tt(-)var(feature)' is issued.  It is not an error to request an autoload
+for a feature of a module that is already loaded.  
+
+When the module is loaded each autoload is checked against the features
+actually provided by the module; if the feature is not provided the
+autoload request is deleted.  A warning message is output; if the
+module is being loaded to provide a different feature, and that autoload
+is successful, there is no effect on the status of the current command.
+If the module is already loaded at the time when tt(zmodload -Fa) is
+run, an error message is printed and status 1 returned.
+
+tt(zmodload -Fa) can be used with the tt(-l), tt(-L), tt(-e) and
+tt(-P) options for listing and testing the existence of autoloadable
+features.  In this case tt(-l) is ignored if tt(-L) is specified.
+tt(zmodload -FaL) with no module name lists autoloads for all modules.
+
+Note that only standard features as described above can be autoloaded;
+other features require the module to be loaded before enabling.
 )
 xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) ])
 xitem(tt(zmodload) tt(-d) var(name) var(dep) ...)
@@ -1973,10 +1998,12 @@
 item(tt(zmodload) tt(-ub) [ tt(-i) ] var(builtin) ...)(
 The tt(-ab) option defines autoloaded builtins.  It defines the specified
 var(builtin)s.  When any of those builtins is called, the module specified
-in the first argument is loaded.  If only the var(name) is given, one
-builtin is defined, with the same name as the module.  tt(-i) suppresses
-the error if the builtin is already defined or autoloaded, regardless of
-which module it came from.
+in the first argument is loaded and all its features are enabled (for
+selective control of features use `tt(zmodload -F -a)' as described
+above).  If only the var(name) is given, one builtin is defined, with
+the same name as the module.  tt(-i) suppresses the error if the builtin
+is already defined or autoloaded, but not if another builtin of the
+same name is already defined.
 
 With tt(-ab) and no arguments, all autoloaded builtins are listed, with the
 module name (if different) shown in parentheses after the builtin name.
@@ -1987,6 +2014,9 @@
 previously defined with tt(-ab).  This is only possible if the builtin is
 not yet loaded.  tt(-i) suppresses the error if the builtin is already
 removed (or never existed).
+
+Autoload requests are retained if the module is subsequently unloaded
+until an explicit `tt(zmodload -ub) var(builtin)' is issued.
 )
 xitem(tt(zmodload) tt(-ac) [ tt(-IL) ])
 xitem(tt(zmodload) tt(-ac) [ tt(-iI) ] var(name) [ var(cond) ... ])
@@ -2021,12 +2051,12 @@
 item(tt(zmodload -e) [ tt(-A) ] [ var(string) ... ])(
 The tt(-e) option without arguments lists all loaded modules; if the tt(-A)
 option is also given, module aliases corresponding to loaded modules are
-also shown.  With arguments only the return status is set to zero
-if all var(string)s given as arguments are names of loaded modules
-and to one if at least on var(string) is not the name of a
-loaded module.  This can be used to test for the availability 
-of things implemented by modules.  In this case, any aliases are
-automatically resolved and the tt(-A) flag is not used.
+also shown.  If arguments are provided, nothing is printed;
+the return status is set to zero if all var(string)s given as arguments
+are names of loaded modules and to one if at least on var(string) is not
+the name of a loaded module.  This can be used to test for the
+availability of things implemented by modules.  In this case, any
+aliases are automatically resolved and the tt(-A) flag is not used.
 )
 item(tt(zmodload) tt(-A) [ tt(-L) ] [ var(modalias)[tt(=)var(module)] ... ])(
 For each argument, if both var(modalias) and var(module) are given,
Index: Etc/zsh-development-guide
===================================================================
RCS file: /cvsroot/zsh/zsh/Etc/zsh-development-guide,v
retrieving revision 1.13
diff -u -r1.13 zsh-development-guide
--- Etc/zsh-development-guide	29 May 2007 17:01:08 -0000	1.13
+++ Etc/zsh-development-guide	6 Jul 2007 20:57:44 -0000
@@ -218,7 +218,7 @@
 needed in the module, at least any data other modules may be interested
 in.
 
-The next pair are features_ and enables_ and deal with enabling module
+The next pair are `features_' and `enables_' and deal with enabling module
 features.  Ensure you are familiar with the description of features under
 `zmodload -F'.  The function features_ takes an argument `char
 ***featuresp'; *featuresp is to be set to a NULL-terminated array
@@ -235,8 +235,7 @@
 A structure "struct features" should
 be used to contain all standard features as well as the number of
 abstract features (those only understood by the module itself).
-It contains pointers to all builtins, conditions, parameters and
-conditions controlled by the module.
+See below.
 
 enables_ takes an argument `int **enablesp'.  If *enablesp is NULL, it
 should be set to an array of the same length as *featuresp without the
@@ -248,31 +247,44 @@
 present in the module's features structure; abstract features must be
 handled by the module (as with the features array, the area of the enables
 array for abstract features is not even initialised by the main shell).  As
-with features_, any handling of the array by the module itself should take
+with `features_', any handling of the array by the module itself should take
 into account that the array will not be freed and any allocation should
 therefore be from heap memory.
 
-The functions features_ and enables_ can be called at any point
-after setup_ has been called and before cleanup_ is called.  In
-particular they can be called before or after boot_.
+The functions `features_' and `enables_' can be called at any point
+after `setup_' has been called and before `cleanup_' is called.  In
+particular they can be called before or after `boot_'.
 
 The function named `boot_' should register function wrappers, hooks and
 anything that will be visible to the user that is not handled by features_
 and enables_ (so features should not be turned on here).  It will be called
 after the `setup_'-function, and also after the intial set of features
-have been set by calls to features_ and enables_.
+have been set by calls to `features_' and `enables_'.
 
 The function named `cleanup_', is called when the user tries to unload
 a module and should de-register all features and hooks.  A call
 to setfeatures with the final argument NULL will remove all standard
-features present in the module's features structure.
+features present in the module's features structure.  Note that
+`cleanup_' is called whenever `setup_' succeeded, so that `cleanup_'
+must be prepared to handle any state resulting from a failed `boot_'
+or initial call to `features_'.  Note also that a return code of 1
+from `cleanup_' will result in the module not being unloaded, so
+usually `cleanup_' will return 0 even if it has to handle an unclean
+state; if it does return 1, it must be prepared to be called again
+in a future attempt to unload.
 
 The last function, `finish_' is called when the module is actually unloaded
 and should finalize all the data initialized in the `setup_'-function.
+However, `finish_' is called even if `setup_' failed, so it should
+not rely on the module successfully being set up.
+The state from `finish_' module is currently ignored; it is called
+too late to prevent the module from being unloaded.
 
 In short, the `cleanup_'-function should undo what the `boot_'-function did
-(together with handling any residual effects of enables_), and the
-`finish_'-function should undo what the `setup_'-function did.
+(together with handling any residual effects of `enables_'), but should
+not rely on `boot_' having been successful, and the
+`finish_'-function should undo what the `setup_'-function did, but
+should not rely on `setup_' having been successful.
 
 All of these functions should return zero if they succeeded and
 non-zero otherwise.
@@ -302,6 +314,10 @@
     0, /* number of abstract features */
   }
 
+Within each individual table ("bintab", etc.), features should be listed
+in ASCII order as no further sorting is performed by the shell when
+features are listed.
+
 Abstract features are handled by the module; the number present
 in `struct features' is there to ensure the main shell allocated
 space in the features and enables array in the standard
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.179
diff -u -r1.179 builtin.c
--- Src/builtin.c	29 May 2007 17:01:08 -0000	1.179
+++ Src/builtin.c	6 Jul 2007 20:57:45 -0000
@@ -250,7 +250,7 @@
     name = (char *) ugetnode(args);
 
     if (!bn->handlerfunc) {
-	zwarnnam(name, "autoload failed");
+	DPUTS(1, "Missing builtin detected too late");
 	deletebuiltin(bn->node.nam);
 	return 1;
     }
Index: Src/cond.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/cond.c,v
retrieving revision 1.11
diff -u -r1.11 cond.c
--- Src/cond.c	29 May 2007 14:16:03 -0000	1.11
+++ Src/cond.c	6 Jul 2007 20:57:46 -0000
@@ -96,11 +96,7 @@
 	{
 	    char *modname = isset(REMATCHPCRE) ? "zsh/pcre" : "zsh/regex";
 	    sprintf(overridename = overridebuf, "-%s-match", modname+4);
-	    if (ensurefeature(modname, "c:", overridename+1)) {
-		zwarnnam(fromtest, "%s not available for regex",
-			 modname);
-		return 2;
-	    }
+	    (void)ensurefeature(modname, "c:", overridename+1);
 	    ctype = COND_MODI;
 	}
 	/*FALLTHROUGH*/
@@ -129,7 +125,7 @@
 	    if ((cd = getconddef((ctype == COND_MODI), name + 1, 1))) {
 		if (ctype == COND_MOD &&
 		    (l < cd->min || (cd->max >= 0 && l > cd->max))) {
-		    zwarnnam(fromtest, "unrecognized condition: `%s'", name);
+		    zwarnnam(fromtest, "unknown condition: -%s", name);
 		    return 2;
 		}
 		if (tracingcond)
@@ -139,13 +135,23 @@
 	    else {
 		char *s = strs[0];
 
+		if (overridename) {
+		    /*
+		     * Standard regex function not available: this
+		     * is a hard error.
+		     */
+		    zerrnam(fromtest, "%s not available for regex",
+			     overridename);
+		    return 2;
+		}
+
 		strs[0] = dupstring(name);
 		name = s;
 
 		if (name && name[0] == '-' &&
 		    (cd = getconddef(0, name + 1, 1))) {
 		    if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
-			zwarnnam(fromtest, "unrecognized condition: `%s'",
+			zwarnnam(fromtest, "unknown condition: -%s",
 				 name);
 			return 2;
 		    }
@@ -154,7 +160,7 @@
 		    return !cd->handler(strs, cd->condid);
 		} else {
 		    zwarnnam(fromtest,
-			     "unrecognized condition: `%s'",
+			     "unknown condition: -%s",
 			     name ? name : "<null>");
 		}
 	    }
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.117
diff -u -r1.117 exec.c
--- Src/exec.c	15 Jun 2007 10:20:35 -0000	1.117
+++ Src/exec.c	6 Jul 2007 20:57:47 -0000
@@ -871,7 +871,7 @@
     /* Loop over all sets of comands separated by newline, *
      * semi-colon or ampersand (`sublists').               */
     code = *state->pc++;
-    while (wc_code(code) == WC_LIST && !breaks && !retflag) {
+    while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) {
 	int donedebug;
 
 	ltype = WC_LIST_TYPE(code);
@@ -1915,6 +1915,34 @@
     }
 }
 
+/*
+ * Check if a builtin requires an autoload and if so
+ * deal with it.  This may return NULL.
+ */
+
+/**/
+static HashNode
+resolvebuiltin(const char *cmdarg, HashNode hn)
+{
+    if (!((Builtin) hn)->handlerfunc) {
+	/*
+	 * Ensure the module is loaded and the
+	 * feature corresponding to the builtin
+	 * is enabled.
+	 */
+	(void)ensurefeature(((Builtin) hn)->optstr, "b:",
+			    (hn->flags & BINF_AUTOALL) ? NULL :
+			    hn->nam);
+	hn = builtintab->getnode(builtintab, cmdarg);
+	if (!hn) {
+	    lastval = 1;
+	    zerr("unknown builtin: %s");
+	    return NULL;
+	}
+    }
+    return hn;
+}
+
 /**/
 static void
 execcmd(Estate state, int input, int output, int how, int last1)
@@ -2011,16 +2039,9 @@
 		is_builtin = 1;
 
 		/* autoload the builtin if necessary */
-		if (!((Builtin) hn)->handlerfunc) {
-		    /*
-		     * Ensure the module is loaded and the
-		     * feature corresponding to the builtin
-		     * is enabled.
-		     */
-		    (void)ensurefeature(((Builtin) hn)->optstr, "b:", hn->nam);
-		    hn = builtintab->getnode(builtintab, cmdarg);
-		}
-		assign = (hn && (hn->flags & BINF_MAGICEQUALS));
+		if (!(hn = resolvebuiltin(cmdarg, hn)))
+		    return;
+		assign = (hn->flags & BINF_MAGICEQUALS);
 		break;
 	    }
 	    cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
@@ -2233,10 +2254,8 @@
 		is_builtin = 1;
 
 		/* autoload the builtin if necessary */
-		if (!((Builtin) hn)->handlerfunc) {
-		    (void)ensurefeature(((Builtin) hn)->optstr, "b:", cmdarg);
-		    hn = builtintab->getnode(builtintab, cmdarg);
-		}
+		if (!(hn = resolvebuiltin(cmdarg, hn)))
+		    return;
 		break;
 	    }
 	    cflags &= ~BINF_BUILTIN & ~BINF_COMMAND;
@@ -4104,8 +4123,8 @@
 	wrap->module->wrapper--;
 
 	if (!wrap->module->wrapper &&
-	    (wrap->module->flags & MOD_UNLOAD))
-	    unload_module(wrap->module, NULL);
+	    (wrap->module->node.flags & MOD_UNLOAD))
+	    unload_module(wrap->module);
 
 	if (!cont)
 	    return;
Index: Src/hashtable.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hashtable.c,v
retrieving revision 1.25
diff -u -r1.25 hashtable.c
--- Src/hashtable.c	6 Feb 2007 21:47:54 -0000	1.25
+++ Src/hashtable.c	6 Jul 2007 20:57:48 -0000
@@ -78,7 +78,7 @@
 
 /**/
 mod_export unsigned
-hasher(char *str)
+hasher(const char *str)
 {
     unsigned hashval = 0, c;
 
@@ -223,7 +223,7 @@
 
 /**/
 mod_export HashNode
-gethashnode(HashTable ht, char *nam)
+gethashnode(HashTable ht, const char *nam)
 {
     unsigned hashval;
     HashNode hp;
@@ -247,7 +247,7 @@
 
 /**/
 mod_export HashNode
-gethashnode2(HashTable ht, char *nam)
+gethashnode2(HashTable ht, const char *nam)
 {
     unsigned hashval;
     HashNode hp;
@@ -267,7 +267,7 @@
 
 /**/
 mod_export HashNode
-removehashnode(HashTable ht, char *nam)
+removehashnode(HashTable ht, const char *nam)
 {
     unsigned hashval;
     HashNode hp, hq;
@@ -795,7 +795,7 @@
 
 /**/
 static HashNode
-removeshfuncnode(UNUSED(HashTable ht), char *nam)
+removeshfuncnode(UNUSED(HashTable ht), const char *nam)
 {
     HashNode hn;
     int signum;
@@ -1378,7 +1378,7 @@
 
 /**/
 static HashNode
-removenameddirnode(HashTable ht, char *nam)
+removenameddirnode(HashTable ht, const char *nam)
 {
     HashNode hn = removehashnode(ht, nam);
 
@@ -1453,7 +1453,7 @@
 
 /**/
 unsigned
-histhasher(char *str)
+histhasher(const char *str)
 {
     unsigned hashval = 0;
 
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.75
diff -u -r1.75 init.c
--- Src/init.c	29 May 2007 17:01:08 -0000	1.75
+++ Src/init.c	6 Jul 2007 20:57:48 -0000
@@ -701,7 +701,7 @@
 	    close(tmppipe[1]);
     }
 
-    (void)addhookdefs(argzero, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks));
+    (void)addhookdefs(NULL, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks));
 
     init_eprog();
 
@@ -769,7 +769,7 @@
     watch    = mkarray(NULL);
     psvar    = mkarray(NULL);
     module_path = mkarray(ztrdup(MODULE_DIR));
-    modules = znewlinklist();
+    modulestab = newmoduletable(17, "modules");
     linkedmodules = znewlinklist();
 
     /* Set default prompts */
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.57
diff -u -r1.57 jobs.c
--- Src/jobs.c	23 May 2007 11:21:16 -0000	1.57
+++ Src/jobs.c	6 Jul 2007 20:57:49 -0000
@@ -2147,7 +2147,7 @@
 
 /**/
 mod_export int
-getsignum(char *s)
+getsignum(const char *s)
 {
     int x, i;
 
@@ -2205,7 +2205,7 @@
 {
     char fname[20];
     HashNode hn;
-    HashNode (*getptr)(HashTable ht, char *name);
+    HashNode (*getptr)(HashTable ht, const char *name);
     int i;
     if (ignoredisable)
 	getptr = shfunctab->getnode2;
Index: Src/mkbltnmlst.sh
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/mkbltnmlst.sh,v
retrieving revision 1.8
diff -u -r1.8 mkbltnmlst.sh
--- Src/mkbltnmlst.sh	26 Jun 2007 19:38:34 -0000	1.8
+++ Src/mkbltnmlst.sh	6 Jul 2007 20:57:49 -0000
@@ -37,8 +37,7 @@
         echo "/* non-linked-in known module \`$x_mod' */"
 	linked=no
     esac
-    unset moddeps autobins autoinfixconds autoprefixconds autoparams
-    unset automathfuncs
+    unset moddeps autofeatures
     . $srcdir/../$modfile
     if test "x$autofeatures" != x; then
 	echo "  if (emulation == EMULATE_ZSH) {"
Index: Src/module.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/module.c,v
retrieving revision 1.33
diff -u -r1.33 module.c
--- Src/module.c	27 Jun 2007 13:56:11 -0000	1.33
+++ Src/module.c	6 Jul 2007 20:57:50 -0000
@@ -24,13 +24,16 @@
  * provided hereunder is on an "as is" basis, and Zoltán Hidvégi and the
  * Zsh Development Group have no obligation to provide maintenance,
  * support, updates, enhancements, or modifications.
- *
  */
 
 #include "zsh.mdh"
 #include "module.pro"
 
-/* List of linked-in modules. */
+/*
+ * List of linked-in modules.
+ * This is set up at boot and remains for the life of the shell;
+ * entries do not appear in "zmodload" listings.
+ */
 
 /**/
 LinkList linkedmodules;
@@ -40,19 +43,42 @@
 /**/
 char **module_path;
 
-/* List of modules */
+/* Hash of modules */
 
 /**/
-mod_export LinkList modules;
+mod_export HashTable modulestab;
 
 /*
  * Bit flags passed as the "flags" argument of a autofeaturefn_t.
+ * Used in other places, such as the final argument to
+ * do_module_features().
  */
 enum {
-    /* `-i' option: ignore errors pertaining to redefinitions */
-    AUTOFEAT_IGNORE = 0x0001,
+    /*
+     * `-i' option: ignore errors pertaining to redefinitions,
+     * or indicate to do_module_features() that it should be
+     * silent.
+     */
+    FEAT_IGNORE = 0x0001,
     /* If a condition, condition is infix rather than prefix */
-    AUTOFEAT_INFIX = 0x0002
+    FEAT_INFIX = 0x0002,
+    /*
+     * Enable all features in the module when autoloading.
+     * This is the traditional zmodload -a behaviour;
+     * zmodload -Fa only enables features explicitly marked for
+     * autoloading.
+     */
+    FEAT_AUTOALL = 0x0004,
+    /*
+     * Remove feature:  alternative to "-X:NAME" used if
+     * X is passed separately from NAME.
+     */
+    FEAT_REMOVE = 0x0008,
+    /*
+     * For do_module_features().  Check that any autoloads
+     * for the module are actually provided.
+     */
+    FEAT_CHECKAUTO = 0x0010
 };
 
 /*
@@ -65,7 +91,7 @@
  *
  * "flags" is a set of the bits above.
  *
- * The return value is 0 for success, a negative value for failure with no
+ * The return value is 0 for success, -1 for failure with no
  * message needed, and one of the following to indicate the calling
  * function should print a message:
  *
@@ -73,7 +99,199 @@
  * 2:  [feature]: no such [type]
  * 3:  [feature]: [type] is already defined
  */
-typedef int (*autofeaturefn_t)(char *module, char *feature, int flags);
+typedef int (*autofeaturefn_t)(const char *module, const char *feature,
+			       int flags);
+
+/* Bits in the second argument to find_module. */
+enum {
+    /*
+     * Resolve any aliases to the underlying module.
+     */
+    FINDMOD_ALIASP = 0x0001,
+    /*
+     * Create an element for the module in the list if
+     * it is not found.
+     */
+    FINDMOD_CREATE = 0x0002,
+};
+
+static void
+freemodulenode(HashNode hn)
+{
+    Module m = (Module) hn;
+
+    if (m->node.flags & MOD_ALIAS)
+	zsfree(m->u.alias);
+    zsfree(m->node.nam);
+    if (m->autoloads)
+	freelinklist(m->autoloads, freestr);
+    if (m->deps)
+	freelinklist(m->deps, freestr);
+    zfree(m, sizeof(*m));
+}
+
+/* flags argument to printmodulenode */
+enum {
+    /* -L flag, output zmodload commands */
+    PRINTMOD_LIST = 0x0001,
+    /* -e flag */
+    PRINTMOD_EXIST = 0x0002,
+    /* -A flag */
+    PRINTMOD_ALIAS = 0x0004,
+    /* -d flag */
+    PRINTMOD_DEPS = 0x0008,
+    /* -F flag */
+    PRINTMOD_FEATURES = 0x0010,
+    /* -l flag in combination with -L flag */
+    PRINTMOD_LISTALL = 0x0020,
+    /* -a flag */
+    PRINTMOD_AUTO = 0x0040
+};
+
+/* Scan function for printing module details */
+
+static void
+printmodulenode(HashNode hn, int flags)
+{
+    Module m = (Module)hn;
+    /*
+     * If we check for a module loaded under an alias, we
+     * need the name of the alias.  We can use it in other
+     * cases, too.
+     */
+    const char *modname = m->node.nam;
+
+    if (flags & PRINTMOD_DEPS) {
+	/*
+	 * Print the module's dependencies.
+	 */
+	LinkNode n;
+
+	if (!m->deps)
+	    return;
+
+	if (flags & PRINTMOD_LIST) {
+	    printf("zmodload -d ");
+	    if (modname[0] == '-')
+		fputs("-- ", stdout);
+	    quotedzputs(modname, stdout);
+	} else {
+	    nicezputs(modname, stdout);
+	    putchar(':');
+	}
+	for (n = firstnode(m->deps); n; incnode(n)) {
+	    putchar(' ');
+	    if (flags & PRINTMOD_LIST)
+		quotedzputs((char *) getdata(n), stdout);
+	    else
+		nicezputs((char *) getdata(n), stdout);
+	}
+    } else if (flags & PRINTMOD_EXIST) {
+	/*
+	 * Just print the module name, provided the module is
+	 * present under an alias or otherwise.
+	 */
+	if (m->node.flags & MOD_ALIAS) {
+	    if (!(flags & PRINTMOD_ALIAS) ||
+		!(m = find_module(m->u.alias, FINDMOD_ALIASP, NULL)))
+		return;
+	}
+	if (!m->u.handle || (m->node.flags & MOD_UNLOAD))
+	    return;
+	nicezputs(modname, stdout);
+   } else if (m->node.flags & MOD_ALIAS) {
+	/*
+	 * Normal listing, but for aliases.
+	 */
+	if (flags & PRINTMOD_LIST) {
+	    printf("zmodload -A ");
+	    if (modname[0] == '-')
+		fputs("-- ", stdout);
+	    quotedzputs(modname, stdout);
+	    putchar('=');
+	    quotedzputs(m->u.alias, stdout);
+	} else {
+	    nicezputs(modname, stdout);
+	    fputs(" -> ", stdout);
+	    nicezputs(m->u.alias, stdout);
+	}
+    } else if (m->u.handle) {
+	/*
+	 * Loaded module.
+	 */
+	if (flags & PRINTMOD_LIST) {
+	    /*
+	     * List with -L format.  Possibly we are printing
+	     * features, either enables or autoloads.
+	     */
+	    char **features = NULL;
+	    int *enables = NULL;
+	    if (flags & PRINTMOD_AUTO) {
+		if (!m->autoloads || !firstnode(m->autoloads))
+		    return;
+	    } else if (flags & PRINTMOD_FEATURES) {
+		if (features_module(m, &features) ||
+		    enables_module(m, &enables) ||
+		    !*features)
+		    return;
+	    }
+	    printf("zmodload ");
+	    if (flags & PRINTMOD_AUTO) {
+		fputs("-Fa ", stdout);
+	    } else if (features)
+		fputs("-F ", stdout);
+	    if(modname[0] == '-')
+		fputs("-- ", stdout);
+	    quotedzputs(modname, stdout);
+	    if (flags & PRINTMOD_AUTO) {
+		LinkNode an;
+		for (an = firstnode(m->autoloads); an; incnode(an)) {
+		    putchar(' ');
+		    quotedzputs((char *)getdata(an), stdout);
+		}
+	    } else if (features) {
+		const char *f;
+		while ((f = *features++)) {
+		    int on = *enables++;
+		    if (flags & PRINTMOD_LISTALL)
+			printf(" %s", on ? "+" : "-");
+		    else if (!on)
+			continue;
+		    else
+			putchar(' ');
+		    quotedzputs(f, stdout);
+		}
+	    }
+	} else /* -l */
+	    nicezputs(modname, stdout);
+    } else
+	return;
+    putchar('\n');
+}
+
+/**/
+HashTable
+newmoduletable(int size, char const *name)
+{
+    HashTable ht;
+    ht = newhashtable(size, name, NULL);
+
+    ht->hash        = hasher;
+    ht->emptytable  = emptyhashtable;
+    ht->filltable   = NULL;
+    ht->cmpnodes    = strcmp;
+    ht->addnode     = addhashnode;
+    /* DISABLED is not supported */
+    ht->getnode     = gethashnode2;
+    ht->getnode2    = gethashnode2;
+    ht->removenode  = removehashnode;
+    ht->disablenode = NULL;
+    ht->enablenode  = NULL;
+    ht->freenode    = freemodulenode;
+    ht->printnode   = printmodulenode;
+
+    return ht;
+}
 
 /************************************************************************
  * zsh/main standard module functions
@@ -160,27 +378,6 @@
     zaddlinknode(linkedmodules, m);
 }
 
-/* Print an alias. */
-
-/**/
-static void
-printmodalias(Module m, Options ops)
-{
-    if (OPT_ISSET(ops,'L')) {
-	printf("zmodload -A ");
-	if (m->nam[0] == '-')
-	    fputs("-- ", stdout);
-	quotedzputs(m->nam, stdout);
-	putchar('=');
-	quotedzputs(m->u.alias, stdout);
-    } else {
-	nicezputs(m->nam, stdout);
-	fputs(" -> ", stdout);
-	nicezputs(m->u.alias, stdout);
-    }
-    putchar('\n');
-}
-
 /* Check if a module is linked in. */
 
 /**/
@@ -208,7 +405,7 @@
  * builtin can be replaced using this function.                       */
 
 /**/
-int
+static int
 addbuiltin(Builtin b)
 {
     Builtin bn = (Builtin) builtintab->getnode2(builtintab, b->node.nam);
@@ -226,16 +423,19 @@
 
 /**/
 static int
-add_autobin(char *module, char *bnam, int flags)
+add_autobin(const char *module, const char *bnam, int flags)
 {
     Builtin bn;
+    int ret;
 
     bn = zshcalloc(sizeof(*bn));
     bn->node.nam = ztrdup(bnam);
     bn->optstr = ztrdup(module);
-    if (addbuiltin(bn)) {
+    if (flags & FEAT_AUTOALL)
+	bn->node.flags |= BINF_AUTOALL;
+    if ((ret = addbuiltin(bn))) {
 	builtintab->freenode(&bn->node);
-	if (!(flags & AUTOFEAT_IGNORE))
+	if (!(flags & FEAT_IGNORE))
 	    return 1;
     }
     return 0;
@@ -246,7 +446,7 @@
 
 /**/
 int
-deletebuiltin(char *nam)
+deletebuiltin(const char *nam)
 {
     Builtin bn;
 
@@ -261,14 +461,15 @@
 
 /**/
 static int
-del_autobin(UNUSED(char *module), char *bnam, int flags)
+del_autobin(UNUSED(const char *module), const char *bnam, int flags)
 {
     Builtin bn = (Builtin) builtintab->getnode2(builtintab, bnam);
     if (!bn) {
-	if(!(flags & AUTOFEAT_IGNORE))
+	if(!(flags & FEAT_IGNORE))
 	    return 2;
     } else if (bn->node.flags & BINF_ADDED) {
-	return 3;
+	if (!(flags & FEAT_IGNORE))
+	    return 3;
     } else
 	deletebuiltin(bnam);
 
@@ -383,7 +584,7 @@
      * happen since we usually add wrappers when a real module is
      * loaded.
      */
-    if (m->flags & MOD_ALIAS)
+    if (m->node.flags & MOD_ALIAS)
 	return 1;
 
     if (w->flags & WRAPF_ADDED)
@@ -409,7 +610,7 @@
 {
     FuncWrap p, q;
 
-    if (m->flags & MOD_ALIAS)
+    if (m->node.flags & MOD_ALIAS)
 	return 1;
 
     if (w->flags & WRAPF_ADDED) {
@@ -444,7 +645,7 @@
 
 /**/
 Conddef
-getconddef(int inf, char *name, int autol)
+getconddef(int inf, const char *name, int autol)
 {
     Conddef p;
     int f = 1;
@@ -462,8 +663,8 @@
 	     */
 	    if (f) {
 		(void)ensurefeature(p->module,
-				    (p->flags & CONDF_INFIX) ?
-				    "C:" : "c:", name);
+				    (p->flags & CONDF_INFIX) ? "C:" : "c:",
+				    (p->flags & CONDF_AUTOALL) ? NULL : name);
 		f = 0;
 		p = NULL;
 	    } else {
@@ -577,14 +778,16 @@
 
 /**/
 static int
-add_autocond(char *module, char *cnam, int flags)
+add_autocond(const char *module, const char *cnam, int flags)
 {
     Conddef c;
 
     c = (Conddef) zalloc(sizeof(*c));
 
     c->name = ztrdup(cnam);
-    c->flags = ((flags & AUTOFEAT_INFIX) ? CONDF_INFIX : 0);
+    c->flags = ((flags & FEAT_INFIX) ? CONDF_INFIX : 0);
+    if (flags & FEAT_AUTOALL)
+	c->flags |= CONDF_AUTOALL;
     c->module = ztrdup(module);
 
     if (addconddef(c)) {
@@ -592,7 +795,7 @@
 	zsfree(c->module);
 	zfree(c, sizeof(*c));
 
-	if (!(flags & AUTOFEAT_IGNORE))
+	if (!(flags & FEAT_IGNORE))
 	    return 1;
     }
     return 0;
@@ -602,16 +805,17 @@
 
 /**/
 static int
-del_autocond(UNUSED(char *modnam), char *cnam, int flags)
+del_autocond(UNUSED(const char *modnam), const char *cnam, int flags)
 {
-    Conddef cd = getconddef((flags & AUTOFEAT_INFIX) ? 1 : 0, cnam, 0);
+    Conddef cd = getconddef((flags & FEAT_INFIX) ? 1 : 0, cnam, 0);
 
     if (!cd) {
-	if (!(flags & AUTOFEAT_IGNORE)) {
+	if (!(flags & FEAT_IGNORE)) {
 	    return 2;
 	}
     } else if (cd->flags & CONDF_ADDED) {
-	return 3;
+	if (!(flags & FEAT_IGNORE))
+	    return 3;
     } else
 	deleteconddef(cd);
 
@@ -658,17 +862,21 @@
     return 0;
 }
 
-/* This adds multiple hook definitions. This is like addbuiltins(). */
+/*
+ * This adds multiple hook definitions. This is like addbuiltins().
+ * This allows a NULL module because we call it from init.c.
+ */
 
 /**/
 mod_export int
-addhookdefs(char const *nam, Hookdef h, int size)
+addhookdefs(Module m, Hookdef h, int size)
 {
     int ret = 0;
 
     while (size--) {
 	if (addhookdef(h)) {
-	    zwarnnam(nam, "name clash when adding hook `%s'", h->name);
+	    zwarnnam(m ? m->node.nam : NULL,
+		     "name clash when adding hook `%s'", h->name);
 	    ret = 1;
 	}
 	h++;
@@ -701,7 +909,7 @@
 
 /**/
 mod_export int
-deletehookdefs(UNUSED(char const *nam), Hookdef h, int size)
+deletehookdefs(UNUSED(Module m), Hookdef h, int size)
 {
     int ret = 0;
 
@@ -804,7 +1012,7 @@
  */
 
 static int
-checkaddparam(char *nam, int opt_i)
+checkaddparam(const char *nam, int opt_i)
 {
     Param pm;
 
@@ -970,13 +1178,13 @@
 
 /**/
 static int
-add_autoparam(char *module, char *pnam, int flags)
+add_autoparam(const char *module, const char *pnam, int flags)
 {
     Param pm;
     int ret;
 
     queue_signals();
-    if ((ret = checkaddparam(pnam, (flags & AUTOFEAT_IGNORE)))) {
+    if ((ret = checkaddparam(pnam, (flags & FEAT_IGNORE)))) {
 	unqueue_signals();
 	/*
 	 * checkaddparam() has already printed a message if one was
@@ -988,9 +1196,11 @@
 	return ret == 2 ? 0 : -1;
     }
 
-    pm = setsparam(pnam, ztrdup(module));
+    pm = setsparam(dupstring(pnam), ztrdup(module));
 
     pm->node.flags |= PM_AUTOLOAD;
+    if (flags & FEAT_AUTOALL)
+	pm->node.flags |= PM_AUTOALL;
     unqueue_signals();
 
     return 0;
@@ -1000,15 +1210,16 @@
 
 /**/
 static int
-del_autoparam(UNUSED(char *modnam), char *pnam, int flags)
+del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags)
 {
     Param pm = (Param) gethashnode2(paramtab, pnam);
 
     if (!pm) {
-	if (!(flags & AUTOFEAT_IGNORE))
+	if (!(flags & FEAT_IGNORE))
 	    return 2;
     } else if (!(pm->node.flags & PM_AUTOLOAD)) {
-	return 3;
+	if (!(flags & FEAT_IGNORE))
+	    return 3;
     } else
 	unsetparam_pm(pm, 0, 1);
 
@@ -1047,7 +1258,7 @@
 
 /**/
 MathFunc
-getmathfunc(char *name, int autol)
+getmathfunc(const char *name, int autol)
 {
     MathFunc p, q = NULL;
 
@@ -1058,7 +1269,8 @@
 
 		removemathfunc(q, p);
 
-		(void)ensurefeature(n, "f:", name);
+		(void)ensurefeature(n, "f:", (p->flags & MFF_AUTOALL) ? NULL :
+				    name);
 
 		return getmathfunc(name, 0);
 	    }
@@ -1171,7 +1383,7 @@
 
 /**/
 static int
-add_automathfunc(char *module, char *fnam, int flags)
+add_automathfunc(const char *module, const char *fnam, int flags)
 {
     MathFunc f;
 
@@ -1186,7 +1398,7 @@
 	zsfree(f->module);
 	zfree(f, sizeof(*f));
 
-	if (!(flags & AUTOFEAT_IGNORE))
+	if (!(flags & FEAT_IGNORE))
 	    return 1;
     }
 
@@ -1197,15 +1409,16 @@
 
 /**/
 static int
-del_automathfunc(UNUSED(char *modnam), char *fnam, int flags)
+del_automathfunc(UNUSED(const char *modnam), const char *fnam, int flags)
 {
     MathFunc f = getmathfunc(fnam, 0);
     
     if (!f) {
-	if (!(flags & AUTOFEAT_IGNORE))
+	if (!(flags & FEAT_IGNORE))
 	    return 2;
     } else if (f->flags & MFF_ADDED) {
-	return 3;
+	if (!(flags & FEAT_IGNORE))
+	    return 3;
     } else
 	deletemathfunc(f);
 
@@ -1233,13 +1446,15 @@
     void *ret = (void *) load((char *) fn, L_NOAUTODEFER, NULL);
 
     if (ret) {
-	LinkNode node;
-	int err = loadbind(0, (void *) addbuiltin, ret);
-	for (node = firstnode(modules); !err && node; incnode(node)) {
-	    Module m = (Module) getdata(node);
-	    if (!(m->flags & MOD_ALIAS) &&
-		m->u.handle && !(m->flags & MOD_LINKED))
-		err |= loadbind(0, m->u.handle, ret);
+	Module m;
+	int i, err = loadbind(0, (void *) addbuiltin, ret);
+	for (i = 0; i < modulestab->hsize && !err; i++) {
+	    for (m = (Module)modulestab->nodes[i]; m && !err;
+		 m = m->node.next) {
+		if (!(m->flags & MOD_ALIAS) &&
+		    m->u.handle && !(m->flags & MOD_LINKED))
+		    err |= loadbind(0, m->u.handle, ret);
+	    }
 	}
 
 	if (err) {
@@ -1256,6 +1471,9 @@
 #define dlopen(X,Y) load_and_bind(X)
 #define dlclose(X)  unload(X)
 #define dlerror()   (dlerrstr[0])
+#ifndef HAVE_DLERROR
+# define HAVE_DLERROR 1
+#endif
 
 /**/
 #else
@@ -1294,7 +1512,9 @@
 }
 
 # define dlsym(handle,name) hpux_dlsym(handle,name)
-# define dlerror() 0
+# ifdef HAVE_DLERROR		/* paranoia */
+#  undef HAVE_DLERROR
+# endif
 #else
 # ifndef HAVE_DLCLOSE
 #  define dlclose(X) ((X), 0)
@@ -1366,8 +1586,13 @@
     void *ret;
 
     ret = try_load_module(name);
-    if (!ret && !silent)
+    if (!ret && !silent) {
+#ifdef HAVE_DLERROR
+	zwarn("failed to load module `%s': %s", name, dlerror());
+#else
 	zwarn("failed to load module: %s", name);
+#endif
+    }
     return ret;
 }
 
@@ -1391,19 +1616,6 @@
 /**/
 #endif /* !DYNAMIC */
 
-/* Bits in the second argument to find_module. */
-enum {
-    /*
-     * Resolve any aliases to the underlying module.
-     */
-    FINDMOD_ALIASP = 0x0001,
-    /*
-     * Create an element for the module in the list if
-     * it is not found.
-     */
-    FINDMOD_CREATE = 0x0002,
-};
-
 /*
  * Find a module in the list.
  * flags is a set of bits defined in the enum above.
@@ -1413,35 +1625,29 @@
  * Return NULL if the module named is not stored as a structure, or if we were
  * resolving aliases and the final module named is not stored as a
  * structure.
- *
- * TODO: now we have aliases, there may be some merit in using a hash
- * table instead of a linked list.
  */
 /**/
-static LinkNode
+static Module
 find_module(const char *name, int flags, const char **namep)
 {
     Module m;
-    LinkNode node;
 
-    for (node = firstnode(modules); node; incnode(node)) {
-	m = (Module) getdata(node);
-	if (!strcmp(m->nam, name)) {
-	    if ((flags & FINDMOD_ALIASP) && (m->flags & MOD_ALIAS)) {
-		if (namep)
-		    *namep = m->u.alias;
-		return find_module(m->u.alias, flags, namep);
-	    }
+    m = (Module)modulestab->getnode2(modulestab, name);
+    if (m) {
+	if ((flags & FINDMOD_ALIASP) && (m->node.flags & MOD_ALIAS)) {
 	    if (namep)
-		*namep = m->nam;
-	    return node;
+		*namep = m->u.alias;
+	    return find_module(m->u.alias, flags, namep);
 	}
+	if (namep)
+	    *namep = m->node.nam;
+	return m;
     }
     if (!(flags & FINDMOD_CREATE))
 	return NULL;
     m = zshcalloc(sizeof(*m));
-    m->nam = ztrdup(name);
-    return zaddlinknode(modules, m);
+    modulestab->addnode(modulestab, ztrdup(name), m);
+    return m;
 }
 
 /*
@@ -1450,16 +1656,11 @@
 
 /**/
 static void
-delete_module(LinkNode node)
+delete_module(Module m)
 {
-    Module m = (Module) remnode(modules, node);
+    modulestab->removenode(modulestab, m->node.nam);
 
-    if (m->flags & MOD_ALIAS)
-	zsfree(m->u.alias);
-    zsfree(m->nam);
-    if (m->deps)
-	freelinklist(m->deps, freestr);
-    zfree(m, sizeof(*m));
+    modulestab->freenode(&m->node);
 }
 
 /*
@@ -1473,12 +1674,11 @@
 mod_export int
 module_loaded(const char *name)
 {
-    LinkNode node;
     Module m;
 
-    return ((node = find_module(name, FINDMOD_ALIASP, NULL)) &&
-	    (m = ((Module) getdata(node)))->u.handle &&
-	    !(m->flags & MOD_UNLOAD));
+    return ((m = find_module(name, FINDMOD_ALIASP, NULL)) &&
+	    m->u.handle &&
+	    !(m->node.flags & MOD_UNLOAD));
 }
 
 /*
@@ -1575,7 +1775,7 @@
 
     if (fn)
 	return fn(m);
-    zwarnnam(m->nam, "no setup function");
+    zwarnnam(m->node.nam, "no setup function");
     return 1;
 }
 
@@ -1612,7 +1812,7 @@
 
     if(fn)
 	return fn(m);
-    zwarnnam(m->nam, "no boot function");
+    zwarnnam(m->node.nam, "no boot function");
     return 1;
 }
 
@@ -1624,7 +1824,7 @@
 
     if(fn)
 	return fn(m);
-    zwarnnam(m->nam, "no cleanup function");
+    zwarnnam(m->node.nam, "no cleanup function");
     return 1;
 }
 
@@ -1641,7 +1841,7 @@
     if (fn)
 	r = fn(m);
     else {
-	zwarnnam(m->nam, "no finish function");
+	zwarnnam(m->node.nam, "no finish function");
 	r = 1;
     }
     dlclose(m->u.handle);
@@ -1655,7 +1855,7 @@
 static int
 setup_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->setup)(m) : dyn_setup_module(m));
 }
 
@@ -1663,7 +1863,7 @@
 static int
 features_module(Module m, char ***features)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->features)(m, features) :
 	    dyn_features_module(m, features));
 }
@@ -1672,7 +1872,7 @@
 static int
 enables_module(Module m, int **enables)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->enables)(m, enables) :
 	    dyn_enables_module(m, enables));
 }
@@ -1681,7 +1881,7 @@
 static int
 boot_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->boot)(m) : dyn_boot_module(m));
 }
 
@@ -1689,7 +1889,7 @@
 static int
 cleanup_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->cleanup)(m) : dyn_cleanup_module(m));
 }
 
@@ -1697,7 +1897,7 @@
 static int
 finish_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ?
+    return ((m->node.flags & MOD_LINKED) ?
 	    (m->u.linked->finish)(m) : dyn_finish_module(m));
 }
 
@@ -1708,14 +1908,14 @@
 static int
 setup_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1);
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1);
 }
 
 /**/
 static int
 features_module(Module m, char ***features)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->features)(m, features)
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->features)(m, features)
 	    : 1);
 }
 
@@ -1723,7 +1923,7 @@
 static int
 enables_module(Module m, int **enables)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables)
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables)
 	    : 1);
 }
 
@@ -1731,21 +1931,21 @@
 static int
 boot_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1);
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->boot)(m) : 1);
 }
 
 /**/
 static int
 cleanup_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1);
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->cleanup)(m) : 1);
 }
 
 /**/
 static int
 finish_module(Module m)
 {
-    return ((m->flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1);
+    return ((m->node.flags & MOD_LINKED) ? (m->u.linked->finish)(m) : 1);
 }
 
 /**/
@@ -1761,14 +1961,16 @@
  * by now (though may not be fully set up).
  *
  * Return 0 for success, 1 for failure, 2 if some features
- * couldn't be set.
+ * couldn't be set by the module itself (non-existent features
+ * are tested here and cause 1 to be returned).
  */
 
 /**/
 static int
-do_module_features(Module m, char **enablesstr, int silent)
+do_module_features(Module m, char **enablesstr, int flags)
 {
     char **features;
+    int ret = 0;
 
     if (features_module(m, &features) == 0) {
 	/*
@@ -1781,12 +1983,62 @@
 	int *enables = NULL;
 	if (enables_module(m, &enables)) {
 	    /* If features are supported, enables should be, too */
-	    if (!silent)
+	    if (!(flags & FEAT_IGNORE))
 		zwarn("error getting enabled features for module `%s'",
-		      m->nam);
+		      m->node.nam);
 	    return 1;
 	}
 
+	if ((flags & FEAT_CHECKAUTO) && m->autoloads) {
+	    /*
+	     * Check autoloads are available.  Since these
+	     * have been requested at some other point, they
+	     * don't affect the return status unless something
+	     * in enablesstr doesn't work.
+	     */
+	    LinkNode an, nextn;
+	    for (an = firstnode(m->autoloads); an; an = nextn) {
+		char *al = (char *)getdata(an), **ptr;
+		/* careful, we can delete the current node */
+		nextn = nextnode(an);
+		for (ptr = features; *ptr; ptr++)
+		    if (!strcmp(al, *ptr))
+			break;
+		if (!*ptr) {
+		    char *arg[2];
+		    if (!(flags & FEAT_IGNORE))
+			zwarn(
+		    "module `%s' has no such feature: `%s': autoload cancelled",
+		    m->node.nam, al);
+		    /*
+		     * This shouldn't happen, so it's not worth optimising
+		     * the call to autofeatures...
+		     */
+		    arg[0] = al = dupstring(al);
+		    arg[1] = NULL;
+		    (void)autofeatures(NULL, m->node.nam, arg, 0,
+				       FEAT_IGNORE|FEAT_REMOVE);
+		    /*
+		     * don't want to try to enable *that*... 
+		     * expunge it from the enable string.
+		     */
+		    if (enablesstr) {
+			for (ptr = enablesstr; *ptr; ptr++) {
+			    if (!strcmp(al, *ptr)) {
+				/* can't enable it after all, so return 1 */
+				ret = 1;
+				while (*ptr) {
+				    *ptr = ptr[1];
+				    ptr++;
+				}
+				break;
+			    }
+			}
+		    }
+		}
+	    }
+	}
+
 	if (enablesstr) {
 	    char **ep;
 	    for (ep = enablesstr; *ep; ep++) {
@@ -1804,9 +2056,9 @@
 			break;
 		    }
 		if (!*fp) {
-		    if (!silent)
-			zwarn("module `%s' has no such feature: %s",
-			      m->nam, esp);
+		    if (!(flags & FEAT_IGNORE))
+			zwarn("module `%s' has no such feature: `%s'",
+			      m->node.nam, esp);
 		    return 1;
 		}
 	    }
@@ -1824,13 +2076,13 @@
 	if (enables_module(m, &enables))
 	    return 2;
     } else if (enablesstr) {
-	if (!silent)
-	    zwarn("module `%s' does not support features", m->nam);
+	if (!(flags & FEAT_IGNORE))
+	    zwarn("module `%s' does not support features", m->node.nam);
 	return 1;
     }
     /* Else it doesn't support features but we don't care. */
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -1847,7 +2099,9 @@
 static int
 do_boot_module(Module m, char **enablesstr, int silent)
 {
-    int ret = do_module_features(m, enablesstr, silent);
+    int ret = do_module_features(m, enablesstr,
+				 silent ? FEAT_IGNORE|FEAT_CHECKAUTO :
+				 FEAT_CHECKAUTO);
 
     if (ret == 1)
 	return 1;
@@ -1865,7 +2119,7 @@
 static int
 do_cleanup_module(Module m)
 {
-    return (m->flags & MOD_LINKED) ?
+    return (m->node.flags & MOD_LINKED) ?
 	(m->u.linked && m->u.linked->cleanup(m)) :
 	(m->u.handle && cleanup_module(m));
 }
@@ -1910,7 +2164,6 @@
     Module m;
     void *handle = NULL;
     Linkedmod linked;
-    LinkNode node, n;
     int set, bootret;
 
     if (!modname_ok(name)) {
@@ -1924,66 +2177,65 @@
      * is the right one.
      */
     queue_signals();
-    if (!(node = find_module(name, FINDMOD_ALIASP, &name))) {
+    if (!(m = find_module(name, FINDMOD_ALIASP, &name))) {
 	if (!(linked = module_linked(name)) &&
 	    !(handle = do_load_module(name, silent))) {
 	    unqueue_signals();
 	    return 1;
 	}
 	m = zshcalloc(sizeof(*m));
-	m->nam = ztrdup(name);
 	if (handle) {
 	    m->u.handle = handle;
-	    m->flags |= MOD_SETUP;
+	    m->node.flags |= MOD_SETUP;
 	} else {
 	    m->u.linked = linked;
-	    m->flags |= MOD_SETUP | MOD_LINKED;
+	    m->node.flags |= MOD_SETUP | MOD_LINKED;
 	}
-	node = zaddlinknode(modules, m);
+	modulestab->addnode(modulestab, ztrdup(name), m);
 
 	if ((set = setup_module(m)) ||
 	    (bootret = do_boot_module(m, enablesstr, silent)) == 1) {
-	    if (!set) {
+	    if (!set)
 		do_cleanup_module(m);
-		finish_module(m);
-	    }
-	    delete_module(node);
+	    finish_module(m);
+	    delete_module(m);
 	    unqueue_signals();
 	    return 1;
 	}
-	m->flags |= MOD_INIT_S | MOD_INIT_B;
-	m->flags &= ~MOD_SETUP;
+	m->node.flags |= MOD_INIT_S | MOD_INIT_B;
+	m->node.flags &= ~MOD_SETUP;
 	unqueue_signals();
 	return bootret;
     }
-    m = (Module) getdata(node);
-    if (m->flags & MOD_SETUP) {
+    if (m->node.flags & MOD_SETUP) {
 	unqueue_signals();
 	return 0;
     }
-    if (m->flags & MOD_UNLOAD)
-	m->flags &= ~MOD_UNLOAD;
-    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
+    if (m->node.flags & MOD_UNLOAD)
+	m->node.flags &= ~MOD_UNLOAD;
+    else if ((m->node.flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
 	unqueue_signals();
 	return 0;
     }
-    if (m->flags & MOD_BUSY) {
-	zerr("circular dependencies for module %s", name);
+    if (m->node.flags & MOD_BUSY) {
+	zerr("circular dependencies for module ;%s", name);
 	return 1;
     }
-    m->flags |= MOD_BUSY;
+    m->node.flags |= MOD_BUSY;
     /*
      * TODO: shouldn't we unload the module if one of
      * its dependencies fails?
      */
-    if (m->deps)
+    if (m->deps) {
+	LinkNode n;
 	for (n = firstnode(m->deps); n; incnode(n))
 	    if (load_module((char *) getdata(n), NULL, silent) == 1) {
-		m->flags &= ~MOD_BUSY;
+		m->node.flags &= ~MOD_BUSY;
 		unqueue_signals();
 		return 1;
 	    }
-    m->flags &= ~MOD_BUSY;
+    }
+    m->node.flags &= ~MOD_BUSY;
     if (!m->u.handle) {
 	handle = NULL;
 	if (!(linked = module_linked(name)) &&
@@ -1993,36 +2245,37 @@
 	}
 	if (handle) {
 	    m->u.handle = handle;
-	    m->flags |= MOD_SETUP;
+	    m->node.flags |= MOD_SETUP;
 	} else {
 	    m->u.linked = linked;
-	    m->flags |= MOD_SETUP | MOD_LINKED;
+	    m->node.flags |= MOD_SETUP | MOD_LINKED;
 	}
 	if (setup_module(m)) {
+	    finish_module(m);
 	    if (handle)
 		m->u.handle = NULL;
 	    else
 		m->u.linked = NULL;
-	    m->flags &= ~MOD_SETUP;
+	    m->node.flags &= ~MOD_SETUP;
 	    unqueue_signals();
 	    return 1;
 	}
-	m->flags |= MOD_INIT_S;
+	m->node.flags |= MOD_INIT_S;
     }
-    m->flags |= MOD_SETUP;
+    m->node.flags |= MOD_SETUP;
     if ((bootret = do_boot_module(m, enablesstr, silent)) == 1) {
 	do_cleanup_module(m);
 	finish_module(m);
-	if (m->flags & MOD_LINKED)
+	if (m->node.flags & MOD_LINKED)
 	    m->u.linked = NULL;
 	else
 	    m->u.handle = NULL;
-	m->flags &= ~MOD_SETUP;
+	m->node.flags &= ~MOD_SETUP;
 	unqueue_signals();
 	return 1;
     }
-    m->flags |= MOD_INIT_B;
-    m->flags &= ~MOD_SETUP;
+    m->node.flags |= MOD_INIT_B;
+    m->node.flags &= ~MOD_SETUP;
     unqueue_signals();
     return bootret;
 }
@@ -2030,7 +2283,8 @@
 /* This ensures that the module with the name given as the first argument
  * is loaded.
  * The other argument is the array of features to set.  If this is NULL
- * and the module needs to be loaded, all features are enabled.
+ * all features are enabled (even if the module was already loaded).
+ *
  * If this is non-NULL the module features are set accordingly
  * whether or not the module is loaded; it is an error if the
  * module does not support the features passed (even if the feature
@@ -2050,14 +2304,13 @@
 require_module(const char *module, char **features)
 {
     Module m = NULL;
-    LinkNode node;
     int ret = 0;
 
     /* Resolve aliases and actual loadable module as for load_module */
     queue_signals();
-    node = find_module(module, 1, &module);
-    if (!node || !(m = ((Module) getdata(node)))->u.handle ||
-	(m->flags & MOD_UNLOAD))
+    m = find_module(module, FINDMOD_ALIASP, &module);
+    if (!m || !m->u.handle ||
+	(m->node.flags & MOD_UNLOAD))
 	ret = load_module(module, features, 0);
     else
 	ret = do_module_features(m, features, 0);
@@ -2090,7 +2343,7 @@
      * Better make sure.  (There's no problem making a an alias which
      * *points* to a module with dependencies, of course.)
      */
-    m = getdata(find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name));
+    m = find_module(name, FINDMOD_ALIASP|FINDMOD_CREATE, &name);
     if (!m->deps)
 	m->deps = znewlinklist();
     for (node = firstnode(m->deps);
@@ -2179,7 +2432,8 @@
 	return 1;
     }
     if (OPT_ISSET(ops,'e') && (OPT_ISSET(ops,'I') || OPT_ISSET(ops,'L') || 
-			       OPT_ISSET(ops,'a') || OPT_ISSET(ops,'d') ||
+			       (OPT_ISSET(ops,'a') && !OPT_ISSET(ops,'F'))
+			       || OPT_ISSET(ops,'d') ||
 			       OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) {
 	zwarnnam(nam, "-e cannot be combined with other options");
 	/* except -F ... */
@@ -2233,7 +2487,6 @@
      * suppose other names are aliased to the same file?  It might be
      * kettle of fish best left unwormed.
      */
-    LinkNode node;
     Module m;
 
     if (!*args) {
@@ -2241,11 +2494,9 @@
 	    zwarnnam(nam, "no module alias to remove");
 	    return 1;
 	}
-	for (node = firstnode(modules); node; incnode(node)) {
-	    m = (Module) getdata(node);
-	    if (m->flags & MOD_ALIAS)
-		printmodalias(m, ops);
-	}
+	scanhashtable(modulestab, 1, MOD_ALIAS, 0,
+		      modulestab->printnode,
+		      OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
 	return 0;
     }
 
@@ -2264,14 +2515,13 @@
 			 *args);
 		return 1;
 	    }
-	    node = find_module(*args, 0, NULL);
-	    if (node) {
-		m = (Module) getdata(node);
-		if (!(m->flags & MOD_ALIAS)) {
+	    m = find_module(*args, 0, NULL);
+	    if (m) {
+		if (!(m->node.flags & MOD_ALIAS)) {
 		    zwarnnam(nam, "module is not an alias: %s", *args);
 		    return 1;
 		}
-		delete_module(node);
+		delete_module(m);
 	    } else {
 		zwarnnam(nam, "no such module alias: %s", *args);
 		return 1;
@@ -2289,29 +2539,28 @@
 				 *args);
 			return 1;
 		    }
-		} while ((node = find_module(mname, 0, NULL))
-			 && ((m = (Module) getdata(node))->flags & MOD_ALIAS)
+		} while ((m = find_module(mname, 0, NULL))
+			 && (m->node.flags & MOD_ALIAS)
 			 && (mname = m->u.alias));
-		node = find_module(*args, 0, NULL);
-		if (node) {
-		    m = (Module) getdata(node);
-		    if (!(m->flags & MOD_ALIAS)) {
+		m = find_module(*args, 0, NULL);
+		if (m) {
+		    if (!(m->node.flags & MOD_ALIAS)) {
 			zwarnnam(nam, "module is not an alias: %s", *args);
 			return 1;
 		    }
 		    zsfree(m->u.alias);
 		} else {
 		    m = (Module) zshcalloc(sizeof(*m));
-		    m->nam = ztrdup(*args);
-		    m->flags = MOD_ALIAS;
-		    zaddlinknode(modules, m);
+		    m->node.flags = MOD_ALIAS;
+		    modulestab->addnode(modulestab, ztrdup(*args), m);
 		}
 		m->u.alias = ztrdup(aliasname);
 	    } else {
-		if ((node = find_module(*args, 0, NULL))) {
-		    m = (Module) getdata(node);
-		    if (m->flags & MOD_ALIAS)
-			printmodalias(m, ops);
+		if ((m = find_module(*args, 0, NULL))) {
+		    if (m->node.flags & MOD_ALIAS)
+			modulestab->printnode(&m->node,
+					      OPT_ISSET(ops,'L') ?
+					      PRINTMOD_LIST : 0);
 		    else {
 			zwarnnam(nam, "module is not an alias: %s", *args);
 			return 1;
@@ -2333,35 +2582,20 @@
 static int
 bin_zmodload_exist(UNUSED(char *nam), char **args, Options ops)
 {
-    LinkNode node;
     Module m;
-    char *modname;
 
     if (!*args) {
-	for (node = firstnode(modules); node; incnode(node)) {
-	    m = (Module) getdata(node);
-	    modname = m->nam;
-	    if (m->flags & MOD_ALIAS) {
-		LinkNode node2;
-		if (OPT_ISSET(ops,'A') && 
-		    (node2 = find_module(m->u.alias, FINDMOD_ALIASP, NULL)))
-		    m = (Module) getdata(node2);
-		else
-		    continue;
-	    }
-	    if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
-		nicezputs(modname, stdout);
-		putchar('\n');
-	    }
-	}
+	scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
+		      OPT_ISSET(ops,'A') ? PRINTMOD_EXIST|PRINTMOD_ALIAS :
+		      PRINTMOD_EXIST);
 	return 0;
     } else {
 	int ret = 0;
 
 	for (; !ret && *args; args++) {
-	    if (!(node = find_module(*args, FINDMOD_ALIASP, NULL))
-		|| !(m = (Module) getdata(node))->u.handle
-		|| (m->flags & MOD_UNLOAD))
+	    if (!(m = find_module(*args, FINDMOD_ALIASP, NULL))
+		|| !m->u.handle
+		|| (m->node.flags & MOD_UNLOAD))
 		ret = 1;
 	}
 	return ret;
@@ -2374,15 +2608,13 @@
 static int
 bin_zmodload_dep(UNUSED(char *nam), char **args, Options ops)
 {
-    LinkNode node;
     Module m;
     if (OPT_ISSET(ops,'u')) {
 	/* remove dependencies, which can't pertain to aliases */
 	const char *tnam = *args++;
-	node = find_module(tnam, FINDMOD_ALIASP, &tnam);
-	if (!node)
+	m = find_module(tnam, FINDMOD_ALIASP, &tnam);
+	if (!m)
 	    return 0;
-	m = (Module) getdata(node);
 	if (*args && m->deps) {
 	    do {
 		LinkNode dnode;
@@ -2404,32 +2636,18 @@
 	    }
 	}
 	if (!m->deps && !m->u.handle)
-	    delete_module(node);
+	    delete_module(m);
 	return 0;
     } else if (!args[0] || !args[1]) {
 	/* list dependencies */
-	for (node = firstnode(modules); node; incnode(node)) {
-	    m = (Module) getdata(node);
-	    if (m->deps && (!args[0] || !strcmp(args[0], m->nam))) {
-		LinkNode n;
-		if (OPT_ISSET(ops,'L')) {
-		    printf("zmodload -d ");
-		    if(m->nam[0] == '-')
-			fputs("-- ", stdout);
-		    quotedzputs(m->nam, stdout);
-		} else {
-		    nicezputs(m->nam, stdout);
-		    putchar(':');
-		}
-		for (n = firstnode(m->deps); n; incnode(n)) {
-		    putchar(' ');
-		    if(OPT_ISSET(ops,'L'))
-			quotedzputs((char *) getdata(n), stdout);
-		    else
-			nicezputs((char *) getdata(n), stdout);
-		}
-		putchar('\n');
-	    }
+	int depflags = OPT_ISSET(ops,'L') ?
+	    PRINTMOD_DEPS|PRINTMOD_LIST : PRINTMOD_DEPS;
+	if (args[0]) {
+	    if ((m = (Module)modulestab->getnode2(modulestab, args[0])))
+		modulestab->printnode(&m->node, depflags);
+	} else {
+	    scanhashtable(modulestab, 1, 0, 0, modulestab->printnode,
+			  depflags);
 	}
 	return 0;
     } else {
@@ -2467,7 +2685,7 @@
 static int
 bin_zmodload_auto(char *nam, char **args, Options ops)
 {
-    int fchar;
+    int fchar, flags;
     char *modnam;
 
     if (OPT_ISSET(ops,'c')) {
@@ -2530,9 +2748,12 @@
 	fchar = 'b';
     }
 
+    flags = FEAT_AUTOALL;
+    if (OPT_ISSET(ops,'i'))
+	flags |= FEAT_IGNORE;
     if (OPT_ISSET(ops,'u')) {
 	/* remove autoload */
-	fchar *= -1;
+	flags |= FEAT_REMOVE;
 	modnam = NULL;
     } else {
 	/* add autoload */
@@ -2541,94 +2762,113 @@
 	if (args[1])
 	    args++;
     }
-    return autofeatures(nam, modnam, args, fchar, OPT_ISSET(ops,'i'));
+    return autofeatures(nam, modnam, args, fchar, flags);
 }
 
 /* Backend handler for zmodload -u */
 
 /**/
 int
-unload_module(Module m, LinkNode node)
+unload_module(Module m)
 {
+    int del;
+
     /*
      * Only unload the real module, so resolve aliases.
      */
-    if (m->flags & MOD_ALIAS) {
-	LinkNode node = find_module(m->u.alias, FINDMOD_ALIASP, NULL);
-	if (!node)
+    if (m->node.flags & MOD_ALIAS) {
+	m = find_module(m->u.alias, FINDMOD_ALIASP, NULL);
+	if (!m)
 	    return 1;
-	m = (Module) getdata(node);
     }
-    if ((m->flags & MOD_INIT_S) &&
-	!(m->flags & MOD_UNLOAD) &&
+    /*
+     * We may need to clean up the module any time setup_ has been
+     * called.  After cleanup_ is successful we are no longer in the
+     * booted state (because features etc. are deregistered), so remove
+     * MOD_INIT_B, and also MOD_INIT_S since we won't need to cleanup
+     * again if this succeeded.
+     */
+    if ((m->node.flags & MOD_INIT_S) &&
+	!(m->node.flags & MOD_UNLOAD) &&
 	do_cleanup_module(m))
 	return 1;
-    else {
-	int del = (m->flags & MOD_UNLOAD);
+    m->node.flags &= ~(MOD_INIT_B|MOD_INIT_S);
 
-	if (m->wrapper) {
-	    m->flags |= MOD_UNLOAD;
-	    return 0;
+    del = (m->node.flags & MOD_UNLOAD);
+
+    if (m->wrapper) {
+	m->node.flags |= MOD_UNLOAD;
+	return 0;
+    }
+    m->node.flags &= ~MOD_UNLOAD;
+
+    /*
+     * We always need to finish the module (and unload it)
+     * if it is present.
+     */
+    if (m->node.flags & MOD_LINKED) {
+	if (m->u.linked) {
+	    m->u.linked->finish(m);
+	    m->u.linked = NULL;
 	}
-	m->flags &= ~MOD_UNLOAD;
-	if (m->flags & MOD_INIT_B) {
-	    if (m->flags & MOD_LINKED) {
-		if (m->u.linked) {
-		    m->u.linked->finish(m);
-		    m->u.linked = NULL;
-		}
-	    } else {
-		if (m->u.handle) {
-		    finish_module(m);
-		    m->u.handle = NULL;
-		}
-	    }
+    } else {
+	if (m->u.handle) {
+	    finish_module(m);
+	    m->u.handle = NULL;
 	}
-	if (del && m->deps) {
-	    /* The module was unloaded delayed, unload all modules *
-	     * on which it depended. */
-	    LinkNode n;
-
-	    for (n = firstnode(m->deps); n; incnode(n)) {
-		LinkNode dn = find_module((char *) getdata(n),
-					  FINDMOD_ALIASP, NULL);
-		Module dm;
-
-		if (dn && (dm = (Module) getdata(dn)) &&
-		    (dm->flags & MOD_UNLOAD)) {
-		    /* See if this is the only module depending on it. */
-
-		    LinkNode an;
-		    Module am;
-		    int du = 1;
-
-		    for (an = firstnode(modules); du && an; incnode(an)) {
-			am = (Module) getdata(an);
-			if (am != m && am->deps &&
-			    ((am->flags & MOD_LINKED) ?
-			     am->u.linked : am->u.handle)) {
-			    LinkNode sn;
-
-			    for (sn = firstnode(am->deps); du && sn;
-				 incnode(sn)) {
-				if (!strcmp((char *) getdata(sn), dm->nam))
-				    du = 0;
-			    }
+    }
+
+    if (del && m->deps) {
+	/* The module was unloaded delayed, unload all modules *
+	 * on which it depended. */
+	LinkNode n;
+
+	for (n = firstnode(m->deps); n; incnode(n)) {
+	    Module dm = find_module((char *) getdata(n),
+				    FINDMOD_ALIASP, NULL);
+
+	    if (dm &&
+		(dm->node.flags & MOD_UNLOAD)) {
+		/* See if this is the only module depending on it. */
+		Module am;
+		int du = 1, i;
+		/* Scan hash table the hard way */
+		for (i = 0; du && i < modulestab->hsize; i++) {
+		    for (am = (Module)modulestab->nodes[i]; du && am;
+			 am = (Module)am->node.next) {
+			LinkNode sn;
+			/*
+			 * Don't scan the module we're unloading;
+			 * ignore if no dependencies.
+			 */
+			if (am == m || !am->deps)
+			    continue;
+			/* Don't scan if not loaded nor linked */
+			if ((am->node.flags & MOD_LINKED) ?
+			    !am->u.linked : !am->u.handle)
+			    continue;
+			for (sn = firstnode(am->deps); du && sn;
+			     incnode(sn)) {
+			    if (!strcmp((char *) getdata(sn),
+					dm->node.nam))
+				du = 0;
 			}
 		    }
-		    if (du)
-			unload_module(dm, NULL);
 		}
+		if (du)
+		    unload_module(dm);
 	    }
 	}
-	if(!m->deps) {
-	    if (!node) {
-		node = linknodebydatum(modules, m);
-		if (!node)
-		    return 1;
-	    }
-	    delete_module(node);
-	}
+    }
+    if (m->autoloads && firstnode(m->autoloads)) {
+	/*
+	 * Module has autoloadable features.  Restore them
+	 * so that the module will be reloaded when needed.
+	 */
+	autofeatures("zsh", m->node.nam,
+		     hlinklist2array(m->autoloads, 0), 0, FEAT_IGNORE);
+    } else if (!m->deps) {
+	delete_module(m);
     }
     return 0;
 }
@@ -2644,32 +2884,35 @@
 unload_named_module(char *modname, char *nam, int silent)
 {
     const char *mname;
-    LinkNode node;
     Module m;
     int ret = 0;
 
-    node = find_module(modname, FINDMOD_ALIASP, &mname);
-    if (node) {
-	LinkNode mn, dn;
-	int del = 0;
-
-	for (mn = firstnode(modules); mn; incnode(mn)) {
-	    m = (Module) getdata(mn);
-	    if (m->deps && m->u.handle)
-		for (dn = firstnode(m->deps); dn; incnode(dn))
+    m = find_module(modname, FINDMOD_ALIASP, &mname);
+    if (m) {
+	int i, del = 0;
+	Module dm;
+
+	for (i = 0; i < modulestab->hsize; i++) {
+	    for (dm = (Module)modulestab->nodes[i]; dm;
+		 dm = (Module)dm->node.next) {
+		LinkNode dn;
+		if (!dm->deps || !dm->u.handle)
+		    continue;
+		for (dn = firstnode(dm->deps); dn; incnode(dn)) {
 		    if (!strcmp((char *) getdata(dn), mname)) {
-			if (m->flags & MOD_UNLOAD)
+			if (dm->node.flags & MOD_UNLOAD)
 			    del = 1;
 			else {
 			    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname);
 			    return 1;
 			}
 		    }
+		}
+	    }
 	}
-	m = (Module) getdata(node);
 	if (del)
 	    m->wrapper++;
-	if (unload_module(m, node))
+	if (unload_module(m))
 	    ret = 1;
 	if (del)
 	    m->wrapper--;
@@ -2687,8 +2930,6 @@
 static int
 bin_zmodload_load(char *nam, char **args, Options ops)
 {
-    LinkNode node;
-    Module m;
     int ret = 0;
     if(OPT_ISSET(ops,'u')) {
 	/* unload modules */
@@ -2699,19 +2940,9 @@
 	return ret;
     } else if(!*args) {
 	/* list modules */
-	for (node = firstnode(modules); node; incnode(node)) {
-	    m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & (MOD_UNLOAD|MOD_ALIAS))) {
-		if(OPT_ISSET(ops,'L')) {
-		    printf("zmodload ");
-		    if(m->nam[0] == '-')
-			fputs("-- ", stdout);
-		    quotedzputs(m->nam, stdout);
-		} else
-		    nicezputs(m->nam, stdout);
-		putchar('\n');
-	    }
-	}
+	scanhashtable(modulestab, 1, 0, MOD_UNLOAD|MOD_ALIAS,
+		      modulestab->printnode,
+		      OPT_ISSET(ops,'L') ? PRINTMOD_LIST : 0);
 	return 0;
     } else {
 	/* load modules */
@@ -2729,15 +2960,31 @@
 
 /**/
 static int
-bin_zmodload_features(char *nam, char **args, Options ops)
+bin_zmodload_features(const char *nam, char **args, Options ops)
 {
     char *modname = *args;
 
+    if (modname)
+	args++;
+    else if (OPT_ISSET(ops,'L')) {
+	int printflags = PRINTMOD_LIST|PRINTMOD_FEATURES;
+	if (OPT_ISSET(ops,'P')) {
+	    zwarnnam(nam, "-P is only allowed with a module name");
+	    return 1;
+	}
+	if (OPT_ISSET(ops,'l'))
+	    printflags |= PRINTMOD_LISTALL;
+	if (OPT_ISSET(ops,'a'))
+	    printflags |= PRINTMOD_AUTO;
+	scanhashtable(modulestab, 1, 0, MOD_ALIAS,
+		      modulestab->printnode, printflags);
+	return 0;
+    }
+
     if (!modname) {
 	zwarnnam(nam, "-F requires a module name");
 	return 1;
     }
-    args++;
 
     if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) {
 	/*
@@ -2746,32 +2993,74 @@
 	 * only options turned on.
 	 * With both options, list as zmodload showing options
 	 * to be turned both on and off.
-	 *
-	 * TODO: handle -a, list only autoloads.
 	 */
-	LinkNode node;
-	Module m = NULL;
+	Module m;
 	char **features, **fp, **arrset = NULL, **arrp = NULL;
 	int *enables = NULL, *ep;
 	char *param = OPT_ARG_SAFE(ops,'P');
 
-	node = find_module(modname, FINDMOD_ALIASP, NULL);
-	if (node)
-	    m = ((Module) getdata(node));
-	if (!m || !m->u.handle || (m->flags & MOD_UNLOAD)) {
+	m = find_module(modname, FINDMOD_ALIASP, NULL);
+	if (OPT_ISSET(ops,'a')) {
+	    LinkNode ln;
+	    /*
+	     * If there are no autoloads defined, return status 1.
+	     */
+	    if (!m || !m->autoloads)
+		return 1;
+	    if (OPT_ISSET(ops,'e')) {
+		for (fp = args; *fp; fp++) {
+		    char *fstr = *fp;
+		    int sense = 1;
+		    if (*fstr == '+')
+			fstr++;
+		    else if (*fstr == '-') {
+			fstr++;
+			sense = 0;
+		    }
+		    if ((linknodebystring(m->autoloads, fstr) != NULL) !=
+			sense)
+			return 1;
+		}
+		return 0;
+	    }
+	    if (param) {
+		arrp = arrset = (char **)zalloc(sizeof(char*) *
+				 (countlinknodes(m->autoloads)+1));
+	    } else if (OPT_ISSET(ops,'L')) {
+		printf("zmodload -aF %s%c", m->node.nam,
+		       m->autoloads && firstnode(m->autoloads) ? ' ' : '\n');
+		arrp = NULL;
+	    }
+	    for (ln = firstnode(m->autoloads); ln; incnode(ln)) {
+		char *al = (char *)getdata(ln);
+		if (param)
+		    *arrp++ = ztrdup(al);
+		else
+		    printf("%s%c", al,
+			   OPT_ISSET(ops,'L') && nextnode(ln) ? ' ' : '\n');
+	    }
+	    if (param) {
+		*arrp = NULL;
+		if (!setaparam(param, arrset))
+		    return 1;
+	    }
+	    return 0;
+	}
+	if (!m || !m->u.handle || (m->node.flags & MOD_UNLOAD)) {
 	    if (!OPT_ISSET(ops,'e'))
 		zwarnnam(nam, "module `%s' is not yet loaded", modname);
 	    return 1;
 	}
 	if (features_module(m, &features)) {
 	    if (!OPT_ISSET(ops,'e'))
-		zwarnnam(nam, "module `%s' does not support features", m->nam);
+		zwarnnam(nam, "module `%s' does not support features",
+			 m->node.nam);
 	    return 1;
 	}
 	if (enables_module(m, &enables)) {
 	    /* this shouldn't ever happen, so don't silence this error */
 	    zwarnnam(nam, "error getting enabled features for module `%s'",
-		     m->nam);
+		     m->node.nam);
 	    return 1;
 	}
 	for (arrp = args; *arrp; arrp++) {
@@ -2796,14 +3085,14 @@
 	    }
 	    if (!*fp) {
 		if (!OPT_ISSET(ops,'e'))
-		    zwarnnam(nam, "module `%s' has no such feature: %s",
+		    zwarnnam(nam, "module `%s' has no such feature: `%s'",
 			     *arrp);
 		return 1;
 	    }
 	}
 	if (OPT_ISSET(ops,'e'))		/* yep, everything we want exists */
 	    return 0;
-	if (OPT_ISSET(ops,'P')) {
+	if (param) {
 	    int arrlen = 0;
 	    for (fp = features, ep = enables; *fp; fp++, ep++) {
 		if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') &&
@@ -2826,7 +3115,7 @@
 	    }
 	    arrp = arrset = zalloc(sizeof(char *) * (arrlen+1));
 	} else if (OPT_ISSET(ops, 'L'))
-	    printf("zmodload -F %s ", m->nam);
+	    printf("zmodload -F %s ", m->node.nam);
 	for (fp = features, ep = enables; *fp; fp++, ep++) {
 	    char *onoff;
 	    int term;
@@ -2872,7 +3161,18 @@
 	zwarnnam(nam, "-P can only be used with -l or -L");
 	return 1;
     } else if (OPT_ISSET(ops,'a')) {
-	return autofeatures(nam, modname, args, 0, OPT_ISSET(ops,'i'));
+	/*
+	 * With zmodload -aF, we always use the effect of -i.
+	 * The thinking is that marking a feature for
+	 * autoload is separate from enabling or disabling it.
+	 * Arguably we could do this with the zmodload -ab method
+	 * but I've kept it there for old time's sake.
+	 * The decoupling has meant FEAT_IGNORE/-i also
+	 * suppresses an error for attempting to remove an
+	 * autoload when the feature is enabled, which used
+	 * to be a hard error before.
+	 */
+	return autofeatures(nam, modname, args, 0, FEAT_IGNORE);
     }
 
     return require_module(modname, args);
@@ -2894,15 +3194,15 @@
 
 /**/
 mod_export char **
-featuresarray(char const *nam, Features f)
+featuresarray(UNUSED(Module m), Features f)
 {
     int bn_size = f->bn_size, cd_size = f->cd_size;
-    int pd_size = f->pd_size, mf_size = f->mf_size;
+    int mf_size = f->mf_size, pd_size = f->pd_size;
     int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
     Builtin bnp = f->bn_list;
     Conddef cdp = f->cd_list;
-    Paramdef pdp = f->pd_list;
     MathFunc mfp = f->mf_list;
+    Paramdef pdp = f->pd_list;
     char **features = (char **)zhalloc((features_size + 1) * sizeof(char *));
     char **featurep = features;
 
@@ -2913,10 +3213,10 @@
 			     cdp->name);
 	cdp++;
     }
-    while (pd_size--)
-	*featurep++ = dyncat("p:", (pdp++)->name);
     while (mf_size--)
 	*featurep++ = dyncat("f:", (mfp++)->name);
+    while (pd_size--)
+	*featurep++ = dyncat("p:", (pdp++)->name);
 
     features[features_size] = NULL;
     return features;
@@ -2929,15 +3229,15 @@
  */
 /**/
 mod_export int *
-getfeatureenables(char const *nam, Features f)
+getfeatureenables(UNUSED(Module m), Features f)
 {
     int bn_size = f->bn_size, cd_size = f->cd_size;
-    int pd_size = f->pd_size, mf_size = f->mf_size;
-    int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
+    int mf_size = f->mf_size, pd_size = f->pd_size;
+    int features_size = bn_size + cd_size + mf_size + pd_size + f->n_abstract;
     Builtin bnp = f->bn_list;
     Conddef cdp = f->cd_list;
-    Paramdef pdp = f->pd_list;
     MathFunc mfp = f->mf_list;
+    Paramdef pdp = f->pd_list;
     int *enables = zhalloc(sizeof(int) * features_size);
     int *enablep = enables;
 
@@ -2945,10 +3245,10 @@
 	*enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0;
     while (cd_size--)
 	*enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0;
-    while (pd_size--)
-	*enablep++ = (pdp++)->pm ? 1 : 0;
     while (mf_size--)
 	*enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0;
+    while (pd_size--)
+	*enablep++ = (pdp++)->pm ? 1 : 0;
 
     return enables;
 }
@@ -2965,32 +3265,32 @@
 
 /**/
 mod_export int
-setfeatureenables(char const *nam, Features f, int *e)
+setfeatureenables(Module m, Features f, int *e)
 {
     int ret = 0;
 
     if (f->bn_size) {
-	if (setbuiltins(nam, f->bn_list, f->bn_size, e))
+	if (setbuiltins(m->node.nam, f->bn_list, f->bn_size, e))
 	    ret = 1;
 	if (e)
 	    e += f->bn_size;
     }
     if (f->cd_size) {
-	if (setconddefs(nam, f->cd_list, f->cd_size, e))
+	if (setconddefs(m->node.nam, f->cd_list, f->cd_size, e))
 	    ret = 1;
 	if (e)
 	    e += f->cd_size;
     }
+    if (f->mf_size) {
+	if (setmathfuncs(m->node.nam, f->mf_list, f->mf_size, e))
+	    ret = 1;
+    }
     if (f->pd_size) {
-	if (setparamdefs(nam, f->pd_list, f->pd_size, e))
+	if (setparamdefs(m->node.nam, f->pd_list, f->pd_size, e))
 	    ret = 1;
 	if (e)
 	    e += f->pd_size;
     }
-    if (f->mf_size) {
-	if (setmathfuncs(nam, f->mf_list, f->mf_size, e))
-	    ret = 1;
-    }
     return ret;
 }
 
@@ -3001,31 +3301,40 @@
 
 /**/
 mod_export int
-handlefeatures(char *nam, Features f, int **enables)
+handlefeatures(Module m, Features f, int **enables)
 {
     if (!enables || *enables)
-	return setfeatureenables(nam, f, *enables);
-    *enables = getfeatureenables(nam, f);
+	return setfeatureenables(m, f, *enables);
+    *enables = getfeatureenables(m, f);
     return 0;
 }
 
 /*
  * Ensure module "modname" is providing feature with "prefix"
- * and "feature" (e.g. "b:", "limit").
+ * and "feature" (e.g. "b:", "limit").  If feature is NULL,
+ * ensure all features are loaded (used for compatibility
+ * with the pre-feature autoloading behaviour).
  *
  * This will usually be called from the main shell to handle
  * loading of an autoloadable feature.
  *
  * Returns 0 on success, 1 for error in module, 2 for error
- * setting the feature.
+ * setting the feature.  However, this isn't actually all
+ * that useful for testing immediately on an autoload since
+ * it could be a failure to autoload a different feature
+ * from the one we want.  We could fix this but it's
+ * possible to test other ways.
  */
 
 /**/
 mod_export int
-ensurefeature(char *modname, char *prefix, char *feature)
+ensurefeature(const char *modname, const char *prefix, const char *feature)
 {
-    char *f = dyncat(prefix, feature);
-    char *features[2];
+    char *f, *features[2];
+
+    if (!feature)
+	return require_module(modname, NULL);
+    f = dyncat(prefix, feature);
 
     features[0] = f;
     features[1] = NULL;
@@ -3038,28 +3347,38 @@
 
 /**/
 int
-autofeatures(char *cmdnam, char *module, char **features, int prefchar,
-	     int opt_i)
+autofeatures(const char *cmdnam, const char *module, char **features,
+	     int prefchar, int defflags)
 {
     int ret = 0, subret;
-    int defflags = opt_i ? AUTOFEAT_IGNORE : 0;
+    Module defm, m;
+    char **modfeatures = NULL;
+    if (module) {
+	defm = (Module)find_module(module,
+				   FINDMOD_ALIASP|FINDMOD_CREATE, NULL);
+	if ((defm->node.flags & MOD_LINKED) ? defm->u.linked :
+	    defm->u.handle)
+	    (void)features_module(defm, &modfeatures);
+    } else
+	defm = NULL;
 
-    while (*features) {
-	char *fnam, *typnam;
+    for (; *features; features++) {
+	char *fnam, *typnam, *feature;
 	int add, fchar, flags = defflags;
 	autofeaturefn_t fn;
 
 	if (prefchar) {
-	    if (prefchar < 0) {
-		add = 0;
-		fchar = - prefchar;
-	    } else {
-		add = 1;
-		fchar = prefchar;
-	    }
+	    /*
+	     * "features" is list of bare features with no
+	     * type prefix; prefchar gives type character.
+	     */
+	    add = 1; 		/* unless overridden by flag */
+	    fchar = prefchar;
 	    fnam = *features;
+	    feature = zhalloc(strlen(fnam) + 3);
+	    sprintf(feature, "%c:%s", fchar, fnam);
 	} else {
-	    char *feature = *features;
+	    feature = *features;
 	    if (*feature == '-') {
 		add = 0;
 		feature++;
@@ -3073,12 +3392,13 @@
 		zwarnnam(cmdnam, "bad format for autoloadable feature: `%s'",
 			 feature);
 		ret = 1;
+		continue;
 	    }
 	    fnam = feature + 2;
 	    fchar = feature[0];
 	}
-
-	features++;
+	if (flags & FEAT_REMOVE)
+	    add = 0;
 
 	switch (fchar) {
 	case 'b':
@@ -3087,23 +3407,23 @@
 	    break;
 
 	case 'C':
-	    flags |= AUTOFEAT_INFIX;
+	    flags |= FEAT_INFIX;
 	    /* FALLTHROUGH */
 	case 'c':
 	    fn = add ? add_autocond : del_autocond;
 	    typnam = "condition";
 	    break;
 
-	case 'p':
-	    fn = add ? add_autoparam : del_autoparam;
-	    typnam = "parameter";
-	    break;
-
 	case 'f':
 	    fn = add ? add_automathfunc : del_automathfunc;
 	    typnam = "math function";
 	    break;
 
+	case 'p':
+	    fn = add ? add_autoparam : del_autoparam;
+	    typnam = "parameter";
+	    break;
+
 	default:
 	    zwarnnam(cmdnam, "bad autoloadable feature type: `%c'",
 		     fchar);
@@ -3116,10 +3436,91 @@
 	    ret = 1;
 	    continue;
 	} 
-	subret = fn(module, fnam, flags);
+
+	if (!module) {
+	    /*
+	     * Traditional un-autoload syntax doesn't tell us
+	     * which module this came from.
+	     */
+	    int i;
+	    for (i = 0, m = NULL; !m && i < modulestab->hsize; i++) {
+		for (m = (Module)modulestab->nodes[i]; m;
+		     m = (Module)m->node.next) {
+		    if (m->autoloads &&
+			linknodebystring(m->autoloads, feature))
+			break;
+		}
+	    }
+	    if (!m) {
+		if (!(flags & FEAT_IGNORE)) {
+		    ret = 1;
+		    zwarnnam(cmdnam, "%s: no such %s", fnam, typnam);
+		}
+		continue;
+	    }
+	} else
+	    m = defm;
+
+	subret = 0;
+	if (add) {
+	    char **ptr;
+	    if (modfeatures) {
+		/*
+		 * If the module is already available, check that
+		 * it does in fact provide the necessary feature.
+		 */
+		for (ptr = modfeatures; *ptr; ptr++)
+		    if (!strcmp(*ptr, feature))
+			break;
+		if (!*ptr) {
+		    zwarnnam(cmdnam, "module `%s' has no such feature: `%s'",
+			     m->node.nam, feature);
+		    ret = 1;
+		    continue;
+		}
+	    }
+	    if (!m->autoloads) {
+		m->autoloads = znewlinklist();
+		zaddlinknode(m->autoloads, ztrdup(feature));
+	    } else {
+		/* Insert in lexical order */
+		LinkNode ln, prev = (LinkNode)m->autoloads;
+		while ((ln = nextnode(prev))) {
+		    int cmp = strcmp(feature, (char *)getdata(ln));
+		    if (cmp == 0) {
+			/* Already there.  Never an error. */
+			break;
+		    }
+		    if (cmp < 0) {
+			zinsertlinknode(m->autoloads, prev,
+					ztrdup(feature));
+			break;
+		    }
+		    prev = ln;
+		}
+		if (!ln)
+		    zaddlinknode(m->autoloads, ztrdup(feature));
+	    }
+	} else if (m->autoloads) {
+	    LinkNode ln;
+	    if ((ln = linknodebystring(m->autoloads, feature)))
+		zsfree((char *)remnode(m->autoloads, ln));
+	    else {
+		/*
+		 * With -i (or zmodload -Fa), removing an autoload
+		 * that's not there is not an error.
+		 */
+		subret = (flags & FEAT_IGNORE) ? -2 : 2;
+	    }
+	}
+
+	if (subret == 0)
+	    subret = fn(module, fnam, flags);
 
 	if (subret != 0) {
-	    ret = 1;
+	    /* -2 indicates not an error, just skip running fn() */
+	    if (subret != -2)
+		ret = 1;
 	    switch (subret) {
 	    case 1:
 		zwarnnam(cmdnam, "failed to add %s `%s'", typnam, fnam);
Index: Src/params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/params.c,v
retrieving revision 1.131
diff -u -r1.131 params.c
--- Src/params.c	18 Jun 2007 13:25:06 -0000	1.131
+++ Src/params.c	6 Jul 2007 20:57:51 -0000
@@ -411,7 +411,7 @@
 
 /**/
 static HashNode
-getparamnode(HashTable ht, char *nam)
+getparamnode(HashTable ht, const char *nam)
 {
     HashNode hn = gethashnode2(ht, nam);
     Param pm = (Param) hn;
@@ -419,12 +419,16 @@
     if (pm && pm->u.str && (pm->node.flags & PM_AUTOLOAD)) {
 	char *mn = dupstring(pm->u.str);
 
-	if (ensurefeature(mn, "p:", nam))
-	    return NULL;
+	(void)ensurefeature(mn, "p:", (pm->node.flags & PM_AUTOALL) ? NULL :
+			    nam);
 	hn = gethashnode2(ht, nam);
-	if (((Param) hn) == pm && (pm->node.flags & PM_AUTOLOAD)) {
-	    pm->node.flags &= ~PM_AUTOLOAD;
-	    zwarnnam(nam, "autoload failed");
+	if (!hn) {
+	    /*
+	     * This used to be a warning, but surely if we allow
+	     * stuff to go ahead with the autoload stub with
+	     * no error status we're in for all sorts of mayhem?
+	     */
+	    zerr("unknown parameter: %s", nam);
 	}
     }
     return hn;
Index: Src/string.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/string.c,v
retrieving revision 1.9
diff -u -r1.9 string.c
--- Src/string.c	2 Feb 2007 21:42:15 -0000	1.9
+++ Src/string.c	6 Jul 2007 20:57:51 -0000
@@ -109,7 +109,7 @@
 
 /**/
 mod_export char *
-dyncat(char *s1, char *s2)
+dyncat(const char *s1, const char *s2)
 {
     /* This version always uses space from the current heap. */
     char *ptr;
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.116
diff -u -r1.116 zsh.h
--- Src/zsh.h	18 Jun 2007 13:25:06 -0000	1.116
+++ Src/zsh.h	6 Jul 2007 20:57:52 -0000
@@ -92,6 +92,8 @@
 #define MFF_ADDED    2
 /* Math function is implemented by a shell function */
 #define MFF_USERFUNC 4
+/* When autoloading, enable all features in module */
+#define MFF_AUTOALL  8
 
 
 #define NUMMATHFUNC(name, func, min, max, id) \
@@ -538,8 +540,12 @@
     char *module;		/* module to autoload                 */
 };
 
-#define CONDF_INFIX  1
-#define CONDF_ADDED  2
+/* Condition is an infix */
+#define CONDF_INFIX   1
+/* Condition has been loaded from library */
+#define CONDF_ADDED   2
+/* When autoloading, enable all features in library */
+#define CONDF_AUTOALL 4
 
 #define CONDDEF(name, flags, handler, min, max, condid) \
     { NULL, name, flags, handler, min, max, condid, NULL }
@@ -928,11 +934,16 @@
 typedef void *(*VFunc) _((void *));
 typedef void (*FreeFunc) _((void *));
 
-typedef unsigned (*HashFunc)       _((char *));
+typedef unsigned (*HashFunc)       _((const char *));
 typedef void     (*TableFunc)      _((HashTable));
+/*
+ * Note that this is deliberately "char *", not "const char *",
+ * since the AddNodeFunc is passed a pointer to a string that
+ * will be stored and later freed.
+ */
 typedef void     (*AddNodeFunc)    _((HashTable, char *, void *));
-typedef HashNode (*GetNodeFunc)    _((HashTable, char *));
-typedef HashNode (*RemoveNodeFunc) _((HashTable, char *));
+typedef HashNode (*GetNodeFunc)    _((HashTable, const char *));
+typedef HashNode (*RemoveNodeFunc) _((HashTable, const char *));
 typedef void     (*FreeNodeFunc)   _((HashNode));
 typedef int      (*CompareFunc)    _((const char *, const char *));
 
@@ -1152,25 +1163,37 @@
 #define BINF_SKIPDASH		(1<<14) /* Treat `-' as argument (maybe `+') */
 #define BINF_DASHDASHVALID	(1<<15) /* Handle `--' even if SKIPINVALD */
 #define BINF_CLEARENV		(1<<16) /* new process started with cleared env */
+#define BINF_AUTOALL		(1<<17) /* autoload all features at once */
 
 struct module {
-    char *nam;
-    int flags;
+    struct hashnode node;
     union {
 	void *handle;
 	Linkedmod linked;
 	char *alias;
     } u;
+    LinkList autoloads;
     LinkList deps;
     int wrapper;
 };
 
+/* We are in the process of loading the module */
 #define MOD_BUSY    (1<<0)
+/*
+ * We are in the process of unloading the module.
+ * Note this is not needed to indicate a module is actually
+ * unloaded: for that, the handle (or linked pointer) is set to NULL.
+ */
 #define MOD_UNLOAD  (1<<1)
+/* We are in the process of setting up the module */
 #define MOD_SETUP   (1<<2)
+/* Module is statically linked into the main binary */
 #define MOD_LINKED  (1<<3)
+/* Module setup has been carried out (and module has not been finished) */
 #define MOD_INIT_S  (1<<4)
+/* Module boot has been carried out (and module has not been finished) */
 #define MOD_INIT_B  (1<<5)
+/* Module record is an alias */
 #define MOD_ALIAS   (1<<6)
 
 typedef int (*Module_generic_func) _((void));
@@ -1199,12 +1222,12 @@
     /* List of conditions provided by the module and the size thereof */
     Conddef cd_list;
     int cd_size;
-    /* List of parameters provided by the module and the size thereof */
-    Paramdef pd_list;
-    int pd_size;
     /* List of math functions provided by the module and the size thereof */
     MathFunc mf_list;
     int mf_size;
+    /* List of parameters provided by the module and the size thereof */
+    Paramdef pd_list;
+    int pd_size;
     /* Number of abstract features */
     int n_abstract;
 };
@@ -1408,6 +1431,10 @@
 #define PM_REMOVABLE	(1<<26)	/* special can be removed from paramtab     */
 #define PM_AUTOLOAD	(1<<27) /* autoloaded from module                   */
 #define PM_NORESTORE	(1<<28)	/* do not restore value of local special    */
+#define PM_AUTOALL	(1<<28) /* autoload all features in module
+				 * when loading: valid only if PM_AUTOLOAD
+				 * is also present.
+				 */
 #define PM_HASHELEM     (1<<29) /* is a hash-element */
 #define PM_NAMEDDIR     (1<<30) /* has a corresponding nameddirtab entry    */
 
Index: Src/Builtins/rlimits.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Builtins/rlimits.c,v
retrieving revision 1.19
diff -u -r1.19 rlimits.c
--- Src/Builtins/rlimits.c	28 May 2007 22:57:41 -0000	1.19
+++ Src/Builtins/rlimits.c	6 Jul 2007 20:57:53 -0000
@@ -908,7 +908,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -916,7 +916,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -930,7 +930,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
     return 0;
 }
 
Index: Src/Builtins/sched.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Builtins/sched.c,v
retrieving revision 1.12
diff -u -r1.12 sched.c
--- Src/Builtins/sched.c	14 Jun 2007 13:25:58 -0000	1.12
+++ Src/Builtins/sched.c	6 Jul 2007 20:57:53 -0000
@@ -381,8 +381,8 @@
 static struct features module_features = {
     bintab, sizeof(bintab)/sizeof(*bintab),
     NULL, 0,
-    partab, sizeof(partab)/sizeof(*partab),
     NULL, 0,
+    partab, sizeof(partab)/sizeof(*partab),
     0
 };
 
@@ -397,7 +397,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -405,7 +405,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -430,7 +430,7 @@
 	zfree(sch, sizeof(*sch));
     }
     delprepromptfn(&checksched);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/cap.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/cap.c,v
retrieving revision 1.6
diff -u -r1.6 cap.c
--- Src/Modules/cap.c	28 May 2007 22:57:41 -0000	1.6
+++ Src/Modules/cap.c	6 Jul 2007 20:57:53 -0000
@@ -141,7 +141,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -149,7 +149,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -163,7 +163,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/clone.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/clone.c,v
retrieving revision 1.7
diff -u -r1.7 clone.c
--- Src/Modules/clone.c	28 May 2007 22:57:41 -0000	1.7
+++ Src/Modules/clone.c	6 Jul 2007 20:57:53 -0000
@@ -128,7 +128,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -136,7 +136,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -150,7 +150,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/datetime.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/datetime.c,v
retrieving revision 1.16
diff -u -r1.16 datetime.c
--- Src/Modules/datetime.c	28 May 2007 22:57:41 -0000	1.16
+++ Src/Modules/datetime.c	6 Jul 2007 20:57:53 -0000
@@ -161,8 +161,8 @@
 static struct features module_features = {
     bintab, sizeof(bintab)/sizeof(*bintab),
     NULL, 0,
-    patab, sizeof(patab)/sizeof(*patab),
     NULL, 0,
+    patab, sizeof(patab)/sizeof(*patab),
     0
 };
 
@@ -177,7 +177,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -185,7 +185,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -199,7 +199,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/example.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/example.c,v
retrieving revision 1.4
diff -u -r1.4 example.c
--- Src/Modules/example.c	28 May 2007 22:57:41 -0000	1.4
+++ Src/Modules/example.c	6 Jul 2007 20:57:53 -0000
@@ -165,19 +165,19 @@
 };
 
 static struct conddef cotab[] = {
-    CONDDEF("len", 0, cond_p_len, 1, 2, 0),
     CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
+    CONDDEF("len", 0, cond_p_len, 1, 2, 0),
 };
 
 static struct paramdef patab[] = {
+    ARRPARAMDEF("exarr", &arrparam),
     INTPARAMDEF("exint", &intparam),
     STRPARAMDEF("exstr", &strparam),
-    ARRPARAMDEF("exarr", &arrparam),
 };
 
 static struct mathfunc mftab[] = {
-    NUMMATHFUNC("sum", math_sum, 1, -1, 0),
     STRMATHFUNC("length", math_length, 0),
+    NUMMATHFUNC("sum", math_sum, 1, -1, 0),
 };
 
 static struct funcwrap wrapper[] = {
@@ -187,8 +187,8 @@
 static struct features module_features = {
     bintab, sizeof(bintab)/sizeof(*bintab),
     cotab, sizeof(cotab)/sizeof(*cotab),
-    patab, sizeof(patab)/sizeof(*patab),
     mftab, sizeof(mftab)/sizeof(*mftab),
+    patab, sizeof(patab)/sizeof(*patab),
     0
 };
 
@@ -205,7 +205,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -213,7 +213,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -234,7 +234,7 @@
 cleanup_(Module m)
 {
     deletewrapper(m, wrapper);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/files.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/files.c,v
retrieving revision 1.16
diff -u -r1.16 files.c
--- Src/Modules/files.c	28 May 2007 22:57:41 -0000	1.16
+++ Src/Modules/files.c	6 Jul 2007 20:57:53 -0000
@@ -725,7 +725,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -733,7 +733,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -747,7 +747,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/langinfo.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/langinfo.c,v
retrieving revision 1.7
diff -u -r1.7 langinfo.c
--- Src/Modules/langinfo.c	28 May 2007 22:57:41 -0000	1.7
+++ Src/Modules/langinfo.c	6 Jul 2007 20:57:53 -0000
@@ -376,7 +376,7 @@
 };
 
 static nl_item *
-liitem(char *name)
+liitem(const char *name)
 {
     char **element;
     nl_item *nlcode;
@@ -393,16 +393,17 @@
 
 /**/
 static HashNode
-getlanginfo(UNUSED(HashTable ht), char *name)
+getlanginfo(UNUSED(HashTable ht), const char *name)
 {
     int len, *elem;
-    char *listr;
+    char *listr, *nameu;
     Param pm = NULL;
 
-    unmetafy(name, &len);
+    nameu = dupstring(name);
+    unmetafy(nameu, &len);
 
     pm = (Param) hcalloc(sizeof(struct param));
-    pm->node.nam = dupstring(name);
+    pm->node.nam = nameu;
     pm->node.flags = PM_READONLY | PM_SCALAR;
     pm->gsu.s = &nullsetscalar_gsu;
 
@@ -456,12 +457,12 @@
 static struct features module_features = {
     NULL, 0,
     NULL, 0,
+    NULL, 0,
 #ifdef HAVE_NL_LANGINFO
     partab, sizeof(partab)/sizeof(*partab),
 #else
     NULL, 0,
 #endif
-    NULL, 0,
     0
 };
 
@@ -476,7 +477,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -484,7 +485,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -498,7 +499,7 @@
 int
 cleanup_(UNUSED(Module m))
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/mapfile.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/mapfile.c,v
retrieving revision 1.10
diff -u -r1.10 mapfile.c
--- Src/Modules/mapfile.c	18 Jun 2007 13:25:07 -0000	1.10
+++ Src/Modules/mapfile.c	6 Jul 2007 20:57:53 -0000
@@ -213,7 +213,7 @@
 
 /**/
 static HashNode
-getpmmapfile(UNUSED(HashTable ht), char *name)
+getpmmapfile(UNUSED(HashTable ht), const char *name)
 {
     char *contents;
     Param pm = NULL;
@@ -268,8 +268,8 @@
 static struct features module_features = {
     NULL, 0,
     NULL, 0,
-    partab, sizeof(partab)/sizeof(*partab),
     NULL, 0,
+    partab, sizeof(partab)/sizeof(*partab),
     0
 };
 
@@ -284,7 +284,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -292,7 +292,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -306,7 +306,7 @@
 int
 cleanup_(UNUSED(Module m))
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/mathfunc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/mathfunc.c,v
retrieving revision 1.9
diff -u -r1.9 mathfunc.c
--- Src/Modules/mathfunc.c	28 May 2007 22:57:41 -0000	1.9
+++ Src/Modules/mathfunc.c	6 Jul 2007 20:57:53 -0000
@@ -125,12 +125,6 @@
 
 
 static struct mathfunc mftab[] = {
-  /* Functions taking string arguments */
-#ifdef HAVE_ERAND48
-  /* here to avoid comma hassle */
-  STRMATHFUNC("rand48", math_string, MS_RAND48),
-#endif
-
   NUMMATHFUNC("abs", math_func, 1, 1, MF_ABS | BFLAG(BF_FRAC) |
 	      TFLAG(TF_NOCONV|TF_NOASS)),
   NUMMATHFUNC("acos", math_func, 1, 1, MF_ACOS | BFLAG(BF_FRAC)),
@@ -167,6 +161,9 @@
   NUMMATHFUNC("log1p", math_func, 1, 1, MF_LOG1P | BFLAG(BF_GTRM1)),
   NUMMATHFUNC("logb", math_func, 1, 1, MF_LOGB | BFLAG(BF_NONZ)),
   NUMMATHFUNC("nextafter", math_func, 2, 2, MF_NEXTAFTER),
+#ifdef HAVE_ERAND48
+  STRMATHFUNC("rand48", math_string, MS_RAND48),
+#endif
   NUMMATHFUNC("rint", math_func, 1, 1, MF_RINT),
   NUMMATHFUNC("scalb", math_func, 2, 2, MF_SCALB | TFLAG(TF_INT2)),
 #ifdef HAVE_SIGNGAM
@@ -564,8 +561,8 @@
 static struct features module_features = {
     NULL, 0,
     NULL, 0,
-    NULL, 0,
     mftab, sizeof(mftab)/sizeof(*mftab),
+    NULL, 0,
     0
 };
 
@@ -580,7 +577,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -588,7 +585,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -602,7 +599,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.43
diff -u -r1.43 parameter.c
--- Src/Modules/parameter.c	27 Jun 2007 13:56:11 -0000	1.43
+++ Src/Modules/parameter.c	6 Jul 2007 20:57:53 -0000
@@ -93,7 +93,7 @@
 
 /**/
 static HashNode
-getpmparameter(UNUSED(HashTable ht), char *name)
+getpmparameter(UNUSED(HashTable ht), const char *name)
 {
     Param rpm, pm = NULL;
 
@@ -199,7 +199,7 @@
 
 /**/
 static HashNode
-getpmcommand(UNUSED(HashTable ht), char *name)
+getpmcommand(UNUSED(HashTable ht), const char *name)
 {
     Cmdnam cmd;
     Param pm = NULL;
@@ -372,7 +372,7 @@
 
 /**/
 static HashNode
-getfunction(UNUSED(HashTable ht), char *name, int dis)
+getfunction(UNUSED(HashTable ht), const char *name, int dis)
 {
     Shfunc shf;
     Param pm = NULL;
@@ -416,14 +416,14 @@
 
 /**/
 static HashNode
-getpmfunction(HashTable ht, char *name)
+getpmfunction(HashTable ht, const char *name)
 {
     return getfunction(ht, name, 0);
 }
 
 /**/
 static HashNode
-getpmdisfunction(HashTable ht, char *name)
+getpmdisfunction(HashTable ht, const char *name)
 {
     return getfunction(ht, name, DISABLED);
 }
@@ -542,7 +542,7 @@
 
 /**/
 static HashNode
-getbuiltin(UNUSED(HashTable ht), char *name, int dis)
+getbuiltin(UNUSED(HashTable ht), const char *name, int dis)
 {
     Param pm = NULL;
     Builtin bn;
@@ -566,14 +566,14 @@
 
 /**/
 static HashNode
-getpmbuiltin(HashTable ht, char *name)
+getpmbuiltin(HashTable ht, const char *name)
 {
     return getbuiltin(ht, name, 0);
 }
 
 /**/
 static HashNode
-getpmdisbuiltin(HashTable ht, char *name)
+getpmdisbuiltin(HashTable ht, const char *name)
 {
     return getbuiltin(ht, name, DISABLED);
 }
@@ -721,7 +721,7 @@
 
 /**/
 static HashNode
-getpmoption(UNUSED(HashTable ht), char *name)
+getpmoption(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     int n;
@@ -771,69 +771,29 @@
 
 /* Functions for the modules special parameter. */
 
-static char *modpmname;
-static int modpmfound;
-
-/**/
-static void
-modpmbuiltinscan(HashNode hn, UNUSED(int dummy))
-{
-    if (!(((Builtin) hn)->node.flags & BINF_ADDED) &&
-	!strcmp(((Builtin) hn)->optstr, modpmname))
-	modpmfound = 1;
-}
-
-/**/
-static void
-modpmparamscan(HashNode hn, UNUSED(int dummy))
-{
-    if ((((Param) hn)->node.flags & PM_AUTOLOAD) &&
-	!strcmp(((Param) hn)->u.str, modpmname))
-	modpmfound = 1;
-}
-
 /**/
 static HashNode
-getpmmodule(UNUSED(HashTable ht), char *name)
+getpmmodule(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     char *type = NULL;
-    LinkNode node;
+    Module m;
 
     pm = (Param) hcalloc(sizeof(struct param));
     pm->node.nam = dupstring(name);
     pm->node.flags = PM_SCALAR | PM_READONLY;
     pm->gsu.s = &nullsetscalar_gsu;
 
-    if (!type) {
-	Module m;
+    m = (Module)modulestab->getnode2(modulestab, name);
 
-	for (node = firstnode(modules); node; incnode(node)) {
-	    m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & MOD_UNLOAD) &&
-		!strcmp(name, m->nam)) {
-		type = ((m->flags & MOD_ALIAS) ?
-			dyncat("alias:", m->u.alias) : "loaded");
-		break;
-	    }
-	}
+    if (!m)
+	return NULL;
+    if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) {
+	type = ((m->node.flags & MOD_ALIAS) ?
+		dyncat("alias:", m->u.alias) : "loaded");
     }
-    modpmname = name;
-    modpmfound = 0;
     if (!type) {
-	scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0);
-	if (!modpmfound) {
-	    Conddef p;
-
-	    for (p = condtab; p; p = p->next)
-		if (p->module && !strcmp(name, p->module)) {
-		    modpmfound = 1;
-		    break;
-		}
-	    if (!modpmfound)
-		scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0);
-	}
-	if (modpmfound)
+	if (m->autoloads && firstnode(m->autoloads))
 	    type = "autoloaded";
     }
     if (type)
@@ -853,7 +813,6 @@
     int i;
     HashNode hn;
     LinkList done = newlinklist();
-    LinkNode node;
     Module m;
     Conddef p;
     char *loaded = dupstring("loaded");
@@ -862,14 +821,16 @@
     pm.node.flags = PM_SCALAR | PM_READONLY;
     pm.gsu.s = &nullsetscalar_gsu;
 
-    for (node = firstnode(modules); node; incnode(node)) {
-	m = (Module) getdata(node);
-	if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
-	    pm.node.nam = m->nam;
-	    pm.u.str = ((m->flags & MOD_ALIAS) ?
-			dyncat("alias:", m->u.alias) : loaded);
-	    addlinknode(done, pm.node.nam);
-	    func(&pm.node, flags);
+    for (i = 0; i < modulestab->hsize; i++) {
+	for (hn = modulestab->nodes[i]; hn; hn = hn->next) {
+	    m = (Module) hn;
+	    if (m->u.handle && !(m->node.flags & MOD_UNLOAD)) {
+		pm.node.nam = m->node.nam;
+		pm.u.str = ((m->node.flags & MOD_ALIAS) ?
+			    dyncat("alias:", m->u.alias) : loaded);
+		addlinknode(done, pm.node.nam);
+		func(&pm.node, flags);
+	    }
 	}
     }
     pm.u.str = dupstring("autoloaded");
@@ -928,11 +889,11 @@
 
 /**/
 static HashNode
-getpmhistory(UNUSED(HashTable ht), char *name)
+getpmhistory(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     Histent he;
-    char *p;
+    const char *p;
     int ok = 1;
 
     pm = (Param) hcalloc(sizeof(struct param));
@@ -1042,7 +1003,7 @@
 
 /**/
 static HashNode
-getpmjobtext(UNUSED(HashTable ht), char *name)
+getpmjobtext(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     int job;
@@ -1139,7 +1100,7 @@
 
 /**/
 static HashNode
-getpmjobstate(UNUSED(HashTable ht), char *name)
+getpmjobstate(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     int job;
@@ -1201,7 +1162,7 @@
 
 /**/
 static HashNode
-getpmjobdir(UNUSED(HashTable ht), char *name)
+getpmjobdir(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     int job;
@@ -1329,7 +1290,7 @@
 
 /**/
 static HashNode
-getpmnameddir(UNUSED(HashTable ht), char *name)
+getpmnameddir(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     Nameddir nd;
@@ -1378,7 +1339,7 @@
 
 /**/
 static HashNode
-getpmuserdir(UNUSED(HashTable ht), char *name)
+getpmuserdir(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     Nameddir nd;
@@ -1631,7 +1592,7 @@
 
 /**/
 static HashNode
-getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags)
+getalias(HashTable alht, UNUSED(HashTable ht), const char *name, int flags)
 {
     Param pm = NULL;
     Alias al;
@@ -1653,45 +1614,45 @@
 
 /**/
 static HashNode
-getpmralias(HashTable ht, char *name)
+getpmralias(HashTable ht, const char *name)
 {
     return getalias(aliastab, ht, name, 0);
 }
 
 /**/
 static HashNode
-getpmdisralias(HashTable ht, char *name)
+getpmdisralias(HashTable ht, const char *name)
 {
     return getalias(aliastab, ht, name, DISABLED);
 }
 
 /**/
 static HashNode
-getpmgalias(HashTable ht, char *name)
+getpmgalias(HashTable ht, const char *name)
 {
     return getalias(aliastab, ht, name, ALIAS_GLOBAL);
 }
 
 /**/
 static HashNode
-getpmdisgalias(HashTable ht, char *name)
+getpmdisgalias(HashTable ht, const char *name)
 {
     return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED);
 }
 
 /**/
 static HashNode
-getpmsalias(HashTable ht, char *name)
+getpmsalias(HashTable ht, const char *name)
 {
     return getalias(sufaliastab, ht, name, ALIAS_SUFFIX);
 }
 
 /**/
 static HashNode
-getpmdissalias(HashTable ht, char *name)
+getpmdissalias(HashTable ht, const char *name)
 {
     return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED);
-}
+} 
 
 /**/
 static void
@@ -1809,63 +1770,63 @@
 { histwgetfn, arrsetfn, stdunsetfn };
 
 static struct paramdef partab[] = {
-    SPECIALPMDEF("parameters", PM_READONLY,
-	    NULL, getpmparameter, scanpmparameters),
+    SPECIALPMDEF("aliases", 0,
+	    &pmraliases_gsu, getpmralias, scanpmraliases),
+    SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins),
     SPECIALPMDEF("commands", 0, &pmcommands_gsu, getpmcommand, scanpmcommands),
-    SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
-		 scanpmfunctions),
+    SPECIALPMDEF("dirstack", PM_ARRAY,
+	    &dirs_gsu, NULL, NULL),
+    SPECIALPMDEF("dis_aliases", 0,
+	    &pmdisraliases_gsu, getpmdisralias, scanpmdisraliases),
+    SPECIALPMDEF("dis_builtins", PM_READONLY,
+	    NULL, getpmdisbuiltin, scanpmdisbuiltins),
     SPECIALPMDEF("dis_functions", 0, 
 	    &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
+    SPECIALPMDEF("dis_galiases", 0,
+	    &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
+    SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY,
+	    &disreswords_gsu, NULL, NULL),
+    SPECIALPMDEF("dis_saliases", 0,
+	    &pmdissaliases_gsu, getpmdissalias, scanpmdissaliases),
     SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY,
 	    &funcstack_gsu, NULL, NULL),
+    SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
+		 scanpmfunctions),
     SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY,
 	    &functrace_gsu, NULL, NULL),
-    SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins),
-    SPECIALPMDEF("dis_builtins", PM_READONLY,
-	    NULL, getpmdisbuiltin, scanpmdisbuiltins),
-    SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY,
-	    &reswords_gsu, NULL, NULL),
-    SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY,
-	    &disreswords_gsu, NULL, NULL),
-    SPECIALPMDEF("options", 0,
-	    &pmoptions_gsu, getpmoption, scanpmoptions),
-    SPECIALPMDEF("modules", PM_READONLY,
-	    NULL, getpmmodule, scanpmmodules),
-    SPECIALPMDEF("dirstack", PM_ARRAY,
-	    &dirs_gsu, NULL, NULL),
+    SPECIALPMDEF("galiases", 0,
+	    &pmgaliases_gsu, getpmgalias, scanpmgaliases),
     SPECIALPMDEF("history", PM_READONLY,
 	    NULL, getpmhistory, scanpmhistory),
     SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY,
 	    &historywords_gsu, NULL, NULL),
-    SPECIALPMDEF("jobtexts", PM_READONLY,
-	    NULL, getpmjobtext, scanpmjobtexts),
-    SPECIALPMDEF("jobstates", PM_READONLY,
-	    NULL, getpmjobstate, scanpmjobstates),
     SPECIALPMDEF("jobdirs", PM_READONLY,
 	    NULL, getpmjobdir, scanpmjobdirs),
+    SPECIALPMDEF("jobstates", PM_READONLY,
+	    NULL, getpmjobstate, scanpmjobstates),
+    SPECIALPMDEF("jobtexts", PM_READONLY,
+	    NULL, getpmjobtext, scanpmjobtexts),
+    SPECIALPMDEF("modules", PM_READONLY,
+	    NULL, getpmmodule, scanpmmodules),
     SPECIALPMDEF("nameddirs", 0,
 	    &pmnameddirs_gsu, getpmnameddir, scanpmnameddirs),
-    SPECIALPMDEF("userdirs", PM_READONLY,
-	    NULL, getpmuserdir, scanpmuserdirs),
-    SPECIALPMDEF("aliases", 0,
-	    &pmraliases_gsu, getpmralias, scanpmraliases),
-    SPECIALPMDEF("galiases", 0,
-	    &pmgaliases_gsu, getpmgalias, scanpmgaliases),
+    SPECIALPMDEF("options", 0,
+	    &pmoptions_gsu, getpmoption, scanpmoptions),
+    SPECIALPMDEF("parameters", PM_READONLY,
+	    NULL, getpmparameter, scanpmparameters),
+    SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY,
+	    &reswords_gsu, NULL, NULL),
     SPECIALPMDEF("saliases", 0,
 	    &pmsaliases_gsu, getpmsalias, scanpmsaliases),
-    SPECIALPMDEF("dis_aliases", 0,
-	    &pmdisraliases_gsu, getpmdisralias, scanpmdisraliases),
-    SPECIALPMDEF("dis_galiases", 0,
-	    &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
-    SPECIALPMDEF("dis_saliases", 0,
-	    &pmdissaliases_gsu, getpmdissalias, scanpmdissaliases)
+    SPECIALPMDEF("userdirs", PM_READONLY,
+	    NULL, getpmuserdir, scanpmuserdirs)
 };
 
 static struct features module_features = {
     NULL, 0,
     NULL, 0,
-    partab, sizeof(partab)/sizeof(*partab),
     NULL, 0,
+    partab, sizeof(partab)/sizeof(*partab),
     0
 };
 
@@ -1880,7 +1841,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -1894,7 +1855,7 @@
      * on the main shell, so set the flag to indicate.
      */
     incleanup = 1;
-    ret = handlefeatures(m->nam, &module_features, enables);
+    ret = handlefeatures(m, &module_features, enables);
     incleanup = 0;
     return ret;
 }
@@ -1912,7 +1873,7 @@
 {
     int ret;
     incleanup = 1;
-    ret = setfeatureenables(m->nam, &module_features, NULL);
+    ret = setfeatureenables(m, &module_features, NULL);
     incleanup = 0;
     return ret;
 }
Index: Src/Modules/pcre.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/pcre.c,v
retrieving revision 1.14
diff -u -r1.14 pcre.c
--- Src/Modules/pcre.c	28 May 2007 22:57:41 -0000	1.14
+++ Src/Modules/pcre.c	6 Jul 2007 20:57:53 -0000
@@ -290,8 +290,8 @@
 
 static struct builtin bintab[] = {
     BUILTIN("pcre_compile", 0, bin_pcre_compile, 1, 1, 0, "aimx",  NULL),
-    BUILTIN("pcre_study",   0, bin_pcre_study,   0, 0, 0, NULL,    NULL),
-    BUILTIN("pcre_match",   0, bin_pcre_match,   1, 1, 0, "a:v:",    NULL)
+    BUILTIN("pcre_match",   0, bin_pcre_match,   1, 1, 0, "a:v:",    NULL),
+    BUILTIN("pcre_study",   0, bin_pcre_study,   0, 0, 0, NULL,    NULL)
 };
 
 
@@ -319,7 +319,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -327,7 +327,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -341,7 +341,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/regex.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/regex.c,v
retrieving revision 1.2
diff -u -r1.2 regex.c
--- Src/Modules/regex.c	28 May 2007 22:57:41 -0000	1.2
+++ Src/Modules/regex.c	6 Jul 2007 20:57:53 -0000
@@ -152,7 +152,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -160,7 +160,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -174,7 +174,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/socket.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/socket.c,v
retrieving revision 1.10
diff -u -r1.10 socket.c
--- Src/Modules/socket.c	28 May 2007 22:57:41 -0000	1.10
+++ Src/Modules/socket.c	6 Jul 2007 20:57:53 -0000
@@ -276,7 +276,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -284,7 +284,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -298,7 +298,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/stat.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/stat.c,v
retrieving revision 1.14
diff -u -r1.14 stat.c
--- Src/Modules/stat.c	28 May 2007 22:57:41 -0000	1.14
+++ Src/Modules/stat.c	6 Jul 2007 20:57:54 -0000
@@ -643,7 +643,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -651,7 +651,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -665,7 +665,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/system.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/system.c,v
retrieving revision 1.8
diff -u -r1.8 system.c
--- Src/Modules/system.c	28 May 2007 22:57:41 -0000	1.8
+++ Src/Modules/system.c	6 Jul 2007 20:57:54 -0000
@@ -365,7 +365,7 @@
 
 /**/
 static void
-fillpmsysparams(Param pm, char *name)
+fillpmsysparams(Param pm, const char *name)
 {
     char buf[DIGBUFSIZE];
     int num;
@@ -390,7 +390,7 @@
 
 /**/
 static HashNode
-getpmsysparams(UNUSED(HashTable ht), char *name)
+getpmsysparams(UNUSED(HashTable ht), const char *name)
 {
     Param pm;
 
@@ -423,8 +423,8 @@
 static struct features module_features = {
     bintab, sizeof(bintab)/sizeof(*bintab),
     NULL, 0,
-    partab, sizeof(partab)/sizeof(*partab),
     NULL, 0,
+    partab, sizeof(partab)/sizeof(*partab),
     0
 };
 
@@ -441,7 +441,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -449,7 +449,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -464,7 +464,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/tcp.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/tcp.c,v
retrieving revision 1.44
diff -u -r1.44 tcp.c
--- Src/Modules/tcp.c	29 May 2007 09:53:44 -0000	1.44
+++ Src/Modules/tcp.c	6 Jul 2007 20:57:54 -0000
@@ -696,7 +696,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -704,7 +704,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -722,7 +722,7 @@
 {
     tcp_cleanup();
     freelinklist(ztcp_sessions, (FreeFunc) ztcp_free_session);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/termcap.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/termcap.c,v
retrieving revision 1.23
diff -u -r1.23 termcap.c
--- Src/Modules/termcap.c	28 May 2007 22:57:41 -0000	1.23
+++ Src/Modules/termcap.c	6 Jul 2007 20:57:54 -0000
@@ -164,10 +164,10 @@
 
 /**/
 static HashNode
-gettermcap(UNUSED(HashTable ht), char *name)
+gettermcap(UNUSED(HashTable ht), const char *name)
 {
     int len, num;
-    char *tcstr, buf[2048], *u;
+    char *tcstr, buf[2048], *u, *nameu;
     Param pm = NULL;
 
     /* This depends on the termcap stuff in init.c */
@@ -176,16 +176,18 @@
     if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
 	return NULL;
 
-    unmetafy(name, &len);
+    
+    nameu = dupstring(name);
+    unmetafy(nameu, &len);
 
     pm = (Param) hcalloc(sizeof(struct param));
-    pm->node.nam = dupstring(name);
+    pm->node.nam = nameu;
     pm->node.flags = PM_READONLY;
     u = buf;
 
     /* logic in the following cascade copied from echotc, above */
 
-    if ((num = tgetnum(name)) != -1) {
+    if ((num = tgetnum(nameu)) != -1) {
 	pm->gsu.i = &nullsetinteger_gsu;
 	pm->u.val = num;
 	pm->node.flags |= PM_INTEGER;
@@ -193,7 +195,7 @@
     }
 
     pm->gsu.s = &nullsetscalar_gsu;
-    switch (ztgetflag(name)) {
+    switch (ztgetflag(nameu)) {
     case -1:
 	break;
     case 0:
@@ -205,7 +207,7 @@
 	pm->node.flags |= PM_SCALAR;
 	return &pm->node;
     }
-    if ((tcstr = tgetstr(name, &u)) != NULL && tcstr != (char *)-1) {
+    if ((tcstr = tgetstr(nameu, &u)) != NULL && tcstr != (char *)-1) {
 	pm->u.str = dupstring(tcstr);
 	pm->node.flags |= PM_SCALAR;
     } else {
@@ -324,12 +326,12 @@
     NULL, 0,
 #endif
     NULL, 0,
+    NULL, 0,
 #ifdef HAVE_TGETENT
     partab, sizeof(partab)/sizeof(*partab),
 #else
     NULL, 0,
 #endif
-    NULL, 0,
     0
 };
 
@@ -344,7 +346,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -352,7 +354,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -371,7 +373,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/terminfo.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/terminfo.c,v
retrieving revision 1.29
diff -u -r1.29 terminfo.c
--- Src/Modules/terminfo.c	28 May 2007 22:57:41 -0000	1.29
+++ Src/Modules/terminfo.c	6 Jul 2007 20:57:54 -0000
@@ -129,10 +129,10 @@
 
 /**/
 static HashNode
-getterminfo(UNUSED(HashTable ht), char *name)
+getterminfo(UNUSED(HashTable ht), const char *name)
 {
     int len, num;
-    char *tistr;
+    char *tistr, *nameu;
     Param pm = NULL;
 
     /* This depends on the termcap stuff in init.c */
@@ -141,21 +141,22 @@
     if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
 	return NULL;
 
-    unmetafy(name, &len);
+    nameu = dupstring(name);
+    unmetafy(nameu, &len);
 
     pm = (Param) hcalloc(sizeof(struct param));
-    pm->node.nam = dupstring(name);
+    pm->node.nam = nameu;
     pm->node.flags = PM_READONLY;
 
-    if (((num = tigetnum(name)) != -1) && (num != -2)) {
+    if (((num = tigetnum(nameu)) != -1) && (num != -2)) {
 	pm->u.val = num;
 	pm->node.flags |= PM_INTEGER;
 	pm->gsu.i = &nullsetinteger_gsu;
-    } else if ((num = tigetflag(name)) != -1) {
+    } else if ((num = tigetflag(nameu)) != -1) {
 	pm->u.str = num ? dupstring("yes") : dupstring("no");
 	pm->node.flags |= PM_SCALAR;
 	pm->gsu.s = &nullsetscalar_gsu;
-    } else if ((tistr = (char *)tigetstr(name)) != NULL && tistr != (char *)-1) {
+    } else if ((tistr = (char *)tigetstr(nameu)) != NULL && tistr != (char *)-1) {
 	pm->u.str = dupstring(tistr);
 	pm->node.flags |= PM_SCALAR;
 	pm->gsu.s = &nullsetscalar_gsu;
@@ -298,12 +299,12 @@
     NULL, 0,
 #endif
     NULL, 0,
+    NULL, 0,
 #ifdef USE_TERMINFO_MODULE
     partab, sizeof(partab)/sizeof(*partab),
 #else
     NULL, 0,
 #endif
-    NULL, 0,
     0
 };
 
@@ -318,7 +319,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -326,7 +327,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -349,7 +350,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/zftp.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zftp.c,v
retrieving revision 1.44
diff -u -r1.44 zftp.c
--- Src/Modules/zftp.c	29 May 2007 17:01:09 -0000	1.44
+++ Src/Modules/zftp.c	6 Jul 2007 20:57:55 -0000
@@ -3181,7 +3181,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -3189,7 +3189,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -3221,7 +3221,7 @@
 {
     deletehookfunc("exit", zftpexithook);
     zftp_cleanup();
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/zprof.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zprof.c,v
retrieving revision 1.7
diff -u -r1.7 zprof.c
--- Src/Modules/zprof.c	28 May 2007 22:57:41 -0000	1.7
+++ Src/Modules/zprof.c	6 Jul 2007 20:57:55 -0000
@@ -225,7 +225,7 @@
     struct timezone dummy;
     double prev = 0, now;
 
-    if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
+    if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) {
         active = 1;
         if (!(f = findpfunc(name))) {
             f = (Pfunc) zalloc(sizeof(*f));
@@ -260,7 +260,7 @@
     }
     runshfunc(prog, w, name);
     if (active) {
-        if (zprof_module && !(zprof_module->flags & MOD_UNLOAD)) {
+        if (zprof_module && !(zprof_module->node.flags & MOD_UNLOAD)) {
             tv.tv_sec = tv.tv_usec = 0;
             gettimeofday(&tv, &dummy);
 
@@ -315,7 +315,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -323,7 +323,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -345,7 +345,7 @@
     freepfuncs(calls);
     freeparcs(arcs);
     deletewrapper(m, wrapper);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/zpty.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zpty.c,v
retrieving revision 1.35
diff -u -r1.35 zpty.c
--- Src/Modules/zpty.c	28 May 2007 22:57:41 -0000	1.35
+++ Src/Modules/zpty.c	6 Jul 2007 20:57:55 -0000
@@ -750,7 +750,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -758,7 +758,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -777,7 +777,7 @@
 {
     deletehookfunc("exit", ptyhook);
     deleteallptycmds();
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/zselect.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zselect.c,v
retrieving revision 1.9
diff -u -r1.9 zselect.c
--- Src/Modules/zselect.c	28 May 2007 22:57:41 -0000	1.9
+++ Src/Modules/zselect.c	6 Jul 2007 20:58:00 -0000
@@ -294,7 +294,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -302,7 +302,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -317,7 +317,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Modules/zutil.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/zutil.c,v
retrieving revision 1.22
diff -u -r1.22 zutil.c
--- Src/Modules/zutil.c	8 Jun 2007 13:58:40 -0000	1.22
+++ Src/Modules/zutil.c	6 Jul 2007 20:58:00 -0000
@@ -1801,10 +1801,10 @@
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
     BUILTIN("zformat", 0, bin_zformat, 3, -1, 0, NULL, NULL),
-    BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
     BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL),
+    BUILTIN("zregexparse", 0, bin_zregexparse, 3, -1, 0, "c", NULL),
+    BUILTIN("zstyle", 0, bin_zstyle, 0, -1, 0, NULL, NULL),
 };
 
 static struct features module_features = {
@@ -1828,7 +1828,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -1836,7 +1836,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -1850,7 +1850,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/compctl.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compctl.c,v
retrieving revision 1.33
diff -u -r1.33 compctl.c
--- Src/Zle/compctl.c	28 May 2007 22:57:42 -0000	1.33
+++ Src/Zle/compctl.c	6 Jul 2007 20:58:00 -0000
@@ -3938,8 +3938,8 @@
 
 
 static struct builtin bintab[] = {
-    BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
     BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
+    BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
 };
 
 static struct features module_features = {
@@ -3974,7 +3974,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -3982,7 +3982,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -4000,7 +4000,7 @@
 {
     deletehookfunc("compctl_make", (Hookfn) ccmakehookfn);
     deletehookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/complete.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complete.c,v
retrieving revision 1.38
diff -u -r1.38 complete.c
--- Src/Zle/complete.c	18 Jun 2007 13:25:10 -0000	1.38
+++ Src/Zle/complete.c	6 Jul 2007 20:58:00 -0000
@@ -1445,10 +1445,10 @@
 };
 
 static struct conddef cotab[] = {
+    CONDDEF("after", 0, cond_range, 1, 1, 0),
+    CONDDEF("between", 0, cond_range, 2, 2, 1),
     CONDDEF("prefix", 0, cond_psfix, 1, 2, CVT_PREPAT),
     CONDDEF("suffix", 0, cond_psfix, 1, 2, CVT_SUFPAT),
-    CONDDEF("between", 0, cond_range, 2, 2, 1),
-    CONDDEF("after", 0, cond_range, 1, 1, 0),
 };
 
 static struct funcwrap wrapper[] = {
@@ -1502,7 +1502,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -1510,7 +1510,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -1524,7 +1524,7 @@
     addhookfunc("reverse_menu", (Hookfn) reverse_menu);
     addhookfunc("list_matches", (Hookfn) list_matches);
     addhookfunc("invalidate_list", (Hookfn) invalidate_list);
-    (void)addhookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks));
+    (void)addhookdefs(m, comphooks, sizeof(comphooks)/sizeof(*comphooks));
     return addwrapper(m, wrapper);
 }
 
@@ -1539,10 +1539,10 @@
     deletehookfunc("reverse_menu", (Hookfn) reverse_menu);
     deletehookfunc("list_matches", (Hookfn) list_matches);
     deletehookfunc("invalidate_list", (Hookfn) invalidate_list);
-    (void)deletehookdefs(m->nam, comphooks,
+    (void)deletehookdefs(m, comphooks,
 			 sizeof(comphooks)/sizeof(*comphooks));
     deletewrapper(m, wrapper);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/complist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complist.c,v
retrieving revision 1.104
diff -u -r1.104 complist.c
--- Src/Zle/complist.c	28 May 2007 22:57:42 -0000	1.104
+++ Src/Zle/complist.c	6 Jul 2007 20:58:00 -0000
@@ -3238,7 +3238,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -3246,7 +3246,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -3261,7 +3261,8 @@
     w_menuselect = addzlefunction("menu-select", menuselect,
                                     ZLE_MENUCMP|ZLE_KEEPSUFFIX|ZLE_ISCOMP);
     if (!w_menuselect) {
-	zwarnnam(m->nam, "name clash when adding ZLE function `menu-select'");
+	zwarnnam(m->node.nam,
+		 "name clash when adding ZLE function `menu-select'");
 	return -1;
     }
     addhookfunc("comp_list_matches", (Hookfn) complistmatches);
@@ -3302,7 +3303,7 @@
     deletehookfunc("menu_start", (Hookfn) domenuselect);
     unlinkkeymap("menuselect", 1);
     unlinkkeymap("listscroll", 1);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/computil.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/computil.c,v
retrieving revision 1.104
diff -u -r1.104 computil.c
--- Src/Zle/computil.c	27 Jun 2007 13:56:12 -0000	1.104
+++ Src/Zle/computil.c	6 Jul 2007 20:58:00 -0000
@@ -4544,14 +4544,14 @@
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
     BUILTIN("comparguments", 0, bin_comparguments, 1, -1, 0, NULL, NULL),
-    BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL),
+    BUILTIN("compdescribe", 0, bin_compdescribe, 3, -1, 0, NULL, NULL),
+    BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL),
+    BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL),
     BUILTIN("compquote", 0, bin_compquote, 1, -1, 0, "p", NULL),
     BUILTIN("comptags", 0, bin_comptags, 1, -1, 0, NULL, NULL),
     BUILTIN("comptry", 0, bin_comptry, 0, -1, 0, NULL, NULL),
-    BUILTIN("compfiles", 0, bin_compfiles, 1, -1, 0, NULL, NULL),
-    BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL),
+    BUILTIN("compvalues", 0, bin_compvalues, 1, -1, 0, NULL, NULL)
 };
 
 static struct features module_features = {
@@ -4581,7 +4581,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -4589,7 +4589,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -4603,7 +4603,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/deltochar.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/deltochar.c,v
retrieving revision 1.7
diff -u -r1.7 deltochar.c
--- Src/Zle/deltochar.c	28 May 2007 22:57:42 -0000	1.7
+++ Src/Zle/deltochar.c	6 Jul 2007 20:58:00 -0000
@@ -95,7 +95,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -103,7 +103,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -119,7 +119,7 @@
 	    return 0;
 	deletezlefunction(w_deletetochar);
     }
-    zwarnnam(m->nam, "deltochar: name clash when adding ZLE functions");
+    zwarnnam(m->node.nam, "deltochar: name clash when adding ZLE functions");
     return -1;
 }
 
@@ -129,7 +129,7 @@
 {
     deletezlefunction(w_deletetochar);
     deletezlefunction(w_zaptochar);
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.98
diff -u -r1.98 zle_main.c
--- Src/Zle/zle_main.c	29 May 2007 17:01:09 -0000	1.98
+++ Src/Zle/zle_main.c	6 Jul 2007 20:58:05 -0000
@@ -1827,7 +1827,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -1835,7 +1835,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -1844,7 +1844,7 @@
 {
     addhookfunc("before_trap", (Hookfn) zlebeforetrap);
     addhookfunc("after_trap", (Hookfn) zleaftertrap);
-    (void)addhookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
+    (void)addhookdefs(m, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
     return 0;
 }
 
@@ -1853,13 +1853,14 @@
 cleanup_(Module m)
 {
     if(zleactive) {
-	zerrnam(m->nam, "can't unload the zle module while zle is active");
+	zerrnam(m->node.nam,
+		"can't unload the zle module while zle is active");
 	return 1;
     }
     deletehookfunc("before_trap", (Hookfn) zlebeforetrap);
     deletehookfunc("after_trap", (Hookfn) zleaftertrap);
-    (void)deletehookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
-    return setfeatureenables(m->nam, &module_features, NULL);
+    (void)deletehookdefs(m, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Src/Zle/zleparameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zleparameter.c,v
retrieving revision 1.8
diff -u -r1.8 zleparameter.c
--- Src/Zle/zleparameter.c	28 May 2007 22:57:42 -0000	1.8
+++ Src/Zle/zleparameter.c	6 Jul 2007 20:58:05 -0000
@@ -56,7 +56,7 @@
 
 /**/
 static HashNode
-getpmwidgets(UNUSED(HashTable ht), char *name)
+getpmwidgets(UNUSED(HashTable ht), const char *name)
 {
     Param pm = NULL;
     Thingy th;
@@ -129,16 +129,16 @@
 { keymapsgetfn, arrsetfn, stdunsetfn };
 
 static struct paramdef partab[] = {
-    SPECIALPMDEF("widgets", PM_READONLY,
-		 &zlestdhash_gsu, getpmwidgets, scanpmwidgets),
     SPECIALPMDEF("keymaps", PM_ARRAY|PM_READONLY, &keymaps_gsu, NULL, NULL),
+    SPECIALPMDEF("widgets", PM_READONLY,
+		 &zlestdhash_gsu, getpmwidgets, scanpmwidgets)
 };
 
 static struct features module_features = {
     NULL, 0,
     NULL, 0,
-    partab, sizeof(partab)/sizeof(*partab),
     NULL, 0,
+    partab, sizeof(partab)/sizeof(*partab),
     0
 };
 
@@ -153,7 +153,7 @@
 int
 features_(Module m, char ***features)
 {
-    *features = featuresarray(m->nam, &module_features);
+    *features = featuresarray(m, &module_features);
     return 0;
 }
 
@@ -161,7 +161,7 @@
 int
 enables_(Module m, int **enables)
 {
-    return handlefeatures(m->nam, &module_features, enables);
+    return handlefeatures(m, &module_features, enables);
 }
 
 /**/
@@ -175,7 +175,7 @@
 int
 cleanup_(Module m)
 {
-    return setfeatureenables(m->nam, &module_features, NULL);
+    return setfeatureenables(m, &module_features, NULL);
 }
 
 /**/
Index: Test/V01zmodload.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/V01zmodload.ztst,v
retrieving revision 1.9
diff -u -r1.9 V01zmodload.ztst
--- Test/V01zmodload.ztst	26 Jun 2007 19:38:34 -0000	1.9
+++ Test/V01zmodload.ztst	6 Jul 2007 20:58:05 -0000
@@ -39,6 +39,9 @@
    fi
  }
 
+ mkdir zmodload.tmp
+ cd zmodload.tmp
+
 %test
 
 # This first test depends on knowing that zsh is run with +Z from the
@@ -118,10 +121,85 @@
    zmodload -ab zsh/example example
    builtin example
    zmodload -e zsh/example
- else print -u8 Warning: zsh/example not linked: not checking autoloading
+ else print -u$ZTST_fd Warning: zsh/example not linked: not checking autoloading
  fi
 0d:Autoload a module via a builtin
 
+  zmodload -u zsh/example
+  builtin example
+0d:Autoloads are persistent
+
+  (zmodload -u zsh/parameter
+  zmodload -aF zsh/parameter b:fail
+  fail
+  print "Shouldn't get here.")
+1:Failed builtin autoload
+?(eval):3: module `zsh/parameter' has no such feature: `b:fail': autoload cancelled
+?(eval):3: unknown builtin: fail
+
+  (zmodload -u zsh/parameter
+  zmodload -aF zsh/parameter p:fail
+  print $fail
+  print "Shouldn't get here.")
+1:Failed parameter autoload
+?(eval):3: module `zsh/parameter' has no such feature: `p:fail': autoload cancelled
+?(eval):3: unknown parameter: fail
+
+  (zmodload -u zsh/parameter
+  zmodload -aF zsh/parameter c:fail
+  [[ -fail foo ]]
+  print "Shouldn't get here.")
+2:Failed condition autoload
+?(eval):3: module `zsh/parameter' has no such feature: `c:fail': autoload cancelled
+?(eval):3: unknown condition: -foo
+
+  (zmodload -u zsh/parameter
+  zmodload -aF zsh/parameter f:fail
+  (( fail() )) )
+2:Failed math function autoload
+?(eval):3: module `zsh/parameter' has no such feature: `f:fail': autoload cancelled
+?(eval):3: unknown function: fail
+
+  zmodload -aF zsh/parameter f:fail2
+1:Immediate autoload failure on non-existent feature when module loaded
+?(eval):zmodload:1: module `zsh/parameter' has no such feature: `f:fail2'
+
+  (zmodload -u zsh/parameter
+  zmodload -aF zsh/parameter p:fail
+  print $(( ${#modules} > 1 )) )
+0:Autoloads checked on loading but don't necessarily effect current command
+>1
+?(eval):3: module `zsh/parameter' has no such feature: `p:fail': autoload cancelled
+
+  zmodload -laF zsh/parameter
+0:List default autoloads
+>p:aliases
+>p:builtins
+>p:commands
+>p:dirstack
+>p:dis_aliases
+>p:dis_builtins
+>p:dis_functions
+>p:dis_galiases
+>p:dis_reswords
+>p:dis_saliases
+>p:funcstack
+>p:functions
+>p:functrace
+>p:galiases
+>p:history
+>p:historywords
+>p:jobdirs
+>p:jobstates
+>p:jobtexts
+>p:modules
+>p:nameddirs
+>p:options
+>p:parameters
+>p:reswords
+>p:saliases
+>p:userdirs
+
  if [[ $mods[(r)zsh/example] == zsh/example ]]; then
    zmodload -u zsh/example
    zmodload -ac -I zsh/example ex
@@ -169,6 +247,11 @@
  zmodload -e example
 1:Delete the module alias again
 
+  zmodload >zmodload_list
+  print -l ${(o)mods} >mods_list
+  diff zmodload_list mods_list
+0:Listing with zmodload should give all our modules.
+
 # Don't unload the main module.
 # Do unload zsh/parameter, but reload it as it is needed.
 

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author