about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Doc/Zsh/builtins.yo8
-rw-r--r--Src/builtin.c14
-rw-r--r--Src/parse.c27
3 files changed, 43 insertions, 6 deletions
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 95c1cdf42..b0382dcd8 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -76,8 +76,9 @@ which no alias has been defined.
 findex(autoload)
 cindex(functions, autoloading)
 cindex(autoloading functions)
-item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(UXmt) ] [ var(name) ... ])(
-Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X).
+item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(UXmt) ] [ tt(-w) ] [ var(name) ... ])(
+Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X)
+and tt(-w).
 
 The flag tt(-X) may be used only inside a shell function, and may not be
 followed by a var(name).  It causes the calling function to be marked for
@@ -93,6 +94,9 @@ This does em(not) replace any existing definition of the function.  The
 exit status is nonzero (failure) if the function was already defined or
 when no definition was found.  In the latter case the function remains
 undefined and marked for autoloading.
+
+With the tt(-w) flag, the var(name)s are taken as names of wordcode
+files and all functions defined in them are marked for autoloading.
 )
 findex(bg)
 cindex(jobs, backgrounding)
diff --git a/Src/builtin.c b/Src/builtin.c
index 90ca5133c..73876b1fa 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -43,7 +43,7 @@ static struct builtin builtins[] =
     BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
     BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
     BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmr", NULL),
-    BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tUX", "u"),
+    BUILTIN("autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "tUXw", "u"),
     BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
     BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
     BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -1996,7 +1996,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 
 /* Helper for bin_functions() when run as "autoload -X" */
 
-static int
+/**/
+int
 eval_autoload(Shfunc shf, char *name, char *ops, int func)
 {
     if (!(shf->flags & PM_UNDEFINED))
@@ -2114,7 +2115,12 @@ bin_functions(char *name, char **argv, char *ops, int func)
 
     /* Take the arguments literally -- do not glob */
     for (; *argv; argv++) {
-	if ((shf = (Shfunc) shfunctab->getnode(shfunctab, *argv))) {
+	if (ops['w']) {
+	    if (dump_autoload(*argv, on, ops, func)) {
+		zwarnnam(name, "invalid wordcode file: %s", *argv, 0);
+		returnval = 1;
+	    }
+	} else if ((shf = (Shfunc) shfunctab->getnode(shfunctab, *argv))) {
 	    /* if any flag was given */
 	    if (on|off) {
 		/* turn on/off the given flags */
@@ -2140,7 +2146,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 }
 
 /**/
-static Eprog
+Eprog
 mkautofn(Shfunc shf)
 {
     Eprog p;
diff --git a/Src/parse.c b/Src/parse.c
index 373e35ab9..608e68cc7 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2801,3 +2801,30 @@ decrdumpcount(FuncDump f)
 }
 
 #endif
+
+/**/
+int
+dump_autoload(char *file, int on, char *ops, int func)
+{
+    Wordcode h;
+    FDHead n, e;
+    Shfunc shf;
+    int ret = 0;
+
+    if (!strsfx(FD_EXT, file))
+	file = dyncat(file, FD_EXT);
+
+    if (!(h = load_dump_header(file)))
+	return 1;
+
+    for (n = firstfdhead(h), e = (FDHead) (h + fdheaderlen(h)); n < e;
+	 n = nextfdhead(n)) {
+	shf = (Shfunc) zcalloc(sizeof *shf);
+	shf->flags = on;
+	shf->funcdef = mkautofn(shf);
+	shfunctab->addnode(shfunctab, ztrdup(fdname(n) + n->tail), shf);
+	if (ops['X'] && eval_autoload(shf, shf->nam, ops, func))
+	    ret = 1;
+    }
+    return ret;
+}