From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: PATH: autoload with explicit path
Date: Sun, 11 Dec 2016 22:18:44 +0000 [thread overview]
Message-ID: <20161211221844.5e51affe@ntlworld.com> (raw)
Not to be committed until 5.3 is safely done and dusted, but you might
as well see it now.
I wanted to autoload a function from an explicit path. (Not so auto, in
fact, but there isn't a trivial way of manually loading an autoload -z
format file without using autoload.) I could rig something up in a
function, saving and restoring fpath or wrapping the contents of the
file, but it strikes me it's a bit mean of the shell not simply to do
something sensible with
autoload +X /path/to/myfunc
That doesn't do anything sensible at the moment --- relative paths to
functions do, with the full relative path as the name, which is entirely
consistent, but absolute paths don't and in fact it tries the name as a
relative path anyway which seems Just Plain Wrong.
Then I found it was pretty much as easy (easier, actually, since fewer
special cases) to implement this generally:
autoload -Uz /path/to/myfunc
defines myfunc to be found in the directory /path/to by reusing the
filename element of the shfunc structure that's currently unused at this
stage.
This seemed quite a useful feature. No doc or tests at this stage.
Also TBD: output from "autoload" with no name. Just needs to update the
output of the autoload -X line appropriately, so this is a minor detail,
I think.
Also TBD: I should clearly document that autoload has its normal
semantics i.e. if the function already exists that definition is kept.
Explicit path != forced reload.
Also TBD: should output a special error message if not found so
user knows where it was looking.
pws
diff --git a/Src/builtin.c b/Src/builtin.c
index 65e0cb1..96571df 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2962,6 +2962,27 @@ listusermathfunc(MathFunc p)
}
+static void
+add_autoload_function(Shfunc shf, char *funcname)
+{
+ char *nam;
+ if (*funcname == '/' && funcname[1] &&
+ (nam = strrchr(funcname, '/')) && nam[1]) {
+ char *dir;
+ nam = strrchr(funcname, '/');
+ if (nam == funcname) {
+ dir = "/";
+ } else {
+ *nam++ = '\0';
+ dir = funcname;
+ }
+ shf->filename = ztrdup(dir);
+ shfunctab->addnode(shfunctab, ztrdup(nam), shf);
+ } else {
+ shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
+ }
+}
+
/* Display or change the attributes of shell functions. *
* If called as autoload, it will define a new autoloaded *
* (undefined) shell function. */
@@ -3195,7 +3216,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
"BUG: Calling autoload from empty function");
} else {
shf = (Shfunc) zshcalloc(sizeof *shf);
- shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
+ add_autoload_function(shf, funcname);
}
shf->node.flags = on;
ret = eval_autoload(shf, funcname, ops, func);
@@ -3266,6 +3287,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
printshfuncexpand(&shf->node, pflags, expand);
} else if (on & PM_UNDEFINED) {
int signum = -1, ok = 1;
+ char *nam;
if (!strncmp(*argv, "TRAP", 4) &&
(signum = getsignum(*argv + 4)) != -1) {
@@ -3282,7 +3304,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
shf->node.flags = on;
shf->funcdef = mkautofn(shf);
shfunc_set_sticky(shf);
- shfunctab->addnode(shfunctab, ztrdup(*argv), shf);
+ add_autoload_function(shf, *argv);
if (signum != -1) {
if (settrap(signum, NULL, ZSIG_FUNC)) {
diff --git a/Src/exec.c b/Src/exec.c
index a439aec..6e4e99c 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -5155,12 +5155,23 @@ loadautofn(Shfunc shf, int fksh, int autol)
{
int noalias = noaliases, ksh = 1;
Eprog prog;
- char *fname;
+ char *fname, **alt_path, *spec_path[2];
pushheap();
+ if (shf->filename && shf->filename[0] == '/')
+ {
+ spec_path[0] = dupstring(shf->filename);
+ spec_path[1] = NULL;
+ alt_path = spec_path;
+ }
+ else
+ {
+ alt_path = NULL;
+ }
+
noaliases = (shf->node.flags & PM_UNALIASED);
- prog = getfpfunc(shf->node.nam, &ksh, &fname);
+ prog = getfpfunc(shf->node.nam, &ksh, &fname, alt_path);
noaliases = noalias;
if (ksh == 1) {
@@ -5607,7 +5618,7 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
/**/
Eprog
-getfpfunc(char *s, int *ksh, char **fname)
+getfpfunc(char *s, int *ksh, char **fname, char **alt_path)
{
char **pp, buf[PATH_MAX+1];
off_t len;
@@ -5616,7 +5627,7 @@ getfpfunc(char *s, int *ksh, char **fname)
Eprog r;
int fd;
- pp = fpath;
+ pp = alt_path ? alt_path : fpath;
for (; *pp; pp++) {
if (strlen(*pp) + strlen(s) + 1 >= PATH_MAX)
continue;
diff --git a/Src/parse.c b/Src/parse.c
index 50a0d5f..38c6da2 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -3324,7 +3324,7 @@ cur_add_func(char *nam, Shfunc shf, LinkList names, LinkList progs,
return 1;
}
noaliases = (shf->node.flags & PM_UNALIASED);
- if (!(prog = getfpfunc(shf->node.nam, NULL, NULL)) ||
+ if (!(prog = getfpfunc(shf->node.nam, NULL, NULL, NULL)) ||
prog == &dummy_eprog) {
noaliases = ona;
zwarnnam(nam, "can't load function: %s", shf->node.nam);
diff --git a/Src/zsh.h b/Src/zsh.h
index f22d8b1..4fdd09a 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1233,7 +1233,9 @@ struct cmdnam {
struct shfunc {
struct hashnode node;
- char *filename; /* Name of file located in */
+ char *filename; /* Name of file located in.
+ For not yet autoloaded file, name
+ of explicit directory, if not NULL. */
zlong lineno; /* line number in above file */
Eprog funcdef; /* function definition */
Eprog redir; /* redirections to apply */
next reply other threads:[~2016-12-11 22:18 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-11 22:18 Peter Stephenson [this message]
2016-12-12 16:05 ` Bart Schaefer
2016-12-12 16:31 ` Peter Stephenson
2016-12-12 18:09 ` Bart Schaefer
2017-01-10 19:31 ` Peter Stephenson
2017-01-11 11:42 ` Peter Stephenson
2017-01-11 20:51 ` Peter Stephenson
2017-01-12 20:42 ` Peter Stephenson
2017-01-13 18:04 ` Peter Stephenson
2017-01-16 10:37 ` Peter Stephenson
2017-01-16 15:04 ` Daniel Shahaf
2017-01-16 15:48 ` Peter Stephenson
2017-01-16 15:22 ` Bart Schaefer
2017-01-16 15:59 ` Peter Stephenson
[not found] ` <CAHYJk3SB1NDj6y5TRHHsAVsyjHfZQhTzMRzTR2c-SVEc9oAwzA@mail.gmail.com>
2017-01-24 11:10 ` Peter Stephenson
2017-01-11 21:13 ` Peter Stephenson
2017-01-17 18:36 ` PATCH: " Peter Stephenson
2017-01-17 22:17 ` Daniel Shahaf
2017-01-18 0:06 ` Bart Schaefer
2017-01-18 9:21 ` Peter Stephenson
2017-01-18 9:17 ` Peter Stephenson
2017-01-18 22:26 ` Bart Schaefer
2017-01-19 9:39 ` Peter Stephenson
2017-01-18 9:53 ` Peter Stephenson
[not found] <CGME20170127151334epcas2p4c32b57f69fcae22b40b309793eb8ceb6@epcas2p4.samsung.com>
2017-01-27 15:12 ` PATH: " Sebastian Gniazdowski
2017-01-27 16:24 ` Peter Stephenson
2017-01-27 18:40 ` Sebastian Gniazdowski
2017-01-27 18:44 ` Peter Stephenson
2017-01-27 19:00 ` Sebastian Gniazdowski
2017-01-28 18:05 ` Bart Schaefer
2017-01-28 19:12 ` Peter Stephenson
2017-01-28 19:45 ` Bart Schaefer
2017-01-28 19:56 ` Peter Stephenson
2017-01-28 20:37 ` Sebastian Gniazdowski
2017-01-29 12:27 ` Sebastian Gniazdowski
2017-01-29 16:11 ` Bart Schaefer
2017-01-29 17:32 ` Sebastian Gniazdowski
2017-01-29 18:37 ` Bart Schaefer
2017-01-29 21:53 ` Vin Shelton
2017-01-30 10:06 ` Peter Stephenson
2017-01-29 17:58 ` Peter Stephenson
2017-01-30 11:37 ` Sebastian Gniazdowski
2017-01-30 11:55 ` Peter Stephenson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161211221844.5e51affe@ntlworld.com \
--to=p.w.stephenson@ntlworld.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).