mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-15 04:32:24 +00:00
whence -v/-a: report path to autoloadable functions
Since at least 1999, whence -v on pdksh (and its successor mksh) reports the path where an autoloadable function may be found: $ mkdir ~/fun; FPATH=~/fun $ echo 'myfn() { echo hi; }' >~/fun/myfn $ whence -v myfn myfn is a undefined (autoload from /home/user/fun/myfn) function Whereas ksh93 only reports, rather uselessly: myfn is an undefined function As of this commit, whence -v/-a on ksh 93u+m does the same as pdksh, but with correct grammar: myfn is an undefined function (autoload from /home/user/fun/myfn) This may be a small violation of my own "no new features" policy for 93u+m, but I couldn't resist. This omission has been annoying me, and it's just embarrassing to lack a pdksh feature :) src/cmd/ksh93/include/path.h, src/cmd/ksh93/data/msg.c: - Add e_autoloadfrom[] = " (autoload from %s)" message. src/cmd/ksh93/bltins/whence.c: whence(): - Report the path (if any) when reporting an undefined function. This needs to be done in two places: 1. When a function has been explicitly marked undefined with 'autoload', we need to do a quick path_search() loop to find the path. (These undefined functions take precedence over regular commands, so are reported first.) 2. When a function is not explicitly autoloaded but merely available in $FPATH, that path search was already done, so all we need to do is report it. (These are reported last.) Note that the output remains as on 93u+ if no function definition file is found on $FPATH. This is also like pdksh/mksh. src/cmd/ksh93/data/builtins.c: - Bump 'whence' version date. The inline docs never detailed very exactly what 'whence -v' reports, so no need for further edits. src/cmd/ksh93/tests/path.sh: - Regress-test the new whence behaviour plus actual autoloading, including the command override behaviour of autoloaded functions.
This commit is contained in:
parent
cefe087d23
commit
3050bf28bc
6 changed files with 64 additions and 11 deletions
3
NEWS
3
NEWS
|
@ -5,6 +5,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
|||
|
||||
2020-09-25:
|
||||
|
||||
- whence -v/-a now reports the path to the file that an "undefined" (i.e.
|
||||
autoloadable) function will be loaded from when invoked, if found in $FPATH.
|
||||
|
||||
- When ksh invoked a shell script that does not have a leading
|
||||
#!/hashbang/path, 'ps' and /proc/<PID>/cmdline showed corrupted output if
|
||||
the new script's command line was shorter than that of the invoking script.
|
||||
|
|
|
@ -139,7 +139,7 @@ static int whence(Shell_t *shp,char **argv, register int flags)
|
|||
register const char *msg;
|
||||
Namval_t *nq;
|
||||
char *notused;
|
||||
Pathcomp_t *pp=0;
|
||||
Pathcomp_t *pp;
|
||||
if(flags&Q_FLAG)
|
||||
flags &= ~A_FLAG;
|
||||
while(name= *argv++)
|
||||
|
@ -179,16 +179,24 @@ static int whence(Shell_t *shp,char **argv, register int flags)
|
|||
bltins:
|
||||
if(!(flags&F_FLAG) && (np = nv_bfsearch(name, shp->fun_tree, &nq, ¬used)) && !is_abuiltin(np))
|
||||
{
|
||||
if(flags&V_FLAG)
|
||||
if(nv_isnull(np))
|
||||
cp = sh_translate(is_ufunction);
|
||||
else
|
||||
cp = sh_translate(is_function);
|
||||
else
|
||||
cp = "";
|
||||
if(flags&Q_FLAG)
|
||||
continue;
|
||||
sfprintf(sfstdout,"%s%s\n",name,cp);
|
||||
sfputr(sfstdout,name,-1);
|
||||
if(flags&V_FLAG)
|
||||
{
|
||||
if(nv_isnull(np))
|
||||
{
|
||||
sfprintf(sfstdout,sh_translate(is_ufunction));
|
||||
pp = 0;
|
||||
while(!path_search(shp,name,&pp,3) && pp && (pp = pp->next))
|
||||
;
|
||||
if(*stakptr(PATH_OFFSET)=='/')
|
||||
sfprintf(sfstdout,sh_translate(e_autoloadfrom),sh_fmtq(stakptr(PATH_OFFSET)));
|
||||
}
|
||||
else
|
||||
sfprintf(sfstdout,sh_translate(is_function));
|
||||
}
|
||||
sfputc(sfstdout,'\n');
|
||||
if(!aflag)
|
||||
continue;
|
||||
aflag++;
|
||||
|
@ -210,6 +218,7 @@ static int whence(Shell_t *shp,char **argv, register int flags)
|
|||
aflag++;
|
||||
}
|
||||
search:
|
||||
pp = 0;
|
||||
do
|
||||
{
|
||||
int maybe_undef_fn = 0; /* flag for possible undefined (i.e. autoloadable) function */
|
||||
|
@ -246,7 +255,10 @@ static int whence(Shell_t *shp,char **argv, register int flags)
|
|||
/* Undefined/autoloadable function on FPATH */
|
||||
sfputr(sfstdout,sh_fmtq(cp),-1);
|
||||
if(flags&V_FLAG)
|
||||
sfputr(sfstdout,sh_translate(is_ufunction),-1);
|
||||
{
|
||||
sfprintf(sfstdout,sh_translate(is_ufunction));
|
||||
sfprintf(sfstdout,sh_translate(e_autoloadfrom),sh_fmtq(stakptr(PATH_OFFSET)));
|
||||
}
|
||||
sfputc(sfstdout,'\n');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1988,7 +1988,7 @@ _JOB_
|
|||
;
|
||||
|
||||
const char sh_optwhence[] =
|
||||
"[-1c?\n@(#)$Id: whence (AT&T Research/ksh93) 2020-07-20 $\n]"
|
||||
"[-1c?\n@(#)$Id: whence (AT&T Research/ksh93) 2020-09-25 $\n]"
|
||||
USAGE_LICENSE
|
||||
"[+NAME?whence, type - locate a command and describe its type]"
|
||||
"[+DESCRIPTION?Without \b-v\b, \bwhence\b writes on standard output an "
|
||||
|
|
|
@ -141,6 +141,7 @@ const char is_alias[] = "%s is an alias for ";
|
|||
const char is_talias[] = "is a tracked alias for";
|
||||
const char is_function[] = " is a function";
|
||||
const char is_ufunction[] = " is an undefined function";
|
||||
const char e_autoloadfrom[] = " (autoload from %s)";
|
||||
#ifdef JOBS
|
||||
# ifdef SIGTSTP
|
||||
const char e_newtty[] = "Switching to new tty driver...";
|
||||
|
|
|
@ -129,6 +129,7 @@ extern const char is_reserved[];
|
|||
extern const char is_talias[];
|
||||
extern const char is_function[];
|
||||
extern const char is_ufunction[];
|
||||
extern const char e_autoloadfrom[];
|
||||
#ifdef SHELLMAGIC
|
||||
extern const char e_prohibited[];
|
||||
#endif /* SHELLMAGIC */
|
||||
|
|
|
@ -29,6 +29,7 @@ Command=${0##*/}
|
|||
integer Errors=0
|
||||
|
||||
[[ -d $tmp && -w $tmp && $tmp == "$PWD" ]] || { err\_exit "$LINENO" '$tmp not set; run this from shtests. Aborting.'; exit 1; }
|
||||
PATH_orig=$PATH
|
||||
|
||||
type /xxxxxx > out1 2> out2
|
||||
[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
|
||||
|
@ -417,6 +418,8 @@ ${.sh.version}
|
|||
END
|
||||
) || err_exit '${.sh.xxx} variables causes cat not be found'
|
||||
|
||||
PATH=$PATH_orig
|
||||
|
||||
# ======
|
||||
# Check that 'command -p' searches the default OS utility PATH.
|
||||
expect=/dev/null
|
||||
|
@ -448,6 +451,39 @@ actual=$(PATH=$tmp; redirect 2>&1; hash ls; command -p -v ls)
|
|||
[[ $actual == "$expect" ]] || err_exit "'command -p -v' fails to search default path if tracked alias exists" \
|
||||
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
|
||||
|
||||
# ======
|
||||
# Unlike pdksh, ksh93 didn't report the path to autoloadable functions, which was an annoying omission.
|
||||
if ((.sh.version >= 20200925))
|
||||
then fundir=$tmp/whencefun
|
||||
mkdir $fundir
|
||||
echo "whence_FPATH_test() { echo I\'m just on FPATH; }" >$fundir/whence_FPATH_test
|
||||
echo "whence_autoload_test() { echo I was explicitly autoloaded; }" >$fundir/whence_autoload_test
|
||||
echo "function chmod { echo Hi, I\'m your new chmod!; }" >$fundir/chmod
|
||||
echo "function ls { echo Hi, I\'m your new ls!; }" >$fundir/ls
|
||||
hash -r
|
||||
actual=$("$SHELL" -c 'FPATH=$1
|
||||
autoload chmod whence_autoload_test
|
||||
whence -a chmod whence_FPATH_test whence_autoload_test ls cp
|
||||
whence_FPATH_test
|
||||
whence_autoload_test
|
||||
cp --totally-invalid-option 2>/dev/null
|
||||
ls --totally-invalid-option 2>/dev/null
|
||||
chmod --totally-invalid-option' \
|
||||
whence_autoload_test "$fundir" 2>&1)
|
||||
expect="chmod is an undefined function (autoload from $fundir/chmod)"
|
||||
expect+=$'\n'"chmod is ${ whence -p chmod; }"
|
||||
expect+=$'\n'"whence_FPATH_test is an undefined function (autoload from $fundir/whence_FPATH_test)"
|
||||
expect+=$'\n'"whence_autoload_test is an undefined function (autoload from $fundir/whence_autoload_test)"
|
||||
expect+=$'\n'"ls is a tracked alias for ${ whence -p ls; }"
|
||||
expect+=$'\n'"ls is an undefined function (autoload from $fundir/ls)"
|
||||
expect+=$'\n'"cp is a tracked alias for ${ whence -p cp; }"
|
||||
expect+=$'\n'"I'm just on FPATH"
|
||||
expect+=$'\n'"I was explicitly autoloaded"
|
||||
expect+=$'\n'"Hi, I'm your new chmod!"
|
||||
[[ $actual == "$expect" ]] || err_exit "failure in reporting or running autoloadable functions" \
|
||||
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
|
||||
fi
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
||||
|
|
Loading…
Reference in a new issue