zsh-workers
 help / color / mirror / code / Atom feed
* Re: Default fpath
@ 2000-03-15 15:57 Sven Wischnowsky
  2000-03-15 18:15 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 2000-03-15 15:57 UTC (permalink / raw)
  To: zsh-workers



If you apply this patch and have wordcode files, you have to build
them anew, because the header format has changed slightly. zrecompile
will not be able to detect this.


Bart Schaefer wrote:

> ...
> 
> [Tagging .zwc for zsh/ksh loading:]
> } 
> }   zcompile -z comp.zwc .../Completion/*/_*
> } 
> } to have them all loaded zsh-like.
> } 
> }   zcompile foo.zwc -z bar -k baz
> } 
> } would load bar zsh-like and baz ksh-like.
> } 
> } Ok?
> 
> Seems fine to me.  Hmm, maybe autoload should have the `k' and `z' opts,
> too, but they only work with +X (the load-it now option).  That would
> fix something that's been bugging me for a while.

Here is the patch for zcompile. If neither is given, the setting of
KSHAUTOLOAD at the time of loading is used to determine how to load
the function.

I haven't added that for autoload yet and there is another thing:
loadautofn() should probably make use of this too, maybe execute the
Eprog it gets from getfpfunc() when it knows that the function should
be ksh-autoloaded (either because the dump file said so or because
`autoload +x' said so). But then, it doesn't do that if KSHAUTOLOAD is 
set. I guess that's some security issue?

Bye
 Sven

diff -ru ../z.old/Doc/Zsh/builtins.yo Doc/Zsh/builtins.yo
--- ../z.old/Doc/Zsh/builtins.yo	Wed Mar 15 14:28:37 2000
+++ Doc/Zsh/builtins.yo	Wed Mar 15 16:50:13 2000
@@ -1295,8 +1295,8 @@
 findex(zcompile)
 cindex(wordcode, creation)
 cindex(compilation)
-xitem(tt(zcompile) [ tt(-U) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
-xitem(tt(zcompile) tt(-c) [ tt(-M) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
+xitem(tt(zcompile) [ tt(-U) ] [ tt(-z) | tt(-k) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
+xitem(tt(zcompile) tt(-c) [ tt(-M) ] [ tt(-z) | tt(-k) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
 item(tt(zcompile -t) var(file) [ var(name) ... ])(
 This builtin command can be used to create and display files
 containing the wordcode for functions or scripts. In the first form, a wordcode
@@ -1331,6 +1331,16 @@
 map wordcode files into memory. On such systems, the wordcode will
 only be read from the file, independent on the mode selected when the 
 file was created.
+
+The tt(-z) and tt(-k) options are used when the wordcode file contains
+functions and these functions are autoloaded. If tt(-z) is given, the
+function will be autoloaded as if the tt(KSHAUTOLOAD) option weren't
+set, even if it is. The tt(-k) makes the function be loaded as if
+tt(KASHAUTOLOAD) were set and if neither of these options is given,
+the function will be loaded as determined by the setting of the
+tt(KSHAUTOLOAD) option at the time the function is loaded. These
+options may also be given in the lists of var(name)s and make all
+following functions be loaded as described.
 
 When creating wordcode files for scripts instead of functions, it is
 often better to use the tt(-r) option. Otherwise the whole wordcode
diff -ru ../z.old/Src/builtin.c Src/builtin.c
--- ../z.old/Src/builtin.c	Wed Mar 15 14:28:22 2000
+++ Src/builtin.c	Wed Mar 15 15:57:34 2000
@@ -124,7 +124,7 @@
     BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
     BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcfdipue", NULL),
-    BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUmrcM", NULL),
+    BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUmrcMzk", NULL),
 };
 
 /****************************************/
diff -ru ../z.old/Src/exec.c Src/exec.c
--- ../z.old/Src/exec.c	Wed Mar 15 14:28:23 2000
+++ Src/exec.c	Wed Mar 15 16:16:05 2000
@@ -3153,13 +3153,13 @@
 execautofn(Estate state, int do_exec)
 {
     Shfunc shf = state->prog->shf;
-    int noalias = noaliases;
+    int noalias = noaliases, ksh = 1;
     Eprog prog;
 
     pushheap();
 
     noaliases = (shf->flags & PM_UNALIASED);
-    prog = getfpfunc(shf->nam);
+    prog = getfpfunc(shf->nam, &ksh);
     noaliases = noalias;
 
     if (prog == &dummy_eprog) {
@@ -3169,7 +3169,7 @@
     }
     if (!prog)
 	prog = &dummy_eprog;
-    if (isset(KSHAUTOLOAD)) {
+    if (ksh == 2 || (ksh == 1 && isset(KSHAUTOLOAD))) {
 	VARARR(char, n, strlen(shf->nam) + 1);
 	strcpy(n, shf->nam);
 	execode(prog, 1, 0);
@@ -3205,7 +3205,7 @@
     pushheap();
 
     noaliases = (shf->flags & PM_UNALIASED);
-    prog = getfpfunc(shf->nam);
+    prog = getfpfunc(shf->nam, NULL);
     noaliases = noalias;
 
     if (prog == &dummy_eprog) {
@@ -3360,7 +3360,7 @@
 
 /**/
 Eprog
-getfpfunc(char *s)
+getfpfunc(char *s, int *ksh)
 {
     char **pp, buf[PATH_MAX];
     off_t len;
@@ -3376,7 +3376,7 @@
 	    sprintf(buf, "%s/%s", *pp, s);
 	else
 	    strcpy(buf, s);
-	if ((r = try_dump_file(*pp, s, buf)))
+	if ((r = try_dump_file(*pp, s, buf, ksh)))
 	    return r;
 	unmetafy(buf, NULL);
 	if (!access(buf, R_OK) && (fd = open(buf, O_RDONLY | O_NOCTTY)) != -1) {
diff -ru ../z.old/Src/parse.c Src/parse.c
--- ../z.old/Src/parse.c	Wed Mar 15 14:28:25 2000
+++ Src/parse.c	Wed Mar 15 16:40:18 2000
@@ -2206,8 +2206,8 @@
 #define FD_MINMAP 4096
 
 #define FD_PRELEN 12
-#define FD_MAGIC  0x01020304
-#define FD_OMAGIC 0x04030201
+#define FD_MAGIC  0x02030405
+#define FD_OMAGIC 0x05040302
 
 #define FDF_MAP   1
 #define FDF_OTHER 2
@@ -2220,7 +2220,7 @@
     wordcode npats;		/* number of patterns needed */
     wordcode strs;		/* offset to strings */
     wordcode hlen;		/* header length (incl. name) */
-    wordcode tail;		/* offset to name tail */
+    wordcode flags;		/* flags and offset to name tail */
 };
 
 #define fdheaderlen(f) (((Wordcode) (f))[FD_PRELEN])
@@ -2243,8 +2243,25 @@
 #define firstfdhead(f) ((FDHead) (((Wordcode) (f)) + FD_PRELEN))
 #define nextfdhead(f)  ((FDHead) (((Wordcode) (f)) + (f)->hlen))
 
+#define fdhflags(f)      (((FDHead) (f))->flags)
+#define fdhtail(f)       (((FDHead) (f))->flags >> 2)
+#define fdhbldflags(f,t) ((f) | ((t) << 2))
+
+#define FDHF_KSHLOAD 1
+#define FDHF_ZSHLOAD 2
+
 #define fdname(f)      ((char *) (((FDHead) (f)) + 1))
 
+/* This is used when building wordcode files. */
+
+typedef struct wcfunc *WCFunc;
+
+struct wcfunc {
+    char *name;
+    Eprog prog;
+    int flags;
+};
+
 /* Try to find the description for the given function name. */
 
 static FDHead
@@ -2253,7 +2270,7 @@
     FDHead n, e = (FDHead) (h + fdheaderlen(h));
 
     for (n = firstfdhead(h); n < e; n = nextfdhead(n))
-	if (!strcmp(name, fdname(n) + n->tail))
+	if (!strcmp(name, fdname(n) + fdhtail(n)))
 	    return n;
 
     return NULL;
@@ -2263,9 +2280,16 @@
 int
 bin_zcompile(char *nam, char **args, char *ops, int func)
 {
-    int map;
+    int map, flags;
     char *dump;
 
+    if (ops['k'] && ops['z']) {
+	zwarnnam(nam, "illegal combination of options", NULL, 0);
+	return 1;
+    }
+    flags = (ops['k'] ? FDHF_KSHLOAD :
+	     (ops['z'] ? FDHF_ZSHLOAD : 0));
+
     if (ops['t']) {
 	Wordcode f;
 
@@ -2304,12 +2328,12 @@
     map = (ops['m'] ? 2 : (ops['r'] ? 0 : 1));
 
     if (!args[1] && !ops['c'])
-	return build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map);
+	return build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map, flags);
 
     dump = (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT));
 
-    return (ops['c'] ? build_cur_dump(nam, dump, args + 1, ops['M'], map) :
-	    build_dump(nam, dump, args + 1, ops['U'], map));
+    return (ops['c'] ? build_cur_dump(nam, dump, args + 1, ops['M'], map, flags) :
+	    build_dump(nam, dump, args + 1, ops['U'], map, flags));
 }
 
 /* Load the header of a dump file. Returns NULL if the file isn't a
@@ -2327,6 +2351,7 @@
 
     if (read(fd, buf, (FD_PRELEN + 1) * sizeof(wordcode)) !=
 	((FD_PRELEN + 1) * sizeof(wordcode)) ||
+	(fdmagic(buf) != FD_MAGIC && fdmagic(buf) != FD_OMAGIC) ||
 	strcmp(ZSH_VERSION, fdversion(buf))) {
 	close(fd);
 	return NULL;
@@ -2382,10 +2407,10 @@
 /* Write a dump file. */
 
 static void
-write_dump(int dfd, LinkList names, LinkList progs, int map,
-	   int hlen, int tlen)
+write_dump(int dfd, LinkList progs, int map, int hlen, int tlen)
 {
-    LinkNode name, node;
+    LinkNode node;
+    WCFunc wcf;
     int other = 0, ohlen, tmp;
     wordcode pre[FD_PRELEN];
     char *tail, *n;
@@ -2402,10 +2427,10 @@
 	strcpy(fdversion(pre), ZSH_VERSION);
 	write(dfd, pre, FD_PRELEN * sizeof(wordcode));
 
-	for (node = firstnode(progs), name = firstnode(names); node;
-	     incnode(node), incnode(name)) {
-	    n = (char *) getdata(name);
-	    prog = (Eprog) getdata(node);
+	for (node = firstnode(progs); node; incnode(node)) {
+	    wcf = (WCFunc) getdata(node);
+	    n = wcf->name;
+	    prog = wcf->prog;
 	    head.start = hlen;
 	    hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
 		     sizeof(wordcode) - 1) / sizeof(wordcode);
@@ -2417,8 +2442,8 @@
 	    if ((tail = strrchr(n, '/')))
 		tail++;
 	    else
-		tail= n;
-	    head.tail = tail - n;
+		tail = n;
+	    head.flags = fdhbldflags(wcf->flags, (tail - n));
 	    if (other)
 		fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
 	    write(dfd, &head, sizeof(head));
@@ -2428,7 +2453,7 @@
 		write(dfd, &head, sizeof(wordcode) - tmp);
 	}
 	for (node = firstnode(progs); node; incnode(node)) {
-	    prog = (Eprog) getdata(node);
+	    prog = ((WCFunc) getdata(node))->prog;
 	    tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
 		   sizeof(wordcode) - 1) / sizeof(wordcode);
 	    if (other)
@@ -2443,12 +2468,13 @@
 
 /**/
 static int
-build_dump(char *nam, char *dump, char **files, int ali, int map)
+build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
 {
     int dfd, fd, hlen, tlen, flen, ona = noaliases;
-    LinkList progs, names;
+    LinkList progs;
     char *file;
     Eprog prog;
+    WCFunc wcf;
 
     if (!strsfx(FD_EXT, dump))
 	dump = dyncat(dump, FD_EXT);
@@ -2458,10 +2484,16 @@
 	return 1;
     }
     progs = newlinklist();
-    names = newlinklist();
     noaliases = ali;
 
     for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
+	if (!strcmp(*files, "-k")) {
+	    flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
+	    continue;
+	} else if (!strcmp(*files, "-z")) {
+	    flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
+	    continue;
+	}
 	if ((fd = open(*files, O_RDONLY)) < 0 ||
 	    (flen = lseek(fd, 0, 2)) == -1) {
 	    if (fd >= 0)
@@ -2498,8 +2530,11 @@
 	}
 	zfree(file, flen);
 
-	addlinknode(progs, prog);
-	addlinknode(names, *files);
+	wcf = (WCFunc) zhalloc(sizeof(*wcf));
+	wcf->name = *files;
+	wcf->prog = prog;
+	wcf->flags = flags;
+	addlinknode(progs, wcf);
 
 	flen = (strlen(*files) + sizeof(wordcode)) / sizeof(wordcode);
 	hlen += (sizeof(struct fdhead) / sizeof(wordcode)) + flen;
@@ -2511,7 +2546,7 @@
 
     tlen = (tlen + hlen) * sizeof(wordcode);
 
-    write_dump(dfd, names, progs, map, hlen, tlen);
+    write_dump(dfd, progs, map, hlen, tlen);
 
     close(dfd);
 
@@ -2519,15 +2554,17 @@
 }
 
 static int
-cur_add_func(Shfunc shf, LinkList names, LinkList progs, int *hlen, int *tlen)
+cur_add_func(Shfunc shf, LinkList names, LinkList progs,
+	     int *hlen, int *tlen, int flags)
 {
     Eprog prog;
+    WCFunc wcf;
 
     if (shf->flags & PM_UNDEFINED) {
 	int ona = noaliases;
 
 	noaliases = (shf->flags & PM_UNALIASED);
-	if (!(prog = getfpfunc(shf->nam)) || prog == &dummy_eprog) {
+	if (!(prog = getfpfunc(shf->nam, NULL)) || prog == &dummy_eprog) {
 	    noaliases = ona;
 
 	    return 1;
@@ -2538,7 +2575,11 @@
     } else
 	prog = dupeprog(shf->funcdef, 1);
 
-    addlinknode(progs, prog);
+    wcf = (WCFunc) zhalloc(sizeof(*wcf));
+    wcf->name = shf->nam;
+    wcf->prog = prog;
+    wcf->flags = flags;
+    addlinknode(progs, wcf);
     addlinknode(names, shf->nam);
 
     *hlen += ((sizeof(struct fdhead) / sizeof(wordcode)) +
@@ -2551,7 +2592,7 @@
 
 /**/
 static int
-build_cur_dump(char *nam, char *dump, char **names, int match, int map)
+build_cur_dump(char *nam, char *dump, char **names, int match, int map, int flags)
 {
     int dfd, hlen, tlen;
     LinkList progs, lnames;
@@ -2576,7 +2617,8 @@
 
 	for (i = 0; i < shfunctab->hsize; i++)
 	    for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
-		if (cur_add_func((Shfunc) hn, lnames, progs, &hlen, &tlen)) {
+		if (cur_add_func((Shfunc) hn, lnames, progs,
+				 &hlen, &tlen, flags)) {
 		    zwarnnam(nam, "can't load function: %s", shf->nam, 0);
 		    errflag = 0;
 		    close(dfd);
@@ -2590,6 +2632,13 @@
 	HashNode hn;
 
 	for (; *names; names++) {
+	    if (!strcmp(*names, "-k")) {
+		flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
+		continue;
+	    } else if (!strcmp(*names, "-z")) {
+		flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
+		continue;
+	    }
 	    tokenize(pat = dupstring(*names));
 	    if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) {
 		zwarnnam(nam, "bad pattern: %s", *names, 0);
@@ -2602,7 +2651,7 @@
 		    if (!listcontains(lnames, hn->nam) &&
 			pattry(pprog, hn->nam) &&
 			cur_add_func((Shfunc) hn, lnames, progs,
-				     &hlen, &tlen)) {
+				     &hlen, &tlen, flags)) {
 			zwarnnam(nam, "can't load function: %s", shf->nam, 0);
 			errflag = 0;
 			close(dfd);
@@ -2612,6 +2661,13 @@
 	}
     } else {
 	for (; *names; names++) {
+	    if (!strcmp(*names, "-k")) {
+		flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_KSHLOAD;
+		continue;
+	    } else if (!strcmp(*names, "-z")) {
+		flags = (flags & ~(FDHF_KSHLOAD | FDHF_ZSHLOAD)) | FDHF_ZSHLOAD;
+		continue;
+	    }
 	    if (errflag ||
 		!(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
 		zwarnnam(nam, "unknown function: %s", *names, 0);
@@ -2620,7 +2676,7 @@
 		unlink(dump);
 		return 1;
 	    }
-	    if (cur_add_func(shf, lnames, progs, &hlen, &tlen)) {
+	    if (cur_add_func(shf, lnames, progs, &hlen, &tlen, flags)) {
 		zwarnnam(nam, "can't load function: %s", shf->nam, 0);
 		errflag = 0;
 		close(dfd);
@@ -2638,7 +2694,7 @@
     }
     tlen = (tlen + hlen) * sizeof(wordcode);
 
-    write_dump(dfd, lnames, progs, map, hlen, tlen);
+    write_dump(dfd, progs, map, hlen, tlen);
 
     close(dfd);
 
@@ -2722,7 +2778,7 @@
 
 /**/
 Eprog
-try_dump_file(char *path, char *name, char *file)
+try_dump_file(char *path, char *name, char *file, int *ksh)
 {
     Eprog prog;
     struct stat std, stc, stn;
@@ -2730,7 +2786,7 @@
     char *dig, *wc;
 
     if (strsfx(FD_EXT, path))
-	return check_dump_file(path, name);
+	return check_dump_file(path, name, ksh);
 
     dig = dyncat(path, FD_EXT);
     wc = dyncat(file, FD_EXT);
@@ -2746,13 +2802,13 @@
     if (!rd &&
 	(rc || std.st_mtime > stc.st_mtime) &&
 	(rn || std.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(dig, name)))
+	(prog = check_dump_file(dig, name, ksh)))
 	return prog;
 
     /* No digest file. Now look for the per-function compiled file. */
     if (!rc &&
 	(rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, name)))
+	(prog = check_dump_file(wc, name, ksh)))
 	return prog;
 
     /* No compiled file for the function. The caller (getfpfunc() will
@@ -2777,7 +2833,7 @@
 	tail = file;
 
     if (strsfx(FD_EXT, file))
-	return check_dump_file(file, tail);
+	return check_dump_file(file, tail, NULL);
 
     wc = dyncat(file, FD_EXT);
 
@@ -2785,7 +2841,7 @@
     rn = stat(file, &stn);
 
     if (!rc && (rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, tail)))
+	(prog = check_dump_file(wc, tail, NULL)))
 	return prog;
 
     return NULL;
@@ -2796,7 +2852,7 @@
 
 /**/
 static Eprog
-check_dump_file(char *file, char *name)
+check_dump_file(char *file, char *name, int *ksh)
 {
     int isrec = 0;
     Wordcode d;
@@ -2853,6 +2909,10 @@
 	    while (np--)
 		*pp++ = dummy_patprog1;
 
+	    if (ksh)
+		*ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
+			((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
+
 	    return prog;
 	} else if (fdflags(d) & FDF_MAP) {
 	    load_dump_file(file, (fdflags(d) & FDF_OTHER), fdother(d));
@@ -2898,6 +2958,10 @@
 	    while (np--)
 		*pp++ = dummy_patprog1;
 
+	    if (ksh)
+		*ksh = ((fdhflags(h) & FDHF_KSHLOAD) ? 2 :
+			((fdhflags(h) & FDHF_ZSHLOAD) ? 0 : 1));
+
 	    return prog;
 	}
     }
@@ -2973,7 +3037,7 @@
 	shf = (Shfunc) zcalloc(sizeof *shf);
 	shf->flags = on;
 	shf->funcdef = mkautofn(shf);
-	shfunctab->addnode(shfunctab, ztrdup(fdname(n) + n->tail), shf);
+	shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf);
 	if (ops['X'] && eval_autoload(shf, shf->nam, ops, func))
 	    ret = 1;
     }

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
  2000-03-15 15:57 Default fpath Sven Wischnowsky
@ 2000-03-15 18:15 ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2000-03-15 18:15 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On Mar 15,  4:57pm, Sven Wischnowsky wrote:
} Subject: Re: Default fpath
}
} Bart Schaefer wrote:
} > Hmm, maybe autoload should have the `k' and `z' opts,
} > too, but they only work with +X (the load-it now option).  That would
} > fix something that's been bugging me for a while.
} 
} I haven't added that for autoload yet and there is another thing:
} loadautofn() should probably make use of this too, maybe execute the
} Eprog it gets from getfpfunc() when it knows that the function should
} be ksh-autoloaded (either because the dump file said so or because
} `autoload +x' said so). But then, it doesn't do that if KSHAUTOLOAD is 
} set. I guess that's some security issue?

It's not exactly a security issue; that's the "something that's been
bugging me for a while."

Autoload +X is supposed to promise that the autoloaded function is not
executed.  Unfortunately, in the kshautoload style, you have to execute
the code in order to get the function defined, which may mean executing
other code that's in the file but not inside any function body.

For at least one intended use of "autoload +X" -- finding out whether
the function is in fpath and is syntactically correct -- other code in
the file should NOT be executed; rather, you want the effect of the
`[[ -o kshautoload ]] && run-myself "$@"' trick to take effect at the
time an actual *call* to the function is made.

At the time that I added loadautofn() there wasn't any way to achieve
that result, but perhaps now with wordcode it'll be possible.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
@ 2000-03-15  9:32 Sven Wischnowsky
  0 siblings, 0 replies; 9+ messages in thread
From: Sven Wischnowsky @ 2000-03-15  9:32 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> On Mar 14, 11:19am, Sven Wischnowsky wrote:
> } Subject: Re: Default fpath
> }
> } Bart Schaefer wrote:
> } > Actually, what would suit me fine is a way to dump out a
> } > .zwc of (a subset of the) functions defined in a running zsh.
> } 
> } That's easy. Would you prefer it as an option to `zcompile' or one for
> } `functions'?
> 
> I think it should go in zcompile, just because of potential confusion
> between "functions" and "typeset -f".  It's not *that* big a deal, I
> guess, but somehow having anything that's described as "equivalent to
> typeset" write to a file, bothers me.

Just what I preferred, so I had this patch already...

> [Tagging .zwc for zsh/ksh loading:]
> } 
> }   zcompile -z comp.zwc .../Completion/*/_*
> } 
> } to have them all loaded zsh-like.
> } 
> }   zcompile foo.zwc -z bar -k baz
> } 
> } would load bar zsh-like and baz ksh-like.
> } 
> } Ok?
> 
> Seems fine to me.  Hmm, maybe autoload should have the `k' and `z' opts,
> too, but they only work with +X (the load-it now option).  That would
> fix something that's been bugging me for a while.

Sounds good. No patch for any of this yet.

> } But maybe this is a case where adding functions to a wordcode file
> } would be handy:
> } 
> }   zcompile foo.zwc -z bar1 baz1
> }   zcompile -a foo.zwc -k bar2 baz2
> } 
> } would create a wordcode file with bar1/baz1 loaded zsh-like and then
> } add bar2/baz2 loaded ksh-like to it.
> 
> That would be reasonable, too, but with the "autoload" patches as well,
> I think the `zcompile -a ...' line would be equivalent to
> 
>     zsh -fc 'fpath=(...);\
> 	     autoload +Xw foo;\
> 	     autoload +Xk bar2 baz2;\
> 	     zcompile -c foo'
> 
> which could be provided as a utility function rather than a builtin.

Sounds even better, especially after having thought some more about
trying to append to existing wordcode files -- it would mostly look
like the above, only in C.

One question: `autoload -w' does not use $fpath to search the dump
file, should it? Or maybe with `+Xw' we should (temporarily and only
internally) prepend the dump file to $fpath so that `autoload +Xw dump'
loads all functions from a dump file without having to set $fpath
explicitly? Or would that be irritating for anyone. Or maybe the
current behaviour is irritating?

Anyway, I think, I prefer the latter... (prepending the dump file).


The patch adds the `-c' and `-M' options to autoload. `-c' means that
function definitions from the current shell are written:

  zcompile -c zwc f1 f2 ...

write f1, f2, ... to the wordcode file. If no function name is given,
all functions are written. Functions that are only marked for
autoloading are written, too (i.e. their definition), if they can be
found via $fpath. This will not make them be autoloaded by the shell
(i.e. after zcompile, they are still marked for autoloading).

`-c' can be combined with `-M' which makes the names be taken as
patterns and only functions whose names match any of these patterns
are written. zcompile is careful to write each function only once even 
if its name is matched by multiple patterns (or is it `... name
matches multiple patterns'? To repeat Andrej's question.).

That `-M' is a bit ugly, because normally `-m' is the option to make
arguments be used as patterns. Should we change zcompile's -r and -m
options to -R and -M and use -m for this pattern-thing?

Bye
 Sven

P.S.: The patch looks bigger than it is because I moved the code to
      write a wordcode file in its own function.

diff -ru ../z.old/Doc/Zsh/builtins.yo Doc/Zsh/builtins.yo
--- ../z.old/Doc/Zsh/builtins.yo	Tue Mar 14 16:50:31 2000
+++ Doc/Zsh/builtins.yo	Wed Mar 15 10:31:27 2000
@@ -1296,6 +1296,7 @@
 cindex(wordcode, creation)
 cindex(compilation)
 xitem(tt(zcompile) [ tt(-U) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
+xitem(tt(zcompile) tt(-c) [ tt(-M) ] [ tt(-r) | tt(-m) ] var(file) [ var(name) ... ])
 item(tt(zcompile -t) var(file) [ var(name) ... ])(
 This builtin command can be used to create and display files
 containing the wordcode for functions or scripts. In the first form, a wordcode
@@ -1342,7 +1343,15 @@
 it is read or mapped, only one half of the file will really be used
 (and mapped).
 
-In the second form, with the tt(-t) option, an existing wordcode file is
+If given the tt(-c) option, the names have to be names currently
+defined in the shell or marked as autoloaded. The definitions for all
+these functions will be written into the wordcode var(file). If the
+tt(-M) option is given, too, the var(name)s are used as patterns and
+all functions whose names match one of these patterns will be
+written. If no var(name) is given, the definitions of all functions
+currently defined or marked as autoloaded will be written. 
+
+In the third form, with the tt(-t) option, an existing wordcode file is
 tested. Without further arguments, the names of the original files
 used for it are listed. The first line tells the version of the shell
 the file was created with and how the file will be used (mapping or
diff -ru ../z.old/Src/Modules/parameter.c Src/Modules/parameter.c
--- ../z.old/Src/Modules/parameter.c	Wed Mar 15 10:07:20 2000
+++ Src/Modules/parameter.c	Wed Mar 15 10:09:05 2000
@@ -345,7 +345,7 @@
 	return;
     }
     shf = (Shfunc) zalloc(sizeof(*shf));
-    shf->funcdef = zdupeprog(prog);
+    shf->funcdef = dupeprog(prog, 0);
     shf->flags = dis;
 
     if (!strncmp(name, "TRAP", 4) &&
diff -ru ../z.old/Src/builtin.c Src/builtin.c
--- ../z.old/Src/builtin.c	Wed Mar 15 10:07:10 2000
+++ Src/builtin.c	Wed Mar 15 10:09:06 2000
@@ -124,7 +124,7 @@
     BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
     BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
     BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcfdipue", NULL),
-    BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUmr", NULL),
+    BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUmrcM", NULL),
 };
 
 /****************************************/
@@ -3895,7 +3895,7 @@
 	    zwarnnam(name, "undefined signal: %s", *argv, 0);
 	    break;
 	}
-	t = zdupeprog(prog);
+	t = dupeprog(prog, 0);
 	if (settrap(sig, t))
 	    freeeprog(t);
     }
diff -ru ../z.old/Src/exec.c Src/exec.c
--- ../z.old/Src/exec.c	Wed Mar 15 10:07:10 2000
+++ Src/exec.c	Wed Mar 15 10:09:06 2000
@@ -3184,7 +3184,7 @@
 	if (prog->alloc == EA_MAP)
 	    shf->funcdef = stripkshdef(prog, shf->nam);
 	else
-	    shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
+	    shf->funcdef = dupeprog(stripkshdef(prog, shf->nam), 0);
 	shf->flags &= ~PM_UNDEFINED;
     }
     popheap();
@@ -3217,7 +3217,7 @@
     if (prog->alloc == EA_MAP)
 	shf->funcdef = stripkshdef(prog, shf->nam);
     else
-	shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
+	shf->funcdef = dupeprog(stripkshdef(prog, shf->nam), 0);
     shf->flags &= ~PM_UNDEFINED;
 
     popheap();
@@ -3359,7 +3359,7 @@
  * list of its contents.                                                    */
 
 /**/
-static Eprog
+Eprog
 getfpfunc(char *s)
 {
     char **pp, buf[PATH_MAX];
diff -ru ../z.old/Src/linklist.c Src/linklist.c
--- ../z.old/Src/linklist.c	Wed Mar 15 10:07:11 2000
+++ Src/linklist.c	Wed Mar 15 10:09:06 2000
@@ -239,7 +239,7 @@
 }
 
 /**/
-void
+mod_export void
 rolllist(LinkList l, LinkNode nd)
 {
     l->last->next = l->first;
@@ -251,7 +251,7 @@
 }
 
 /**/
-LinkList
+mod_export LinkList
 newsizedlist(int size)
 {
     LinkList list;
@@ -270,4 +270,17 @@
     node[-1].next = NULL;
 
     return list;
+}
+
+/**/
+mod_export int
+listcontains(LinkList list, void *dat)
+{
+    LinkNode node;
+
+    for (node = firstnode(list); node; incnode(node))
+	if (getdata(node) == dat)
+	    return 1;
+
+    return 0;
 }
diff -ru ../z.old/Src/parse.c Src/parse.c
--- ../z.old/Src/parse.c	Wed Mar 15 10:07:13 2000
+++ Src/parse.c	Wed Mar 15 10:16:09 2000
@@ -1980,7 +1980,7 @@
 
 /**/
 mod_export Eprog
-zdupeprog(Eprog p)
+dupeprog(Eprog p, int heap)
 {
     Eprog r;
     int i;
@@ -1989,12 +1989,13 @@
     if (p == &dummy_eprog)
 	return p;
 
-    r = (Eprog) zalloc(sizeof(*r));
+    r = (heap ? (Eprog) zhalloc(sizeof(*r)) : (Eprog) zalloc(sizeof(*r)));
     r->alloc = EA_REAL;
     r->dump = NULL;
     r->len = p->len;
     r->npats = p->npats;
-    pp = r->pats = (Patprog *) zcalloc(r->len);
+    pp = r->pats = (heap ? (Patprog *) hcalloc(r->len) :
+		    (Patprog *) zcalloc(r->len));
     r->prog = (Wordcode) (r->pats + r->npats);
     r->strs = ((char *) r->prog) + (p->strs - ((char *) p->prog));
     memcpy(r->prog, p->prog, r->len - (p->npats * sizeof(Patprog)));
@@ -2263,6 +2264,7 @@
 bin_zcompile(char *nam, char **args, char *ops, int func)
 {
     int map;
+    char *dump;
 
     if (ops['t']) {
 	Wordcode f;
@@ -2295,14 +2297,19 @@
 	zwarnnam(nam, "too few arguments", NULL, 0);
 	return 1;
     }
+    if ((ops['c'] && ops['U']) || (!ops['c'] && ops['M'])) {
+	zwarnnam(nam, "illegal combination of options", NULL, 0);
+	return 1;
+    }
     map = (ops['m'] ? 2 : (ops['r'] ? 0 : 1));
 
-    if (!args[1])
+    if (!args[1] && !ops['c'])
 	return build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map);
 
-    return build_dump(nam,
-		      (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT)),
-		      args + 1, ops['U'], map);
+    dump = (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT));
+
+    return (ops['c'] ? build_cur_dump(nam, dump, args + 1, ops['M'], map) :
+	    build_dump(nam, dump, args + 1, ops['U'], map));
 }
 
 /* Load the header of a dump file. Returns NULL if the file isn't a
@@ -2374,16 +2381,73 @@
 
 /* Write a dump file. */
 
+static void
+write_dump(int dfd, LinkList names, LinkList progs, int map,
+	   int hlen, int tlen)
+{
+    LinkNode name, node;
+    int other = 0, ohlen, tmp;
+    wordcode pre[FD_PRELEN];
+    char *tail, *n;
+    struct fdhead head;
+    Eprog prog;
+
+    if (map == 1)
+	map = (tlen >= FD_MINMAP);
+
+    for (ohlen = hlen; ; hlen = ohlen) {
+	fdmagic(pre) = (other ? FD_OMAGIC : FD_MAGIC);
+	fdsetflags(pre, ((map ? FDF_MAP : 0) | other));
+	fdsetother(pre, tlen);
+	strcpy(fdversion(pre), ZSH_VERSION);
+	write(dfd, pre, FD_PRELEN * sizeof(wordcode));
+
+	for (node = firstnode(progs), name = firstnode(names); node;
+	     incnode(node), incnode(name)) {
+	    n = (char *) getdata(name);
+	    prog = (Eprog) getdata(node);
+	    head.start = hlen;
+	    hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
+		     sizeof(wordcode) - 1) / sizeof(wordcode);
+	    head.len = prog->len - (prog->npats * sizeof(Patprog));
+	    head.npats = prog->npats;
+	    head.strs = prog->strs - ((char *) prog->prog);
+	    head.hlen = (sizeof(struct fdhead) / sizeof(wordcode)) +
+		(strlen(n) + sizeof(wordcode)) / sizeof(wordcode);
+	    if ((tail = strrchr(n, '/')))
+		tail++;
+	    else
+		tail= n;
+	    head.tail = tail - n;
+	    if (other)
+		fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
+	    write(dfd, &head, sizeof(head));
+	    tmp = strlen(n) + 1;
+	    write(dfd, n, tmp);
+	    if ((tmp &= (sizeof(wordcode) - 1)))
+		write(dfd, &head, sizeof(wordcode) - tmp);
+	}
+	for (node = firstnode(progs); node; incnode(node)) {
+	    prog = (Eprog) getdata(node);
+	    tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
+		   sizeof(wordcode) - 1) / sizeof(wordcode);
+	    if (other)
+		fdswap(prog->prog, (((Wordcode) prog->strs) - prog->prog));
+	    write(dfd, prog->prog, tmp * sizeof(wordcode));
+	}
+	if (other)
+	    break;
+	other = FDF_OTHER;
+    }
+}
+
 /**/
 static int
 build_dump(char *nam, char *dump, char **files, int ali, int map)
 {
-    int dfd, fd, hlen, tlen, flen, tmp, ona = noaliases, other = 0, ohlen;
-    LinkList progs;
-    LinkNode node;
-    struct fdhead head;
-    wordcode pre[FD_PRELEN];
-    char *file, **ofiles = files, **oofiles = files, *tail;
+    int dfd, fd, hlen, tlen, flen, ona = noaliases;
+    LinkList progs, names;
+    char *file;
     Eprog prog;
 
     if (!strsfx(FD_EXT, dump))
@@ -2394,6 +2458,7 @@
 	return 1;
     }
     progs = newlinklist();
+    names = newlinklist();
     noaliases = ali;
 
     for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
@@ -2434,9 +2499,10 @@
 	zfree(file, flen);
 
 	addlinknode(progs, prog);
+	addlinknode(names, *files);
 
 	flen = (strlen(*files) + sizeof(wordcode)) / sizeof(wordcode);
-	hlen += (sizeof(head) / sizeof(wordcode)) + flen;
+	hlen += (sizeof(struct fdhead) / sizeof(wordcode)) + flen;
 
 	tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
 		 sizeof(wordcode) - 1) / sizeof(wordcode);
@@ -2444,53 +2510,138 @@
     noaliases = ona;
 
     tlen = (tlen + hlen) * sizeof(wordcode);
-    if (map == 1)
-	map = (tlen >= FD_MINMAP);
 
-    for (ohlen = hlen; ; hlen = ohlen) {
-	fdmagic(pre) = (other ? FD_OMAGIC : FD_MAGIC);
-	fdsetflags(pre, ((map ? FDF_MAP : 0) | other));
-	fdsetother(pre, tlen);
-	strcpy(fdversion(pre), ZSH_VERSION);
-	write(dfd, pre, FD_PRELEN * sizeof(wordcode));
+    write_dump(dfd, names, progs, map, hlen, tlen);
 
-	for (node = firstnode(progs), ofiles = oofiles; node;
-	     ofiles++, incnode(node)) {
-	    prog = (Eprog) getdata(node);
-	    head.start = hlen;
-	    hlen += (prog->len - (prog->npats * sizeof(Patprog)) +
-		     sizeof(wordcode) - 1) / sizeof(wordcode);
-	    head.len = prog->len - (prog->npats * sizeof(Patprog));
-	    head.npats = prog->npats;
-	    head.strs = prog->strs - ((char *) prog->prog);
-	    head.hlen = (sizeof(struct fdhead) / sizeof(wordcode)) +
-		(strlen(*ofiles) + sizeof(wordcode)) / sizeof(wordcode);
-	    if ((tail = strrchr(*ofiles, '/')))
-		tail++;
-	    else
-		tail= *ofiles;
-	    head.tail = tail - *ofiles;
-	    if (other)
-		fdswap((Wordcode) &head, sizeof(head) / sizeof(wordcode));
-	    write(dfd, &head, sizeof(head));
-	    tmp = strlen(*ofiles) + 1;
-	    write(dfd, *ofiles, tmp);
-	    if ((tmp &= (sizeof(wordcode) - 1)))
-		write(dfd, &head, sizeof(wordcode) - tmp);
+    close(dfd);
+
+    return 0;
+}
+
+static int
+cur_add_func(Shfunc shf, LinkList names, LinkList progs, int *hlen, int *tlen)
+{
+    Eprog prog;
+
+    if (shf->flags & PM_UNDEFINED) {
+	int ona = noaliases;
+
+	noaliases = (shf->flags & PM_UNALIASED);
+	if (!(prog = getfpfunc(shf->nam)) || prog == &dummy_eprog) {
+	    noaliases = ona;
+
+	    return 1;
 	}
-	for (node = firstnode(progs); node; incnode(node)) {
-	    prog = (Eprog) getdata(node);
-	    tmp = (prog->len - (prog->npats * sizeof(Patprog)) +
-		   sizeof(wordcode) - 1) / sizeof(wordcode);
-	    if (other)
-		fdswap(prog->prog, (((Wordcode) prog->strs) - prog->prog));
-	    write(dfd, prog->prog, tmp * sizeof(wordcode));
+	if (prog->dump)
+	    prog = dupeprog(prog, 1);
+	noaliases = ona;
+    } else
+	prog = dupeprog(shf->funcdef, 1);
+
+    addlinknode(progs, prog);
+    addlinknode(names, shf->nam);
+
+    *hlen += ((sizeof(struct fdhead) / sizeof(wordcode)) +
+	      ((strlen(shf->nam) + sizeof(wordcode)) / sizeof(wordcode)));
+    *tlen += (prog->len - (prog->npats * sizeof(Patprog)) +
+	      sizeof(wordcode) - 1) / sizeof(wordcode);
+
+    return 0;
+}
+
+/**/
+static int
+build_cur_dump(char *nam, char *dump, char **names, int match, int map)
+{
+    int dfd, hlen, tlen;
+    LinkList progs, lnames;
+    Shfunc shf;
+
+    if (!strsfx(FD_EXT, dump))
+	dump = dyncat(dump, FD_EXT);
+
+    if ((dfd = open(dump, O_WRONLY|O_CREAT, 0600)) < 0) {
+	zwarnnam(nam, "can't write dump file: %s", dump, 0);
+	return 1;
+    }
+    progs = newlinklist();
+    lnames = newlinklist();
+
+    hlen = FD_PRELEN;
+    tlen = 0;
+
+    if (!*names) {
+	int i;
+	HashNode hn;
+
+	for (i = 0; i < shfunctab->hsize; i++)
+	    for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
+		if (cur_add_func((Shfunc) hn, lnames, progs, &hlen, &tlen)) {
+		    zwarnnam(nam, "can't load function: %s", shf->nam, 0);
+		    errflag = 0;
+		    close(dfd);
+		    unlink(dump);
+		    return 1;
+		}
+    } else if (match) {
+	char *pat;
+	Patprog pprog;
+	int i;
+	HashNode hn;
+
+	for (; *names; names++) {
+	    tokenize(pat = dupstring(*names));
+	    if (!(pprog = patcompile(pat, PAT_STATIC, NULL))) {
+		zwarnnam(nam, "bad pattern: %s", *names, 0);
+		close(dfd);
+		unlink(dump);
+		return 1;
+	    }
+	    for (i = 0; i < shfunctab->hsize; i++)
+		for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
+		    if (!listcontains(lnames, hn->nam) &&
+			pattry(pprog, hn->nam) &&
+			cur_add_func((Shfunc) hn, lnames, progs,
+				     &hlen, &tlen)) {
+			zwarnnam(nam, "can't load function: %s", shf->nam, 0);
+			errflag = 0;
+			close(dfd);
+			unlink(dump);
+			return 1;
+		    }
 	}
-	if (other)
-	    break;
-	other = FDF_OTHER;
+    } else {
+	for (; *names; names++) {
+	    if (errflag ||
+		!(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
+		zwarnnam(nam, "unknown function: %s", *names, 0);
+		errflag = 0;
+		close(dfd);
+		unlink(dump);
+		return 1;
+	    }
+	    if (cur_add_func(shf, lnames, progs, &hlen, &tlen)) {
+		zwarnnam(nam, "can't load function: %s", shf->nam, 0);
+		errflag = 0;
+		close(dfd);
+		unlink(dump);
+		return 1;
+	    }
+	}
+    }
+    if (empty(progs)) {
+	zwarnnam(nam, "no functions", NULL, 0);
+	errflag = 0;
+	close(dfd);
+	unlink(dump);
+	return 1;
     }
+    tlen = (tlen + hlen) * sizeof(wordcode);
+
+    write_dump(dfd, lnames, progs, map, hlen, tlen);
+
     close(dfd);
+
     return 0;
 }
 

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
  2000-03-14 10:19 Sven Wischnowsky
@ 2000-03-14 17:55 ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2000-03-14 17:55 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On Mar 14, 11:19am, Sven Wischnowsky wrote:
} Subject: Re: Default fpath
}
} Bart Schaefer wrote:
} > Actually, what would suit me fine is a way to dump out a
} > .zwc of (a subset of the) functions defined in a running zsh.
} 
} That's easy. Would you prefer it as an option to `zcompile' or one for
} `functions'?

I think it should go in zcompile, just because of potential confusion
between "functions" and "typeset -f".  It's not *that* big a deal, I
guess, but somehow having anything that's described as "equivalent to
typeset" write to a file, bothers me.

[Tagging .zwc for zsh/ksh loading:]
} 
}   zcompile -z comp.zwc .../Completion/*/_*
} 
} to have them all loaded zsh-like.
} 
}   zcompile foo.zwc -z bar -k baz
} 
} would load bar zsh-like and baz ksh-like.
} 
} Ok?

Seems fine to me.  Hmm, maybe autoload should have the `k' and `z' opts,
too, but they only work with +X (the load-it now option).  That would
fix something that's been bugging me for a while.

} But maybe this is a case where adding functions to a wordcode file
} would be handy:
} 
}   zcompile foo.zwc -z bar1 baz1
}   zcompile -a foo.zwc -k bar2 baz2
} 
} would create a wordcode file with bar1/baz1 loaded zsh-like and then
} add bar2/baz2 loaded ksh-like to it.

That would be reasonable, too, but with the "autoload" patches as well,
I think the `zcompile -a ...' line would be equivalent to

    zsh -fc 'fpath=(...);\
	     autoload +Xw foo;\
	     autoload +Xk bar2 baz2;\
	     zcompile -c foo'

which could be provided as a utility function rather than a builtin.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
@ 2000-03-14 10:19 Sven Wischnowsky
  2000-03-14 17:55 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 2000-03-14 10:19 UTC (permalink / raw)
  To: zsh-workers


Bart Schaefer wrote:

> ...
> 
> This gives me an idea ... it ought to be possible to point autoload (or
> some new builtin) at a zcompiled digest file and have it mark all the
> functions therein for autoloading.  That way, you could (once) select
> the functions to compile into the digest, then simply add the digest to
> your $fpath and issue a single autoload command.  (Note 1)
> 
> The digest-file equivalent of `autoload $dir/*(.)`, you see.  I suppose
> you can do `autoload ${$(zcompile -t file.zwc):t}` but that requires an
> extra process, and it doesn't cover cases where one component file of
> the .zwc contained multiple function definitions.

The patch below adds the `-w' option to autoload (and only to that,
like `[-+]X'). If it is given, the arguments are taken as names of
wordcode files and all functions in them are marked for autoloading.


[ in another message: ]

> ...
> 
> Perhaps not.  Actually, what would suit me fine is a way to dump out a
> .zwc of (a subset of the) functions defined in a running zsh.

That's easy. Would you prefer it as an option to `zcompile' or one for
`functions'? E.g. `zcompile -c foo' would put the definitons of all
currently defined function in the wordcode file foo.zwc,
`zcompile -c foo bar baz' would put the functions `bar' and `baz', as
currently defined in foo.zwc, and `zcompile -cm foo "_*"' would put
all functions whose name matches `_*' in foo.zwc.

Or the same with, say `functions -w ...'? We have the code for `-m'
there already, although that isn't that much.

> } > (2) an option to say whether each function should be autoloaded zsh-style
> } >     or ksh-style, so that the right thing happens regardless of the run-
> } >     time setting of kshautoload.)
> } 
> } But currently it is the same as for loading from a normal file,
> } wouldn't it probably be confusing if the wordcode file said how to
> } load it?
> 
> Actually I'd like it if the text file could "say how to load it" as well,
> but that wouldn't be portable -- the whole point of kshautoload is to be
> able to write functions that can load into both zsh and ksh.  So if I set
> kshautoload, I'm probably in a situation where I load ksh functions.  It
> would be possible to require that zsh function text files include some
> token that specifies NOT using kshautoload, but that would put the burden
> on the ordinary zsh writer, which feels wrong.
> 
> There's no such problem with .zwc files -- only zsh will load them, and
> the how-to token is invisible to the user.
> 
> Consider the current problem of initializing the completion system with
> kshautoload set.  (I.e., you can't.)  The kshautoload user could solve
> this problem by precompiling the completion system for zsh loading.

Ah, stupid me. Good idea...

> The one thing I can't decide is whether the default should be initialized
> from the setting of kshautoload, or if it should always default to zsh.

Hm, defaulting to the current setting of kshautoload is probably less
surprising, I think (but then, I've never used kshautoload...).

> } But don't get me wrong: I never use kshautoload, so I
> } wouldn't be against allowing it. Per-function or per-wordcode file?
> 
> Per source file used to build the wordcode file would be the correct
> granularity, which I guess means per-function?

Yep. Suggested syntax: two options `-k' and `-z' which mean: all
following files are loaded like ksh/zsh does it normally. this allows
us to say:

  zcompile -z comp.zwc .../Completion/*/_*

to have them all loaded zsh-like.

  zcompile foo.zwc -z bar -k baz

would load bar zsh-like and baz ksh-like.

Ok? But maybe this is a case where adding functions to a wordcode file
would be handy:

  zcompile foo.zwc -z bar1 baz1
  zcompile -a foo.zwc -k bar2 baz2

would create a wordcode file with bar1/baz1 loaded zsh-like and then
add bar2/baz2 loaded ksh-like to it.


Bye
 Sven

diff -ru ../z.old/Doc/Zsh/builtins.yo Doc/Zsh/builtins.yo
--- ../z.old/Doc/Zsh/builtins.yo	Tue Mar 14 10:55:29 2000
+++ Doc/Zsh/builtins.yo	Tue Mar 14 10:56:20 2000
@@ -76,8 +76,9 @@
 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 @@
 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 -ru ../z.old/Src/builtin.c Src/builtin.c
--- ../z.old/Src/builtin.c	Tue Mar 14 10:55:18 2000
+++ Src/builtin.c	Tue Mar 14 10:56:21 2000
@@ -43,7 +43,7 @@
     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 @@
 
 /* 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 @@
 
     /* 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 @@
 }
 
 /**/
-static Eprog
+Eprog
 mkautofn(Shfunc shf)
 {
     Eprog p;
diff -ru ../z.old/Src/parse.c Src/parse.c
--- ../z.old/Src/parse.c	Tue Mar 14 10:55:21 2000
+++ Src/parse.c	Tue Mar 14 10:56:21 2000
@@ -2801,3 +2801,30 @@
 }
 
 #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;
+}

--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
  2000-03-13 10:42 Sven Wischnowsky
@ 2000-03-13 16:52 ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2000-03-13 16:52 UTC (permalink / raw)
  To: Sven Wischnowsky, zsh-workers

On Mar 13, 11:42am, Sven Wischnowsky wrote:
} Subject: Re: Default fpath
}
} Bart Schaefer wrote:
} 
} > Note 1 -- While we're on the topic of zcompile, it could use:
} > (1) a way to append to an existing .zwc, rather like `ar' works, and
} 
} That's a bit problematic because of the little/big-endian thing. I.e. we
} can't just append to a wordcode file (and I don't want to have
} multiple headers).

I was afraid of that.

} But of course we could make it read/change/re-write
} such files, also allowing deletion of functions. Is it worth it? I
} mean, creating wordcode files is quite fast for me...

Perhaps not.  Actually, what would suit me fine is a way to dump out a
.zwc of (a subset of the) functions defined in a running zsh.
 
} > (2) an option to say whether each function should be autoloaded zsh-style
} >     or ksh-style, so that the right thing happens regardless of the run-
} >     time setting of kshautoload.)
} 
} But currently it is the same as for loading from a normal file,
} wouldn't it probably be confusing if the wordcode file said how to
} load it?

Actually I'd like it if the text file could "say how to load it" as well,
but that wouldn't be portable -- the whole point of kshautoload is to be
able to write functions that can load into both zsh and ksh.  So if I set
kshautoload, I'm probably in a situation where I load ksh functions.  It
would be possible to require that zsh function text files include some
token that specifies NOT using kshautoload, but that would put the burden
on the ordinary zsh writer, which feels wrong.

There's no such problem with .zwc files -- only zsh will load them, and
the how-to token is invisible to the user.

Consider the current problem of initializing the completion system with
kshautoload set.  (I.e., you can't.)  The kshautoload user could solve
this problem by precompiling the completion system for zsh loading.

The one thing I can't decide is whether the default should be initialized
from the setting of kshautoload, or if it should always default to zsh.

} But don't get me wrong: I never use kshautoload, so I
} wouldn't be against allowing it. Per-function or per-wordcode file?

Per source file used to build the wordcode file would be the correct
granularity, which I guess means per-function?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
@ 2000-03-13 10:42 Sven Wischnowsky
  2000-03-13 16:52 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Sven Wischnowsky @ 2000-03-13 10:42 UTC (permalink / raw)
  To: zsh-workers


Oliver Kiddle wrote:

> ...
> 
> The initial fpath contains the Debian and Linux directories despite the
> fact that I always remove them after installation. I get rid of them
> with the (N) but I don't think they should be there. I suppose that in
> the longer term, we'll have to add configure-time checks for these and
> other operating systems we might have functions for. 

We plan to cleanup the directories before release anyway -- every
suggestion about things will then be welcome, I think.

(The Linux/Debian stuff is a bit of a problem anyway, because the
files in it are not only useful on linux/debian systems, I think.)


Bart Schaefer wrote:

> ...
> 
> This gives me an idea ... it ought to be possible to point autoload (or
> some new builtin) at a zcompiled digest file and have it mark all the
> functions therein for autoloading.  That way, you could (once) select
> the functions to compile into the digest, then simply add the digest to
> your $fpath and issue a single autoload command.  (Note 1)

Nice idea...

> ... [ big snip, no strong opinions on that ]
> 
> } The obvious solution is to have a variable which is set when zsh first
> } runs such as $ZSH_FUNCTIONS. In fact, it might be better in the longer
> } term to have an associative array which points to any compile-time
> } defined directories. So we would have something like:
> } ZSH_INSTALL[functions]=/usr/local/share/zsh/$ZSH_VERSION/functions
> } ZSH_INSTALL[lib]=/usr/local/lib/zsh/3.1.6-dev-19
> } ZSH_INSTALL[share]=/usr/local/share/zsh
> } etc.
> 
> That's a reasonable idea, though (other than "functions" and maybe "lib")
> I can't decide what the standard set of key names should be.  I dislike
> the idea of following the autoconf naming convention; I don't really
> think bindir, datadir, infodir, etc. are especially useful.

Agreed.

> ...
> 
> Note 1 -- While we're on the topic of zcompile, it could use:
> (1) a way to append to an existing .zwc, rather like `ar' works, and

That's a bit problematic because of the little/big-endian thing. I.e. we
can't just append to a wordcode file (and I don't want to have
multiple headers). But of course we could make it read/change/re-write
such files, also allowing deletion of functions. Is it worth it? I
mean, creating wordcode files is quite fast for me...

> (2) an option to say whether each function should be autoloaded zsh-style
>     or ksh-style, so that the right thing happens regardless of the run-
>     time setting of kshautoload.)

But currently it is the same as for loading from a normal file,
wouldn't it probably be confusing if the wordcode file said how to
load it? But don't get me wrong: I never use kshautoload, so I
wouldn't be against allowing it. Per-function or per-wordcode file?

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Default fpath
  2000-03-11 21:29 Oliver Kiddle
@ 2000-03-11 23:46 ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2000-03-11 23:46 UTC (permalink / raw)
  To: Zsh workers

On Mar 11,  9:29pm, Oliver Kiddle wrote:
} Subject: Default fpath
}
} I'm not convinced that the current situation with respect to zsh setting
} up the fpath to point to all the directories it installs (plus
} site-functions) is the best way of doing it.

I'm also back to the problem that I install into /usr/local/stow/zsh/
and then use the "stow" package to symlink into /usr/local/ -- but the
compiled-in fpath still references /usr/local/stow/zsh/share/zsh.  I'd
fixed this at one point but it seems to have reverted.  (Same for the
module_path.)

} My .zshrc file contains this:
} 
} fpath=( $fpath(N) ~/.zfunc $fpath[1]/* )
} typeset -U fpath
} for dir in ~/.zfunc(N) $fpath[1]/*
}     [[ -d $dir ]] && autoload $dir/[^_]*(.N:t)
} autoload -U allopt zed
} ...
} autoload -U compinit
} compinit -d
} 
[...]
} 
} As a result of $fpath being set to include all the installed function
} directories, I have to add directories to $fpath, then loop through the
} same duplicated list of directories to autoload any functions. I can't
} just loop through all directories in $fpath and autoload everything
} because I don't want all the zsh supplied functions in Misc.

This gives me an idea ... it ought to be possible to point autoload (or
some new builtin) at a zcompiled digest file and have it mark all the
functions therein for autoloading.  That way, you could (once) select
the functions to compile into the digest, then simply add the digest to
your $fpath and issue a single autoload command.  (Note 1)

The digest-file equivalent of `autoload $dir/*(.)`, you see.  I suppose
you can do `autoload ${$(zcompile -t file.zwc):t}` but that requires an
extra process, and it doesn't cover cases where one component file of
the .zwc contained multiple function definitions.

Meanwhile, I use something like this:

	typeset -U fpath zfpath
	zfpath=( ... )			# Personal function dirs here
	autoload $^zfpath/*(N.:t)	# Aliases OK in my own funcs
	(( $#fpath )) && autoload -U compinit
	fpath[(r)*site-func*]=( $zfpath )

It's actually more complicated than that because I'm in the middle of
inventing some code to set zfpath in a $ZSH_VERSION-specific way, so I
can shuffle out some old functions that aren't needed anymore.  I don't
put anything in site-functions, ever; hence re-slicing it with $zfpath.

Hmm, just noticed that if site-functions doesn't appear in $fpath, but
it's otherwise non-empty, that's going to add $zfpath to the end, not
somewhere near the beginning.  Have to think about that; I don't have
any overrides for the default set of functions *now* ...

} I'm not entirely convinced that putting site-functions in the $fpath is
} a good idea. On many installations, it won't exist, some people might
} want to put it elsewhere or call it something else

That's an argument for making the location a configure-time option, at
least, with one option being to leave it out entirely.  What harm does
it do, though, to have a directory in $fpath that contains no files?

} and others like me subdivide it into various subdirectories but don't
} put any functions directly in it.

There's certainly not going to be a compile-time fix for that -- nor a
way to get compinit to deal with it properly AFAICT.  So you're still
going to have to autoload the functions from those directories yourself.

} As a result of $fpath being set to include all the installed function
} directories, I have to add directories to $fpath, then loop through the
} same duplicated list of directories to autoload any functions. I can't
} just loop through all directories in $fpath and autoload everything
} because I don't want all the zsh supplied functions in Misc.

We need to clean up Misc/ anyway; the compctl-related functions should
be called out as such, not lumped in with other utilities, so that they
can be avoided now and more easily obsoleted in the future.

} Many people upgrading from older zsh or learning about $fpath anew
} will assign to $fpath in their .zshrc, clobbering it's current value
} so I think it is better if they are only added by compinit.
                             ^^^^
"They" being the directories that contain completion functions.

I submit that this mistake can't survive very long, because users won't
be able to run compinit if they've removed its directory from $fpath.
It's the sort of mistake you make exactly once.

} Similarly, promptinit would add the Prompts directory to $fpath.

But then you're enforcing --enable-function-subdirs behavior, aren't you?

Further, if compinit added directories to $fpath, how does the user
specify in what order those directories are added?  I might not want my
local directories to come before the zsh system ones; e.g. with 3.0.x,
I only want my local copy of `multicomp' found when the one that came
with zsh isn't installed, because mine's rather old and the chances are
that the system one works better.  (Yes, I should just copy a newer one
into my directory.  That's not the point.)

} The obvious solution is to have a variable which is set when zsh first
} runs such as $ZSH_FUNCTIONS. In fact, it might be better in the longer
} term to have an associative array which points to any compile-time
} defined directories. So we would have something like:
} ZSH_INSTALL[functions]=/usr/local/share/zsh/$ZSH_VERSION/functions
} ZSH_INSTALL[lib]=/usr/local/lib/zsh/3.1.6-dev-19
} ZSH_INSTALL[share]=/usr/local/share/zsh
} etc.

That's a reasonable idea, though (other than "functions" and maybe "lib")
I can't decide what the standard set of key names should be.  I dislike
the idea of following the autoconf naming convention; I don't really
think bindir, datadir, infodir, etc. are especially useful.

Backing up again:
 
} The other thing which I've never understood is why compinit (and
} promptinit) is an autoloaded function: nobody would ever want to run it
} more than once in a session so why isn't it just sourced?

It's a function so that it can use setopt localoptions, create local
variables, and use "autoload -U" to avoid alias expansions.  That last
is probably the most important.

There's a lengthy discussion of this from June 1999 in the archives; most
messages in the thread have the subject
	Re: PATCH: Re: Completion and global aliases
and the patch that resulted is article 6857.

Of course, we could add a "source -U ..." or some such to stop aliasing
even in sourced files, but as source has never accepted options before I
find that slightly distasteful.


Note 1 -- While we're on the topic of zcompile, it could use:
(1) a way to append to an existing .zwc, rather like `ar' works, and
(2) an option to say whether each function should be autoloaded zsh-style
    or ksh-style, so that the right thing happens regardless of the run-
    time setting of kshautoload.)

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Default fpath
@ 2000-03-11 21:29 Oliver Kiddle
  2000-03-11 23:46 ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Oliver Kiddle @ 2000-03-11 21:29 UTC (permalink / raw)
  To: Zsh workers

I'm not convinced that the current situation with respect to zsh setting
up the fpath to point to all the directories it installs (plus
site-functions) is the best way of doing it. Note that I use
--enable-function-subdirs with configure.

My .zshrc file contains this:

fpath=( $fpath(N) ~/.zfunc $fpath[1]/* )
typeset -U fpath
for dir in ~/.zfunc(N) $fpath[1]/*
    [[ -d $dir ]] && autoload $dir/[^_]*(.N:t)
autoload -U allopt zed
...
autoload -U compinit
compinit -d

There's a few things I don't like about having to do it this way. They
are more aesthetic than anything else but I still don't like it.

I'm not entirely convinced that putting site-functions in the $fpath is
a good idea. On many installations, it won't exist, some people might
want to put it elsewhere or call it something else and others like me
subdivide it into various subdirectories (Apex, Ada, AIX etc) but don't
put any functions directly in it. I don't like having to use $fpath[1] -
it doesn't seem very clean and I'm relying on it always pointing to
site-functions. I realise that I could search for *site-functions in
$fpath but I don't think I'd like that any better.

The initial fpath contains the Debian and Linux directories despite the
fact that I always remove them after installation. I get rid of them
with the (N) but I don't think they should be there. I suppose that in
the longer term, we'll have to add configure-time checks for these and
other operating systems we might have functions for. 

As a result of $fpath being set to include all the installed function
directories, I have to add directories to $fpath, then loop through the
same duplicated list of directories to autoload any functions. I can't
just loop through all directories in $fpath and autoload everything
because I don't want all the zsh supplied functions in Misc. Many people
upgrading from older zsh or learning about $fpath anew will assign to
$fpath in their .zshrc, clobbering it's current value so I think it is
better if they are only added by compinit.

The other thing which I've never understood is why compinit (and
promptinit) is an autoloaded function: nobody would ever want to run it
more than once in a session so why isn't it just sourced?

What I think would be a better system is if zsh started with an empty
$fpath, compinit was sourced and added any completion function
directories to $fpath. Similarly, promptinit would add the Prompts
directory to $fpath. The one issue here is that we would need a way to
find compinit/promptinit from our setup files. The obvious solution is
to have a variable which is set when zsh first runs such as
$ZSH_FUNCTIONS. In fact, it might be better in the longer term to have
an associative array which points to any compile-time defined
directories. So we would have something like:
ZSH_INSTALL[functions]=/usr/local/share/zsh/$ZSH_VERSION/functions
ZSH_INSTALL[lib]=/usr/local/lib/zsh/3.1.6-dev-19
ZSH_INSTALL[share]=/usr/local/share/zsh
etc.

Oliver Kiddle


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2000-03-15 18:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-15 15:57 Default fpath Sven Wischnowsky
2000-03-15 18:15 ` Bart Schaefer
  -- strict thread matches above, loose matches on Subject: below --
2000-03-15  9:32 Sven Wischnowsky
2000-03-14 10:19 Sven Wischnowsky
2000-03-14 17:55 ` Bart Schaefer
2000-03-13 10:42 Sven Wischnowsky
2000-03-13 16:52 ` Bart Schaefer
2000-03-11 21:29 Oliver Kiddle
2000-03-11 23:46 ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).