1
0
Fork 0
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:
Tanaka Akira 1999-04-15 18:10:10 +00:00
parent 9003d99d16
commit 2a5a899a55
47 changed files with 1371 additions and 341 deletions

View file

@ -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
-------------