1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-13 23:31:08 +02:00

40440: Add $functions_source hash to zsh/parameter.

This allows you to find out where a function was loaded from.
This commit is contained in:
Peter Stephenson 2017-01-28 19:33:27 +00:00
parent ea7b4d4b2d
commit 34f70c5dc0
6 changed files with 162 additions and 10 deletions

View file

@ -1,3 +1,10 @@
2017-01-28 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 40440: ../Doc/Zsh/mod_parameter.yo, Modules/parameter.c,
hashtable.c, ../Test/C04funcdef.ztst, ../Test/V06parameter.ztst:
Add $functions_source to zsh/parameter to help find where
functions where loaded from.
2017-01-27 Peter Stephenson <p.stephenson@samsung.com> 2017-01-27 Peter Stephenson <p.stephenson@samsung.com>
* Zach Whaley: 40200: Completion/Unix/Command/_perforce: update * Zach Whaley: 40200: Completion/Unix/Command/_perforce: update

View file

@ -37,6 +37,30 @@ vindex(dis_functions)
item(tt(dis_functions))( item(tt(dis_functions))(
Like tt(functions) but for disabled functions. Like tt(functions) but for disabled functions.
) )
vindex(functions_source)
item(tt(functions_source))(
This readonly associative array maps names of enabled functions to the
name of the file containing the source of the function.
For an autoloaded function that has already been loaded, or marked for
autoload with an absolute path, or that has had its path resolved with
`tt(functions -r)', this is the file found for autoloading, resolved
to an absolute path.
For a function defined within the body of a script or sourced file,
this is the name of that file. In this case, this is the exact path
originally used to that file, which may be a relative path.
For any other function, including any defined at an interactive prompt or
an autoload function whose path has not yet been resolved, this is
the empty string. However, the hash element is reported as defined
just so long as the function is present: the keys to this hash are
the same as those to tt($funcions).
)
vindex(dis_functions_source)
item(tt(dis_functions_source))(
Like tt(functions_source) but for disabled functions.
)
vindex(builtins) vindex(builtins)
item(tt(builtins))( item(tt(builtins))(
This associative array gives information about the builtin commands This associative array gives information about the builtin commands
@ -202,10 +226,13 @@ defined. The line number is the line where the `tt(function) var(name)'
or `var(name) tt(LPAR()RPAR())' started. In the case of an autoloaded or `var(name) tt(LPAR()RPAR())' started. In the case of an autoloaded
function the line number is reported as zero. function the line number is reported as zero.
The format of each element is var(filename)tt(:)var(lineno). The format of each element is var(filename)tt(:)var(lineno).
For functions autoloaded from a file in native zsh format, where only the For functions autoloaded from a file in native zsh format, where only the
body of the function occurs in the file, or for files that have been body of the function occurs in the file, or for files that have been
executed by the tt(source) or `tt(.)' builtins, the trace information is executed by the tt(source) or `tt(.)' builtins, the trace information is
shown as var(filename)tt(:)var(0), since the entire file is the definition. shown as var(filename)tt(:)var(0), since the entire file is the
definition. The source file name is resolved to an absolute path when
the function is loaded or the path to it otherwise resolved.
Most users will be interested in the information in the Most users will be interested in the information in the
tt(funcfiletrace) array instead. tt(funcfiletrace) array instead.

View file

@ -515,6 +515,98 @@ scanpmdisfunctions(HashTable ht, ScanFunc func, int flags)
scanfunctions(ht, func, flags, DISABLED); scanfunctions(ht, func, flags, DISABLED);
} }
/* Functions for the functions_source special parameter. */
/* Retrieve the source file for a function by explicit name */
/**/
static HashNode
getfunction_source(UNUSED(HashTable ht), const char *name, int dis)
{
Shfunc shf;
Param pm = NULL;
pm = (Param) hcalloc(sizeof(struct param));
pm->node.nam = dupstring(name);
pm->node.flags = PM_SCALAR|PM_READONLY;
pm->gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
(dis ? (shf->node.flags & DISABLED) : !(shf->node.flags & DISABLED))) {
pm->u.str = getshfuncfile(shf);
if (!pm->u.str)
pm->u.str = dupstring("");
}
return &pm->node;
}
/* Retrieve the source file for functions by scanning the table */
/**/
static void
scanfunctions_source(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
{
struct param pm;
int i;
HashNode hn;
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags = PM_SCALAR|PM_READONLY;
pm.gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
for (i = 0; i < shfunctab->hsize; i++) {
for (hn = shfunctab->nodes[i]; hn; hn = hn->next) {
if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
pm.node.nam = hn->nam;
if (func != scancountparams &&
((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
!(flags & SCANPM_WANTKEYS))) {
pm.u.str = getshfuncfile((Shfunc)hn);
if (!pm.u.str)
pm.u.str = dupstring("");
}
func(&pm.node, flags);
}
}
}
}
/* Param table entry for retrieving functions_source element */
/**/
static HashNode
getpmfunction_source(HashTable ht, const char *name)
{
return getfunction_source(ht, name, 0);
}
/* Param table entry for retrieving ds_functions_source element */
/**/
static HashNode
getpmdisfunction_source(HashTable ht, const char *name)
{
return getfunction_source(ht, name, 1);
}
/* Param table entry for scanning functions_source table */
/**/
static void
scanpmfunction_source(HashTable ht, ScanFunc func, int flags)
{
scanfunctions_source(ht, func, flags, 0);
}
/* Param table entry for scanning dis_functions_source table */
/**/
static void
scanpmdisfunction_source(HashTable ht, ScanFunc func, int flags)
{
scanfunctions_source(ht, func, flags, 1);
}
/* Functions for the funcstack special parameter. */ /* Functions for the funcstack special parameter. */
/**/ /**/
@ -2095,6 +2187,8 @@ static struct paramdef partab[] = {
NULL, getpmdisbuiltin, scanpmdisbuiltins), NULL, getpmdisbuiltin, scanpmdisbuiltins),
SPECIALPMDEF("dis_functions", 0, SPECIALPMDEF("dis_functions", 0,
&pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions), &pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
SPECIALPMDEF("dis_functions_source", PM_READONLY, NULL,
getpmdisfunction_source, scanpmdisfunction_source),
SPECIALPMDEF("dis_galiases", 0, SPECIALPMDEF("dis_galiases", 0,
&pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases), &pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY, SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY,
@ -2111,6 +2205,8 @@ static struct paramdef partab[] = {
&funcstack_gsu, NULL, NULL), &funcstack_gsu, NULL, NULL),
SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction, SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
scanpmfunctions), scanpmfunctions),
SPECIALPMDEF("functions_source", PM_READONLY, NULL,
getpmfunction_source, scanpmfunction_source),
SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY,
&functrace_gsu, NULL, NULL), &functrace_gsu, NULL, NULL),
SPECIALPMDEF("galiases", 0, SPECIALPMDEF("galiases", 0,

View file

@ -1565,6 +1565,15 @@ dircache_set(char **name, char *value)
zsfree(*name); zsfree(*name);
*name = NULL; *name = NULL;
} else { } else {
/*
* As the function path has been resolved to a particular
* location, we'll store it as an absolute path.
*/
if (*value != '/') {
value = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP),
"/", value);
value = xsymlink(value, 1);
}
/* /*
* We'll maintain the cache at exactly the right size rather * We'll maintain the cache at exactly the right size rather
* than overallocating. The rationale here is that typically * than overallocating. The rationale here is that typically

View file

@ -325,10 +325,10 @@
printf '%s\n' 'oops(){}' 'ninjas-earring(){}' 'oops "$@"' >oops printf '%s\n' 'oops(){}' 'ninjas-earring(){}' 'oops "$@"' >oops
autoload oops autoload oops
oops oops
whence -v oops whence -v oops | sed -e "s%$PWD%CURDIR%"
) )
0:whence -v of zsh-style autoload 0:whence -v of zsh-style autoload
>oops is a shell function from ./oops >oops is a shell function from CURDIR/oops
( (
fpath=(.) fpath=(.)

View file

@ -1,15 +1,15 @@
%test %test
print 'print In sourced file print 'print In sourced file
print $LINENO + $functrace + $funcsourcetrace print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
' >sourcedfile ' >sourcedfile
print -r -- 'print Started functrace.zsh print -r -- 'print Started functrace.zsh
module_path=(./Modules) module_path=(./Modules)
print $LINENO + $functrace + $funcsourcetrace print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
: :
fn() { fn() {
print Inside function $0 print Inside function $0
print $LINENO + $functrace + $funcsourcetrace print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
} }
: :
fn fn
@ -17,7 +17,7 @@
fpath=(. $fpath) fpath=(. $fpath)
: :
echo '\''print Inside $0 echo '\''print Inside $0
print $LINENO + $functrace + $funcsourcetrace print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
'\'' >autofn '\'' >autofn
: :
autoload autofn autoload autofn
@ -32,9 +32,9 @@
>Inside function fn >Inside function fn
>2 + ./functrace.zsh:10 + ./functrace.zsh:5 >2 + ./functrace.zsh:10 + ./functrace.zsh:5
>Inside autofn >Inside autofn
>2 + ./functrace.zsh:20 + ./autofn:0 >2 + ./functrace.zsh:20 + CURDIR/autofn:0
>Inside autofn >Inside autofn
>2 + ./functrace.zsh:21 + ./autofn:0 >2 + ./functrace.zsh:21 + CURDIR/autofn:0
>In sourced file >In sourced file
>2 + ./functrace.zsh:22 + ./sourcedfile:0 >2 + ./functrace.zsh:22 + ./sourcedfile:0
@ -66,6 +66,19 @@
>./rocky3.zsh:13 (eval):2 >./rocky3.zsh:13 (eval):2
>./rocky3.zsh:14 ./rocky3.zsh:14 >./rocky3.zsh:14 ./rocky3.zsh:14
(
fpath=($PWD)
print "print I have been autoloaded" >myfunc
autoload $PWD/myfunc
print ${functions_source[myfunc]/#$PWD/CURDIR}
myfunc
print ${functions_source[myfunc]/#$PWD/CURDIR}
)
0: $functions_source
>CURDIR/myfunc
>I have been autoloaded
>CURDIR/myfunc
%clean %clean
rm -f autofn functrace.zsh rocky3.zsh sourcedfile rm -f autofn functrace.zsh rocky3.zsh sourcedfile myfunc