mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-10 12:40:58 +02:00
zsh-workers/10144
This commit is contained in:
parent
05eb5d93b1
commit
2bb32164c7
6 changed files with 240 additions and 67 deletions
|
@ -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
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
267
Src/parse.c
267
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue