1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-23 17:01:05 +02:00

Add features associated with autoloading a function using an absolute

path.

-d defaults to normal fpath

-r remembers the path without actually loading.  May be combined with -d.

-R does the same but it's an error if not found

-X can now take a directory path: this is used to output not yet loaded
functions that have an associated path.
This commit is contained in:
Peter Stephenson 2017-01-11 11:26:13 +00:00
parent 34656ec2f0
commit f26d1ba6b0
9 changed files with 342 additions and 82 deletions

View file

@ -1,3 +1,11 @@
2017-01-11 Peter Stephenson <p.stephenson@samsung.com>
* 40327 (with minor fixes): Doc/Zsh/builtins.yo,
README,Src/builtin.c, Src/exec.c, Src/hashtable.c, Src/parse.c,
Src/zsh.h, Test/C04funcdef.ztst: add ability to autoload
function from file using full path, with additional related
autoload options -r, -R, -d and extension to -X.
2017-01-10 Peter Stephenson <p.w.stephenson@ntlworld.com>
* 40305: Src/Zle/complist.c, Src/Zle/zle_main.c,

View file

@ -147,20 +147,39 @@ ifnzman(noderef(Aliasing)).
findex(autoload)
cindex(functions, autoloading)
cindex(autoloading functions)
item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(TUXkmtz) ] [ tt(-w) ] [ var(name) ... ])(
item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(RTUXdkmrtz) ] [ tt(-w) ] [ var(name) ... ])(
vindex(fpath, searching)
Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X) and
tt(-w). See the section `Autoloading Functions' in ifzman(zmanref(zshmisc))\
See the section `Autoloading Functions' in ifzman(zmanref(zshmisc))\
ifnzman(noderef(Functions)) for full details. The tt(fpath) parameter
will be searched to find the function definition when the function is
first referenced.
The flag tt(-X) may be used only inside a shell function, and may not be
followed by a var(name). It causes the calling function to be marked for
autoloading and then immediately loaded and executed, with the current
array of positional parameters as arguments. This replaces the previous
definition of the function. If no function definition is found, an error
is printed and the function remains undefined and marked for autoloading.
If var(name) consists of an absolute path, the function is defined to
load from the file given (searching as usual for dump files in the given
location). The name of the function is the basename (non-directory
part) of the file. It is normally an error if the function is not found
in the given location; however, if the option tt(-d) is given, searching
for the function defaults to tt($fpath).
If the option tt(-r) or tt(-R) is given, the function is searched for
immediately and the location is recorded internally for use when the
function is executed; a relative path is expanded using the value of
tt($PWD). This protects against a change to tt($fpath) after the call
to tt(autoload). With tt(-r), if the function is not found, it is
silently left unresolved until execution; with tt(-R), an error message
is printed and command processing aborted immediately the search fails,
i.e. at the tt(autoload) command rather than at function execution..
The flag tt(-X) may be used only inside a shell function. It causes the
calling function to be marked for autoloading and then immediately
loaded and executed, with the current array of positional parameters as
arguments. This replaces the previous definition of the function. If
no function definition is found, an error is printed and the function
remains undefined and marked for autoloading. If an argument is given,
it is used as a directory (i.e. it does not include the name of the
function) in which the function is to be found; this may be combined
with the tt(-d) option to allow the function search to default to tt($fpath)
if it is not in the given location.
The flag tt(+X) attempts to load each var(name) as an autoloaded function,
but does em(not) execute it. The exit status is zero (success) if the
@ -176,6 +195,13 @@ If the tt(-m) flag is also given each var(name) is treated as a
pattern and all functions already marked for autoload that match the
pattern are loaded.
With the tt(-t) flag, turn on execution tracing; with tt(-T), turn on
execution tracing only for the current function, turning it off on entry
to any called functions that do not also have tracing enabled.
With the tt(-U) flag, alias expansion is suppressed when the function is
loaded.
With the tt(-w) flag, the var(name)s are taken as names of files compiled
with the tt(zcompile) builtin, and all functions defined in them are
marked for autoloading.
@ -193,6 +219,10 @@ example(emulate zsh -c 'autoload -Uz var(func)')
arranges that when var(func) is loaded the shell is in native tt(zsh)
emulation, and this emulation is also applied when var(func) is run.
Some of the functions of tt(autoload) are also provided by tt(functions
-u) or tt(functions -U), but tt(autoload) is a more comprehensive
interface.
)
findex(bg)
cindex(jobs, backgrounding)
@ -811,7 +841,8 @@ xitem(tt(functions -M) var(mathfn) [ var(min) [ var(max) [ var(shellfn) ] ] ])
xitem(tt(functions -M) [ tt(-m) var(pattern) ... ])
item(tt(functions +M) [ tt(-m) ] var(mathfn) ... )(
Equivalent to tt(typeset -f), with the exception of the tt(-x) and
tt(-M) options.
tt(-M) options. For tt(functions -u) and tt(functions -U), see
tt(autoload), which provides additional options.
The tt(-x) option indicates that any functions output will have
each leading tab for indentation, added by the shell to show syntactic
@ -2034,7 +2065,9 @@ expansion to be suppressed when the function is loaded. See the
description of the `tt(autoload)' builtin for details.
Note that the builtin tt(functions) provides the same basic capabilities
as tt(typeset -f) but gives access to a few extra options.
as tt(typeset -f) but gives access to a few extra options; tt(autoload)
gives further additional options for the case tt(typeset -fu) and
tt(typeset -fU).
)
item(tt(-h))(
Hide: only useful for special parameters (those marked `<S>' in the table in

16
README
View file

@ -32,7 +32,7 @@ details, see the documentation.
Incompatibilities since 5.3.1
-----------------------------
The default behaviour of code like the following has changed:
1) The default behaviour of code like the following has changed:
alias foo='noglob foo'
foo() { print function body; }
@ -52,8 +52,18 @@ ALIAS_FUNC_DEF, has been added, which can be set to make the shell
behave as in previous versions. It is in any case recommended to use
the "function" keyword, as aliases are not expanded afterwards.
Incompatibilities between 5.0.8 and 5.3.1
-----------------------------------------
2) It was an undocumented, and largely useless, feature that a function
autoloaded with an absolute path was searched for along the normal fpath
(as if the leading / was missing) and, if found, loaded under the full
name including the leading slash. This has been replaced with the more
useful feature that the function is searched for only at the given
absolute path; the name of the function is the base name of the file.
Note that functions including a non-leading / behave as before,
e.g. if `dir/name' is found anywhere under a directory in $fpath it is
loaded as a function named `dir/name'.
Incompatibilities between 5.0.8 and 5.3
----------------------------------------
1) In character classes delimited by "[" and "]" within patterns, whether
used for filename generation (globbing) or other forms of pattern

View file

@ -46,7 +46,7 @@ static struct builtin builtins[] =
BUILTIN(".", BINF_PSPECIAL, bin_dot, 1, -1, 0, NULL, NULL),
BUILTIN(":", BINF_PSPECIAL, bin_true, 0, -1, 0, NULL, NULL),
BUILTIN("alias", BINF_MAGICEQUALS | BINF_PLUSOPTS, bin_alias, 0, -1, 0, "Lgmrs", NULL),
BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "mktTUwXz", "u"),
BUILTIN("autoload", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "dmktrRTUwXz", "u"),
BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@ -2922,9 +2922,59 @@ eval_autoload(Shfunc shf, char *name, Options ops, int func)
}
return !loadautofn(shf, (OPT_ISSET(ops,'k') ? 2 :
(OPT_ISSET(ops,'z') ? 0 : 1)), 1);
(OPT_ISSET(ops,'z') ? 0 : 1)), 1,
OPT_ISSET(ops,'d'));
}
/* Helper for bin_functions() for -X and -r options */
/**/
static int
check_autoload(Shfunc shf, char *name, Options ops, int func)
{
if (OPT_ISSET(ops,'X'))
{
return eval_autoload(shf, name, ops, func);
}
if (OPT_ISSET(ops,'r') || OPT_ISSET(ops,'R'))
{
char *dir_path;
if (shf->filename) {
char *spec_path[2];
spec_path[0] = shf->filename;
spec_path[1] = NULL;
if (getfpfunc(shf->node.nam, NULL, &dir_path, spec_path, 1)) {
/* shf->filename is already correct. */
return 0;
}
if (!OPT_ISSET(ops,'d')) {
if (OPT_ISSET(ops,'R')) {
zerr("%s: function definition file not found",
shf->node.nam);
return 1;
}
return 0;
}
}
if (getfpfunc(shf->node.nam, NULL, &dir_path, NULL, 1)) {
zsfree(shf->filename);
if (*dir_path != '/') {
dir_path = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP),
"/", dir_path);
dir_path = xsymlink(dir_path, 1);
}
shf->filename = ztrdup(dir_path);
return 0;
}
if (OPT_ISSET(ops,'R')) {
zerr("%s: function definition file not found",
shf->node.nam);
return 1;
}
/* with -r, we don't flag an error, just let it be found later. */
}
return 0;
}
/* List a user-defined math function. */
static void
@ -2962,6 +3012,28 @@ 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;
}
zsfree(shf->filename);
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. */
@ -3007,10 +3079,17 @@ bin_functions(char *name, char **argv, Options ops, int func)
off |= PM_KSHSTORED;
roff |= PM_KSHSTORED;
}
if (OPT_MINUS(ops,'d')) {
on |= PM_CUR_FPATH;
off |= PM_CUR_FPATH;
} else if (OPT_PLUS(ops,'d')) {
off |= PM_CUR_FPATH;
roff |= PM_CUR_FPATH;
}
if ((off & PM_UNDEFINED) || (OPT_ISSET(ops,'k') && OPT_ISSET(ops,'z')) ||
(OPT_ISSET(ops,'x') && !OPT_HASARG(ops,'x')) ||
(OPT_MINUS(ops,'X') && (OPT_ISSET(ops,'m') || *argv || !scriptname))) {
(OPT_MINUS(ops,'X') && (OPT_ISSET(ops,'m') || !scriptname))) {
zwarnnam(name, "invalid option(s)");
return 1;
}
@ -3165,47 +3244,55 @@ bin_functions(char *name, char **argv, Options ops, int func)
return returnval;
}
/* If no arguments given, we will print functions. If flags *
* are given, we will print only functions containing these *
* flags, else we'll print them all. */
if (!*argv) {
if (OPT_MINUS(ops,'X')) {
Funcstack fs;
char *funcname = NULL;
int ret;
if (*argv && argv[1]) {
zwarnnam(name, "-X: too many arguments");
return 1;
}
queue_signals();
for (fs = funcstack; fs; fs = fs->prev) {
if (fs->tp == FS_FUNC) {
/*
* dupstring here is paranoia but unlikely to be
* problematic
*/
funcname = dupstring(fs->name);
break;
}
}
if (!funcname)
{
zerrnam(name, "bad autoload");
ret = 1;
} else {
if ((shf = (Shfunc) shfunctab->getnode(shfunctab, funcname))) {
DPUTS(!shf->funcdef,
"BUG: Calling autoload from empty function");
} else {
shf = (Shfunc) zshcalloc(sizeof *shf);
shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
}
if (*argv)
shf->filename = ztrdup(*argv);
shf->node.flags = on;
ret = eval_autoload(shf, funcname, ops, func);
}
unqueue_signals();
return ret;
} else if (!*argv) {
/* If no arguments given, we will print functions. If flags *
* are given, we will print only functions containing these *
* flags, else we'll print them all. */
int ret = 0;
queue_signals();
if (OPT_MINUS(ops,'X')) {
Funcstack fs;
char *funcname = NULL;
for (fs = funcstack; fs; fs = fs->prev) {
if (fs->tp == FS_FUNC) {
/*
* dupstring here is paranoia but unlikely to be
* problematic
*/
funcname = dupstring(fs->name);
break;
}
}
if (!funcname)
{
zerrnam(name, "bad autoload");
ret = 1;
} else {
if ((shf = (Shfunc) shfunctab->getnode(shfunctab, funcname))) {
DPUTS(!shf->funcdef,
"BUG: Calling autoload from empty function");
} else {
shf = (Shfunc) zshcalloc(sizeof *shf);
shfunctab->addnode(shfunctab, ztrdup(funcname), shf);
}
shf->node.flags = on;
ret = eval_autoload(shf, funcname, ops, func);
}
} else {
if (OPT_ISSET(ops,'U') && !OPT_ISSET(ops,'u'))
if (OPT_ISSET(ops,'U') && !OPT_ISSET(ops,'u'))
on &= ~PM_UNDEFINED;
scanshfunc(1, on|off, DISABLED, shfunctab->printnode,
pflags, expand);
}
unqueue_signals();
return ret;
}
@ -3231,8 +3318,8 @@ bin_functions(char *name, char **argv, Options ops, int func)
!(shf->node.flags & DISABLED)) {
shf->node.flags = (shf->node.flags |
(on & ~PM_UNDEFINED)) & ~off;
if (OPT_ISSET(ops,'X') &&
eval_autoload(shf, shf->node.nam, ops, func)) {
if (check_autoload(shf, shf->node.nam,
ops, func)) {
returnval = 1;
}
}
@ -3258,8 +3345,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
if (on|off) {
/* turn on/off the given flags */
shf->node.flags = (shf->node.flags | (on & ~PM_UNDEFINED)) & ~off;
if (OPT_ISSET(ops,'X') &&
eval_autoload(shf, shf->node.nam, ops, func))
if (check_autoload(shf, shf->node.nam, ops, func))
returnval = 1;
} else
/* no flags, so just print */
@ -3282,7 +3368,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)) {
@ -3293,8 +3379,7 @@ bin_functions(char *name, char **argv, Options ops, int func)
}
}
if (ok && OPT_ISSET(ops,'X') &&
eval_autoload(shf, shf->node.nam, ops, func))
if (ok && check_autoload(shf, shf->node.nam, ops, func))
returnval = 1;
} else
returnval = 1;

View file

@ -3124,7 +3124,7 @@ execcmd_exec(Estate state, Execcmd_params eparams,
if (is_shfunc)
shf = (Shfunc)hn;
else {
shf = loadautofn(state->prog->shf, 1, 0);
shf = loadautofn(state->prog->shf, 1, 0, 0);
if (shf)
state->prog->shf = shf;
else {
@ -5142,7 +5142,7 @@ execautofn(Estate state, UNUSED(int do_exec))
{
Shfunc shf;
if (!(shf = loadautofn(state->prog->shf, 1, 0)))
if (!(shf = loadautofn(state->prog->shf, 1, 0, 0)))
return 1;
state->prog->shf = shf;
@ -5151,7 +5151,7 @@ execautofn(Estate state, UNUSED(int do_exec))
/**/
Shfunc
loadautofn(Shfunc shf, int fksh, int autol)
loadautofn(Shfunc shf, int fksh, int autol, int current_fpath)
{
int noalias = noaliases, ksh = 1;
Eprog prog;
@ -5160,7 +5160,18 @@ loadautofn(Shfunc shf, int fksh, int autol)
pushheap();
noaliases = (shf->node.flags & PM_UNALIASED);
prog = getfpfunc(shf->node.nam, &ksh, &fname);
if (shf->filename && shf->filename[0] == '/')
{
char *spec_path[2];
spec_path[0] = dupstring(shf->filename);
spec_path[1] = NULL;
prog = getfpfunc(shf->node.nam, &ksh, &fname, spec_path, 0);
if (prog == &dummy_eprog &&
(current_fpath || (shf->node.flags & PM_CUR_FPATH)))
prog = getfpfunc(shf->node.nam, &ksh, &fname, NULL, 0);
}
else
prog = getfpfunc(shf->node.nam, &ksh, &fname, NULL, 0);
noaliases = noalias;
if (ksh == 1) {
@ -5602,12 +5613,18 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
unqueue_signals();
}
/* Search fpath for an undefined function. Finds the file, and returns the *
* list of its contents. */
/*
* Search fpath for an undefined function. Finds the file, and returns the
* list of its contents.
*
* 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)
*/
/**/
Eprog
getfpfunc(char *s, int *ksh, char **fname)
getfpfunc(char *s, int *ksh, char **fname, char **alt_path, int test_only)
{
char **pp, buf[PATH_MAX+1];
off_t len;
@ -5616,7 +5633,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;
@ -5624,9 +5641,9 @@ getfpfunc(char *s, int *ksh, char **fname)
sprintf(buf, "%s/%s", *pp, s);
else
strcpy(buf, s);
if ((r = try_dump_file(*pp, s, buf, ksh))) {
if ((r = try_dump_file(*pp, s, buf, ksh, test_only))) {
if (fname)
*fname = ztrdup(buf);
*fname = test_only ? *pp : ztrdup(buf);
return r;
}
unmetafy(buf, NULL);
@ -5634,6 +5651,11 @@ getfpfunc(char *s, int *ksh, char **fname)
struct stat st;
if (!fstat(fd, &st) && S_ISREG(st.st_mode) &&
(len = lseek(fd, 0, 2)) != -1) {
if (test_only) {
close(fd);
*fname = *pp;
return &dummy_eprog;
}
d = (char *) zalloc(len + 1);
lseek(fd, 0, 0);
if ((rlen = read(fd, d, len)) >= 0) {
@ -5661,7 +5683,7 @@ getfpfunc(char *s, int *ksh, char **fname)
close(fd);
}
}
return &dummy_eprog;
return test_only ? NULL : &dummy_eprog;
}
/* Handle the most common type of ksh-style autoloading, when doing a *

View file

@ -949,16 +949,20 @@ printshfuncnode(HashNode hn, int printflags)
zoutputtab(stdout);
}
if (!t) {
char *fopt = "UtTkz";
char *fopt = "UtTkzc";
int flgs[] = {
PM_UNALIASED, PM_TAGGED, PM_TAGGED_LOCAL,
PM_KSHSTORED, PM_ZSHSTORED, 0
PM_KSHSTORED, PM_ZSHSTORED, PM_CUR_FPATH, 0
};
int fl;;
zputs("builtin autoload -X", stdout);
for (fl=0;fopt[fl];fl++)
if (f->node.flags & flgs[fl]) putchar(fopt[fl]);
if (f->filename) {
putchar(' ');
zputs(f->filename, stdout);
}
} else {
zputs(t, stdout);
zsfree(t);

View file

@ -3338,7 +3338,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, 0)) ||
prog == &dummy_eprog) {
noaliases = ona;
zwarnnam(nam, "can't load function: %s", shf->node.nam);
@ -3580,7 +3580,7 @@ load_dump_file(char *dump, struct stat *sbuf, int other, int len)
/**/
Eprog
try_dump_file(char *path, char *name, char *file, int *ksh)
try_dump_file(char *path, char *name, char *file, int *ksh, int test_only)
{
Eprog prog;
struct stat std, stc, stn;
@ -3589,7 +3589,7 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
if (strsfx(FD_EXT, path)) {
queue_signals();
prog = check_dump_file(path, NULL, name, ksh);
prog = check_dump_file(path, NULL, name, ksh, test_only);
unqueue_signals();
return prog;
}
@ -3608,14 +3608,14 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
if (!rd &&
(rc || std.st_mtime > stc.st_mtime) &&
(rn || std.st_mtime > stn.st_mtime) &&
(prog = check_dump_file(dig, &std, name, ksh))) {
(prog = check_dump_file(dig, &std, name, ksh, test_only))) {
unqueue_signals();
return prog;
}
/* No digest file. Now look for the per-function compiled file. */
if (!rc &&
(rn || stc.st_mtime > stn.st_mtime) &&
(prog = check_dump_file(wc, &stc, name, ksh))) {
(prog = check_dump_file(wc, &stc, name, ksh, test_only))) {
unqueue_signals();
return prog;
}
@ -3643,7 +3643,7 @@ try_source_file(char *file)
if (strsfx(FD_EXT, file)) {
queue_signals();
prog = check_dump_file(file, NULL, tail, NULL);
prog = check_dump_file(file, NULL, tail, NULL, 0);
unqueue_signals();
return prog;
}
@ -3654,7 +3654,7 @@ try_source_file(char *file)
queue_signals();
if (!rc && (rn || stc.st_mtime > stn.st_mtime) &&
(prog = check_dump_file(wc, &stc, tail, NULL))) {
(prog = check_dump_file(wc, &stc, tail, NULL, 0))) {
unqueue_signals();
return prog;
}
@ -3667,7 +3667,8 @@ try_source_file(char *file)
/**/
static Eprog
check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh,
int test_only)
{
int isrec = 0;
Wordcode d;
@ -3709,6 +3710,11 @@ check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
if ((h = dump_find_func(d, name))) {
/* Found the name. If the file is already mapped, return the eprog,
* otherwise map it and just go up. */
if (test_only)
{
/* This is all we need. Just return dummy. */
return &dummy_eprog;
}
#ifdef USE_MMAP
@ -3745,7 +3751,7 @@ check_dump_file(char *file, struct stat *sbuf, char *name, int *ksh)
#endif
{
{
Eprog prog;
Patprog *pp;
int np, fd, po = h->npats * sizeof(Patprog);

View file

@ -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 */
@ -1811,6 +1813,7 @@ struct tieddata {
#define PM_UNALIASED (1<<13) /* do not expand aliases when autoloading */
#define PM_HIDE (1<<14) /* Special behaviour hidden by local */
#define PM_CUR_FPATH (1<<14) /* (function): can use $fpath with filename */
#define PM_HIDEVAL (1<<15) /* Value not shown in `typeset' commands */
#define PM_TIED (1<<16) /* array tied to colon-path or v.v. */
#define PM_TAGGED_LOCAL (1<<16) /* (function): non-recursive PM_TAGGED */

View file

@ -330,6 +330,95 @@
0:whence -v of zsh-style autoload
>oops is a shell function from ./oops
(
fpath=(.)
mkdir extra
print 'print "I have been loaded by explicit path."' >extra/spec
autoload -Uz $PWD/extra/spec
spec
)
0:autoload with explicit path
>I have been loaded by explicit path.
(
fpath=(.)
print 'print "I have been loaded by default path."' >def
autoload -Uz $PWD/extra/def
def
)
1:autoload with explicit path with function in normal path, no -d
?(eval):5: def: function definition file not found
(
fpath=(.)
autoload -dUz $PWD/extra/def
def
)
0:autoload with explicit path with function in normal path, with -d
>I have been loaded by default path.
(
cd extra
fpath=(.)
autoload -r spec
cd ..
spec
)
0:autoload -r
>I have been loaded by explicit path.
(
cd extra
fpath=(.)
autoload -r def
cd ..
def
)
0:autoload -r is permissive
>I have been loaded by default path.
(
cd extra
fpath=(.)
autoload -R def
)
1:autoload -R is not permissive
?(eval):4: def: function definition file not found
(
spec() { autoload -XUz $PWD/extra; }
spec
)
0:autoload -X with path
>I have been loaded by explicit path.
# The line number 1 here and in the next test seems suspect,
# but this example proves it's not down to the new features
# being tested here.
(
fpath=(.)
cod() { autoload -XUz; }
cod
)
1:autoload -X with no path, failure
?(eval):1: cod: function definition file not found
(
fpath=(.)
def() { autoload -XUz $PWD/extra; }
def
)
1:autoload -X with wrong path and no -d
?(eval):1: def: function definition file not found
(
fpath=(.)
def() { autoload -dXUz $PWD/extra; }
def
)
0:autoload -dX with path
>I have been loaded by default path.
%clean
rm -f file.in file.out