1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-05-31 20:36:03 +02:00

see 23479: add initial features support for modules

This commit is contained in:
Peter Stephenson 2007-05-28 22:57:39 +00:00
parent bd76320790
commit b0c5f09169
59 changed files with 2900 additions and 1662 deletions

View File

@ -1,5 +1,30 @@
2007-05-28 Peter Stephenson <p.w.stephenson@ntlworld.com>
* Not posted but see 23479:Completion/Unix/Command/_chmod,
Completion/Unix/Command/_chown, Completion/Unix/Command/_cvs,
Completion/Unix/Type/_list_files, Completion/Zsh/Command/_stat,
Completion/Zsh/Command/_zstyle,
Completion/Zsh/Type/_file_descriptors,Doc/Zsh/builtins.yo,
Doc/Zsh/compsys.yo, Doc/Zsh/mod_stat.yo,
Etc/zsh-development-guide, Src/builtin.c, Src/cond.c, Src/exec.c
Src/init.c, Src/mkbltnmlst.sh, Src/mkmakemod.sh, Src/modentry.c,
Src/module.c, Src/params.c, Src/zsh.h, Src/Builtins/rlimits.c,
Src/Builtins/sched.c, Src/Modules/cap.c, Src/Modules/clone.c,
Src/Modules/datetime.c, Src/Modules/example.c,
Src/Modules/files.c, Src/Modules/langinfo.c,
Src/Modules/langinfo.mdd, Src/Modules/mapfile.c,
Src/Modules/mathfunc.c, Src/Modules/parameter.c,
Src/Modules/pcre.c, Src/Modules/regex.c, Src/Modules/socket.c,
Src/Modules/stat.c, Src/Modules/system.c, Src/Modules/tcp.c,
Src/Modules/termcap.c, Src/Modules/terminfo.c, Src/Modules/zftp.c,
Src/Modules/zprof.c, Src/Modules/zpty.c, Src/Modules/zselect.c,
Src/Modules/zutil.c, Src/Zle/compctl.c, Src/Zle/complete.c,
Src/Zle/complist.c, Src/Zle/computil.c, Src/Zle/deltochar.c,
Src/Zle/zle_main.c, Src/Zle/zle_thingy.c, Src/Zle/zle_tricky.c,
Src/Zle/zleparameter.c, Test/B02typeset.ztst,
Test/V01zmodload.ztst, Test/V04features.ztst: add "zmodload -F"
and internal features support for modules.
* 23478: Src/Zle/compresult.c: don't run reverse-menu-complete
if no completion yet.

View File

@ -54,13 +54,9 @@ case "$state" in
;;
files)
if [[ -n $opt_args[--reference] ]]; then
if zstyle -t ":completion:${curcontext}:" disable-stat; then
_files && ret=0
else
zmodload -i zsh/stat 2>/dev/null
typeset -i8 ref=$(stat +mode $opt_args[--reference])
_wanted files expl file _files -g "*(-.^f${ref#??})" && ret=0
fi
zmodload -F zsh/stat zstat 2>/dev/null
typeset -i8 ref=$(zstat +mode $opt_args[--reference])
_wanted files expl file _files -g "*(-.^f${ref#??})" && ret=0
elif [[ $words[2] = [0-7]## ]]; then
_wanted files expl file _files -g "*(-.^f$words[2])" && ret=0
else

View File

@ -50,14 +50,10 @@ case $state in
files)
(( $+opt_args[-h] || $+opt_args[--no-dereference] )) || deref="-"
if (( $+opt_args[--reference] )); then
if zstyle -t ":completion:${curcontext}:" disable-stat; then
_files && ret=0
else
zmodload -i zsh/stat 2>/dev/null
usr=$(stat +uid $opt_args[--reference])
grp=$(stat +gid $opt_args[--reference])
_wanted files expl file _files -g "*($deref^u$usr,$deref^g$grp)" && ret=0
fi
zmodload -F zsh/stat zstat 2>/dev/null
usr=$(zstat +uid $opt_args[--reference])
grp=$(zstat +gid $opt_args[--reference])
_wanted files expl file _files -g "*($deref^u$usr,$deref^g$grp)" && ret=0
return ret
fi
if [[ $service = chgrp ]]; then

View File

@ -550,11 +550,10 @@ _cvs_watchers() {
(( $+functions[_cvs_loadstat] )) ||
_cvs_loadstat() {
zstyle -t ":completion:${curcontext}:" disable-stat && return 1
(( $+_cvs_loadstat_status )) && return $_cvs_loadstat_status
zmodload -i zsh/stat 2>/dev/null
(( _cvs_loadstat_status = ! $+builtins[stat] ))
zmodload -F zsh/stat zstat 2>/dev/null
(( _cvs_loadstat_status = ! $+builtins[zstat] ))
return $_cvs_loadstat_status
}
@ -566,7 +565,7 @@ _cvs_root() {
if [[ -f "${cvspassfile::=${CVS_PASSFILE:-$HOME/.cvspass}}" ]]; then
if _cvs_loadstat; then
id="$(LC_ALL=C builtin stat -g +mtime -F '%Y/%m/%d-%T' "$cvspassfile")"
id="$(LC_ALL=C builtin zstat -g +mtime -F '%Y/%m/%d-%T' "$cvspassfile")"
else
id="$(LC_ALL=C ls -l "$cvspassfile")"
fi
@ -865,7 +864,7 @@ _cvs_modified_entries() {
realdir=${(e)~linedir}
[[ -f "$realdir"CVS/Entries ]] && {
local -a mtime
LC_ALL=C builtin stat -A mtime -gn +mtime -F $'%a %b %e %T %Y\n' ${realdir}*(D) 2>/dev/null
LC_ALL=C builtin zstat -A mtime -gn +mtime -F $'%a %b %e %T %Y\n' ${realdir}*(D) 2>/dev/null
[[ -n ${pat::="${(@j:|:)${(@)${(@)${(@)${(@)${(@)${(@M)${(@f)"$(<"$realdir"CVS/Entries)"}:#/*}#/}/${slash}[^${slash}]#${slash}//}%/[^/]#/[^/]#}:#${(j:|:)~${(f)${(j:/:)${mtime##*/}}//(#m)[][*?()<|^~#\\]/\\$MATCH}#/}}%%/*}//(#m)[][*?()<|^~#\\]/\\$MATCH}"} ]]
} &&
_wanted files expl 'modified file' _path_files -g "$pat"

View File

@ -46,15 +46,7 @@ done
(( ok )) || return 1
zmodload -i zsh/stat 2>/dev/null || return 1
{
# Enable stat temporarily if disabled to avoid clashes.
integer disable_stat
if [[ ${builtins[stat]} != defined ]]; then
(( disable_stat = 1 ))
enable stat
fi
zmodload -F zsh/stat zstat 2>/dev/null || return 1
dir=${2:+$2/}
dir=${(Q)dir}
@ -66,7 +58,7 @@ for f in ${(PQ)1}; do
fi
# Borrowed from Functions/Example/zls
stat -s -H stat -F "%b %e %H:%M" - "$dir$f" >/dev/null 2>&1
zstat -s -H stat -F "%b %e %H:%M" - "$dir$f" >/dev/null 2>&1
listfiles+=("$stat[mode] ${(l:3:)stat[nlink]} ${(r:8:)stat[uid]} \
${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[mtime] $f")
@ -74,7 +66,4 @@ done
(( ${#listfiles} )) && listopts=(-d listfiles -l -o)
} always {
(( disable_stat )) && disable stat
}
return 0

View File

@ -1,4 +1,4 @@
#compdef stat
#compdef stat zstat
local expl ret=1

View File

@ -40,7 +40,6 @@ styles=(
completer c:completer
condition c:bool
cursor c:cursor
disable-stat c:bool
disabled c:bool
domains c:
expand c:

View File

@ -7,9 +7,9 @@ for i in {0..9}; [[ -e /dev/fd/$i ]] && fds+=( $i )
if zstyle -T ":completion:${curcontext}:" verbose && [[ -e /proc/$$/fd ]]; then
zstyle -s ":completion:${curcontext}:" list-separator sep || sep=--
if zmodload -e zsh/stat; then
if zmodload -F zsh/stat zstat; then
for i in "${fds[@]}"; do
stat +link -A link /proc/$$/fd/$i
zstat +link -A link /proc/$$/fd/$i
list+=( "$i $sep ${link[1]}" )
done
elif (( $+commands[readlink] )); then

View File

@ -1845,6 +1845,7 @@ findex(zmodload)
cindex(modules, loading)
cindex(loading modules)
xitem(tt(zmodload) [ tt(-dL) ] [ ... ])
xitem(tt(zmodload -F) [ tt(-lLe) tt(-P) tt(param) ] var(module) [tt(PLUS()-)]var(feature...))
xitem(tt(zmodload -e) [ tt(-A) ] [ ... ])
xitem(tt(zmodload) [ tt(-a) [ tt(-bcpf) [ tt(-I) ] ] ] [ tt(-iL) ] ...)
xitem(tt(zmodload) tt(-u) [ tt(-abcdpf) [ tt(-I) ] ] [ tt(-iL) ] ...)
@ -1867,21 +1868,24 @@ item(tt(zmodload) tt(-u) [ tt(-i) ] var(name) ...)(
In the simplest case, tt(zmodload) loads a binary module. The module must
be in a file with a name consisting of the specified var(name) followed by
a standard suffix, usually `tt(.so)' (`tt(.sl)' on HPUX).
If the module to be loaded is
already loaded and the tt(-i) option is given, the duplicate module is
ignored. Otherwise tt(zmodload) prints an error message and returns
a non-zero status. If tt(zmodload) detects an inconsistency, such as an
If the module to be loaded is already loaded the duplicate module is
ignored. If tt(zmodload) detects an inconsistency, such as an
invalid module name or circular dependency list, the current code block is
aborted. Hence `tt(zmodload -i) var(module) tt(2>/dev/null)' is sufficient
aborted. Hence `tt(zmodload) var(module) tt(2>/dev/null)' is sufficient
to test whether a module is available.
If it is available, the module is loaded if necessary, while if it
is not available, non-zero status is silently returned.
is not available, non-zero status is silently returned. The option
tt(-i) is accepted for compatibility but has no effect.
The var(name)d module is searched for in the same way a command is, using
tt($module_path) instead of tt($path). However, the path search is
performed even when the module name contains a `tt(/)', which it usually does.
There is no way to prevent the path search.
If the module supports features (see below), tt(zmodload) tries to
enable all features when loading a module. If the module was successfully
loaded but not all features could be enabled, tt(zmodload) returns status 2.
With tt(-u), tt(zmodload) unloads modules. The same var(name)
must be given that was given when the module was loaded, but it is not
necessary for the module to exist in the filesystem.
@ -1892,6 +1896,54 @@ Each module has a boot and a cleanup function. The module
will not be loaded if its boot function fails. Similarly a module
can only be unloaded if its cleanup function runs successfully.
)
item(tt(zmodload -F) [ tt(-lLe) tt(-P) tt(param) ] var(module) [tt(PLUS()-)]var(feature...))(
tt(zmodload -F) allows more selective control over the features provided
by modules. With no options apart from tt(-F), the module named
var(module) is loaded, if it was not already loaded, and the list of
var(feature)s is set to the required state. If no
var(feature)s are specified, the module is loaded, if it was not already
loaded, but the state of features is unchanged. Each feature
may be preceded by a tt(PLUS()) to turn the feature on, or tt(-) to turn it
off; the tt(PLUS()) is assumed if neither character is present.
Any feature not explicitly mentioned is left in its current state;
if the module was not previously loaded this means any such features will
remain disabled. The return status is zero if all features were
set, 1 if the module failed to load, and 2 if some features could
not be set (for example, a parameter couldn't be added because there
was a different parameter of the same name) but the module was loaded.
The standard features are builtins, conditions, parameters and math
functions; these are indicated by the prefix `tt(b:)', `tt(c:)', `tt(p:)'
and `tt(f:)', respectively, followed by the name that the corresponding
feature would have in the shell. For example, `tt(b:strftime)' indicates
a builtin named tt(strftime) and tt(p:EPOCHSECONDS) indicates a parameter
named tt(EPOCHSECONDS). The module may provide other (`abstract') features
of its own as indicated by its documentation; these have no prefix.
With tt(-l) or tt(-L), features provided by the module are listed. With
tt(-l) alone, a list of features together with their states is shown, one
feature per line. With tt(-L) alone, a tt(zmodload -F) command that would
cause enabled features of the module to be turned on is shown. With
tt(-lL), a tt(zmodload -F) command that would cause all the features to be
set to their current state is shown. If one of these combinations is given
the option tt(-P) var(param) then the parameter tt(param) is set to an
array of features, either features together with their state or (if
tt(-L) alone is given) enabled features.
A set of features may be provided together with tt(-l) or tt(-L); in
that case only the state of features provided is considered. Each
feature may be preceded by tt(PLUS()) or tt(-) but the character
has no effect. If no set of features is provided, all features
are considered.
With tt(-e), the command first tests that the module is loaded;
if it is not, status 1 is returned. If the module is loaded,
the list of features given as an argument is examined. Any feature
given with no prefix is simply tested to see if the module provides it;
any feature given with a prefix tt(PLUS()) or tt(-) is tested to
see if is provided and in the given state. If the tests on all features
in the list succeed, status 0 is returned, else status 1.
)
xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) ])
xitem(tt(zmodload) tt(-d) var(name) var(dep) ...)
item(tt(zmodload) tt(-ud) var(name) [ var(dep) ... ])(

View File

@ -1268,13 +1268,6 @@ If this is set to `true', the tt(_expand_alias) completer and bindable
command will try to expand disabled aliases, too. The default is
`tt(false)'.
)
kindex(disable-stat, completion style)
item(tt(disable-stat))(
This is used with an empty tag by the tt(_cvs) function
to decide whether the tt(zsh/stat) module should be used to
generate names of modified files in the appropriate places (this is its
only use). If the style is set, completion will use the tt(ls) command.
)
kindex(domains, completion style)
item(tt(domains))(
A list of names of network domains for completion.

View File

@ -1,17 +1,24 @@
COMMENT(!MOD!zsh/stat
A builtin command interface to the tt(stat) system call.
!MOD!)
The tt(zsh/stat) module makes available one builtin command:
The tt(zsh/stat) module makes available one builtin command under
two possible names:
startitem()
findex(stat)
cindex(files, listing)
cindex(files, examining)
item(tt(stat) [ tt(-gnNolLtTrs) ] [ tt(-f) var(fd) ] \
xitem(tt(zstat) [ tt(-gnNolLtTrs) ] [ tt(-f) var(fd) ] \
[ tt(-H) var(hash) ] [ tt(-A) var(array) ] \
[ tt(-F) var(fmt) ] [ tt(PLUS())var(element) ] [ var(file) ... ])(
[ tt(-F) var(fmt) ] [ tt(PLUS())var(element) ] [ var(file) ... ])
itme(tt(stat) var(...))(
The command acts as a front end to the tt(stat) system call (see
manref(stat)(2)).
manref(stat)(2)). The same command is provided with two names; as
the name tt(stat) is often used by an external command it is recommended
that only the tt(zstat) form of the command is used. This can be
arranged by loading the module with the command `tt(zmodload -F zsh/stat
zstat)'.
If the tt(stat) call fails, the appropriate system error message
printed and status 1 is returned.
The fields of tt(struct stat) give information about
@ -69,7 +76,7 @@ The number of disk blocks used by the file.
item(tt(link))(
If the file is a link and the tt(-L) option is in
effect, this contains the name of the file linked to, otherwise
it is empty. Note that if this element is selected (``tt(stat PLUS()link)'')
it is empty. Note that if this element is selected (``tt(zstat PLUS()link)'')
then the tt(-L) option is automatically used.
)
enditem()

View File

@ -213,25 +213,146 @@ following shell variables:
Be sure to put the values in quotes. For further enlightenment have a look
at the `mkmakemod.sh' script in the Src directory of the distribution.
Modules have to define four functions which will be called automatically
Modules have to define six functions which will be called automatically
by the zsh core. The first one, named `setup_', should set up any data
needed in the module, at least any data other modules may be interested
in. The second one, named `boot_', should register all builtins,
conditional codes, and function wrappers (i.e. anything that will be
visible to the user) and will be called after the `setup_'-function.
in.
The third one, named `cleanup_', is called when the user tries to unload
a module and should de-register the builtins etc. The last function,
`finish_' is called when the module is actually unloaded and should
finalize all the data initialized in the `setup_'-function.
The next pair are features_ and enables_ and deal with enabling module
features. Ensure you are familiar with the description of features under
`zmodload -F'. The function features_ takes an argument `char
***featuresp'; *featuresp is to be set to a NULL-terminated array
containing a list of all the features. It should then return zero.
It may return one to indicate features are not supported, but this is
not recommended. The function featuresarray conveniently interrogates
the module's feature strctures for all standard features; space
is left for abstract features at the end of the array and the names
must be added by the module. Note that heap memory should
be used for this (zhalloc, etc.) as memory for the features array is not
freed.
In short, the `cleanup_'-function should undo what the `boot_'-function
did, and the `finish_'-function should undo what the `setup_'-function
did.
A structure "struct features" should
be used to contain all standard features as well as the number of
abstract features (those only understood by the module itself).
It contains pointers to all builtins, conditions, parameters and
conditions controlled by the module.
enables_ takes an argument `int **enablesp'. If *enablesp is NULL, it
should be set to an array of the same length as *featuresp without the
NULL, containing a 1 for every feature that is enabled and a zero for other
feature. By default features are disabled. If *enablesp is not NULL, its
values should be used to decide whether features are to be turned off. It
should return status 0 for success, 1 on a failure to alter a feature.
The function handlefeatures() conveniently handles all standard features
present in the module's features structure; abstract features must
be handled by the module. As with features_, any handling of the
array by the module itself should take into account that the array
will not be freed and any allocation should therefore be from heap memory.
The functions features_ and enables_ can be called at any point
after setup_ has been called and before cleanup_ is called. In
particular they can be called before or after boot_.
The function named `boot_' should register function wrappers, hooks and
anything that will be visible to the user that is not handled by features_
and enables_ (so features should not be turned on here). It will be called
after the `setup_'-function, and also after the intial set of features
have been set by calls to features_ and enables_.
The function named `cleanup_', is called when the user tries to unload
a module and should de-register all features and hooks. A call
to setfeatures with the final argument NULL will remove all standard
features present in the module's features structure.
The last function, `finish_' is called when the module is actually unloaded
and should finalize all the data initialized in the `setup_'-function.
In short, the `cleanup_'-function should undo what the `boot_'-function did
(together with handling any residual effects of enables_), and the
`finish_'-function should undo what the `setup_'-function did.
All of these functions should return zero if they succeeded and
non-zero otherwise.
Features
========
Builtins, conditions, parameters (variables) and math functions
are described as "features". They should be made available to
the shell by declaring a `struct feature' for each module.
Below are descriptions of the individual features; first here
is generic information.
`struct feature' contains a pointer to the array that declares each
feature, followed by the number of entries in the array. The pointer
can be NULL and the the size zero for any feature that is not present in
the module. For example, to register only builtins in zsh and thereby
make them visible to the user, the structure should contain
"bintab" where the array is declared as an array of struct builtin,
as discussed below:
static struct feature module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0, /* declare any conditions here */
NULL, 0, /* declare any parameters here */
NULL, 0, /* declare any math functions here */
0, /* number of abstract features */
}
Abstract features are handled by the module; the number present
in `struct features' is there to ensure the main shell allocated
space in the features and enables array in the standard
featuresarray() and handlefeatures() calls. However, the inserting
of names in the features array and the getting and setting of
feature enables is left entirely to the module. Note that abstract
features should not contain a colon (to avoid clashes with the
prefixes used in standard features). It is recommended that
only alphanumerics, - and _ be used in the names of abstract
features, and - not be the first character (to avoid confusion
with disabling features) but this is not required by the main shell.
The features_ and enables_ functions for such a module will look
like:
/**/
int
features_example(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
/* fill in any abstract features in (*features) here */
return 0;
}
/**/
int
enables_example(Module m, int **enables)
{
int ret;
ret = handlefeatures(m->nam, &module_features, enables);
/* handle any abstract features here */
...
return ret;
}
The functions shown take the name of the module, the set of features,
To de-register builtins, pass the features structure to
setfeatureenables with a NULL final value:
/**/
int
cleanup_example(Module m)
{
setfeatureenables(m->nam, &module_features, NULL);
...
}
Builtins
--------
Builtins are described in a table, for example:
static struct builtin bintab[] = {
@ -280,37 +401,8 @@ integer value from the table (the sixth argument to `BUILTIN(...)').
The integer return value by the function is the value returned by the
builtin in shell level.
To register builtins in zsh and thereby making them visible to the
user the function `addbuiltins()' is used:
/**/
int
boot_example(Module m)
{
int ret;
ret = addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
...
}
The arguments are the name of the module (taken from the argument in
the example), the table of definitions and the number of entries in
this table.
The return value is 1 if everything went fine, 2 if at least one
builtin couldn't be defined, and 0 if none of the builtin could be
defined.
To de-register builtins use the function `deletebuiltins()':
/**/
int
cleanup_example(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
...
}
The arguments and the return value are the same as for `addbuiltins()'
Conditions
----------
The definition of condition codes in modules is equally simple. First
we need a table with the descriptions:
@ -374,30 +466,8 @@ tokenized. There are three helper functions available:
function is non-zero if the the num'th string from the array taken
as a glob pattern matches the given string.
Registering and de-registering condition codes with the shell is
almost exactly the same as for builtins, using the functions
`addconddefs()' and `deleteconddefs()' instead:
/**/
int
boot_example(Module m)
{
int ret;
ret = addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
...
}
/**/
int
cleanup_example(Module m)
{
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
...
}
Arguments and return values are the same as for the functions for
builtins.
Parameters
----------
For defining parameters, a module can call `createparam()' directly or
use a table to describe them, e.g.:
@ -443,33 +513,12 @@ initialized to either `NULL' or to a a piece of memory created with
finish-function of the module because that will be taken care of by
the `deleteparamdefs()' function described below.
To register the parameters in the zsh core, the function
`addparamdefs()' is called as in:
It is also possible to declare special parameters using
the macro SPECIALPMDEF(). More care is required in this case.
See, for example, many of the definitios in Src/Modules/parameter.c.
/**/
int
boot_example(Module m)
{
int ret;
ret = addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab))
...
}
The arguments and the return value are as for the functions used to
add builtins and condition codes and like these, it should be called
in the boot-function of the module. To remove the parameters defined,
the function `deleteparamdefs()' should be called, again with the same
arguments and the same return value as for the functions to remove
builtins and condition codes:
/**/
int
cleanup_example(Module m)
{
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
...
}
Math functions
--------------
Modules can also define math functions. Again, they are described
using a table:
@ -531,33 +580,13 @@ union looking like:
The `type' field should be set to `MN_INTEGER' or `MN_FLOAT' and
depending on its value either `u.l' or `u.d' contains the value.
To register and de-register math functions, the functions
`addmathfuncs()' and `deletemathfuncs()' are used:
/**/
int
boot_example(Module m)
{
int ret;
ret = addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
...
}
/**/
int
cleanup_example(Module m)
{
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
...
}
The arguments and return values are as for the functions used to
register and de-register parameters, conditions, etc.
Hooks
-----
Modules can also define function hooks. Other modules can then add
functions to these hooks to make the first module call these functions
instead of the default.
instead of the default. These are not handled by the features
mechanism as they are not directly visible to the user.
Again, an array is used to define hooks:
@ -629,8 +658,13 @@ that are changed or called very often. These functions,
structure defining the hook instead of the name and otherwise behave
like their counterparts.
Finally, modules can define wrapper functions. These functions are
called whenever a shell function is to be executed.
Wrappers
--------
Finally, modules can define wrapper functions. These functions are
called whenever a shell function is to be executed. Again, they
are not handled by the features mechanism as they are not visible
to the user.
The definition is simple:

View File

@ -889,6 +889,14 @@ static struct builtin bintab[] = {
BUILTIN("unlimit", 0, bin_unlimit, 0, -1, 0, "hs", NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -896,18 +904,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return setfeatureenables(m->nam, &module_features, NULL);
return 0;
}

View File

@ -333,6 +333,14 @@ static struct builtin bintab[] = {
BUILTIN("sched", 0, bin_sched, 0, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -340,12 +348,25 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
if(!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)))
return 1;
addprepromptfn(&checksched);
return 0;
}
@ -364,8 +385,7 @@ cleanup_(Module m)
zfree(sch, sizeof(*sch));
}
delprepromptfn(&checksched);
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -122,6 +122,14 @@ static struct builtin bintab[] = {
BUILTIN("setcap", 0, bin_setcap, 2, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -131,17 +139,31 @@ setup_(UNUSED(Module m))
/**/
int
boot_(Module m)
features_(Module m, char ***features)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -109,6 +109,14 @@ static struct builtin bintab[] = {
BUILTIN("clone", 0, bin_clone, 1, 1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -118,17 +126,31 @@ setup_(UNUSED(Module m))
/**/
int
boot_(Module m)
features_(Module m, char ***features)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -154,8 +154,16 @@ static const struct gsu_integer epochseconds_gsu =
{ getcurrentsecs, NULL, stdunsetfn };
static struct paramdef patab[] = {
PARAMDEF("EPOCHSECONDS", PM_INTEGER|PM_SPECIAL|PM_READONLY,
NULL, &epochseconds_gsu),
SPECIALPMDEF("EPOCHSECONDS", PM_INTEGER|PM_READONLY,
&epochseconds_gsu, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
patab, sizeof(patab)/sizeof(*patab),
NULL, 0,
0
};
/**/
@ -165,28 +173,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab))
);
return 0;
}
/**/
int
cleanup_(Module m)
{
Param pm;
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
pm = (Param) paramtab->getnode(paramtab, "EPOCHSECONDS");
if (pm && (pm->node.flags & PM_SPECIAL)) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -184,6 +184,14 @@ static struct funcwrap wrapper[] = {
WRAPDEF(ex_wrapper),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
cotab, sizeof(cotab)/sizeof(*cotab),
patab, sizeof(patab)/sizeof(*patab),
mftab, sizeof(mftab)/sizeof(*mftab),
0
};
/**/
int
setup_(UNUSED(Module m))
@ -193,6 +201,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -203,23 +226,15 @@ boot_(Module m)
arrparam[0] = ztrdup("example");
arrparam[1] = ztrdup("array");
arrparam[2] = NULL;
return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) |
addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab)) |
!addwrapper(m, wrapper));
return addwrapper(m, wrapper);
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
deletewrapper(m, wrapper);
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -706,6 +706,14 @@ static struct builtin bintab[] = {
BUILTIN("sync", 0, bin_sync, 0, 0, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -713,19 +721,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -30,14 +30,10 @@
#include "langinfo.mdh"
#include "langinfo.pro"
static char langinfo_nam[] = "langinfo";
#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#endif
static Param langinfo_pm;
/**/
#ifdef HAVE_NL_LANGINFO
@ -395,46 +391,6 @@ liitem(char *name)
return NULL;
}
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
static Param
createlihash()
{
Param pm;
HashTable ht;
unsetparam(langinfo_nam);
if (!(pm = createparam(langinfo_nam, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &stdhash_gsu;
pm->u.hash = ht = newhashtable(7, langinfo_nam, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = getlanginfo;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scanlanginfo;
return (langinfo_pm = pm);
}
/**/
static HashNode
getlanginfo(UNUSED(HashTable ht), char *name)
@ -490,9 +446,25 @@ scanlanginfo(UNUSED(HashTable ht), ScanFunc func, int flags)
}
static struct paramdef partab[] = {
SPECIALPMDEF("langinfo", 0, NULL, getlanginfo, scanlanginfo)
};
/**/
#endif /* HAVE_NL_LANGINFO */
static struct features module_features = {
NULL, 0,
NULL, 0,
#ifdef HAVE_NL_LANGINFO
partab, sizeof(partab)/sizeof(*partab),
#else
NULL, 0,
#endif
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -500,16 +472,25 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
#ifdef HAVE_NL_LANGINFO
if (!createlihash())
return 1;
#else
unsetparam(langinfo_nam);
#endif
return 0;
}
@ -517,16 +498,7 @@ boot_(UNUSED(Module m))
int
cleanup_(UNUSED(Module m))
{
#ifdef HAVE_NL_LANGINFO
Param pm;
if ((pm = (Param) paramtab->getnode(paramtab, langinfo_nam)) &&
pm == langinfo_pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
#endif
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -1,6 +1,6 @@
name=zsh/langinfo
link=either
link=`if test x$ac_cv_func_nl_langinfo; then echo either; else echo no; fi`
load=no
autoparams="langinfo"

View File

@ -58,60 +58,9 @@
#endif /* HAVE_MMAP && HAVE_MUNMAP && HAVE_MSYNC */
#endif /* HAVE_SYS_MMAN_H && HAVE_FTRUNCATE */
/*
* Name of the special parameter. If zmodload took arguments,
* we could make this selectable.
*/
static char mapfile_nam[] = "mapfile";
static Param mapfile_pm;
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
static const struct gsu_hash mapfiles_gsu =
{ hashgetfn, setpmmapfiles, stdunsetfn };
/* Create the special hash parameter. */
/**/
static Param
createmapfilehash()
{
Param pm;
HashTable ht;
unsetparam(mapfile_nam);
mapfile_pm = NULL;
if (!(pm = createparam(mapfile_nam, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &mapfiles_gsu;
pm->u.hash = ht = newhashtable(7, mapfile_nam, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = getpmmapfile;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scanpmmapfile;
return (mapfile_pm = pm);
}
/* Functions for the options special parameter. */
/**/
@ -192,9 +141,6 @@ setpmmapfiles(Param pm, HashTable ht)
int i;
HashNode hn;
/* just to see if I've understood what's happening */
DPUTS(pm != mapfile_pm, "BUG: setpmmapfiles called for wrong param");
if (!ht)
return;
@ -261,6 +207,10 @@ get_contents(char *fname)
static const struct gsu_scalar mapfile_gsu =
{ strgetfn, setpmmapfile, unsetpmmapfile };
static struct paramdef partab[] = {
SPECIALPMDEF("mapfile", 0, &mapfiles_gsu, getpmmapfile, scanpmmapfile)
};
/**/
static HashNode
getpmmapfile(UNUSED(HashTable ht), char *name)
@ -272,7 +222,7 @@ getpmmapfile(UNUSED(HashTable ht), char *name)
pm->node.nam = dupstring(name);
pm->node.flags = PM_SCALAR;
pm->gsu.s = &mapfile_gsu;
pm->node.flags |= (mapfile_pm->node.flags & PM_READONLY);
pm->node.flags |= (partab[0].pm->node.flags & PM_READONLY);
/* Set u.str to contents of file given by name */
if ((contents = get_contents(pm->node.nam)))
@ -298,7 +248,7 @@ scanpmmapfile(UNUSED(HashTable ht), ScanFunc func, int flags)
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags = PM_SCALAR;
pm.gsu.s = &mapfile_gsu;
pm.node.flags |= (mapfile_pm->node.flags & PM_READONLY);
pm.node.flags |= (partab[0].pm->node.flags & PM_READONLY);
/* Here we scan the current directory, calling func() for each file */
while ((pm.node.nam = zreaddir(dir, 1))) {
@ -315,6 +265,14 @@ scanpmmapfile(UNUSED(HashTable ht), ScanFunc func, int flags)
closedir(dir);
}
static struct features module_features = {
NULL, 0,
NULL, 0,
partab, sizeof(partab)/sizeof(*partab),
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -322,15 +280,25 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
/* Create the special associative array. */
if (!createmapfilehash())
return 1;
return 0;
}
@ -338,16 +306,7 @@ boot_(UNUSED(Module m))
int
cleanup_(UNUSED(Module m))
{
Param pm;
/* Remove the special parameter if it is still the same. */
if ((pm = (Param) paramtab->getnode(paramtab, mapfile_nam)) &&
pm == mapfile_pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -561,6 +561,14 @@ math_string(UNUSED(char *name), char *arg, int id)
}
static struct features module_features = {
NULL, 0,
NULL, 0,
NULL, 0,
mftab, sizeof(mftab)/sizeof(*mftab),
0
};
/**/
int
setup_(UNUSED(Module m))
@ -568,19 +576,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addmathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletemathfuncs(m->nam, mftab, sizeof(mftab)/sizeof(*mftab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -34,46 +34,6 @@
static int incleanup;
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
static Param
createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan)
{
Param pm;
HashTable ht;
if (!(pm = createparam(name, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &stdhash_gsu;
pm->u.hash = ht = newhashtable(0, name, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = get;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scan;
return pm;
}
/* Functions for the parameters special parameter. */
/* Return a string describing the type of a parameter. */
@ -1838,13 +1798,6 @@ struct pardef {
Param pm;
};
/*
* This is a duplicate of nullsethash_gsu. On some systems
* (such as Cygwin) we can't put a pointer to an imported variable
* in a compile-time initialiser, so we use this instead.
*/
static const struct gsu_hash pmnullsethash_gsu =
{ hashgetfn, nullsethashfn, nullunsetfn };
static const struct gsu_hash pmcommands_gsu =
{ hashgetfn, setpmcommands, stdunsetfn };
static const struct gsu_hash pmfunctions_gsu =
@ -1881,147 +1834,115 @@ static const struct gsu_array dirs_gsu =
static const struct gsu_array historywords_gsu =
{ histwgetfn, arrsetfn, stdunsetfn };
static struct pardef partab[] = {
{ "parameters", PM_READONLY,
getpmparameter, scanpmparameters, &pmnullsethash_gsu,
NULL, NULL },
{ "commands", 0,
getpmcommand, scanpmcommands, &pmcommands_gsu,
NULL, NULL },
{ "functions", 0,
getpmfunction, scanpmfunctions, &pmfunctions_gsu,
NULL, NULL },
{ "dis_functions", 0,
getpmdisfunction, scanpmdisfunctions, &pmdisfunctions_gsu,
NULL, NULL },
{ "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&funcstack_gsu, NULL },
{ "functrace", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&functrace_gsu, NULL },
{ "builtins", PM_READONLY,
getpmbuiltin, scanpmbuiltins, NULL,
NULL, NULL },
{ "dis_builtins", PM_READONLY,
getpmdisbuiltin, scanpmdisbuiltins, NULL,
NULL, NULL },
{ "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&reswords_gsu, NULL },
{ "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&disreswords_gsu, NULL },
{ "options", 0,
getpmoption, scanpmoptions, &pmoptions_gsu,
NULL, NULL },
{ "modules", PM_READONLY,
getpmmodule, scanpmmodules, NULL,
NULL, NULL },
{ "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE,
NULL, NULL, NULL,
&dirs_gsu, NULL },
{ "history", PM_READONLY,
getpmhistory, scanpmhistory, NULL,
NULL, NULL, },
{ "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&historywords_gsu, NULL },
{ "jobtexts", PM_READONLY,
getpmjobtext, scanpmjobtexts, NULL,
NULL, NULL },
{ "jobstates", PM_READONLY,
getpmjobstate, scanpmjobstates, NULL,
NULL, NULL },
{ "jobdirs", PM_READONLY,
getpmjobdir, scanpmjobdirs, NULL,
NULL, NULL },
{ "nameddirs", 0,
getpmnameddir, scanpmnameddirs, &pmnameddirs_gsu,
NULL, NULL },
{ "userdirs", PM_READONLY,
getpmuserdir, scanpmuserdirs, NULL,
NULL, NULL },
{ "aliases", 0,
getpmralias, scanpmraliases, &pmraliases_gsu,
NULL, NULL },
{ "galiases", 0,
getpmgalias, scanpmgaliases, &pmgaliases_gsu,
NULL, NULL },
{ "saliases", 0,
getpmsalias, scanpmsaliases, &pmsaliases_gsu,
NULL, NULL },
{ "dis_aliases", 0,
getpmdisralias, scanpmdisraliases, &pmdisraliases_gsu,
NULL, NULL },
{ "dis_galiases", 0,
getpmdisgalias, scanpmdisgaliases, &pmdisgaliases_gsu,
NULL, NULL },
{ "dis_saliases", 0,
getpmdissalias, scanpmdissaliases, &pmdissaliases_gsu,
NULL, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL, NULL }
static struct paramdef partab[] = {
SPECIALPMDEF("parameters", PM_READONLY,
NULL, getpmparameter, scanpmparameters),
SPECIALPMDEF("commands", 0, &pmcommands_gsu, getpmcommand, scanpmcommands),
SPECIALPMDEF("functions", 0, &pmfunctions_gsu, getpmfunction,
scanpmfunctions),
SPECIALPMDEF("dis_functions", 0,
&pmdisfunctions_gsu, getpmdisfunction, scanpmdisfunctions),
SPECIALPMDEF("funcstack", PM_ARRAY|PM_READONLY,
&funcstack_gsu, NULL, NULL),
SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY,
&functrace_gsu, NULL, NULL),
SPECIALPMDEF("builtins", PM_READONLY, NULL, getpmbuiltin, scanpmbuiltins),
SPECIALPMDEF("dis_builtins", PM_READONLY,
NULL, getpmdisbuiltin, scanpmdisbuiltins),
SPECIALPMDEF("reswords", PM_ARRAY|PM_READONLY,
&reswords_gsu, NULL, NULL),
SPECIALPMDEF("dis_reswords", PM_ARRAY|PM_READONLY,
&disreswords_gsu, NULL, NULL),
SPECIALPMDEF("options", 0,
&pmoptions_gsu, getpmoption, scanpmoptions),
SPECIALPMDEF("modules", PM_READONLY,
NULL, getpmmodule, scanpmmodules),
SPECIALPMDEF("dirstack", PM_ARRAY,
&dirs_gsu, NULL, NULL),
SPECIALPMDEF("history", PM_READONLY,
NULL, getpmhistory, scanpmhistory),
SPECIALPMDEF("historywords", PM_ARRAY|PM_READONLY,
&historywords_gsu, NULL, NULL),
SPECIALPMDEF("jobtexts", PM_READONLY,
NULL, getpmjobtext, scanpmjobtexts),
SPECIALPMDEF("jobstates", PM_READONLY,
NULL, getpmjobstate, scanpmjobstates),
SPECIALPMDEF("jobdirs", PM_READONLY,
NULL, getpmjobdir, scanpmjobdirs),
SPECIALPMDEF("nameddirs", 0,
&pmnameddirs_gsu, getpmnameddir, scanpmnameddirs),
SPECIALPMDEF("userdirs", PM_READONLY,
NULL, getpmuserdir, scanpmuserdirs),
SPECIALPMDEF("aliases", 0,
&pmraliases_gsu, getpmralias, scanpmraliases),
SPECIALPMDEF("galiases", 0,
&pmgaliases_gsu, getpmgalias, scanpmgaliases),
SPECIALPMDEF("saliases", 0,
&pmsaliases_gsu, getpmsalias, scanpmsaliases),
SPECIALPMDEF("dis_aliases", 0,
&pmdisraliases_gsu, getpmdisralias, scanpmdisraliases),
SPECIALPMDEF("dis_galiases", 0,
&pmdisgaliases_gsu, getpmdisgalias, scanpmdisgaliases),
SPECIALPMDEF("dis_saliases", 0,
&pmdissaliases_gsu, getpmdissalias, scanpmdissaliases)
};
static struct features module_features = {
NULL, 0,
NULL, 0,
partab, sizeof(partab)/sizeof(*partab),
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
{
incleanup = 0;
return 0;
}
/**/
int
boot_(UNUSED(Module m))
features_(Module m, char ***features)
{
/* Create the special associative arrays.
* As an example for autoloaded parameters, this is probably a bad
* example, because the zsh core doesn't support creation of
* special hashes, yet. */
struct pardef *def;
for (def = partab; def->name; def++) {
unsetparam(def->name);
if (def->getnfn) {
if (!(def->pm = createspecialhash(def->name, def->getnfn,
def->scantfn)))
return 1;
def->pm->node.flags |= def->flags;
if (def->hash_gsu)
def->pm->gsu.h = def->hash_gsu;
} else {
if (!(def->pm = createparam(def->name, def->flags | PM_HIDE|
PM_HIDEVAL | PM_REMOVABLE)))
return 1;
def->pm->gsu.a = def->array_gsu;
}
}
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
cleanup_(UNUSED(Module m))
enables_(Module m, int **enables)
{
Param pm;
struct pardef *def;
int ret;
/*
* If we remove features, we shouldn't have an effect
* on the main shell, so set the flag to indicate.
*/
incleanup = 1;
ret = handlefeatures(m->nam, &module_features, enables);
incleanup = 0;
return ret;
}
for (def = partab; def->name; def++) {
if ((pm = (Param) paramtab->getnode(paramtab, def->name)) &&
pm == def->pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
}
/**/
int
boot_(Module m)
{
return 0;
}
/**/
int
cleanup_(Module m)
{
int ret;
incleanup = 1;
ret = setfeatureenables(m->nam, &module_features, NULL);
incleanup = 0;
return ret;
}
/**/
int
finish_(UNUSED(Module m))

View File

@ -295,6 +295,19 @@ static struct builtin bintab[] = {
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC)
cotab, sizeof(cotab)/sizeof(*cotab),
#else /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */
NULL, 0,
#endif /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -302,27 +315,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC)
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) ||
!addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
#else /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
#endif /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC)
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
#endif /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -131,6 +131,16 @@ static struct conddef cotab[] = {
CONDDEF("regex-match", CONDF_INFIX, zcond_regex_match, 0, 0, ZREGEX_EXTENDED)
};
static struct features module_features = {
NULL, 0,
cotab, sizeof(cotab)/sizeof(*cotab),
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -138,19 +148,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -255,6 +255,14 @@ static struct builtin bintab[] = {
BUILTIN("zsocket", 0, bin_zsocket, 0, 3, 0, "ad:ltv", NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/* The load/unload routines required by the zsh library interface */
/**/
@ -266,18 +274,31 @@ setup_(UNUSED(Module m))
/**/
int
boot_(Module m)
features_(Module m, char ***features)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -621,6 +621,15 @@ bin_stat(char *name, char **args, Options ops, UNUSED(int func))
static struct builtin bintab[] = {
BUILTIN("stat", 0, bin_stat, 0, -1, 0, NULL, NULL),
BUILTIN("zstat", 0, bin_stat, 0, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
@ -630,19 +639,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -364,47 +364,70 @@ static const struct gsu_array errnos_gsu =
/* Functions for the sysparams special parameter. */
/**/
static char *
sysparamgetfn(Param pm)
static void
fillpmsysparams(Param pm, char *name)
{
char buf[DIGBUFSIZE];
int num;
if (!strcmp(pm->node.nam, "pid")) {
pm->node.nam = dupstring(name);
pm->node.flags = PM_SCALAR | PM_READONLY;
pm->gsu.s = &nullsetscalar_gsu;
if (!strcmp(name, "pid")) {
num = (int)getpid();
} else if (!strcmp(pm->node.nam, "ppid")) {
} else if (!strcmp(name, "ppid")) {
num = (int)getppid();
}
else {
#ifdef DEBUG
dputs("Bad sysparam parameter");
#endif
return "";
} else {
pm->u.str = dupstring("");
pm->node.flags |= PM_UNSET;
return;
}
sprintf(buf, "%d", num);
return dupstring(buf);
pm->u.str = dupstring(buf);
}
static const struct gsu_scalar sysparam_gsu =
{ sysparamgetfn, strsetfn, stdunsetfn };
static void
fixsysparams(HashNode hn, int flags)
/**/
static HashNode
getpmsysparams(UNUSED(HashTable ht), char *name)
{
Param pm = (Param)hn;
Param pm;
if (flags) {
/* prepare to free */
pm->node.flags &= ~PM_READONLY;
} else {
/* assign */
pm->gsu.s = &sysparam_gsu;
pm->node.flags |= PM_READONLY;
}
pm = (Param) hcalloc(sizeof(struct param));
fillpmsysparams(pm, name);
return &pm->node;
}
/**/
static void
scanpmsysparams(UNUSED(HashTable ht), ScanFunc func, int flags)
{
struct param spm;
fillpmsysparams(&spm, "pid");
func(&spm.node, flags);
fillpmsysparams(&spm, "ppid");
func(&spm.node, flags);
}
static struct paramdef partab[] = {
SPECIALPMDEF("errnos", PM_ARRAY|PM_READONLY,
&errnos_gsu, NULL, NULL),
SPECIALPMDEF("sysparams", PM_READONLY,
NULL, getpmsysparams, scanpmsysparams)
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
partab, sizeof(partab)/sizeof(*partab),
NULL, 0,
0
};
/* The load/unload routines required by the zsh library interface */
/**/
@ -415,61 +438,24 @@ setup_(UNUSED(Module m))
}
/**/
static void
tidyparam(Param pm)
int
features_(Module m, char ***features)
{
if (!pm)
return;
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
Param pm_nos, pm_params;
HashTable ht;
const char *sysparams_args[] = {
"pid", "ppid", NULL
}, **srcptr;
char **arglist, **dstptr;
/* this takes care of an autoload on errnos */
unsetparam("errnos");
if (!(pm_nos = createparam("errnos", PM_ARRAY|PM_SPECIAL|PM_READONLY|
PM_HIDE|PM_HIDEVAL|PM_REMOVABLE)))
return 1;
pm_nos->gsu.a = &errnos_gsu;
if (!(pm_params = createparam("sysparams", PM_HASHED|PM_SPECIAL|
PM_HIDE|PM_HIDEVAL|PM_REMOVABLE))) {
tidyparam(pm_nos);
return 1;
}
pm_params->level = pm_params->old ? locallevel : 0;
pm_params->gsu.h = &stdhash_gsu;
pm_params->u.hash = ht = newparamtable(0, "sysparams");
arglist = (char **)zshcalloc((2*arrlen((char **)sysparams_args) + 1) *
sizeof(char *));
for (srcptr = sysparams_args, dstptr = arglist; *srcptr; ) {
*dstptr++ = ztrdup(*srcptr++);
*dstptr++ = ztrdup("");
}
*dstptr = NULL;
/* make sure we don't overwrite the hash table: use the "augment" arg */
arrhashsetfn(pm_params, arglist, 1);
scanhashtable(ht, 0, 0, 0, fixsysparams, 0);
pm_params->node.flags |= PM_READONLY;
if (!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) {
tidyparam(pm_nos);
tidyparam(pm_params);
return 1;
}
return 0;
}
@ -478,17 +464,7 @@ boot_(Module m)
int
cleanup_(Module m)
{
Param pm;
if ((pm = (Param)paramtab->getnode(paramtab, "errnos")))
tidyparam(pm);
if ((pm = (Param)paramtab->getnode(paramtab, "sysparams")))
{
scanhashtable(pm->u.hash, 0, 0, 0, fixsysparams, 1);
tidyparam(pm);
}
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -675,6 +675,14 @@ static struct builtin bintab[] = {
BUILTIN("ztcp", 0, bin_ztcp, 0, 3, 0, "acd:flLtv", NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/* The load/unload routines required by the zsh library interface */
/**/
@ -684,12 +692,27 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
ztcp_sessions = znewlinklist();
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
@ -698,9 +721,8 @@ int
cleanup_(Module m)
{
tcp_cleanup();
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
freelinklist(ztcp_sessions, (FreeFunc) ztcp_free_session);
return 0;
return setfeatureeanbles(m->nam, &module_features, NULL);
}
/**/

View File

@ -48,8 +48,7 @@
#include "termcap.mdh"
#include "termcap.pro"
static char termcap_nam[] = "termcap";
/**/
#ifdef HAVE_TGETENT
# ifdef USES_TERM_H
# ifdef HAVE_TERMIO_H
@ -65,8 +64,6 @@ static char termcap_nam[] = "termcap";
# endif
# endif
static Param termcap_pm;
#ifndef HAVE_BOOLCODES
static char *boolcodes[] = {
"bw", "am", "ut", "cc", "xs", "YA", "YF", "YB", "xt", "xn", "eo",
@ -161,61 +158,10 @@ bin_echotc(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
return 0;
}
#else /* ! HAVE_TGETENT */
#define bin_echotc bin_notavail
#endif /* HAVE_TGETENT */
static struct builtin bintab[] = {
BUILTIN("echotc", 0, bin_echotc, 1, -1, 0, NULL, NULL),
};
/**/
#ifdef HAVE_TGETENT
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
static Param
createtchash()
{
Param pm;
HashTable ht;
unsetparam(termcap_nam);
if (!(pm = createparam(termcap_nam, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &stdhash_gsu;
pm->u.hash = ht = newhashtable(7, termcap_nam, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = gettermcap;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scantermcap;
return (termcap_pm = pm);
}
/**/
static HashNode
gettermcap(UNUSED(HashTable ht), char *name)
@ -364,9 +310,29 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags)
}
}
struct paramdef partab[] = {
SPECIALPMDEF("termcap", PM_READONLY, NULL, gettermcap, scantermcap)
};
/**/
#endif /* HAVE_TGETENT */
static struct features module_features = {
#ifdef HAVE_TGETENT
bintab, sizeof(bintab)/sizeof(*bintab),
#else
NULL, 0,
#endif
NULL, 0,
#ifdef HAVE_TGETENT
partab, sizeof(partab)/sizeof(*partab),
#else
NULL, 0,
#endif
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -374,6 +340,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -382,30 +363,15 @@ boot_(Module m)
# ifdef HAVE_SETUPTERM
setupterm((char *)0, 1, (int *)0);
# endif
if (!createtchash())
return 1;
#else
unsetparam(termcap_nam);
#endif
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
#ifdef HAVE_TGETENT
Param pm;
if ((pm = (Param) paramtab->getnode(paramtab, termcap_nam)) &&
pm == termcap_pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
#endif
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -37,7 +37,6 @@
#endif
#include "terminfo.pro"
static char terminfo_nam[] = "terminfo";
/**/
#ifdef USE_TERMINFO_MODULE
@ -55,8 +54,6 @@ static char terminfo_nam[] = "terminfo";
# include <term.h>
# endif
static Param terminfo_pm;
/* echoti: output a terminfo capability */
/**/
@ -126,63 +123,10 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
return 0;
}
/**/
#else /* !USE_TERMINFO_MODULE */
#define bin_echoti bin_notavail
/**/
#endif /* !USE_TERMINFO_MODULE */
static struct builtin bintab[] = {
BUILTIN("echoti", 0, bin_echoti, 1, -1, 0, NULL, NULL),
};
/**/
#ifdef USE_TERMINFO_MODULE
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
static Param
createtihash()
{
Param pm;
HashTable ht;
unsetparam(terminfo_nam);
if (!(pm = createparam(terminfo_nam, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &stdhash_gsu;
pm->u.hash = ht = newhashtable(7, terminfo_nam, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = getterminfo;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scanterminfo;
return (terminfo_pm = pm);
}
/**/
static HashNode
getterminfo(UNUSED(HashTable ht), char *name)
@ -339,9 +283,30 @@ scanterminfo(UNUSED(HashTable ht), ScanFunc func, int flags)
}
}
static struct paramdef partab[] = {
SPECIALPMDEF("terminfo", PM_READONLY, NULL,
getterminfo, scanterminfo)
};
/**/
#endif /* USE_TERMINFO_MODULE */
static struct features module_features = {
#ifdef USE_TERMINFO_MODULE
bintab, sizeof(bintab)/sizeof(*bintab),
#else
NULL, 0,
#endif
NULL, 0,
#ifdef USE_TERMINFO_MODULE
partab, sizeof(partab)/sizeof(*partab),
#else
NULL, 0,
#endif
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -349,6 +314,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -360,30 +340,16 @@ boot_(Module m)
if (setupterm((char *)0, 1, &errret) == ERR)
return 1;
# endif
if (!createtihash())
return 1;
#else
unsetparam(terminfo_nam);
#endif
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
#ifdef USE_TERMINFO_MODULE
Param pm;
if ((pm = (Param) paramtab->getnode(paramtab, terminfo_nam)) &&
pm == terminfo_pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
#endif
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -3151,7 +3151,6 @@ zftp_cleanup(void)
zfunsetparam("ZFTP_SESSION");
freelinklist(zfsessions, (FreeFunc) freesession);
zfree(zfstatusp, sizeof(int)*zfsesscnt);
deletebuiltins("zftp", bintab, sizeof(bintab)/sizeof(*bintab));
}
static int
@ -3161,47 +3160,68 @@ zftpexithook(UNUSED(Hookdef d), UNUSED(void *dummy))
return 0;
}
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/* The load/unload routines required by the zsh library interface */
/**/
int
setup_(UNUSED(Module m))
{
/* setup_ returns 0 for success. require_module returns 1 for success. */
return !require_module("", "zsh/net/tcp", 0, 0);
return (require_module("", "zsh/net/tcp", NULL) == 1);
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(UNUSED(Module m))
{
int ret;
if ((ret = addbuiltins("zftp", bintab,
sizeof(bintab)/sizeof(*bintab))) == 1) {
/* if successful, set some default parameters */
off_t tmout_def = 60;
zfsetparam("ZFTP_VERBOSE", ztrdup("450"), ZFPM_IFUNSET);
zfsetparam("ZFTP_TMOUT", &tmout_def, ZFPM_IFUNSET|ZFPM_INTEGER);
zfsetparam("ZFTP_PREFS", ztrdup("PS"), ZFPM_IFUNSET);
/* default preferences if user deletes variable */
zfprefs = ZFPF_SNDP|ZFPF_PASV;
/*
* Set some default parameters.
* These aren't special, so aren't associated with features.
*/
off_t tmout_def = 60;
zfsetparam("ZFTP_VERBOSE", ztrdup("450"), ZFPM_IFUNSET);
zfsetparam("ZFTP_TMOUT", &tmout_def, ZFPM_IFUNSET|ZFPM_INTEGER);
zfsetparam("ZFTP_PREFS", ztrdup("PS"), ZFPM_IFUNSET);
/* default preferences if user deletes variable */
zfprefs = ZFPF_SNDP|ZFPF_PASV;
zfsessions = znewlinklist();
newsession("default");
zfsessions = znewlinklist();
newsession("default");
addhookfunc("exit", zftpexithook);
}
addhookfunc("exit", zftpexithook);
return !ret;
return 0;
}
/**/
int
cleanup_(UNUSED(Module m))
cleanup_(Module m)
{
deletehookfunc("exit", zftpexithook);
zftp_cleanup();
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -295,6 +295,14 @@ static struct funcwrap wrapper[] = {
WRAPDEF(zprof_wrapper),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(Module m)
@ -303,6 +311,21 @@ setup_(Module m)
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -312,8 +335,7 @@ boot_(Module m)
arcs = NULL;
narcs = 0;
stack = NULL;
return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
!addwrapper(m, wrapper));
return addwrapper(m, wrapper);
}
/**/
@ -322,9 +344,8 @@ cleanup_(Module m)
{
freepfuncs(calls);
freeparcs(arcs);
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
deletewrapper(m, wrapper);
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -725,10 +725,20 @@ ptyhook(UNUSED(Hookdef d), UNUSED(void *dummy))
return 0;
}
static struct builtin bintab[] = {
BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLnt", NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -736,6 +746,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -743,7 +768,7 @@ boot_(Module m)
ptycmds = NULL;
addhookfunc("exit", ptyhook);
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
@ -752,8 +777,7 @@ cleanup_(Module m)
{
deletehookfunc("exit", ptyhook);
deleteallptycmds();
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -267,10 +267,20 @@ bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
#endif
}
static struct builtin bintab[] = {
BUILTIN("zselect", 0, bin_zselect, 0, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/* The load/unload routines required by the zsh library interface */
/**/
@ -280,20 +290,34 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(UNUSED(Module m))
cleanup_(Module m)
{
deletebuiltins("zselect", bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -1740,6 +1740,13 @@ static struct builtin bintab[] = {
BUILTIN("zparseopts", 0, bin_zparseopts, 1, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
@ -1750,19 +1757,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -3942,6 +3942,14 @@ static struct builtin bintab[] = {
BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -3962,13 +3970,28 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
addhookfunc("compctl_make", (Hookfn) ccmakehookfn);
addhookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn);
return (addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) != 1);
return 0;
}
/**/
@ -3977,8 +4000,7 @@ cleanup_(Module m)
{
deletehookfunc("compctl_make", (Hookfn) ccmakehookfn);
deletehookfunc("compctl_cleanup", (Hookfn) cccleanuphookfn);
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -1467,6 +1467,14 @@ struct hookdef comphooks[] = {
HOOKDEF("comp_list_matches", ilistmatches, 0),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
cotab, sizeof(cotab)/sizeof(*cotab),
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -1490,6 +1498,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -1502,11 +1525,7 @@ boot_(Module m)
addhookfunc("list_matches", (Hookfn) list_matches);
addhookfunc("invalidate_list", (Hookfn) invalidate_list);
addhookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks));
if (!(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
!addwrapper(m, wrapper)))
return 1;
return 0;
return addwrapper(m, wrapper);
}
/**/
@ -1521,10 +1540,8 @@ cleanup_(Module m)
deletehookfunc("list_matches", (Hookfn) list_matches);
deletehookfunc("invalidate_list", (Hookfn) invalidate_list);
deletehookdefs(m->nam, comphooks, sizeof(comphooks)/sizeof(*comphooks));
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
deletewrapper(m, wrapper);
return 0;
return seteatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -3219,6 +3219,14 @@ menuselect(char **args)
return 0;
}
static struct features module_features = {
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -3226,6 +3234,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -3269,7 +3292,7 @@ boot_(Module m)
/**/
int
cleanup_(UNUSED(Module m))
cleanup_(Module m)
{
free(mtab);
free(mgtab);
@ -3279,7 +3302,7 @@ cleanup_(UNUSED(Module m))
deletehookfunc("menu_start", (Hookfn) domenuselect);
unlinkkeymap("menuselect", 1);
unlinkkeymap("listscroll", 1);
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -4567,6 +4567,14 @@ static struct builtin bintab[] = {
BUILTIN("compgroups", 0, bin_compgroups, 1, -1, 0, NULL, NULL),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
@ -4582,19 +4590,33 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
/**/
int
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -74,6 +74,16 @@ deltochar(UNUSED(char **args))
return !ok;
}
static struct features module_features = {
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -81,6 +91,21 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
@ -100,11 +125,11 @@ boot_(Module m)
/**/
int
cleanup_(UNUSED(Module m))
cleanup_(Module m)
{
deletezlefunction(w_deletetochar);
deletezlefunction(w_zaptochar);
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -1777,6 +1777,14 @@ mod_export struct hookdef zlehooks[] = {
HOOKDEF("invalidate_list", NULL, 0),
};
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
NULL, 0,
0
};
/**/
int
setup_(UNUSED(Module m))
@ -1815,13 +1823,27 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(Module m, char ***features)
{
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
enables_(Module m, int **enables)
{
return handlefeatures(m->nam, &module_features, enables);
}
/**/
int
boot_(Module m)
{
addhookfunc("before_trap", (Hookfn) zlebeforetrap);
addhookfunc("after_trap", (Hookfn) zleaftertrap);
addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
addhookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
return 0;
}
@ -1836,9 +1858,8 @@ cleanup_(Module m)
}
deletehookfunc("before_trap", (Hookfn) zlebeforetrap);
deletehookfunc("after_trap", (Hookfn) zleaftertrap);
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
deletehookdefs(m->nam, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks));
return 0;
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/

View File

@ -590,7 +590,7 @@ bin_zle_complete(char *name, char **args, UNUSED(Options ops), UNUSED(char func)
Thingy t;
Widget w, cw;
if (!require_module(name, "zsh/complete", 0, 0)) {
if (require_module(name, "zsh/complete", NULL) == 1) {
zwarnnam(name, "can't load complete module");
return 1;
}

View File

@ -612,7 +612,7 @@ docomplete(int lst)
* no completion widgets are defined. */
if (!module_loaded("zsh/compctl") && !hascompwidgets)
load_module("zsh/compctl");
(void)load_module("zsh/compctl", NULL);
if (runhookdef(BEFORECOMPLETEHOOK, (void *) &lst)) {
active = 0;

View File

@ -30,45 +30,6 @@
#include "zleparameter.mdh"
#include "zleparameter.pro"
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
static Param
createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan)
{
Param pm;
HashTable ht;
if (!(pm = createparam(name, PM_SPECIAL|PM_HIDE|PM_REMOVABLE|PM_HASHED)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = &stdhash_gsu;
pm->u.hash = ht = newhashtable(0, name, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = get;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scan;
return pm;
}
/* Functions for the zlewidgets special parameter. */
/**/
@ -157,18 +118,6 @@ keymapsgetfn(UNUSED(Param pm))
return ret;
}
/* Table for defined parameters. */
struct pardef {
char *name;
int flags;
GetNodeFunc getnfn;
ScanTabFunc scantfn;
GsuHash hash_gsu;
GsuArray array_gsu;
Param pm;
};
/*
* This is a duplicate of stdhash_gsu. On some systems
* (such as Cygwin) we can't put a pointer to an imported variable
@ -179,14 +128,18 @@ static const struct gsu_hash zlestdhash_gsu =
static const struct gsu_array keymaps_gsu =
{ keymapsgetfn, arrsetfn, stdunsetfn };
static struct pardef partab[] = {
{ "widgets", PM_READONLY,
getpmwidgets, scanpmwidgets, &zlestdhash_gsu,
NULL, NULL },
{ "keymaps", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
&keymaps_gsu, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL, NULL }
static struct paramdef partab[] = {
SPECIALPMDEF("widgets", PM_READONLY,
&zlestdhash_gsu, getpmwidgets, scanpmwidgets),
SPECIALPMDEF("keymaps", PM_ARRAY|PM_READONLY, &keymaps_gsu, NULL, NULL),
};
static struct features module_features = {
NULL, 0,
NULL, 0,
partab, sizeof(partab)/sizeof(*partab),
NULL, 0,
0
};
/**/
@ -198,46 +151,33 @@ setup_(UNUSED(Module m))
/**/
int
boot_(UNUSED(Module m))
features_(Module m, char ***features)
{
struct pardef *def;
for (def = partab; def->name; def++) {
unsetparam(def->name);
if (def->getnfn) {
if (!(def->pm = createspecialhash(def->name, def->getnfn,
def->scantfn)))
return 1;
def->pm->node.flags |= def->flags;
if (def->hash_gsu)
def->pm->gsu.h = def->hash_gsu;
} else {
if (!(def->pm = createparam(def->name, def->flags | PM_HIDE)))
return 1;
def->pm->gsu.a = def->array_gsu;
}
}
*features = featuresarray(m->nam, &module_features);
return 0;
}
/**/
int
cleanup_(UNUSED(Module m))
enables_(Module m, int **enables)
{
Param pm;
struct pardef *def;
return handlefeatures(m->nam, &module_features, enables);
}
for (def = partab; def->name; def++) {
if ((pm = (Param) paramtab->getnode(paramtab, def->name)) &&
pm == def->pm) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
}
/**/
int
boot_(UNUSED(Module m))
{
return 0;
}
/**/
int
cleanup_(Module m)
{
return setfeatureenables(m->nam, &module_features, NULL);
}
/**/
int
finish_(UNUSED(Module m))

View File

@ -131,7 +131,7 @@ static struct builtin builtins[] =
BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsw", NULL),
BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ARILabcfdipue", NULL),
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "AFRILP:abcfdilpue", NULL),
BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUMRcmzka", NULL),
};
@ -2033,6 +2033,10 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
* because we've checked for unpleasant surprises above.
*/
pm->node.flags = (PM_TYPE(pm->node.flags) | on | PM_SPECIAL) & ~off;
/*
* Readonlyness of special parameters must be preserved.
*/
pm->node.flags |= tpm->node.flags & PM_READONLY;
if (newspecial == NS_SECONDS) {
/* We save off the raw internal value of the SECONDS var */
tpm->u.dval = getrawseconds();
@ -2085,7 +2089,21 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
"%s: array elements must be scalar", pname);
return NULL;
}
} else if (isident(pname) && !idigit(*pname)) {
}
/*
* As we can hide existing parameters, we allow a name if
* it's not a normal identifier but is one of the special
* set found in the parameter table. The second test is
* because we can set individual positional parameters;
* however "0" is not a positional parameter and is OK.
*
* It would be neater to extend isident() and be clearer
* about where we allow various parameter types. It's
* not entirely clear to me isident() should reject
* specially named parameters given that it accepts digits.
*/
else if ((isident(pname) || paramtab->getnode(paramtab, pname))
&& (!idigit(*pname) || !strcmp(pname, "0"))) {
/*
* Create a new node for a parameter with the flags in `on' minus the
* readonly flag
@ -2101,10 +2119,10 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
return NULL;
}
} else {
if (isident(pname))
zerrnam(cname, "not valid in this context: %s", pname);
else
if (idigit(*pname))
zerrnam(cname, "not an identifier: %s", pname);
else
zerrnam(cname, "not valid in this context: %s", pname);
return NULL;
}
@ -2138,7 +2156,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
"BUG: parameter recreated with wrong flags");
unsetparam_pm(ipm, 0, 1);
}
} else if (newspecial != NS_NONE && !(pm->old->node.flags & PM_NORESTORE)) {
} else if (newspecial != NS_NONE &&
!(pm->old->node.flags & (PM_NORESTORE|PM_READONLY))) {
/*
* We need to use the special setting function to re-initialise
* the special parameter to empty.

View File

@ -95,7 +95,10 @@ evalcond(Estate state, char *fromtest)
case COND_REGEX:
{
char *modname = isset(REMATCHPCRE) ? "zsh/pcre" : "zsh/regex";
if (!load_module_silence(modname, 1)) {
/*
* TODO: we just need to load the appropriate condition.
*/
if (load_module_silence(modname, NULL, 1) == 1) {
zwarnnam(fromtest, "%s not available for regex",
modname);
return 2;

View File

@ -2012,7 +2012,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
/* autoload the builtin if necessary */
if (!((Builtin) hn)->handlerfunc) {
load_module(((Builtin) hn)->optstr);
(void)load_module(((Builtin) hn)->optstr, NULL);
hn = builtintab->getnode(builtintab, cmdarg);
}
assign = (hn && (hn->flags & BINF_MAGICEQUALS));
@ -2229,7 +2229,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
/* autoload the builtin if necessary */
if (!((Builtin) hn)->handlerfunc) {
load_module(((Builtin) hn)->optstr);
(void)load_module(((Builtin) hn)->optstr, NULL);
hn = builtintab->getnode(builtintab, cmdarg);
}
break;

View File

@ -979,7 +979,7 @@ run_init_scripts(void)
* Always attempt to load the newuser module to perform
* checks for new zsh users. Don't care if we can't load it.
*/
if (load_module_silence("zsh/newuser", 1)) {
if (!load_module_silence("zsh/newuser", NULL, 1)) {
/* Unload it immediately. */
unload_named_module("zsh/newuser", "zsh", 1);
}
@ -1152,7 +1152,7 @@ init_bltinmods(void)
#include "bltinmods.list"
load_module("zsh/main");
(void)load_module("zsh/main", NULL);
}
/**/
@ -1213,8 +1213,8 @@ char *
autoload_zleread(char **lp, char **rp, int ha, int con)
{
zlereadptr = fallback_zleread;
if (load_module("zsh/zle"))
load_module("zsh/compctl");
if (load_module("zsh/zle", NULL) != 1)
(void)load_module("zsh/compctl", NULL);
return zlereadptr(lp, rp, ha, con);
}
@ -1240,7 +1240,7 @@ static void
autoload_zlesetkeymap(int mode)
{
zlesetkeymapptr = noop_function_int;
load_module("zsh/zle");
(void)load_module("zsh/zle", NULL);
(*zlesetkeymapptr)(mode);
}

View File

@ -87,11 +87,16 @@ for bin_mod in $bin_mods; do
echo " {"
echo " extern int setup_${q_bin_mod} _((Module));"
echo " extern int boot_${q_bin_mod} _((Module));"
echo " extern int features_${q_bin_mod} _((Module,char***));"
echo " extern int enables_${q_bin_mod} _((Module,int**));"
echo " extern int cleanup_${q_bin_mod} _((Module));"
echo " extern int finish_${q_bin_mod} _((Module));"
echo
echo " register_module(\"$bin_mod\","
echo " setup_${q_bin_mod}, boot_${q_bin_mod},"
echo " setup_${q_bin_mod},"
echo " features_${q_bin_mod},"
echo " enables_${q_bin_mod},"
echo " boot_${q_bin_mod},"
echo " cleanup_${q_bin_mod}, finish_${q_bin_mod});"
echo " }"
done_mods="$done_mods$bin_mod "

View File

@ -364,6 +364,8 @@ if $first_stage; then
echo " fi; \\"
echo " echo '# define boot_ boot_${q_name}'; \\"
echo " echo '# define cleanup_ cleanup_${q_name}'; \\"
echo " echo '# define features_ features_${q_name}'; \\"
echo " echo '# define enables_ enables_${q_name}'; \\"
echo " echo '# define setup_ setup_${q_name}'; \\"
echo " echo '# define finish_ finish_${q_name}'; \\"
echo " if test @SHORTBOOTNAMES@ = yes; then \\"

View File

@ -8,7 +8,7 @@ int modentry _((int boot, Module m));
/**/
int
modentry(int boot, Module m)
modentry(int boot, Module m, void *ptr)
{
switch (boot) {
case 0:
@ -27,6 +27,14 @@ modentry(int boot, Module m)
return finish_(m);
break;
case 4:
return features_(m, (char ***)ptr);
break;
case 5:
return enables_(m, (int **)ptr);
break;
default:
zerr("bad call to modentry");
return 1;

View File

@ -35,6 +35,20 @@
/**/
LinkList linkedmodules;
/* $module_path ($MODULE_PATH) */
/**/
char **module_path;
/* List of modules */
/**/
mod_export LinkList modules;
/************************************************************************
* zsh/main standard module functions
************************************************************************/
/* The `zsh/main' module contains all the base code that can't actually be *
* built as a separate module. It is initialised by main(), so there's *
@ -47,6 +61,24 @@ setup_(UNUSED(Module m))
return 0;
}
/**/
int
features_(UNUSED(Module m), UNUSED(char ***features))
{
/*
* There are lots and lots of features, but they're not
* handled here.
*/
return 1;
}
/**/
int
enables_(UNUSED(Module m), UNUSED(int **enables))
{
return 1;
}
/**/
int
boot_(UNUSED(Module m))
@ -68,12 +100,21 @@ finish_(UNUSED(Module m))
return 0;
}
/************************************************************************
* Module utility functions
************************************************************************/
/* This registers a builtin module. */
/**/
void
register_module(char *n, Module_func setup, Module_func boot,
Module_func cleanup, Module_func finish)
register_module(char *n, Module_void_func setup,
Module_features_func features,
Module_enables_func enables,
Module_void_func boot,
Module_void_func cleanup,
Module_void_func finish)
{
Linkedmod m;
@ -81,6 +122,8 @@ register_module(char *n, Module_func setup, Module_func boot,
m->name = ztrdup(n);
m->setup = setup;
m->features = features;
m->enables = enables;
m->boot = boot;
m->cleanup = cleanup;
m->finish = finish;
@ -124,6 +167,12 @@ module_linked(char const *name)
return NULL;
}
/************************************************************************
* Support for the various feature types.
* First, builtins.
************************************************************************/
/* addbuiltin() can be used to add a new builtin. It returns zero on *
* success, 1 on failure. The only possible type of failure is that *
* a builtin with the specified name already exists. An autoloaded *
@ -142,13 +191,81 @@ addbuiltin(Builtin b)
return 0;
}
/* Add multiple builtins. binl points to a table of `size' builtin *
* structures. Those for which (.flags & BINF_ADDED) is false are to be *
* added; that flag is set if they succeed. If any fail, an error *
* message is printed, using nam as the leading name. Returns 1 if all *
* additions succeed, 2 if some succeed and some fail, and 0 if all (and *
* at least 1) fail. The usual usage in a boot_*() function would be *
* return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); */
/* Define an autoloadable builtin. It returns 0 on success, or 1 on *
* failure. The only possible cause of failure is that a builtin *
* with the specified name already exists. */
/**/
int
add_autobin(char *nam, char *module)
{
Builtin bn = zshcalloc(sizeof(*bn));
bn->node.nam = ztrdup(nam);
bn->optstr = ztrdup(module);
return addbuiltin(bn);
}
/* Remove the builtin added previously by addbuiltin(). Returns *
* zero on succes and -1 if there is no builtin with that name. */
/**/
int
deletebuiltin(char *nam)
{
Builtin bn;
bn = (Builtin) builtintab->removenode(builtintab, nam);
if (!bn)
return -1;
builtintab->freenode(&bn->node);
return 0;
}
/**/
mod_export int
setbuiltins(char const *nam, Builtin binl, int size, int *e)
{
int hads = 0, hadf = 0, n;
for(n = 0; n < size; n++) {
Builtin b = &binl[n];
if (e && *e++) {
if (b->node.flags & BINF_ADDED)
continue;
if (addbuiltin(b)) {
zwarnnam(nam,
"name clash when adding builtin `%s'", b->node.nam);
hadf = 1;
} else {
b->node.flags |= BINF_ADDED;
hads = 2;
}
} else {
if (!(b->node.flags & BINF_ADDED))
continue;
if (deletebuiltin(b->node.nam)) {
zwarnnam(nam, "builtin `%s' already deleted", b->node.nam);
hadf = 1;
} else {
hads = 2;
b->node.flags &= ~BINF_ADDED;
}
}
}
return hadf ? hads : 1;
}
/*
* Add multiple builtins. binl points to a table of `size' builtin
* structures. Those for which (.flags & BINF_ADDED) is false are to be
* added; that flag is set if they succeed.
*
* If any fail, an error message is printed, using nam as the leading name.
* Returns 1 if all additions succeed, 2 if some succeed and some fail, and 0
* if all (and at least 1) fail.
*
* This should not be used from a module; instead, use handlefeatures().
*/
/**/
mod_export int
@ -171,6 +288,11 @@ addbuiltins(char const *nam, Builtin binl, int size)
return hadf ? hads : 1;
}
/************************************************************************
* Function wrappers.
************************************************************************/
/* The list of function wrappers defined. */
/**/
@ -208,75 +330,6 @@ addwrapper(Module m, FuncWrap w)
return 0;
}
/* $module_path ($MODULE_PATH) */
/**/
char **module_path;
/* List of modules */
/**/
mod_export LinkList modules;
/* Define an autoloadable builtin. It returns 0 on success, or 1 on *
* failure. The only possible cause of failure is that a builtin *
* with the specified name already exists. */
/**/
int
add_autobin(char *nam, char *module)
{
Builtin bn = zshcalloc(sizeof(*bn));
bn->node.nam = ztrdup(nam);
bn->optstr = ztrdup(module);
return addbuiltin(bn);
}
/* Remove the builtin added previously by addbuiltin(). Returns *
* zero on succes and -1 if there is no builtin with that name. */
/**/
int
deletebuiltin(char *nam)
{
Builtin bn;
bn = (Builtin) builtintab->removenode(builtintab, nam);
if (!bn)
return -1;
builtintab->freenode(&bn->node);
return 0;
}
/* Delete multiple builtins. binl points to a table of `size' builtin *
* structures. Those for which (.flags & BINF_ADDED) is true are to be *
* deleted; that flag is cleared. If any fail, an error message is *
* printed, using nam as the leading name. Returns 1 if all deletions *
* succeed, 2 if some succeed and some fail, and 0 if all (and at least *
* 1) fail. In normal use, from a cleanup_*() function, this return *
* value would be ignored -- the only cause of failure would be that a *
* wayward module had deleted our builtin without telling us. */
/**/
mod_export int
deletebuiltins(char const *nam, Builtin binl, int size)
{
int hads = 0, hadf = 0, n;
for(n = 0; n < size; n++) {
Builtin b = &binl[n];
if(!(b->node.flags & BINF_ADDED))
continue;
if(deletebuiltin(b->node.nam)) {
zwarnnam(nam, "builtin `%s' already deleted", b->node.nam);
hadf = 1;
} else
hads = 2;
b->node.flags &= ~BINF_ADDED;
}
return hadf ? hads : 1;
}
/* This removes the given wrapper definition from the list. Returned is *
* one in case of error and zero otherwise. */
@ -305,6 +358,684 @@ deletewrapper(Module m, FuncWrap w)
return 1;
}
/************************************************************************
* Conditions.
************************************************************************/
/* The list of module-defined conditions. */
/**/
mod_export Conddef condtab;
/* This gets a condition definition with the given name. The first *
* argument says if we have to look for an infix condition. The last *
* argument is non-zero if we should autoload modules if needed. */
/**/
Conddef
getconddef(int inf, char *name, int autol)
{
Conddef p;
int f = 1;
do {
for (p = condtab; p; p = p->next) {
if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
!strcmp(name, p->name))
break;
}
if (autol && p && p->module) {
/* This is a definition for an autoloaded condition, load the *
* module if we haven't tried that already. */
if (f) {
(void)load_module_silence(p->module, NULL, 0);
f = 0;
p = NULL;
} else {
deleteconddef(p);
return NULL;
}
} else
break;
} while (!p);
return p;
}
/*
* This adds the given condition definition. The return value is zero on *
* success and 1 on failure. If there is a matching definition for an *
* autoloaded condition, it is removed.
*
* This is used for adding both an autoload definition or
* a real condition. In the latter case the caller is responsible
* for setting the CONDF_ADDED flag.
*/
/**/
static int
addconddef(Conddef c)
{
Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0);
if (p) {
if (!p->module || (p->flags & CONDF_ADDED))
return 1;
/* There is an autoload definition. */
deleteconddef(p);
}
c->next = condtab;
condtab = c;
return 0;
}
/* This removes the given condition definition from the list(s). If this *
* is a definition for a autoloaded condition, the memory is freed. */
/**/
int
deleteconddef(Conddef c)
{
Conddef p, q;
for (p = condtab, q = NULL; p && p != c; q = p, p = p->next);
if (p) {
if (q)
q->next = p->next;
else
condtab = p->next;
if (p->module) {
/* autoloaded, free it */
zsfree(p->name);
zsfree(p->module);
zfree(p, sizeof(*p));
}
return 0;
}
return -1;
}
/**/
mod_export int
setconddefs(char const *nam, Conddef c, int size, int *e)
{
int hads = 0, hadf = 0;
while (size--) {
if (e && *e++) {
if (c->flags & CONDF_ADDED) {
c++;
continue;
}
if (addconddef(c)) {
zwarnnam(nam, "name clash when adding condition `%s'",
c->name);
hadf = 1;
} else {
c->flags |= CONDF_ADDED;
hads = 2;
}
} else {
if (!(c->flags & CONDF_ADDED)) {
c++;
continue;
}
if (deleteconddef(c)) {
zwarnnam(nam, "condition `%s' already deleted", c->name);
hadf = 1;
} else {
c->flags &= ~CONDF_ADDED;
hads = 2;
}
}
c++;
}
return hadf ? hads : 1;
}
/* This adds a definition for autoloading a module for a condition. */
/**/
int
add_autocond(char *nam, int inf, char *module)
{
Conddef c = (Conddef) zalloc(sizeof(*c));
c->name = ztrdup(nam);
c->flags = (inf ? CONDF_INFIX : 0);
c->module = ztrdup(module);
if (addconddef(c)) {
zsfree(c->name);
zsfree(c->module);
zfree(c, sizeof(*c));
return 1;
}
return 0;
}
/************************************************************************
* Hook functions.
************************************************************************/
/* This list of hook functions defined. */
/**/
Hookdef hooktab;
/* Find a hook definition given the name. */
/**/
Hookdef
gethookdef(char *n)
{
Hookdef p;
for (p = hooktab; p; p = p->next)
if (!strcmp(n, p->name))
return p;
return NULL;
}
/* This adds the given hook definition. The return value is zero on *
* success and 1 on failure. */
/**/
int
addhookdef(Hookdef h)
{
if (gethookdef(h->name))
return 1;
h->next = hooktab;
hooktab = h;
h->funcs = znewlinklist();
return 0;
}
/* This adds multiple hook definitions. This is like addbuiltins(). */
/**/
mod_export int
addhookdefs(char const *nam, Hookdef h, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (addhookdef(h)) {
zwarnnam(nam, "name clash when adding hook `%s'", h->name);
hadf = 1;
} else
hads = 2;
h++;
}
return hadf ? hads : 1;
}
/* Delete hook definitions. */
/**/
int
deletehookdef(Hookdef h)
{
Hookdef p, q;
for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next);
if (!p)
return 1;
if (q)
q->next = p->next;
else
hooktab = p->next;
freelinklist(p->funcs, NULL);
return 0;
}
/**/
mod_export int
deletehookdefs(UNUSED(char const *nam), Hookdef h, int size)
{
while (size--) {
deletehookdef(h);
h++;
}
return 1;
}
/* Add a function to a hook. */
/**/
int
addhookdeffunc(Hookdef h, Hookfn f)
{
zaddlinknode(h->funcs, (void *) f);
return 0;
}
/**/
mod_export int
addhookfunc(char *n, Hookfn f)
{
Hookdef h = gethookdef(n);
if (h)
return addhookdeffunc(h, f);
return 1;
}
/* Delete a function from a hook. */
/**/
int
deletehookdeffunc(Hookdef h, Hookfn f)
{
LinkNode p;
for (p = firstnode(h->funcs); p; incnode(p))
if (f == (Hookfn) getdata(p)) {
remnode(h->funcs, p);
return 0;
}
return 1;
}
/**/
mod_export int
deletehookfunc(char *n, Hookfn f)
{
Hookdef h = gethookdef(n);
if (h)
return deletehookdeffunc(h, f);
return 1;
}
/* Run the function(s) for a hook. */
/**/
mod_export int
runhookdef(Hookdef h, void *d)
{
if (empty(h->funcs)) {
if (h->def)
return h->def(h, d);
return 0;
} else if (h->flags & HOOKF_ALL) {
LinkNode p;
int r;
for (p = firstnode(h->funcs); p; incnode(p))
if ((r = ((Hookfn) getdata(p))(h, d)))
return r;
if (h->def)
return h->def(h, d);
return 0;
} else
return ((Hookfn) getdata(lastnode(h->funcs)))(h, d);
}
/**/
int
runhook(char *n, void *d)
{
Hookdef h = gethookdef(n);
if (h)
return runhookdef(h, d);
return 0;
}
/************************************************************************
* Shell parameters.
************************************************************************/
static int
checkaddparam(char *nam)
{
Param pm;
if (!(pm = (Param) gethashnode2(paramtab, nam)))
return 0;
if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) {
zwarn("Can't add module parameter `%s': %s",
nam, pm->level ?
"local parameter exists" :
"parameter already exists");
return 1;
}
unsetparam_pm(pm, 0, 1);
return 0;
}
/* This adds the given parameter definition. The return value is zero on *
* success and 1 on failure. */
/**/
int
addparamdef(Paramdef d)
{
Param pm;
if (checkaddparam(d->name))
return 1;
if (d->getnfn) {
if (!(pm = createspecialhash(d->name, d->getnfn,
d->scantfn, d->flags)))
return 1;
}
else if (!(pm = createparam(d->name, d->flags)) &&
!(pm = (Param) paramtab->getnode(paramtab, d->name)))
return 1;
d->pm = pm;
pm->level = 0;
if (d->var)
pm->u.data = d->var;
if (d->var || d->gsu) {
/*
* If no get/set/unset class, use the appropriate
* variable type, else use the one supplied.
*/
switch (PM_TYPE(pm->node.flags)) {
case PM_SCALAR:
pm->gsu.s = d->gsu ? (GsuScalar)d->gsu : &varscalar_gsu;
break;
case PM_INTEGER:
pm->gsu.i = d->gsu ? (GsuInteger)d->gsu : &varinteger_gsu;
break;
case PM_ARRAY:
pm->gsu.a = d->gsu ? (GsuArray)d->gsu : &vararray_gsu;
break;
case PM_HASHED:
/* hashes may behave like standard hashes */
if (d->gsu)
pm->gsu.h = (GsuHash)d->gsu;
break;
default:
unsetparam_pm(pm, 0, 1);
return 1;
}
}
return 0;
}
/* Delete parameters defined. No error checking yet. */
/**/
int
deleteparamdef(Paramdef d)
{
Param pm = (Param) paramtab->getnode(paramtab, d->name);
if (!pm)
return 1;
if (pm != d->pm) {
/*
* See if the parameter has been hidden. If so,
* bring it to the front to unset it.
*/
Param prevpm, searchpm;
for (prevpm = pm, searchpm = pm->old;
searchpm;
prevpm = searchpm, searchpm = searchpm->old)
if (searchpm == d->pm)
break;
if (!searchpm)
return 1;
paramtab->removenode(paramtab, pm->node.nam);
prevpm->old = searchpm->old;
searchpm->old = pm;
paramtab->addnode(paramtab, searchpm->node.nam, searchpm);
pm = searchpm;
}
pm->node.flags = (pm->node.flags & ~PM_READONLY) | PM_REMOVABLE;
unsetparam_pm(pm, 0, 1);
d->pm = NULL;
return 0;
}
/**/
mod_export int
setparamdefs(char const *nam, Paramdef d, int size, int *e)
{
int hads = 0, hadf = 0;
while (size--) {
if (e && *e++) {
if (d->pm) {
d++;
continue;
}
if (addparamdef(d)) {
zwarnnam(nam, "error when adding parameter `%s'", d->name);
hadf = 1;
} else {
hads = 2;
}
} else {
if (!d->pm) {
d++;
continue;
}
if (deleteparamdef(d)) {
zwarnnam(nam, "parameter `%s' already deleted", d->name);
hadf = 1;
} else {
hads = 2;
}
}
d++;
}
return hadf ? hads : 1;
}
/* This adds a definition for autoloading a module for a parameter. */
/**/
void
add_autoparam(char *nam, char *module)
{
Param pm;
queue_signals();
if (checkaddparam(nam)) {
unqueue_signals();
return;
}
pm = setsparam(nam, ztrdup(module));
pm->node.flags |= PM_AUTOLOAD;
unqueue_signals();
}
/************************************************************************
* Math functions.
************************************************************************/
/* List of math functions. */
/**/
MathFunc mathfuncs;
/**/
void
removemathfunc(MathFunc previous, MathFunc current)
{
if (previous)
previous->next = current->next;
else
mathfuncs = current->next;
zsfree(current->name);
zsfree(current->module);
zfree(current, sizeof(*current));
}
/**/
MathFunc
getmathfunc(char *name, int autol)
{
MathFunc p, q = NULL;
for (p = mathfuncs; p; q = p, p = p->next)
if (!strcmp(name, p->name)) {
if (autol && p->module && !(p->flags & MFF_USERFUNC)) {
char *n = dupstring(p->module);
removemathfunc(q, p);
(void)load_module_silence(n, NULL, 0);
return getmathfunc(name, 0);
}
return p;
}
return NULL;
}
/**/
static int
addmathfunc(MathFunc f)
{
MathFunc p, q = NULL;
if (f->flags & MFF_ADDED)
return 1;
for (p = mathfuncs; p; q = p, p = p->next)
if (!strcmp(f->name, p->name)) {
if (p->module && !(p->flags & MFF_USERFUNC)) {
/*
* Autoloadable, replace.
*/
removemathfunc(q, p);
break;
}
return 1;
}
f->next = mathfuncs;
mathfuncs = f;
return 0;
}
/**/
mod_export int
deletemathfunc(MathFunc f)
{
MathFunc p, q;
for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next);
if (p) {
if (q)
q->next = f->next;
else
mathfuncs = f->next;
/* the following applies to both unloaded and user-defined functions */
if (f->module) {
zsfree(f->name);
zsfree(f->module);
zfree(f, sizeof(*f));
} else
f->flags &= ~MFF_ADDED;
return 0;
}
return -1;
}
/**/
mod_export int
setmathfuncs(char const *nam, MathFunc f, int size, int *e)
{
int hads = 0, hadf = 0;
while (size--) {
if (e && *e++) {
if (f->flags & MFF_ADDED) {
f++;
continue;
}
if (addmathfunc(f)) {
zwarnnam(nam, "name clash when adding math function `%s'",
f->name);
hadf = 1;
} else {
f->flags |= MFF_ADDED;
hads = 2;
}
} else {
if (!(f->flags & MFF_ADDED)) {
f++;
continue;
}
if (deletemathfunc(f)) {
zwarnnam(nam, "math function `%s' already deleted", f->name);
hadf = 1;
} else {
f->flags &= ~MFF_ADDED;
hads = 2;
}
}
f++;
}
return hadf ? hads : 1;
}
/**/
int
add_automathfunc(char *nam, char *module)
{
MathFunc f = (MathFunc) zalloc(sizeof(*f));
f->name = ztrdup(nam);
f->module = ztrdup(module);
f->flags = 0;
if (addmathfunc(f)) {
zsfree(f->name);
zsfree(f->module);
zfree(f, sizeof(*f));
return 1;
}
return 0;
}
/************************************************************************
* Now support for dynamical loading and the fallback functions
* we use for loading if dynamical loading is not available.
************************************************************************/
/**/
#ifdef DYNAMIC
@ -392,11 +1123,15 @@ hpux_dlsym(void *handle, char *name)
#ifdef DLSYM_NEEDS_UNDERSCORE
# define STR_SETUP "_setup_"
# define STR_FEATURES "_features_"
# define STR_ENABLES "_enables_"
# define STR_BOOT "_boot_"
# define STR_CLEANUP "_cleanup_"
# define STR_FINISH "_finish_"
#else /* !DLSYM_NEEDS_UNDERSCORE */
# define STR_SETUP "setup_"
# define STR_FEATURES "features_"
# define STR_ENABLES "enables_"
# define STR_BOOT "boot_"
# define STR_CLEANUP "cleanup_"
# define STR_FINISH "finish_"
@ -542,38 +1277,52 @@ module_loaded(const char *name)
static int
dyn_setup_module(Module m)
{
return ((int (*)_((int,Module))) m->u.handle)(0, m);
return ((int (*)_((int,Module))) m->u.handle)(0, m, NULL);
}
/**/
static int
dyn_features_module(Module m, char ***features)
{
return ((int (*)_((int,Module))) m->u.handle)(4, m, features);
}
/**/
static int
dyn_enables_module(Module m, int **enables)
{
return ((int (*)_((int,Module))) m->u.handle)(5, m, enables);
}
/**/
static int
dyn_boot_module(Module m)
{
return ((int (*)_((int,Module))) m->u.handle)(1, m);
return ((int (*)_((int,Module))) m->u.handle)(1, m, NULL);
}
/**/
static int
dyn_cleanup_module(Module m)
{
return ((int (*)_((int,Module))) m->u.handle)(2, m);
return ((int (*)_((int,Module))) m->u.handle)(2, m, NULL);
}
/**/
static int
dyn_finish_module(Module m)
{
return ((int (*)_((int,Module))) m->u.handle)(3, m);
return ((int (*)_((int,Module))) m->u.handle)(3, m, NULL);
}
/**/
#else
static Module_func
static Module_generic_func
module_func(Module m, char *name)
{
#ifdef DYNAMIC_NAME_CLASH_OK
return (Module_func) dlsym(m->u.handle, name);
return (Module_generic_func) dlsym(m->u.handle, name);
#else /* !DYNAMIC_NAME_CLASH_OK */
VARARR(char, buf, strlen(name) + strlen(m->nam)*2 + 1);
char const *p;
@ -594,7 +1343,7 @@ module_func(Module m, char *name)
*q++ = *p;
}
*q = 0;
return (Module_func) dlsym(m->u.handle, buf);
return (Module_generic_func) dlsym(m->u.handle, buf);
#endif /* !DYNAMIC_NAME_CLASH_OK */
}
@ -602,7 +1351,7 @@ module_func(Module m, char *name)
static int
dyn_setup_module(Module m)
{
Module_func fn = module_func(m, STR_SETUP);
Module_void_func fn = (Module_void_func)module_func(m, STR_SETUP);
if (fn)
return fn(m);
@ -610,11 +1359,36 @@ dyn_setup_module(Module m)
return 1;
}
/**/
static int
dyn_features_module(Module m, char ***features)
{
Module_features_func fn =
(Module_features_func)module_func(m, STR_FEATURES);
if (fn)
return fn(m, features);
/* not a user-visible error if no features function */
return 1;
}
/**/
static int
dyn_enables_module(Module m, int **enables)
{
Module_enables_func fn = (Module_enables_func)module_func(m, STR_ENABLES);
if (fn)
return fn(m, enables);
/* not a user-visible error if no enables function */
return 1;
}
/**/
static int
dyn_boot_module(Module m)
{
Module_func fn = module_func(m, STR_BOOT);
Module_void_func fn = (Module_void_func)module_func(m, STR_BOOT);
if(fn)
return fn(m);
@ -626,7 +1400,7 @@ dyn_boot_module(Module m)
static int
dyn_cleanup_module(Module m)
{
Module_func fn = module_func(m, STR_CLEANUP);
Module_void_func fn = (Module_void_func)module_func(m, STR_CLEANUP);
if(fn)
return fn(m);
@ -641,7 +1415,7 @@ dyn_cleanup_module(Module m)
static int
dyn_finish_module(Module m)
{
Module_func fn = module_func(m, STR_FINISH);
Module_void_func fn = (Module_void_func)module_func(m, STR_FINISH);
int r;
if (fn)
@ -665,6 +1439,24 @@ setup_module(Module m)
(m->u.linked->setup)(m) : dyn_setup_module(m));
}
/**/
static int
features_module(Module m, char ***features)
{
return ((m->flags & MOD_LINKED) ?
(m->u.linked->features)(m, features) :
dyn_features_module(m, features));
}
/**/
static int
enables_module(Module m, int **enables)
{
return ((m->flags & MOD_LINKED) ?
(m->u.linked->enables)(m, enables) :
dyn_enables_module(m, enables));
}
/**/
static int
boot_module(Module m)
@ -699,6 +1491,22 @@ setup_module(Module m)
return ((m->flags & MOD_LINKED) ? (m->u.linked->setup)(m) : 1);
}
/**/
static int
features_module(Module m, char ***features)
{
return ((m->flags & MOD_LINKED) ? (m->u.linked->features)(m, features)
: 1);
}
/**/
static int
enables_module(Module m, int **enables)
{
return ((m->flags & MOD_LINKED) ? (m->u.linked->enables)(m, enables)
: 1);
}
/**/
static int
boot_module(Module m)
@ -723,6 +1531,125 @@ finish_module(Module m)
/**/
#endif /* !DYNAMIC */
/************************************************************************
* Functions called when manipulating modules
************************************************************************/
/*
* Set the features for the module, which must be loaded
* by now (though may not be fully set up).
*
* Return 0 for success, 1 for failure, 2 if some features
* couldn't be set.
*/
/**/
static int
do_module_features(Module m, char **enablesstr, int silent)
{
char **features;
if (features_module(m, &features) == 0) {
/*
* Features are supported. If we were passed
* a NULL array, enable all features, else
* enable only the features listed.
* (This may in principle be an empty array,
* although that's not very pointful.)
*/
int *enables = NULL;
if (enables_module(m, &enables)) {
/* If features are supported, enables should be, too */
if (!silent)
zwarn("error getting enabled features for module `%s'",
m->nam);
return 1;
}
if (enablesstr) {
char **ep;
for (ep = enablesstr; *ep; ep++) {
char **fp, *esp = *ep;
int on = 1;
if (*esp == '+')
esp++;
else if (*esp == '-') {
on = 0;
esp++;
}
for (fp = features; *fp; fp++)
if (!strcmp(*fp, esp)) {
enables[fp - features] = on;
break;
}
if (!*fp) {
if (!silent)
zwarn("module `%s' has no such feature: %s",
m->nam, esp);
return 1;
}
}
} else {
/*
* Enable all features. This is used when loading
* without using zmodload -F.
*/
int n_features = arrlen(features);
int *ep;
for (ep = enables; n_features--; ep++)
*ep = 1;
}
if (enables_module(m, &enables))
return 2;
} else if (enablesstr) {
if (!silent)
zwarn("module `%s' does not support features", m->nam);
return 1;
}
/* Else it doesn't support features but we don't care. */
return 0;
}
/*
* Boot the module, including setting up features.
* As we've only just loaded the module, we don't yet
* know what features it supports, so we get them passed
* as a string.
*
* Returns 0 if OK, 1 if completely failed, 2 if some features
* couldn't be set up.
*/
/**/
static int
do_boot_module(Module m, char **enablesstr, int silent)
{
int ret = do_module_features(m, enablesstr, silent);
if (ret == 1)
return 1;
if (boot_module(m))
return 1;
return ret;
}
/*
* Cleanup the module.
*/
/**/
static int
do_cleanup_module(Module m)
{
return (m->flags & MOD_LINKED) ?
(m->u.linked && m->u.linked->cleanup(m)) :
(m->u.handle && cleanup_module(m));
}
/**/
static int
modname_ok(char const *p)
@ -735,27 +1662,37 @@ modname_ok(char const *p)
return 0;
}
/**/
mod_export int
load_module(char const *name)
{
return load_module_silence(name, 0);
}
/*
* Now returns 0 for success (changed post-4.3.4),
* 1 for complete failure, 2 if some features couldn't be set.
*/
/**/
mod_export int
load_module_silence(char const *name, int silent)
load_module(char const *name, char **enablesstr)
{
return load_module_silence(name, enablesstr, 0);
}
/*
* Returns 0 for success (changed post-4.3.4), 1 for complete
* failure, 2 if some features couldn't be set.
*/
/**/
mod_export int
load_module_silence(char const *name, char **enablesstr, int silent)
{
Module m;
void *handle = NULL;
Linkedmod linked;
LinkNode node, n;
int set;
int set, bootret;
if (!modname_ok(name)) {
if (!silent)
zerr("invalid module name `%s'", name);
return 0;
return 1;
}
/*
* The following function call may alter name to the final name in a
@ -767,7 +1704,7 @@ load_module_silence(char const *name, int silent)
if (!(linked = module_linked(name)) &&
!(handle = do_load_module(name, silent))) {
unqueue_signals();
return 0;
return 1;
}
m = zshcalloc(sizeof(*m));
m->nam = ztrdup(name);
@ -780,40 +1717,47 @@ load_module_silence(char const *name, int silent)
}
node = zaddlinknode(modules, m);
if ((set = setup_module(m)) || boot_module(m)) {
if (!set)
if ((set = setup_module(m)) ||
(bootret = do_boot_module(m, enablesstr, silent)) == 1) {
if (!set) {
do_cleanup_module(m);
finish_module(m);
}
delete_module(node);
unqueue_signals();
return 0;
return 1;
}
m->flags |= MOD_INIT_S | MOD_INIT_B;
m->flags &= ~MOD_SETUP;
unqueue_signals();
return 1;
}
return bootret;
}
m = (Module) getdata(node);
if (m->flags & MOD_SETUP) {
unqueue_signals();
return 1;
return 0;
}
if (m->flags & MOD_UNLOAD)
m->flags &= ~MOD_UNLOAD;
else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
unqueue_signals();
return 1;
return 0;
}
if (m->flags & MOD_BUSY) {
zerr("circular dependencies for module %s", name);
return 0;
return 1;
}
m->flags |= MOD_BUSY;
/*
* TODO: shouldn't we unload the module if one of
* its dependencies fails?
*/
if (m->deps)
for (n = firstnode(m->deps); n; incnode(n))
if (!load_module_silence((char *) getdata(n), silent)) {
if (load_module_silence((char *) getdata(n), NULL, silent) == 1) {
m->flags &= ~MOD_BUSY;
unqueue_signals();
return 0;
return 1;
}
m->flags &= ~MOD_BUSY;
if (!m->u.handle) {
@ -821,7 +1765,7 @@ load_module_silence(char const *name, int silent)
if (!(linked = module_linked(name)) &&
!(handle = do_load_module(name, silent))) {
unqueue_signals();
return 0;
return 1;
}
if (handle) {
m->u.handle = handle;
@ -837,12 +1781,13 @@ load_module_silence(char const *name, int silent)
m->u.linked = NULL;
m->flags &= ~MOD_SETUP;
unqueue_signals();
return 0;
return 1;
}
m->flags |= MOD_INIT_S;
}
m->flags |= MOD_SETUP;
if (boot_module(m)) {
if ((bootret = do_boot_module(m, enablesstr, silent)) == 1) {
do_cleanup_module(m);
finish_module(m);
if (m->flags & MOD_LINKED)
m->u.linked = NULL;
@ -850,42 +1795,44 @@ load_module_silence(char const *name, int silent)
m->u.handle = NULL;
m->flags &= ~MOD_SETUP;
unqueue_signals();
return 0;
return 1;
}
m->flags |= MOD_INIT_B;
m->flags &= ~MOD_SETUP;
unqueue_signals();
return 1;
return bootret;
}
/* This ensures that the module with the name given as the second argument
* is loaded.
* The third argument should be non-zero if the function should complain
* about trying to load a module with a full path name in restricted mode.
* The last argument should be non-zero if this function should signal an
* error if the module is already loaded.
* The return value is non-zero if the module was found or loaded. */
* The last argument is the array of features to set. If this is NULL
* and the module needs to be loaded, all features are enabled.
* If this is non-NULL the module features are set accordingly
* whether or not the module is loaded; it is an error if the
* module does not support the features passed (even if the feature
* is to be turned off) or if the module does not support features
* at all.
* The return value is 0 if the module was found or loaded
* (this changed post-4.3.4, because I got so confused---pws),
* 1 if loading failed completely, 2 if some features couldn't be set.
*/
/**/
mod_export int
require_module(char *nam, const char *module, UNUSED(int res), int test)
require_module(char *nam, const char *module, char **features)
{
Module m = NULL;
LinkNode node;
int ret = 1;
int ret = 0;
/* Resolve aliases and actual loadable module as for load_module */
queue_signals();
node = find_module(module, 1, &module);
if (node && (m = ((Module) getdata(node)))->u.handle &&
!(m->flags & MOD_UNLOAD)) {
if (test) {
unqueue_signals();
zwarnnam(nam, "module %s already loaded.", module);
return 0;
}
} else
ret = load_module_silence(module, 0);
if (!node || !(m = ((Module) getdata(node)))->u.handle ||
(m->flags & MOD_UNLOAD))
ret = load_module_silence(module, features, 0);
else
ret = do_module_features(m, features, 0);
unqueue_signals();
return ret;
@ -953,6 +1900,11 @@ autoloadscan(HashNode hn, int printflags)
putchar('\n');
}
/************************************************************************
* Handling for the zmodload builtin and its various options.
************************************************************************/
/**/
int
bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
@ -961,10 +1913,18 @@ bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
OPT_ISSET(ops,'p') || OPT_ISSET(ops,'f');
int ops_au = OPT_ISSET(ops,'a') || OPT_ISSET(ops,'u');
int ret = 1;
/* options only allowed with -F */
char *fonly = "lP", *fp;
if (ops_bcpf && !ops_au) {
zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
return 1;
if (ops_bcpf) {
if (!ops_au) {
zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u");
return 1;
}
if (OPT_ISSET(ops,'F')) {
zwarnnam(nam, "-b, -c, -f, and -p cannot be combined with -F");
return 1;
}
}
if (OPT_ISSET(ops,'A') || OPT_ISSET(ops,'R')) {
if (ops_bcpf || ops_au || OPT_ISSET(ops,'d') ||
@ -987,10 +1947,19 @@ bin_zmodload(char *nam, char **args, Options ops, UNUSED(int func))
OPT_ISSET(ops,'a') || OPT_ISSET(ops,'d') ||
OPT_ISSET(ops,'i') || OPT_ISSET(ops,'u'))) {
zwarnnam(nam, "-e cannot be combined with other options");
/* except -F ... */
return 1;
}
for (fp = fonly; *fp; fp++) {
if (OPT_ISSET(ops,STOUC(*fp)) && !OPT_ISSET(ops,'F')) {
zwarnnam(nam, "-%c is only allowed with -F", *fp);
return 1;
}
}
queue_signals();
if (OPT_ISSET(ops,'e'))
if (OPT_ISSET(ops, 'F'))
ret = bin_zmodload_features(nam, args, ops);
else if (OPT_ISSET(ops,'e'))
ret = bin_zmodload_exist(nam, args, ops);
else if (OPT_ISSET(ops,'d'))
ret = bin_zmodload_dep(nam, args, ops);
@ -1471,9 +2440,7 @@ unload_module(Module m, LinkNode node)
}
if ((m->flags & MOD_INIT_S) &&
!(m->flags & MOD_UNLOAD) &&
((m->flags & MOD_LINKED) ?
(m->u.linked && m->u.linked->cleanup(m)) :
(m->u.handle && cleanup_module(m))))
do_cleanup_module(m))
return 1;
else {
int del = (m->flags & MOD_UNLOAD);
@ -1622,608 +2589,274 @@ bin_zmodload_load(char *nam, char **args, Options ops)
return 0;
} else {
/* load modules */
for (; *args; args++)
if (!require_module(nam, *args, 1, (!OPT_ISSET(ops,'i'))))
ret = 1;
for (; *args; args++) {
int tmpret = require_module(nam, *args, NULL);
if (tmpret && ret != 1)
ret = tmpret;
}
return ret;
}
}
/* The list of module-defined conditions. */
/**/
mod_export Conddef condtab;
/* This gets a condition definition with the given name. The first *
* argument says if we have to look for an infix condition. The last *
* argument is non-zero if we should autoload modules if needed. */
/**/
Conddef
getconddef(int inf, char *name, int autol)
static int
bin_zmodload_features(char *nam, char **args, Options ops)
{
Conddef p;
int f = 1;
char *modname = *args;
do {
for (p = condtab; p; p = p->next) {
if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
!strcmp(name, p->name))
break;
}
if (autol && p && p->module) {
/* This is a definition for an autoloaded condition, load the *
* module if we haven't tried that already. */
if (f) {
load_module_silence(p->module, 0);
f = 0;
p = NULL;
} else {
deleteconddef(p);
return NULL;
}
} else
break;
} while (!p);
return p;
}
/* This adds the given condition definition. The return value is zero on *
* success and 1 on failure. If there is a matching definition for an *
* autoloaded condition, it is removed. */
/**/
int
addconddef(Conddef c)
{
Conddef p = getconddef((c->flags & CONDF_INFIX), c->name, 0);
if (p) {
if (!p->module || (p->flags & CONDF_ADDED))
return 1;
/* There is an autoload definition. */
deleteconddef(p);
}
c->next = condtab;
condtab = c;
return 0;
}
/* This adds multiple condition definitions. This is like addbuiltins(). */
/**/
mod_export int
addconddefs(char const *nam, Conddef c, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (c->flags & CONDF_ADDED) {
c++;
continue;
}
if (addconddef(c)) {
zwarnnam(nam, "name clash when adding condition `%s'", c->name);
hadf = 1;
} else {
c->flags |= CONDF_ADDED;
hads = 2;
}
c++;
}
return hadf ? hads : 1;
}
/* This list of hook functions defined. */
/**/
Hookdef hooktab;
/* Find a hook definition given the name. */
/**/
Hookdef
gethookdef(char *n)
{
Hookdef p;
for (p = hooktab; p; p = p->next)
if (!strcmp(n, p->name))
return p;
return NULL;
}
/* This adds the given hook definition. The return value is zero on *
* success and 1 on failure. */
/**/
int
addhookdef(Hookdef h)
{
if (gethookdef(h->name))
if (!modname) {
zwarnnam(nam, "-F requires a module name");
return 1;
h->next = hooktab;
hooktab = h;
h->funcs = znewlinklist();
return 0;
}
/* This adds multiple hook definitions. This is like addbuiltins(). */
/**/
mod_export int
addhookdefs(char const *nam, Hookdef h, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (addhookdef(h)) {
zwarnnam(nam, "name clash when adding hook `%s'", h->name);
hadf = 1;
} else
hads = 2;
h++;
}
return hadf ? hads : 1;
}
args++;
/* Delete hook definitions. */
/**/
int
deletehookdef(Hookdef h)
{
Hookdef p, q;
for (p = hooktab, q = NULL; p && p != h; q = p, p = p->next);
if (!p)
return 1;
if (q)
q->next = p->next;
else
hooktab = p->next;
freelinklist(p->funcs, NULL);
return 0;
}
/**/
mod_export int
deletehookdefs(UNUSED(char const *nam), Hookdef h, int size)
{
while (size--) {
deletehookdef(h);
h++;
}
return 1;
}
/* Add a function to a hook. */
/**/
int
addhookdeffunc(Hookdef h, Hookfn f)
{
zaddlinknode(h->funcs, (void *) f);
return 0;
}
/**/
mod_export int
addhookfunc(char *n, Hookfn f)
{
Hookdef h = gethookdef(n);
if (h)
return addhookdeffunc(h, f);
return 1;
}
/* Delete a function from a hook. */
/**/
int
deletehookdeffunc(Hookdef h, Hookfn f)
{
LinkNode p;
for (p = firstnode(h->funcs); p; incnode(p))
if (f == (Hookfn) getdata(p)) {
remnode(h->funcs, p);
return 0;
}
return 1;
}
/**/
mod_export int
deletehookfunc(char *n, Hookfn f)
{
Hookdef h = gethookdef(n);
if (h)
return deletehookdeffunc(h, f);
return 1;
}
/* Run the function(s) for a hook. */
/**/
mod_export int
runhookdef(Hookdef h, void *d)
{
if (empty(h->funcs)) {
if (h->def)
return h->def(h, d);
return 0;
} else if (h->flags & HOOKF_ALL) {
LinkNode p;
int r;
for (p = firstnode(h->funcs); p; incnode(p))
if ((r = ((Hookfn) getdata(p))(h, d)))
return r;
if (h->def)
return h->def(h, d);
return 0;
} else
return ((Hookfn) getdata(lastnode(h->funcs)))(h, d);
}
/**/
int
runhook(char *n, void *d)
{
Hookdef h = gethookdef(n);
if (h)
return runhookdef(h, d);
return 0;
}
/* This adds the given parameter definition. The return value is zero on *
* success and 1 on failure. */
/**/
int
addparamdef(Paramdef d)
{
Param pm;
if ((pm = (Param) gethashnode2(paramtab, d->name)))
unsetparam_pm(pm, 0, 1);
if (!(pm = createparam(d->name, d->flags)) &&
!(pm = (Param) paramtab->getnode(paramtab, d->name)))
return 1;
pm->level = 0;
pm->u.data = d->var;
if (d->gsu)
pm->gsu.i = (GsuInteger) d->gsu;
else {
if (OPT_ISSET(ops,'l') || OPT_ISSET(ops,'L') || OPT_ISSET(ops,'e')) {
/*
* If no get/set/unset class, use the appropriate
* variable type.
* With option 'l', list all features one per line with + or -.
* With option 'L', list as zmodload statement showing
* only options turned on.
* With both options, list as zmodload showing options
* to be turned both on and off.
*/
switch (PM_TYPE(pm->node.flags)) {
case PM_SCALAR:
pm->gsu.s = &varscalar_gsu;
break;
LinkNode node;
Module m = NULL;
char **features, **fp, **arrset = NULL, **arrp = NULL;
int *enables = NULL, *ep;
char *param = OPT_ARG_SAFE(ops,'P');
case PM_INTEGER:
pm->gsu.i = &varinteger_gsu;
break;
case PM_ARRAY:
pm->gsu.a = &vararray_gsu;
break;
default:
unsetparam_pm(pm, 0, 1);
node = find_module(modname, 1, NULL);
if (node)
m = ((Module) getdata(node));
if (!m || !m->u.handle || (m->flags & MOD_UNLOAD)) {
if (!OPT_ISSET(ops,'e'))
zwarnnam(nam, "module `%s' is not yet loaded", modname);
return 1;
}
}
return 0;
}
/* This adds multiple parameter definitions. This is like addbuiltins(). */
/**/
mod_export int
addparamdefs(char const *nam, Paramdef d, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (addparamdef(d)) {
zwarnnam(nam, "error when adding parameter `%s'", d->name);
hadf = 1;
} else
hads = 2;
d++;
}
return hadf ? hads : 1;
}
/* Delete parameters defined. No error checking yet. */
/**/
int
deleteparamdef(Paramdef d)
{
unsetparam(d->name);
return 0;
}
/**/
mod_export int
deleteparamdefs(UNUSED(char const *nam), Paramdef d, int size)
{
while (size--) {
deleteparamdef(d);
d++;
}
return 1;
}
/* This adds a definition for autoloading a module for a condition. */
/**/
int
add_autocond(char *nam, int inf, char *module)
{
Conddef c = (Conddef) zalloc(sizeof(*c));
c->name = ztrdup(nam);
c->flags = (inf ? CONDF_INFIX : 0);
c->module = ztrdup(module);
if (addconddef(c)) {
zsfree(c->name);
zsfree(c->module);
zfree(c, sizeof(*c));
return 1;
}
return 0;
}
/* This removes the given condition definition from the list(s). If this *
* is a definition for a autoloaded condition, the memory is freed. */
/**/
int
deleteconddef(Conddef c)
{
Conddef p, q;
for (p = condtab, q = NULL; p && p != c; q = p, p = p->next);
if (p) {
if (q)
q->next = p->next;
else
condtab = p->next;
if (p->module) {
/* autoloaded, free it */
zsfree(p->name);
zsfree(p->module);
zfree(p, sizeof(*p));
}
return 0;
}
return -1;
}
/* This removes multiple condition definitions (like deletebuiltins()). */
/**/
mod_export int
deleteconddefs(char const *nam, Conddef c, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (!(c->flags & CONDF_ADDED)) {
c++;
continue;
}
if (deleteconddef(c)) {
zwarnnam(nam, "condition `%s' already deleted", c->name);
hadf = 1;
} else
hads = 2;
c->flags &= ~CONDF_ADDED;
c++;
}
return hadf ? hads : 1;
}
/* This adds a definition for autoloading a module for a parameter. */
/**/
void
add_autoparam(char *nam, char *module)
{
Param pm;
queue_signals();
if ((pm = (Param) gethashnode2(paramtab, nam)))
unsetparam_pm(pm, 0, 1);
pm = setsparam(nam, ztrdup(module));
pm->node.flags |= PM_AUTOLOAD;
unqueue_signals();
}
/* List of math functions. */
/**/
MathFunc mathfuncs;
/**/
void
removemathfunc(MathFunc previous, MathFunc current)
{
if (previous)
previous->next = current->next;
else
mathfuncs = current->next;
zsfree(current->name);
zsfree(current->module);
zfree(current, sizeof(*current));
}
/**/
MathFunc
getmathfunc(char *name, int autol)
{
MathFunc p, q = NULL;
for (p = mathfuncs; p; q = p, p = p->next)
if (!strcmp(name, p->name)) {
if (autol && p->module && !(p->flags & MFF_USERFUNC)) {
char *n = dupstring(p->module);
removemathfunc(q, p);
load_module_silence(n, 0);
return getmathfunc(name, 0);
}
return p;
}
return NULL;
}
/**/
mod_export int
addmathfunc(MathFunc f)
{
MathFunc p, q = NULL;
if (f->flags & MFF_ADDED)
return 1;
for (p = mathfuncs; p; q = p, p = p->next)
if (!strcmp(f->name, p->name)) {
if (p->module && !(p->flags & MFF_USERFUNC)) {
/*
* Autoloadable, replace.
*/
removemathfunc(q, p);
break;
}
if (features_module(m, &features)) {
if (!OPT_ISSET(ops,'e'))
zwarnnam(nam, "module `%s' does not support features", m->nam);
return 1;
}
f->flags |= MFF_ADDED;
f->next = mathfuncs;
mathfuncs = f;
return 0;
}
/**/
mod_export int
addmathfuncs(char const *nam, MathFunc f, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (f->flags & MFF_ADDED) {
f++;
continue;
if (enables_module(m, &enables)) {
/* this shouldn't ever happen, so don't silence this error */
zwarnnam(nam, "error getting enabled features for module `%s'",
m->nam);
return 1;
}
if (addmathfunc(f)) {
zwarnnam(nam, "name clash when adding math function `%s'",
f->name);
hadf = 1;
} else
hads = 2;
f++;
}
return hadf ? hads : 1;
}
/**/
int
add_automathfunc(char *nam, char *module)
{
MathFunc f = (MathFunc) zalloc(sizeof(*f));
f->name = ztrdup(nam);
f->module = ztrdup(module);
f->flags = 0;
if (addmathfunc(f)) {
zsfree(f->name);
zsfree(f->module);
zfree(f, sizeof(*f));
for (arrp = args; *arrp; arrp++) {
char *arg = *arrp;
int on;
if (*arg == '-') {
on = 0;
arg++;
} else if (*arg == '+') {
on = 1;
arg++;
} else
on = -1;
for (fp = features, ep = enables; *fp; fp++, ep++) {
if (!strcmp(arg, *fp)) {
/* for -e, check given state, if any */
if (OPT_ISSET(ops,'e') && on != -1 &&
on != (*ep & 1))
return 1;
break;
}
}
if (!*fp) {
if (!OPT_ISSET(ops,'e'))
zwarnnam(nam, "module `%s' has no such feature: %s",
*arrp);
return 1;
}
}
if (OPT_ISSET(ops,'e')) /* yep, everything we want exists */
return 0;
if (OPT_ISSET(ops,'P')) {
int arrlen = 0;
for (fp = features, ep = enables; *fp; fp++, ep++) {
if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l') &&
!*ep)
continue;
if (*args) {
char **argp;
for (argp = args; *argp; argp++) {
char *arg = *argp;
/* ignore +/- for consistency */
if (*arg == '+' || *arg == '-')
arg++;
if (!strcmp(*fp, arg))
break;
}
if (!*argp)
continue;
}
arrlen++;
}
arrp = arrset = zalloc(sizeof(char *) * (arrlen+1));
} else if (OPT_ISSET(ops, 'L'))
printf("zmodload -F %s ", m->nam);
for (fp = features, ep = enables; *fp; fp++, ep++) {
char *onoff;
int term;
if (*args) {
char **argp;
for (argp = args; *argp; argp++) {
char *arg = *argp;
if (*arg == '+' || *arg == '-')
arg++;
if (!strcmp(*fp, *argp))
break;
}
if (!*argp)
continue;
}
if (OPT_ISSET(ops, 'L') && !OPT_ISSET(ops, 'l')) {
if (!*ep)
continue;
onoff = "";
} else if (*ep) {
onoff = "+";
} else {
onoff = "-";
}
if (param) {
*arrp++ = bicat(onoff, *fp);
} else {
if (OPT_ISSET(ops, 'L') && fp[1]) {
term = ' ';
} else {
term = '\n';
}
printf("%s%s%c", onoff, *fp, term);
}
}
if (param) {
*arrp = NULL;
if (!setaparam(param, arrset))
return 1;
}
return 0;
} else if (OPT_ISSET(ops,'P')) {
zwarnnam(nam, "-P can only be used with -l or -L");
return 1;
}
f->flags &= ~MFF_ADDED; /* still to autoload, not added yet */
return require_module(nam, modname, args);
}
/************************************************************************
* Generic feature support.
* These functions are designed to be called by modules.
************************************************************************/
/*
* Construct a features array out of the list of concrete
* features given, leaving space for any abstract features
* to be added by the module itself.
*
* Note the memory is from the heap.
*/
/**/
mod_export char **
featuresarray(char const *nam, Features f)
{
int bn_size = f->bn_size, cd_size = f->cd_size;
int pd_size = f->pd_size, mf_size = f->mf_size;
int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
Builtin bnp = f->bn_list;
Conddef cdp = f->cd_list;
Paramdef pdp = f->pd_list;
MathFunc mfp = f->mf_list;
char **features = (char **)zhalloc((features_size + 1) * sizeof(char *));
char **featurep = features;
while (bn_size--)
*featurep++ = dyncat("b:", (bnp++)->node.nam);
while (cd_size--)
*featurep++ = dyncat("c:", (cdp++)->name);
while (pd_size--)
*featurep++ = dyncat("p:", (pdp++)->name);
while (mf_size--)
*featurep++ = dyncat("f:", (mfp++)->name);
features[features_size] = NULL;
return features;
}
/*
* Return the current set of enables for the features in a
* module using heap memory. Leave space for abstract
* features. The array is not zero terminated.
*/
/**/
mod_export int *
getfeatureenables(char const *nam, Features f)
{
int bn_size = f->bn_size, cd_size = f->cd_size;
int pd_size = f->pd_size, mf_size = f->mf_size;
int features_size = bn_size + cd_size + pd_size + mf_size + f->n_abstract;
Builtin bnp = f->bn_list;
Conddef cdp = f->cd_list;
Paramdef pdp = f->pd_list;
MathFunc mfp = f->mf_list;
int *enables = zhalloc(sizeof(int) * features_size);
int *enablep = enables;
while (bn_size--)
*enablep++ = ((bnp++)->node.flags & BINF_ADDED) ? 1 : 0;
while (cd_size--)
*enablep++ = ((cdp++)->flags & CONDF_ADDED) ? 1 : 0;
while (pd_size--)
*enablep++ = (pdp++)->pm ? 1 : 0;
while (mf_size--)
*enablep++ = ((mfp++)->flags & MFF_ADDED) ? 1 : 0;
return enables;
}
/*
* Add or remove the concrete features passed in arguments,
* depending on the corresponding element of the array e.
* If e is NULL, disable everything.
* Return 0 for success, 1 for failure; does not attempt
* to imitate the return values of addbuiltins() etc.
* Any failure in adding a requested feature is an
* error.
*/
/**/
mod_export int
setfeatureenables(char const *nam, Features f, int *e)
{
int ret = 0;
if (f->bn_size && setbuiltins(nam, f->bn_list, f->bn_size, e) != 1)
ret = 1;
if (e)
e += f->bn_size;
if (f->cd_size && setconddefs(nam, f->cd_list, f->cd_size, e) != 1)
ret = 1;
if (e)
e += f->cd_size;
if (f->pd_size && setparamdefs(nam, f->pd_list, f->pd_size, e) != 1)
ret = 1;
if (e)
e += f->pd_size;
if (f->mf_size && setmathfuncs(nam, f->mf_list, f->mf_size, e) != 1)
ret = 1;
return ret;
}
/**/
mod_export int
handlefeatures(char *nam, Features f, int **enables)
{
if (!enables || *enables)
return setfeatureenables(nam, f, *enables);
*enables = getfeatureenables(nam, f);
return 0;
}
/**/
mod_export int
deletemathfunc(MathFunc f)
{
MathFunc p, q;
for (p = mathfuncs, q = NULL; p && p != f; q = p, p = p->next);
if (p) {
if (q)
q->next = f->next;
else
mathfuncs = f->next;
/* the following applies to both unloaded and user-defined functions */
if (f->module) {
zsfree(f->name);
zsfree(f->module);
zfree(f, sizeof(*f));
} else
f->flags &= ~MFF_ADDED;
return 0;
}
return -1;
}
/**/
mod_export int
deletemathfuncs(char const *nam, MathFunc f, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (!(f->flags & MFF_ADDED)) {
f++;
continue;
}
if (deletemathfunc(f)) {
zwarnnam(nam, "math function `%s' already deleted", f->name);
hadf = 1;
} else
hads = 2;
f++;
}
return hadf ? hads : 1;
}

View File

@ -419,7 +419,7 @@ getparamnode(HashTable ht, char *nam)
if (pm && pm->u.str && (pm->node.flags & PM_AUTOLOAD)) {
char *mn = dupstring(pm->u.str);
if (!load_module(mn))
if (load_module(mn, NULL) == 1)
return NULL;
hn = gethashnode2(ht, nam);
if (((Param) hn) == pm && (pm->node.flags & PM_AUTOLOAD)) {
@ -840,6 +840,47 @@ createparam(char *name, int flags)
return pm;
}
/* Empty dummy function for special hash parameters. */
/**/
static void
shempty(void)
{
}
/* Create a simple special hash parameter. */
/**/
mod_export Param
createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan, int flags)
{
Param pm;
HashTable ht;
if (!(pm = createparam(name, PM_SPECIAL|PM_HASHED|flags)))
return NULL;
pm->level = pm->old ? locallevel : 0;
pm->gsu.h = (flags & PM_READONLY) ? &stdhash_gsu :
&nullsethash_gsu;
pm->u.hash = ht = newhashtable(0, name, NULL);
ht->hash = hasher;
ht->emptytable = (TableFunc) shempty;
ht->filltable = NULL;
ht->addnode = (AddNodeFunc) shempty;
ht->getnode = ht->getnode2 = get;
ht->removenode = (RemoveNodeFunc) shempty;
ht->disablenode = NULL;
ht->enablenode = NULL;
ht->freenode = (FreeNodeFunc) shempty;
ht->printnode = printparamnode;
ht->scantab = scan;
return pm;
}
/* Copy a parameter */
/**/
@ -4117,7 +4158,7 @@ scanendscope(HashNode hn, UNUSED(int flags))
if (pm->env)
delenv(pm);
if (!(tpm->node.flags & PM_NORESTORE))
if (!(tpm->node.flags & (PM_NORESTORE|PM_READONLY)))
switch (PM_TYPE(pm->node.flags)) {
case PM_SCALAR:
pm->gsu.s->setfn(pm, tpm->u.str);

View File

@ -77,7 +77,7 @@ typedef mnumber (*StrMathFunc)(char *, char *, int);
struct mathfunc {
MathFunc next;
char *name;
int flags;
int flags; /* MFF_* flags defined below */
NumMathFunc nfunc;
StrMathFunc sfunc;
char *module;
@ -93,6 +93,7 @@ struct mathfunc {
/* Math function is implemented by a shell function */
#define MFF_USERFUNC 4
#define NUMMATHFUNC(name, func, min, max, id) \
{ NULL, name, 0, func, NULL, NULL, min, max, id }
#define STRMATHFUNC(name, func, id) \
@ -375,6 +376,7 @@ typedef struct builtin *Builtin;
typedef struct cmdnam *Cmdnam;
typedef struct complist *Complist;
typedef struct conddef *Conddef;
typedef struct features *Features;
typedef struct funcstack *Funcstack;
typedef struct funcwrap *FuncWrap;
typedef struct hashnode *HashNode;
@ -1166,14 +1168,40 @@ struct module {
#define MOD_INIT_B (1<<5)
#define MOD_ALIAS (1<<6)
typedef int (*Module_func) _((Module));
typedef int (*Module_generic_func) _((void));
typedef int (*Module_void_func) _((Module));
typedef int (*Module_features_func) _((Module, char ***));
typedef int (*Module_enables_func) _((Module, int **));
struct linkedmod {
char *name;
Module_func setup;
Module_func boot;
Module_func cleanup;
Module_func finish;
Module_void_func setup;
Module_features_func features;
Module_enables_func enables;
Module_void_func boot;
Module_void_func cleanup;
Module_void_func finish;
};
/*
* Structure combining all the concrete features available in
* a module and with space for information about abstract features.
*/
struct features {
/* List of builtins provided by the module and the size thereof */
Builtin bn_list;
int bn_size;
/* List of conditions provided by the module and the size thereof */
Conddef cd_list;
int cd_size;
/* List of parameters provided by the module and the size thereof */
Paramdef pd_list;
int pd_size;
/* List of math functions provided by the module and the size thereof */
MathFunc mf_list;
int mf_size;
/* Number of abstract features */
int n_abstract;
};
/* C-function hooks */
@ -1422,26 +1450,65 @@ struct tieddata {
#define PF_ASSIGN 0x02 /* argument handled like the RHS of foo=bar */
#define PF_SINGLE 0x04 /* single word substitution */
/*
* Structure for adding parameters in a module.
* The flags should declare the type; note PM_SCALAR is zero.
*
* Special hashes are recognized by getnfn so the PM_HASHED
* is optional. These get slightly non-standard attention:
* the function createspecialhash is used to create them.
*
* The get/set/unset attribute may be NULL; in that case the
* parameter is assigned methods suitable for handling the
* tie variable var, if that is not NULL, else standard methods.
*
* pm is set when the parameter is added to the parameter table
* and serves as a flag that the parameter has been added.
*/
struct paramdef {
char *name;
int flags;
void *var;
void *gsu; /* get/set/unset structure */
void *var; /* tied internal variable, if any */
const void *gsu; /* get/set/unset structure, if special */
GetNodeFunc getnfn; /* function to get node, if special hash */
ScanTabFunc scantfn; /* function to scan table, if special hash */
Param pm; /* structure inserted into param table */
};
/*
* Shorthand for common uses of adding parameters, with no special
* hash properties.
*/
#define PARAMDEF(name, flags, var, gsu) \
{ name, flags, (void *) var, (void *) gsu, }
{ name, flags, (void *) var, (void *) gsu, \
NULL, NULL, NULL \
}
/*
* Note that the following definitions are appropriate for defining
* parameters that reference a variable (var). Hence the get/set/unset
* methods used will assume var needs dereferencing to get the value.
*/
#define INTPARAMDEF(name, var) \
{ name, PM_INTEGER, (void *) var, NULL }
{ name, PM_INTEGER, (void *) var, NULL, NULL, NULL, NULL }
#define STRPARAMDEF(name, var) \
{ name, PM_SCALAR, (void *) var, NULL }
{ name, PM_SCALAR, (void *) var, NULL, NULL, NULL, NULL }
#define ARRPARAMDEF(name, var) \
{ name, PM_ARRAY, (void *) var, NULL }
{ name, PM_ARRAY, (void *) var, NULL, NULL, NULL, NULL }
/*
* The following is appropriate for a module function that behaves
* in a special fashion. Parameters used in a module that don't
* have special behaviour shouldn't be declared in a table but
* should just be added with the standard parameter functions.
*
* These parameters are not marked as removable, since they
* shouldn't be loaded as local parameters, unlike the special
* Zle parameters that are added and removed on each call to Zle.
* We add the PM_REMOVABLE flag when removing the feature corresponding
* to the parameter.
*/
#define SPECIALPMDEF(name, flags, gsufn, getfn, scanfn) \
{ name, flags | PM_SPECIAL | PM_HIDE | PM_HIDEVAL, \
NULL, gsufn, getfn, scanfn, NULL }
#define setsparam(S,V) assignsparam(S,V,0)
#define setaparam(S,V) assignaparam(S,V,0)

View File

@ -356,8 +356,6 @@
local parentenv=preserved
fn() {
# The first declare works around the "not an identifier" bug with -h
declare \! \# \$ \* - \? @ 0
typeset -h +g -m \*
unset -m \*
integer i=9

View File

@ -49,9 +49,11 @@
>zmodload zsh/main
>zmodload zsh/parameter
# You use to need zmodload -i to avoid an error.
# That has been deemed pointless, so now an attempt
# to load a loaded module should succeed.
zmodload zsh/main
1:Test reloading an already-loaded module
?(eval):zmodload:1: module zsh/main already loaded.
0:Test reloading an already-loaded module
# Loop over the modules found above and attempt to load each one. Use
# the -i flag in case dependencies cause multiple modules to be loaded,

162
Test/V04features.ztst Normal file
View File

@ -0,0 +1,162 @@
%prep
# Do some tests on handling of features.
# This also does some slightly more sophisticated loading and
# unloading tests than we did in V01zmodload.ztst.
#
# We use zsh/datetime because it has a list of features that is short
# but contains two types.
if ! (zmodload zsh/datetime >/dev/null 2>/dev/null); then
ZTST_unimplemented="can't load the zsh/datetime module for testing"
fi
%test
zmodload -F zsh/datetime
zmodload -lF zsh/datetime
0:Loading modules with no features
>-b:strftime
>-p:EPOCHSECONDS
zmodload -F zsh/datetime b:strftime
zmodload -lF zsh/datetime
0:Enabling features
>+b:strftime
>-p:EPOCHSECONDS
zmodload -F zsh/datetime +p:EPOCHSECONDS -b:strftime
zmodload -lF zsh/datetime
0:Disabling features
>-b:strftime
>+p:EPOCHSECONDS
zmodload -Fe zsh/datetime p:EPOCHSECONDS b:strftime
0:Testing existing features
zmodload -Fe zsh/datetime +p:EPOCHSECONDS
0:Testing features are in given state (on feature is on)
zmodload -Fe zsh/datetime -p:EPOCHSECONDS
1:Testing features are in given state (on feature is not off
zmodload -Fe zsh/datetime +p:strftime
1:Testing features are in given state (off feature is not on)
zmodload -Fe zsh/datetime -b:strftime
0:Testing features are in given state (off feature is off
zmodload -Fe zsh/datetime p:EPOCHSECONDS b:strftime b:mktimebetter
1:Testing non-existent features
zmodload -FlP dtf zsh/datetime
for feature in b:strftime p:EPOCHSECONDS; do
if [[ ${${dtf[(R)?$feature]}[1]} = + ]]; then
print $feature is enabled
else
print $feature is disabled
fi
done
0:Testing features via array parameter
>b:strftime is disabled
>p:EPOCHSECONDS is enabled
fn() {
local EPOCHSECONDS=scruts
print $EPOCHSECONDS
print ${(t)EPOCHSECONDS}
}
fn
if [[ $EPOCHSECONDS = <-> ]]; then
print EPOCHSECONDS is a number
else
print EPOCHSECONDS is some random piece of junk
fi
print ${(t)EPOCHSECONDS}
0:Module special parameter is hidden by a local parameter
>scruts
>scalar-local
>EPOCHSECONDS is a number
>integer-readonly-hide-hideval-special
typeset +h EPOCHSECONDS
fn() {
local EPOCHSECONDS=scruts
print Didn\'t get here >&2
}
fn
1:Unhidden readonly special can't be assigned to when made local
?fn:1: read-only variable: EPOCHSECONDS
zmodload -u zsh/datetime
0:Module unloaded
zmodload -e zsh/datetime
1:Module doesn't exist when unloaded
zmodload -Fe zsh/datetime p:EPOCHSECONDS
1:Module doesn't have features when unloaded
fn() {
local EPOCHSECONDS=scrimf
zmodload zsh/datetime
}
fn
# status is zero because load succeded although features not all enabled
2:Failed to add parameter if local parameter present
?fn:2: Can't add module parameter `EPOCHSECONDS': local parameter exists
?fn:zsh/datetime:2: error when adding parameter `EPOCHSECONDS'
zmodload -lF zsh/datetime
0:Feature state with loading after error enabling
>+b:strftime
>-p:EPOCHSECONDS
zmodload -F zsh/datetime p:EPOCHSECONDS
zmodload -Fe zsh/datetime +p:EPOCHSECONDS
0:Successfully added feature parameter that previously failed
fn() {
local EPOCHSECONDS=scrooble
zmodload -u zsh/datetime
print $EPOCHSECONDS
}
fn
print ${+EPOCHSECONDS}
0:Successfully unloaded a module despite a parameter being hidden
>scrooble
>0
EPOCHSECONDS=(any old parameter)
print -l $EPOCHSECONDS
0:Using parameter as normal after unloading is OK
>any
>old
>parameter
print strftime is ${builtins[strftime]:-undefined}
zmodload -F zsh/datetime b:strftime
print strftime is ${builtins[strftime]:-undefined}
zmodload -F zsh/datetime -b:strftime
print strftime is ${builtins[strftime]:-undefined}
0:Enabling and disabling of builtins as features
>strftime is undefined
>strftime is defined
>strftime is undefined
zmodload -u zsh/datetime
zmodload zsh/datetime
2:Loading won't override global parameter
?(eval):2: Can't add module parameter `EPOCHSECONDS': parameter already exists
?(eval):zsh/datetime:2: error when adding parameter `EPOCHSECONDS'
unset EPOCHSECONDS
zmodload -F zsh/datetime p:EPOCHSECONDS
zmodload -Fe zsh/datetime +p:EPOCHSECONDS
0:unsetting a global parameter allows feature parameter to be enabled
zmodload -F zsh/datetime -b:strftime -p:EPOCHSECONDS
zmodload zsh/datetime
zmodload -lF zsh/datetime
0:zmodload with no -F enables all features
>+b:strftime
>+p:EPOCHSECONDS