1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-18 03:11:15 +02:00

40353 with tweaks to whence -v: extend directory cache use.

Now used for all autoloaded functions after load, including those
where the file was found along fpath, reducing duplication of
directory names.
This commit is contained in:
Peter Stephenson 2017-01-16 10:31:56 +00:00
parent ebd7fdd932
commit f90a0447aa
4 changed files with 92 additions and 31 deletions

View file

@ -1,3 +1,10 @@
2017-01-16 Peter Stephenson <p.stephenson@samsung.com>
* 40353 (plus improvement to whence -v): Src/exec.c,
Src/hashtable.c, Src/signals.c: use directory cache where
possible for all functions loaded from directory including
fpath.
2017-01-15 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 40362: Src/Zle/computil.c: need duplicated values for setting

View file

@ -5124,12 +5124,12 @@ execautofn_basic(Estate state, UNUSED(int do_exec))
* defined yet.
*/
if (funcstack && !funcstack->filename)
funcstack->filename = dupstring(shf->filename);
funcstack->filename = getshfuncfile(shf);
oldscriptname = scriptname;
oldscriptfilename = scriptfilename;
scriptname = dupstring(shf->node.nam);
scriptfilename = dupstring(shf->filename);
scriptfilename = getshfuncfile(shf);
execode(shf->funcdef, 1, 0, "loadautofunc");
scriptname = oldscriptname;
scriptfilename = oldscriptfilename;
@ -5150,13 +5150,47 @@ execautofn(Estate state, UNUSED(int do_exec))
return execautofn_basic(state, 0);
}
/*
* Helper function to install the source file name of a shell function
* just autoloaded.
*
* We attempt to do this efficiently as the typical case is the
* directory part is a well-known directory, which is cached, and
* the non-directory part is the same as the node name.
*/
/**/
static void
loadautofnsetfile(Shfunc shf, char *fdir)
{
/*
* If shf->filename is already the load directory ---
* keep it as we can still use it to get the load file.
* This makes autoload with an absolute path particularly efficient.
*/
if (!(shf->node.flags & PM_LOADDIR) ||
strcmp(shf->filename, fdir) != 0) {
/* Old directory name not useful... */
dircache_set(&shf->filename, NULL);
if (fdir) {
/* ...can still cache directory */
shf->node.flags |= PM_LOADDIR;
dircache_set(&shf->filename, fdir);
} else {
/* ...no separate directory part to cache, for some reason. */
shf->node.flags &= ~PM_LOADDIR;
shf->filename = ztrdup(shf->node.nam);
}
}
}
/**/
Shfunc
loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
{
int noalias = noaliases, ksh = 1;
Eprog prog;
char *fname;
char *fdir; /* Directory path where func found */
pushheap();
@ -5167,13 +5201,13 @@ loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
char *spec_path[2];
spec_path[0] = dupstring(shf->filename);
spec_path[1] = NULL;
prog = getfpfunc(shf->node.nam, &ksh, &fname, spec_path, 0);
prog = getfpfunc(shf->node.nam, &ksh, &fdir, spec_path, 0);
if (prog == &dummy_eprog &&
(current_fpath || (shf->node.flags & PM_CUR_FPATH)))
prog = getfpfunc(shf->node.nam, &ksh, &fname, NULL, 0);
prog = getfpfunc(shf->node.nam, &ksh, &fdir, NULL, 0);
}
else
prog = getfpfunc(shf->node.nam, &ksh, &fname, NULL, 0);
prog = getfpfunc(shf->node.nam, &ksh, &fdir, NULL, 0);
noaliases = noalias;
if (ksh == 1) {
@ -5192,7 +5226,6 @@ loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
return NULL;
}
if (!prog) {
zsfree(fname);
popheap();
return NULL;
}
@ -5205,10 +5238,8 @@ loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
shf->funcdef = prog;
else
shf->funcdef = dupeprog(prog, 0);
shf->node.flags &= ~(PM_UNDEFINED|PM_LOADDIR);
dircache_set(&shf->filename, NULL);
/* Full filename, don't use dircache */
shf->filename = fname;
shf->node.flags &= ~PM_UNDEFINED;
loadautofnsetfile(shf, fdir);
} else {
VARARR(char, n, strlen(shf->node.nam) + 1);
strcpy(n, shf->node.nam);
@ -5220,7 +5251,6 @@ loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
zwarn("%s: function not defined by file", n);
locallevel++;
popheap();
zsfree(fname);
return NULL;
}
}
@ -5230,10 +5260,8 @@ loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
shf->funcdef = stripkshdef(prog, shf->node.nam);
else
shf->funcdef = dupeprog(stripkshdef(prog, shf->node.nam), 0);
shf->node.flags &= ~(PM_UNDEFINED|PM_LOADDIR);
dircache_set(&shf->filename, NULL);
/* Full filename, don't use dircache */
shf->filename = fname;
shf->node.flags &= ~PM_UNDEFINED;
loadautofnsetfile(shf, fdir);
}
popheap();
@ -5453,7 +5481,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
funcstack = &fstack;
fstack.flineno = shfunc->lineno;
fstack.filename = dupstring(shfunc->filename);
fstack.filename = getshfuncfile(shfunc);
prog = shfunc->funcdef;
if (prog->flags & EF_RUN) {
@ -5623,16 +5651,17 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
* Search fpath for an undefined function. Finds the file, and returns the
* list of its contents.
*
* If test is 0, load the function; *fname is set to zalloc'ed location.
* If test is 0, load the function.
*
* If test_only is 1, don't load function, just test for it:
* - Non-null return means function was found
* - *fname points to path at which found (not duplicated)
* Non-null return means function was found
*
* *fdir points to path at which found (as passed in, not duplicated)
*/
/**/
Eprog
getfpfunc(char *s, int *ksh, char **fname, char **alt_path, int test_only)
getfpfunc(char *s, int *ksh, char **fdir, char **alt_path, int test_only)
{
char **pp, buf[PATH_MAX+1];
off_t len;
@ -5650,8 +5679,8 @@ getfpfunc(char *s, int *ksh, char **fname, char **alt_path, int test_only)
else
strcpy(buf, s);
if ((r = try_dump_file(*pp, s, buf, ksh, test_only))) {
if (fname)
*fname = test_only ? *pp : ztrdup(buf);
if (fdir)
*fdir = *pp;
return r;
}
unmetafy(buf, NULL);
@ -5661,7 +5690,8 @@ getfpfunc(char *s, int *ksh, char **fname, char **alt_path, int test_only)
(len = lseek(fd, 0, 2)) != -1) {
if (test_only) {
close(fd);
*fname = *pp;
if (fdir)
*fdir = *pp;
return &dummy_eprog;
}
d = (char *) zalloc(len + 1);
@ -5677,8 +5707,8 @@ getfpfunc(char *s, int *ksh, char **fname, char **alt_path, int test_only)
r = parse_string(d, 1);
scriptname = oldscriptname;
if (fname)
*fname = ztrdup(buf);
if (fdir)
*fdir = *pp;
zfree(d, len + 1);

View file

@ -926,10 +926,13 @@ printshfuncnode(HashNode hn, int printflags)
(f->node.flags & PM_UNDEFINED) ?
" is an autoload shell function" :
" is a shell function");
if (f->filename && (printflags & PRINT_WHENCE_VERBOSE) &&
strcmp(f->filename, f->node.nam) != 0) {
if ((printflags & PRINT_WHENCE_VERBOSE) && f->filename) {
printf(" from ");
quotedzputs(f->filename, stdout);
if (f->node.flags & PM_LOADDIR) {
printf("/");
quotedzputs(f->node.nam, stdout);
}
}
putchar('\n');
return;
@ -959,7 +962,7 @@ printshfuncnode(HashNode hn, int printflags)
zputs("builtin autoload -X", stdout);
for (fl=0;fopt[fl];fl++)
if (f->node.flags & flgs[fl]) putchar(fopt[fl]);
if (f->filename) {
if (f->filename && (f->node.flags & PM_LOADDIR)) {
putchar(' ');
zputs(f->filename, stdout);
}
@ -1041,6 +1044,24 @@ printshfuncexpand(HashNode hn, int printflags, int expand)
text_expand_tabs = save_expand;
}
/*
* Get a heap-duplicated name of the shell function, for
* use in tracing.
*/
/**/
mod_export char *
getshfuncfile(Shfunc shf)
{
if (shf->node.flags & PM_LOADDIR) {
return zhtricat(shf->filename, "/", shf->node.nam);
} else if (shf->filename) {
return dupstring(shf->filename);
} else {
return NULL;
}
}
/**************************************/
/* Reserved Word Hash Table Functions */
/**************************************/

View file

@ -811,8 +811,11 @@ dosavetrap(int sig, int level)
newshf->node.nam = ztrdup(shf->node.nam);
newshf->node.flags = shf->node.flags;
newshf->funcdef = dupeprog(shf->funcdef, 0);
/* Assume this is a real filename, don't use dircache */
newshf->filename = ztrdup(shf->filename);
if (shf->node.flags & PM_LOADDIR) {
dircache_set(&newshf->filename, shf->filename);
} else {
newshf->filename = ztrdup(shf->filename);
}
if (shf->sticky) {
newshf->sticky = sticky_emulation_dup(shf->sticky, 0);
} else