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:
parent
bd76320790
commit
b0c5f09169
25
ChangeLog
25
ChangeLog
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#compdef stat
|
||||
#compdef stat zstat
|
||||
|
||||
local expl ret=1
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ... ])(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
10
Src/init.c
10
Src/init.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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 \\"
|
||||
|
|
|
@ -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;
|
||||
|
|
2069
Src/module.c
2069
Src/module.c
|
@ -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;
|
||||
}
|
||||
|
|
45
Src/params.c
45
Src/params.c
|
@ -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);
|
||||
|
|
91
Src/zsh.h
91
Src/zsh.h
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue