about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>2000-03-15 09:39:05 +0000
committerTanaka Akira <akr@users.sourceforge.net>2000-03-15 09:39:05 +0000
commit2bb32164c71a0cb61e48d818b1209b952435a63f (patch)
tree681b988d22970d49e7203027359caf4812e07d5d
parent05eb5d93b193379d8a4671f7a7121c4fc73ffeee (diff)
downloadzsh-2bb32164c71a0cb61e48d818b1209b952435a63f.tar.gz
zsh-2bb32164c71a0cb61e48d818b1209b952435a63f.tar.xz
zsh-2bb32164c71a0cb61e48d818b1209b952435a63f.zip
zsh-workers/10144
-rw-r--r--Doc/Zsh/builtins.yo11
-rw-r--r--Src/Modules/parameter.c2
-rw-r--r--Src/builtin.c4
-rw-r--r--Src/exec.c6
-rw-r--r--Src/linklist.c17
-rw-r--r--Src/parse.c261
6 files changed, 237 insertions, 64 deletions
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index b0382dcd8..848f930f6 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -1296,6 +1296,7 @@ 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) ... ])
 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 @@ upshot of this is that the wordcode file is machine independent and if
 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 --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 606ce4583..5dce2f958 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -345,7 +345,7 @@ setfunction(char *name, char *val, int dis)
 	return;
     }
     shf = (Shfunc) zalloc(sizeof(*shf));
-    shf->funcdef = zdupeprog(prog);
+    shf->funcdef = dupeprog(prog, 0);
     shf->flags = dis;
 
     if (!strncmp(name, "TRAP", 4) &&
diff --git a/Src/builtin.c b/Src/builtin.c
index 73876b1fa..bbb8f1457 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -124,7 +124,7 @@ static struct builtin builtins[] =
     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 @@ bin_trap(char *name, char **argv, char *ops, int func)
 	    zwarnnam(name, "undefined signal: %s", *argv, 0);
 	    break;
 	}
-	t = zdupeprog(prog);
+	t = dupeprog(prog, 0);
 	if (settrap(sig, t))
 	    freeeprog(t);
     }
diff --git a/Src/exec.c b/Src/exec.c
index 336983e46..120b55eb5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3184,7 +3184,7 @@ execautofn(Estate state, int do_exec)
 	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 @@ loadautofn(Shfunc shf)
     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 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
  * list of its contents.                                                    */
 
 /**/
-static Eprog
+Eprog
 getfpfunc(char *s)
 {
     char **pp, buf[PATH_MAX];
diff --git a/Src/linklist.c b/Src/linklist.c
index e449957da..ff1c84317 100644
--- a/Src/linklist.c
+++ b/Src/linklist.c
@@ -239,7 +239,7 @@ countlinknodes(LinkList list)
 }
 
 /**/
-void
+mod_export void
 rolllist(LinkList l, LinkNode nd)
 {
     l->last->next = l->first;
@@ -251,7 +251,7 @@ rolllist(LinkList l, LinkNode nd)
 }
 
 /**/
-LinkList
+mod_export LinkList
 newsizedlist(int size)
 {
     LinkList list;
@@ -271,3 +271,16 @@ newsizedlist(int size)
 
     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 --git a/Src/parse.c b/Src/parse.c
index 1d6b18cf3..82404fcad 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -1980,7 +1980,7 @@ yyerror(int noerr)
 
 /**/
 mod_export Eprog
-zdupeprog(Eprog p)
+dupeprog(Eprog p, int heap)
 {
     Eprog r;
     int i;
@@ -1989,12 +1989,13 @@ zdupeprog(Eprog p)
     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 @@ int
 bin_zcompile(char *nam, char **args, char *ops, int func)
 {
     int map;
+    char *dump;
 
     if (ops['t']) {
 	Wordcode f;
@@ -2295,14 +2297,19 @@ bin_zcompile(char *nam, char **args, char *ops, int func)
 	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 @@ fdswap(Wordcode p, int n)
 
 /* 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 @@ build_dump(char *nam, char *dump, char **files, int ali, int map)
 	return 1;
     }
     progs = newlinklist();
+    names = newlinklist();
     noaliases = ali;
 
     for (hlen = FD_PRELEN, tlen = 0; *files; files++) {
@@ -2434,9 +2499,10 @@ build_dump(char *nam, char *dump, char **files, int ali, int map)
 	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 @@ build_dump(char *nam, char *dump, char **files, int ali, int map)
     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;
 }