about summary refs log tree commit diff
path: root/Src/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/module.c')
-rw-r--r--Src/module.c413
1 files changed, 336 insertions, 77 deletions
diff --git a/Src/module.c b/Src/module.c
index 63e0dc2f6..e943fb397 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -88,6 +88,27 @@ register_module(char *n, Module_func setup, Module_func boot,
     zaddlinknode(linkedmodules, m);
 }
 
+/* Print an alias. */
+
+/**/
+static void
+printmodalias(Module m, char *ops)
+{
+    if (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. */
 
 /**/
@@ -164,6 +185,15 @@ addwrapper(Module m, FuncWrap w)
 {
     FuncWrap p, q;
 
+    /*
+     * We can't add a wrapper to an alias, since it's supposed
+     * to behave identically to the resolved module.  This shouldn't
+     * happen since we usually add wrappers when a real module is
+     * loaded.
+     */
+    if (m->flags & MOD_ALIAS)
+	return 1;
+
     if (w->flags & WRAPF_ADDED)
 	return 1;
     for (p = wrappers, q = NULL; p; q = p, p = p->next);
@@ -196,7 +226,7 @@ mod_export LinkList modules;
 int
 add_autobin(char *nam, char *module)
 {
-    Builtin bn = zcalloc(sizeof(*bn));
+    Builtin bn = zshcalloc(sizeof(*bn));
     bn->nam = ztrdup(nam);
     bn->optstr = ztrdup(module);
     return addbuiltin(bn);
@@ -256,6 +286,9 @@ deletewrapper(Module m, FuncWrap w)
 {
     FuncWrap p, q;
 
+    if (m->flags & MOD_ALIAS)
+	return 1;
+
     if (w->flags & WRAPF_ADDED) {
 	for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next);
 
@@ -292,7 +325,8 @@ load_and_bind(const char *fn)
 	int err = loadbind(0, (void *) addbuiltin, ret);
 	for (node = firstnode(modules); !err && node; incnode(node)) {
 	    Module m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & MOD_LINKED))
+	    if (!(m->flags & MOD_ALIAS) &&
+		m->u.handle && !(m->flags & MOD_LINKED))
 		err |= loadbind(0, m->u.handle, ret);
 	}
 
@@ -431,21 +465,78 @@ do_load_module(char const *name)
 /**/
 #endif /* !DYNAMIC */
 
+/*
+ * Find a module in the list.
+ * If aliasp is non-zero, resolve any aliases to the underlying module.
+ * If namep is set, this is set to point to the last alias value resolved,
+ *   even if that module was not loaded. or the module name if no aliases.
+ *   Hence this is always the physical module to load in a chain of aliases.
+ * 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
-find_module(const char *name)
+find_module(const char *name, int aliasp, const char **namep)
 {
     Module m;
     LinkNode node;
 
     for (node = firstnode(modules); node; incnode(node)) {
 	m = (Module) getdata(node);
-	if (!strcmp(m->nam, name))
+	if (!strcmp(m->nam, name)) {
+	    if (aliasp && (m->flags & MOD_ALIAS)) {
+		if (namep)
+		    *namep = m->u.alias;
+		return find_module(m->u.alias, 1, namep);
+	    }
+	    if (namep)
+		*namep = m->nam;
 	    return node;
+	}
     }
     return NULL;
 }
 
+/*
+ * Unlink and free a module node from the linked list.
+ */
+
+/**/
+static void
+delete_module(LinkNode node)
+{
+    Module m = (Module) remnode(modules, node);
+
+    if (m->flags & MOD_ALIAS)
+	zsfree(m->u.alias);
+    zsfree(m->nam);
+    if (m->deps)
+	freelinklist(m->deps, freestr);
+    zfree(m, sizeof(*m));
+}
+
+/**/
+mod_export int
+module_loaded(const char *name)
+{
+    LinkNode node;
+    Module m;
+
+    return ((node = find_module(name, 1, NULL)) &&
+	    (m = ((Module) getdata(node)))->u.handle &&
+	    !(m->flags & MOD_UNLOAD));
+}
+
+/*
+ * Setup and cleanup functions:  we don't search for aliases here,
+ * since they should have been resolved before we try to load or unload
+ * the module.
+ */
+
 /**/
 #ifdef DYNAMIC
 
@@ -654,7 +745,7 @@ modname_ok(char const *p)
 }
 
 /**/
-int
+mod_export int
 load_module(char const *name)
 {
     Module m;
@@ -667,11 +758,19 @@ load_module(char const *name)
 	zerr("invalid module name `%s'", name, 0);
 	return 0;
     }
-    if (!(node = find_module(name))) {
+    /*
+     * The following function call may alter name to the final name in a
+     * chain of aliases.  This makes sure the actual module loaded
+     * is the right one.
+     */
+    queue_signals();
+    if (!(node = find_module(name, 1, &name))) {
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
-	m = zcalloc(sizeof(*m));
+	}
+	m = zshcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	if (handle) {
 	    m->u.handle = handle;
@@ -685,23 +784,26 @@ load_module(char const *name)
 	if ((set = setup_module(m)) || boot_module(m)) {
 	    if (!set)
 		finish_module(m);
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
-	    m->flags &= ~MOD_SETUP;
+	    delete_module(node);
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S | MOD_INIT_B;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 1;
     } 
     m = (Module) getdata(node);
-    if (m->flags & MOD_SETUP)
+    if (m->flags & MOD_SETUP) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_UNLOAD)
 	m->flags &= ~MOD_UNLOAD;
-    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle)
+    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_BUSY) {
 	zerr("circular dependencies for module %s", name, 0);
 	return 0;
@@ -711,14 +813,17 @@ load_module(char const *name)
 	for (n = firstnode(m->deps); n; incnode(n))
 	    if (!load_module((char *) getdata(n))) {
 		m->flags &= ~MOD_BUSY;
+		unqueue_signals();
 		return 0;
 	    }
     m->flags &= ~MOD_BUSY;
     if (!m->u.handle) {
 	handle = NULL;
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
+	}
 	if (handle) {
 	    m->u.handle = handle;
 	    m->flags |= MOD_SETUP;
@@ -732,6 +837,7 @@ load_module(char const *name)
 	    else
 		m->u.linked = NULL;
 	    m->flags &= ~MOD_SETUP;
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S;
@@ -744,10 +850,12 @@ load_module(char const *name)
 	else
 	    m->u.handle = NULL;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 0;
     }
     m->flags |= MOD_INIT_B;
     m->flags &= ~MOD_SETUP;
+    unqueue_signals();
     return 1;
 }
 
@@ -761,38 +869,50 @@ load_module(char const *name)
 
 /**/
 mod_export int
-require_module(char *nam, char *module, int res, int test)
+require_module(char *nam, const char *module, int res, int test)
 {
     Module m = NULL;
     LinkNode node;
+    int ret = 1;
 
-    /* First see if the module is linked in. */
-    for (node = firstnode(linkedmodules); node; incnode(node)) {
-	if (!strcmp((char *) getdata(node), nam))
-	    return 1;
-    }
-    node = find_module(module);
+    /* 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)) {
 	if (test) {
+	    unqueue_signals();
 	    zwarnnam(nam, "module %s already loaded.", module, 0);
 	    return 0;
 	}
     } else
-	return load_module(module);
+	ret = load_module(module);
+    unqueue_signals();
 
-    return 1;
+    return ret;
 }
 
 /**/
 void
-add_dep(char *name, char *from)
+add_dep(const char *name, char *from)
 {
     LinkNode node;
     Module m;
 
-    if (!(node = find_module(name))) {
-	m = zcalloc(sizeof(*m));
+    /*
+     * If we were passed an alias, we must resolve it to a final
+     * module name (and maybe add the corresponding struct), since otherwise
+     * we would need to check all modules to see if they happen
+     * to be aliased to the same thing to implement depencies properly.
+     *
+     * This should mean that an attempt to add an alias which would
+     * have the same name as a module which has dependencies is correctly
+     * rejected, because then the module named already exists as a non-alias.
+     * Better make sure.  (There's no problem making a an alias which
+     * *points* to a module with dependencies, of course.)
+     */
+    if (!(node = find_module(name, 1, &name))) {
+	m = zshcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	zaddlinknode(modules, m);
     } else
@@ -838,12 +958,23 @@ autoloadscan(HashNode hn, int printflags)
 int
 bin_zmodload(char *nam, char **args, char *ops, int func)
 {
-    if ((ops['b'] || ops['c'] || ops['p'] || ops['f']) &&
-	!(ops['a'] || ops['u'])) {
+    int ops_bcpf = ops['b'] || ops['c'] || ops['p'] || ops['f'];
+    int ops_au = ops['a'] || ops['u'];
+    int ret = 1;
+
+    if (ops_bcpf && !ops_au) {
 	zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u",
 		 NULL, 0);
 	return 1;
     }
+    if (ops['A'] || ops['R']) {
+	if (ops_bcpf || ops_au || ops['d'] || (ops['R'] && ops['e'])) {
+	    zwarnnam(nam, "illegal flags combined with -A or -R", NULL, 0);
+	    return 1;
+	}
+	if (!ops['e'])
+	    return bin_zmodload_alias(nam, args, ops);
+    }
     if (ops['d'] && ops['a']) {
 	zwarnnam(nam, "-d cannot be combined with -a", NULL, 0);
 	return 1;
@@ -857,24 +988,137 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
 	zwarnnam(nam, "-e cannot be combined with other options", NULL, 0);
 	return 1;
     }
+    queue_signals();
     if (ops['e'])
-	return bin_zmodload_exist(nam, args, ops);
+	ret = bin_zmodload_exist(nam, args, ops);
     else if (ops['d'])
-	return bin_zmodload_dep(nam, args, ops);
+	ret = bin_zmodload_dep(nam, args, ops);
     else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'] || ops['f']))
-	return bin_zmodload_auto(nam, args, ops);
+	ret = bin_zmodload_auto(nam, args, ops);
     else if (ops['c'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_cond(nam, args, ops);
+	ret = bin_zmodload_cond(nam, args, ops);
     else if (ops['f'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_math(nam, args, ops);
+	ret = bin_zmodload_math(nam, args, ops);
     else if (ops['p'] && !(ops['b'] || ops['c']))
-	return bin_zmodload_param(nam, args, ops);
+	ret = bin_zmodload_param(nam, args, ops);
     else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p']))
-	return bin_zmodload_load(nam, args, ops);
+	ret = bin_zmodload_load(nam, args, ops);
     else
 	zwarnnam(nam, "use only one of -b, -c, or -p", NULL, 0);
+    unqueue_signals();
 
-    return 1;
+    return ret;
+}
+
+/**/
+static int
+bin_zmodload_alias(char *nam, char **args, char *ops)
+{
+    /*
+     * TODO: while it would be too nasty to have aliases, as opposed
+     * to real loadable modules, with dependencies --- just what would
+     * we need to load when, exactly? --- there is in principle no objection
+     * to making it possible to force an alias onto an existing unloaded
+     * module which has dependencies.  This would simply transfer
+     * the dependencies down the line to the aliased-to module name.
+     * This is actually useful, since then you can alias zsh/zle=mytestzle
+     * to load another version of zle.  But then what happens when the
+     * alias is removed?  Do you transfer the dependencies back? And
+     * suppose other names are aliased to the same file?  It might be
+     * kettle of fish best left unwormed.
+     */
+    LinkNode node;
+    Module m;
+    int ret = 0;
+
+    if (!*args) {
+	if (ops['R']) {
+	    zwarnnam(nam, "no module alias to remove", NULL, 0);
+	    return 1;
+	}
+	for (node = firstnode(modules); node; incnode(node)) {
+	    m = (Module) getdata(node);
+	    if (m->flags & MOD_ALIAS)
+		printmodalias(m, ops);
+	}
+	return 0;
+    }
+
+    for (; !ret && *args; args++) {
+	char *eqpos = strchr(*args, '=');
+	char *aliasname = eqpos ? eqpos+1 : NULL;
+	if (eqpos)
+	    *eqpos = '\0';
+	if (!modname_ok(*args)) {
+	    zwarnnam(nam, "invalid module name `%s'", *args, 0);
+	    return 1;
+	}
+	if (ops['R']) {
+	    if (aliasname) {
+		zwarnnam(nam, "bad syntax for removing module alias: %s",
+			 *args, 0);
+		return 1;
+	    }
+	    node = find_module(*args, 0, NULL);
+	    if (node) {
+		m = (Module) getdata(node);
+		if (!(m->flags & MOD_ALIAS)) {
+		    zwarnnam(nam, "module is not an alias: %s", *args, 0);
+		    ret = 1;
+		    break;
+		}
+		delete_module(node);
+	    } else {
+		zwarnnam(nam, "no such module alias: %s", *args, 0);
+		return 1;
+	    }
+	} else {
+	    if (aliasname) {
+		const char *mname = aliasname;
+		if (!modname_ok(aliasname)) {
+		    zwarnnam(nam, "invalid module name `%s'", aliasname, 0);
+		    return 1;
+		}
+		find_module(aliasname, 1, &mname);
+		if (!strcmp(mname, *args)) {
+		    zwarnnam(nam, "module alias would refer to itself: %s",
+			     *args, 0);
+		    return 1;
+		}
+		node = find_module(*args, 0, NULL);
+		if (node) {
+		    m = (Module) getdata(node);
+		    if (!(m->flags & MOD_ALIAS)) {
+			zwarnnam(nam, "module is not an alias: %s", *args, 0);
+			return 1;
+		    }
+		    zsfree(m->u.alias);
+		} else {
+		    m = (Module) zshcalloc(sizeof(*m));
+		    m->nam = ztrdup(*args);
+		    m->flags = MOD_ALIAS;
+		    zaddlinknode(modules, 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);
+		    else {
+			zwarnnam(nam, "module is not an alias: %s",
+				 *args, 0);
+			return 1;
+		    }
+		} else {
+		    zwarnnam(nam, "no such module alias: %s", *args, 0);
+		    return 1;
+		}
+	    }
+	}
+    }
+
+    return 0;
 }
 
 /**/
@@ -883,28 +1127,33 @@ bin_zmodload_exist(char *nam, char **args, char *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 (ops['A'] && (node2 = find_module(m->u.alias, 1, NULL)))
+		    m = (Module) getdata(node2);
+		else
+		    continue;
+	    } 
 	    if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
-		nicezputs(m->nam, stdout);
+		nicezputs(modname, stdout);
 		putchar('\n');
 	    }
 	}
 	return 0;
     } else {
-	int ret = 0, f;
+	int ret = 0;
 
 	for (; !ret && *args; args++) {
-	    f = 0;
-	    for (node = firstnode(modules);
-		 !f && node; incnode(node)) {
-		m = (Module) getdata(node);
-		if (m->u.handle && !(m->flags & MOD_UNLOAD))
-		    f = !strcmp(*args, m->nam);
-	    }
-	    ret = !f;
+	    if (!(node = find_module(*args, 1, NULL))
+		|| !(m = (Module) getdata(node))->u.handle
+		|| (m->flags & MOD_UNLOAD))
+		ret = 1;
 	}
 	return ret;
     }
@@ -916,23 +1165,24 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 {
     LinkNode node;
     Module m;
-    if(ops['u']) {
-	/* remove dependencies */
-	char *tnam = *args++;
-	node = find_module(tnam);
+    if (ops['u']) {
+	/* remove dependencies, which can't pertain to aliases */
+	const char *tnam = *args++;
+	node = find_module(tnam, 1, &tnam);
 	if (!node)
 	    return 0;
 	m = (Module) getdata(node);
-	if(*args && m->deps) {
+	if (*args && m->deps) {
 	    do {
-		for(node = firstnode(m->deps); node; incnode(node))
-		    if(!strcmp(*args, getdata(node))) {
-			zsfree(getdata(node));
-			remnode(m->deps, node);
+		LinkNode dnode;
+		for (dnode = firstnode(m->deps); dnode; incnode(dnode))
+		    if (!strcmp(*args, getdata(dnode))) {
+			zsfree(getdata(dnode));
+			remnode(m->deps, dnode);
 			break;
 		    }
 	    } while(*++args);
-	    if(empty(m->deps)) {
+	    if (empty(m->deps)) {
 		freelinklist(m->deps, freestr);
 		m->deps = NULL;
 	    }
@@ -942,19 +1192,16 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 		m->deps = NULL;
 	    }
 	}
-	if (!m->deps && !m->u.handle) {
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
-	}
+	if (!m->deps && !m->u.handle)
+	    delete_module(node);
 	return 0;
-    } else if(!args[0] || !args[1]) {
+    } 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(ops['L']) {
+		if (ops['L']) {
 		    printf("zmodload -d ");
 		    if(m->nam[0] == '-')
 			fputs("-- ", stdout);
@@ -979,7 +1226,7 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 	int ret = 0;
 	char *tnam = *args++;
 
-	for(; *args; args++)
+	for (; *args; args++)
 	    add_dep(tnam, *args);
 	return ret;
     }
@@ -1099,7 +1346,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
     int ret = 0;
 
     if (ops['u']) {
-	/* remove autoloaded conditions */
+	/* remove autoloaded math functions */
 	for (; *args; args++) {
 	    MathFunc f = getmathfunc(*args, 0);
 
@@ -1108,7 +1355,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
 		    zwarnnam(nam, "%s: no such math function", *args, 0);
 		    ret = 1;
 		}
-	    } else if (f->flags & CONDF_ADDED) {
+	    } else if (f->flags & MFF_ADDED) {
 		zwarnnam(nam, "%s: math function is already defined", *args, 0);
 		ret = 1;
 	    } else
@@ -1130,7 +1377,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
 	}
 	return 0;
     } else {
-	/* add autoloaded conditions */
+	/* add autoloaded math functions */
 	char *modnam;
 
 	modnam = *args++;
@@ -1209,6 +1456,15 @@ bin_zmodload_param(char *nam, char **args, char *ops)
 int
 unload_module(Module m, LinkNode node)
 {
+    /*
+     * Only unload the real module, so resolve aliases.
+     */
+    if (m->flags & MOD_ALIAS) {
+	LinkNode node = find_module(m->u.alias, 1, NULL);
+	if (!node)
+	    return 1;
+	m = (Module) getdata(node);
+    }
     if ((m->flags & MOD_INIT_S) &&
 	!(m->flags & MOD_UNLOAD) &&
 	((m->flags & MOD_LINKED) ?
@@ -1242,7 +1498,7 @@ unload_module(Module m, LinkNode node)
 	    LinkNode n;
 
 	    for (n = firstnode(m->deps); n; incnode(n)) {
-		LinkNode dn = find_module((char *) getdata(n));
+		LinkNode dn = find_module((char *) getdata(n), 1, NULL);
 		Module dm;
 
 		if (dn && (dm = (Module) getdata(dn)) &&
@@ -1280,9 +1536,7 @@ unload_module(Module m, LinkNode node)
 		if (!node)
 		    return 1;
 	    }
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
+	    delete_module(node);
 	}
     }
     return 0;
@@ -1297,8 +1551,9 @@ bin_zmodload_load(char *nam, char **args, char *ops)
     int ret = 0;
     if(ops['u']) {
 	/* unload modules */
+	const char *mname = *args;
 	for(; *args; args++) {
-	    node = find_module(*args);
+	    node = find_module(*args, 1, &mname);
 	    if (node) {
 		LinkNode mn, dn;
 		int del = 0;
@@ -1307,11 +1562,11 @@ bin_zmodload_load(char *nam, char **args, char *ops)
 		    m = (Module) getdata(mn);
 		    if (m->deps && m->u.handle)
 			for (dn = firstnode(m->deps); dn; incnode(dn))
-			    if (!strcmp((char *) getdata(dn), *args)) {
+			    if (!strcmp((char *) getdata(dn), mname)) {
 				if (m->flags & MOD_UNLOAD)
 				    del = 1;
 				else {
-				    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0);
+				    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname, 0);
 				    ret = 1;
 				    goto cont;
 				}
@@ -1335,7 +1590,7 @@ bin_zmodload_load(char *nam, char **args, char *ops)
 	/* list modules */
 	for (node = firstnode(modules); node; incnode(node)) {
 	    m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
+	    if (m->u.handle && !(m->flags & (MOD_UNLOAD|MOD_ALIAS))) {
 		if(ops['L']) {
 		    printf("zmodload ");
 		    if(m->nam[0] == '-')
@@ -1761,12 +2016,14 @@ add_autoparam(char *nam, char *module)
 {
     Param pm;
 
+    queue_signals();
     if ((pm = (Param) gethashnode2(paramtab, nam)))
 	unsetparam_pm(pm, 0, 1);
 
-    pm = setsparam(ztrdup(nam), ztrdup(module));
+    pm = setsparam(nam, ztrdup(module));
 
     pm->flags |= PM_AUTOLOAD;
+    unqueue_signals();
 }
 
 /* List of math functions. */
@@ -1862,6 +2119,8 @@ add_automathfunc(char *nam, char *module)
 
 	return 1;
     }
+    f->flags &= ~MFF_ADDED; /* still to autoload, not added yet */
+
     return 0;
 }