mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-23 16:40:24 +02:00
zsh-3.1.5-pws-4
This commit is contained in:
parent
9003d99d16
commit
2a5a899a55
47 changed files with 1371 additions and 341 deletions
|
@ -112,6 +112,297 @@ C coding style
|
|||
groups of statements in the interests of clarity. There should never
|
||||
be two consecutive blank lines.
|
||||
|
||||
Modules
|
||||
-------
|
||||
|
||||
Modules are described by a file named `foo.mdd' for a module
|
||||
`foo'. This file is actually a shell script that will sourced when zsh
|
||||
is build. To describe the module it can/should set the following shell
|
||||
variables:
|
||||
|
||||
- moddeps modules on which this module depends (default none)
|
||||
- nozshdep non-empty indicates no dependence on the `zsh' pseudo-module
|
||||
- alwayslink if non-empty, always link the module into the executable
|
||||
- autobins builtins defined by the module, for autoloading
|
||||
- objects .o files making up this module (*must* be defined)
|
||||
- proto .pro files for this module (default generated from $objects)
|
||||
- headers extra headers for this module (default none)
|
||||
- hdrdeps extra headers on which the .mdh depends (default none)
|
||||
- otherincs extra headers that are included indirectly (default none)
|
||||
|
||||
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 automatically called
|
||||
by the zsh core. The first one, named `setup_foo' for a module named
|
||||
`foo', should set up any data needed in the module, at least any data
|
||||
other modules may be interested in. The second one, named `boot_foo',
|
||||
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.
|
||||
The third one, named `cleanup_foo' for module `foo' is called when the
|
||||
user tries to unload a module and should de-register the builtins
|
||||
etc. The last function, `finish_foo' is called when the module is
|
||||
actually unloaded and should finalize all the data initialized in the
|
||||
`setup'-function. Since the last two functions are only executed when
|
||||
the module is used as an dynamically loaded module you can surround
|
||||
it with `#ifdef MODULE' and `#endif'.
|
||||
In short, the `cleanup'-function should undo what the `boot'-function
|
||||
did, 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.
|
||||
|
||||
Builtins are described in a table, for example:
|
||||
|
||||
static struct builtin bintab[] = {
|
||||
BUILTIN("example", 0, bin_example, 0, -1, 0, "flags", NULL),
|
||||
};
|
||||
|
||||
Here `BUILTIN(...)' is a macro that simplifies the description. Its
|
||||
arguments are:
|
||||
- the name of the builtin as a string
|
||||
- optional flags (see BINF_* in zsh.h)
|
||||
- the C-function implementing the builtin
|
||||
- the minimum number of arguments the builtin needs
|
||||
- the maximum number of arguments the builtin can handle or -1 if
|
||||
the builtin can get any number of arguments
|
||||
- an integer that is passed to the handler function and can be used
|
||||
to distinguish builtins if the same C-function is used to
|
||||
implement multiple builtins
|
||||
- the options the builtin accepts, given as a string containing the
|
||||
option characters (the above example makes the builtin accept the
|
||||
options `f', `l', `a', `g', and `s')
|
||||
- and finally a optional string containing option characters that
|
||||
will always be reported as set when calling the C-function (this,
|
||||
too, can be used when using one C-function to implement multiple
|
||||
builtins)
|
||||
|
||||
The definition of the handler function looks like:
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_example(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
The special comment /**/ is used by the zsh Makefile to generate the
|
||||
`*.pro' files. The arguments of the function are the number under
|
||||
which this function was invoked (the name of the builtin, but for
|
||||
functions that implement more than one builtin this information is
|
||||
needed). The second argument is the array of arguments *excluding* the
|
||||
options that were defined in the struct and which are handled by the
|
||||
calling code. These options are given as the third argument. It is an
|
||||
array of 256 characters in which the n'th element is non-zero if the
|
||||
option with ASCII-value n was set (i.e. you can easily test if an
|
||||
option was used by `if (ops['f'])' etc.). The last argument is the
|
||||
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()'
|
||||
|
||||
The definition of condition codes in modules is equally simple. First
|
||||
we need a table with the descriptions:
|
||||
|
||||
static struct conddef cotab[] = {
|
||||
CONDDEF("len", 0, cond_p_len, 1, 2, 0),
|
||||
CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
|
||||
};
|
||||
|
||||
Again a macro is used, with the following arguments:
|
||||
|
||||
- the name of the condition code without the leading hyphen
|
||||
(i.e. the example makes the condition codes `-len' and `-ex'
|
||||
usable in `[[...]]' constructs)
|
||||
- an optional flag which for now can only be CONDF_INFIX; if this is
|
||||
given, an infix operator is created (i.e. the above makes
|
||||
`[[ -len str ]]' and `[[ s1 -ex s2 ]]' available)
|
||||
- the C-function implementing the conditional
|
||||
- for non-infix condition codes the next two arguments give the
|
||||
minimum and maximum number of string the conditional can handle
|
||||
(i.e. `-len' can get one or two strings); as with builtins giving
|
||||
-1 as the maximum number means that the conditional accepts any
|
||||
number of strings
|
||||
- finally as the last argument an integer that is passed to the
|
||||
handler function that can be used to distinguish different
|
||||
condition codes if the same C-function implements more than one of
|
||||
them
|
||||
|
||||
The definition for the function looks like:
|
||||
|
||||
/**/
|
||||
static int
|
||||
cond_p_len(char **a, int id)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
The first argument is an array containing the strings (NULL-terminated
|
||||
like the array of arguments for builtins), the second argument is the
|
||||
integer value stored in the table (the last argument to `CONDDEF(...)').
|
||||
The value returned by the function should be non-zero if the condition
|
||||
is true and zero otherwise.
|
||||
|
||||
Note that no preprocessing is done on the strings. This means that
|
||||
no substitutions are performed on them and that they will be
|
||||
tokenized. There are three helper functions available:
|
||||
|
||||
- char *cond_str(args, num)
|
||||
The first argument is the array of strings the handler function
|
||||
got as an argument and the second one is an index into this array.
|
||||
The return value is the num'th string from the array with
|
||||
substitutions performed and untokenized.
|
||||
- long cond_val(args, num)
|
||||
The arguments are the same as for cond_str(). The return value is
|
||||
the result of the mathematical evaluation of the num'th string
|
||||
form the array.
|
||||
- int cond_match(args, num, str)
|
||||
Again, the first two arguments are the same as for the other
|
||||
functions. The third argument is any string. The result of the
|
||||
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-resgitering 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.
|
||||
|
||||
Finally, modules can define wrapper functions. These functions are
|
||||
called whenever a shell function is to be executed.
|
||||
|
||||
The definition is simple:
|
||||
|
||||
static struct funcwrap wrapper[] = {
|
||||
WRAPDEF(ex_wrapper),
|
||||
};
|
||||
|
||||
The macro `WRAPDEF(...)' gets the C-function as its only argument.
|
||||
This function should be defined like:
|
||||
|
||||
/**/
|
||||
static int
|
||||
ex_wrapper(List list, FuncWrap w, char *name)
|
||||
{
|
||||
...
|
||||
runshfunc(list, w, name);
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
|
||||
The first two arguments should only be used to pass them to
|
||||
`runshfunc()' which will execute the shell function. The last argument
|
||||
is the name of the function to be executed. The arguments passed to
|
||||
the function can be accessed vie the global variable `pparams' (a
|
||||
NULL-terminated array of strings).
|
||||
The return value of the wrapper function should be zero if it calls
|
||||
`runshfunc()' itself and non-zero otherwise. This can be used for
|
||||
wrapper functions that only need to run under certain conditions or
|
||||
that don't need to clean anything up after the shell function has
|
||||
finished:
|
||||
|
||||
/**/
|
||||
static int
|
||||
ex_wrapper(List list, FuncWrap w, char *name)
|
||||
{
|
||||
if (wrapper_need_to_run) {
|
||||
...
|
||||
runshfunc(list, w, name);
|
||||
...
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Inside these wrapper functions the global variable `sfcontext' will be
|
||||
set to a vlue indicating the circumstances under which the shell
|
||||
function was called. It can have any of the following values:
|
||||
|
||||
- SFC_DIRECT: the function was invoked directly by the user
|
||||
- SFC_SIGNAL: the function was invoked as a signal handler
|
||||
- SFC_HOOK: the function was automatically invoked as one of the
|
||||
special functions known by the shell (like `chpwd')
|
||||
- SFC_WIDGET: the function was called from the zsh line editor as a
|
||||
user-defined widget
|
||||
- SFC_COMPLETE: the function was called from the completion code
|
||||
(e.g. with `compctl -K func')
|
||||
|
||||
If a module invokes a shell function (e.g. as a hook function), the
|
||||
value of this variable should only be changed temporarily and restored
|
||||
to its previous value after the shell function has finished.
|
||||
|
||||
There is a problem when the user tries to unload a module that has
|
||||
defined wrappers from a shell function. In this case the module can't
|
||||
be unloaded immediately since the wrapper function is still on the
|
||||
call stack. The zsh code delays unloading modules until all wrappers
|
||||
from them have finished. To hide this from the user, the module's
|
||||
cleanup function is run immediatly so that all builtins, condition
|
||||
codes, and wrapper function defined by the module are
|
||||
de-registered. But if there is some module-global state that has to be
|
||||
finalized (e.g. some memory that has to be freed) and that is used by
|
||||
the wrapper functions finalizing this data in the cleanup function
|
||||
won't work.
|
||||
This is why ther are two functions each for the initialization and
|
||||
finalization of modules. The `boot'- and `cleanup'-functions are run
|
||||
whenever the user calls `zmodload' or `zmodload -u' and should only
|
||||
register or de-register the module's interface that is visible to the
|
||||
user. Anything else should be done in the `setup'- and
|
||||
`finish'-functions. Otherwise modules that other modules depend upon
|
||||
may destroy their state too early and wrapper functions in the latter
|
||||
modules may stop working since the state they use is already destroyed.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue