summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/mod_parameter.yo29
-rw-r--r--Src/Modules/parameter.c96
-rw-r--r--Src/hashtable.c9
-rw-r--r--Test/C04funcdef.ztst4
-rw-r--r--Test/V06parameter.ztst27
6 files changed, 162 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 126287cdc..021be2f94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* Zach Whaley: 40200: Completion/Unix/Command/_perforce: update
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo
index 3d260f8e9..942e4c5b6 100644
--- a/Doc/Zsh/mod_parameter.yo
+++ b/Doc/Zsh/mod_parameter.yo
@@ -37,6 +37,30 @@ vindex(dis_functions)
item(tt(dis_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)
item(tt(builtins))(
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
function the line number is reported as zero.
The format of each element is var(filename)tt(:)var(lineno).
+
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
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
tt(funcfiletrace) array instead.
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 98bcaba6e..6e6228732 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -515,6 +515,98 @@ scanpmdisfunctions(HashTable ht, ScanFunc func, int flags)
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. */
/**/
@@ -2095,6 +2187,8 @@ static struct paramdef partab[] = {
NULL, getpmdisbuiltin, scanpmdisbuiltins),
SPECIALPMDEF("dis_functions", 0,
&pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
+ SPECIALPMDEF("dis_functions_source", PM_READONLY, NULL,
+ getpmdisfunction_source, scanpmdisfunction_source),
SPECIALPMDEF("dis_galiases", 0,
&pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
SPECIALPMDEF("dis_patchars", PM_ARRAY|PM_READONLY,
@@ -2111,6 +2205,8 @@ static struct paramdef partab[] = {
&funcstack_gsu, NULL, NULL),
SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
scanpmfunctions),
+ SPECIALPMDEF("functions_source", PM_READONLY, NULL,
+ getpmfunction_source, scanpmfunction_source),
SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY,
&functrace_gsu, NULL, NULL),
SPECIALPMDEF("galiases", 0,
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 1f2789d07..8987c8597 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -1566,6 +1566,15 @@ dircache_set(char **name, char *value)
*name = NULL;
} 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
* than overallocating. The rationale here is that typically
* we'll get a lot of functions in a small number of directories
diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
index 5edbe26bb..176841dd2 100644
--- a/Test/C04funcdef.ztst
+++ b/Test/C04funcdef.ztst
@@ -325,10 +325,10 @@
printf '%s\n' 'oops(){}' 'ninjas-earring(){}' 'oops "$@"' >oops
autoload oops
oops
- whence -v oops
+ whence -v oops | sed -e "s%$PWD%CURDIR%"
)
0:whence -v of zsh-style autoload
->oops is a shell function from ./oops
+>oops is a shell function from CURDIR/oops
(
fpath=(.)
diff --git a/Test/V06parameter.ztst b/Test/V06parameter.ztst
index c7df35dce..c2a2a4da5 100644
--- a/Test/V06parameter.ztst
+++ b/Test/V06parameter.ztst
@@ -1,15 +1,15 @@
%test
print 'print In sourced file
- print $LINENO + $functrace + $funcsourcetrace
+ print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
' >sourcedfile
print -r -- 'print Started functrace.zsh
module_path=(./Modules)
- print $LINENO + $functrace + $funcsourcetrace
+ print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
:
fn() {
print Inside function $0
- print $LINENO + $functrace + $funcsourcetrace
+ print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
}
:
fn
@@ -17,7 +17,7 @@
fpath=(. $fpath)
:
echo '\''print Inside $0
- print $LINENO + $functrace + $funcsourcetrace
+ print $LINENO + $functrace + ${funcsourcetrace/#$PWD/CURDIR}
'\'' >autofn
:
autoload autofn
@@ -32,9 +32,9 @@
>Inside function fn
>2 + ./functrace.zsh:10 + ./functrace.zsh:5
>Inside autofn
->2 + ./functrace.zsh:20 + ./autofn:0
+>2 + ./functrace.zsh:20 + CURDIR/autofn:0
>Inside autofn
->2 + ./functrace.zsh:21 + ./autofn:0
+>2 + ./functrace.zsh:21 + CURDIR/autofn:0
>In sourced file
>2 + ./functrace.zsh:22 + ./sourcedfile:0
@@ -66,6 +66,19 @@
>./rocky3.zsh:13 (eval):2
>./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
- rm -f autofn functrace.zsh rocky3.zsh sourcedfile
+ rm -f autofn functrace.zsh rocky3.zsh sourcedfile myfunc