summary refs log tree commit diff
path: root/Etc
diff options
context:
space:
mode:
Diffstat (limited to 'Etc')
-rw-r--r--Etc/zsh-development-guide274
1 files changed, 154 insertions, 120 deletions
diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide
index 4797f0d02..6e29ed842 100644
--- a/Etc/zsh-development-guide
+++ b/Etc/zsh-development-guide
@@ -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.
-
-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.
-
-In short, the `cleanup_'-function should undo what the `boot_'-function
-did, and the `finish_'-function should undo what the `setup_'-function
-did.
+in.
+
+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.
+
+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:
-
-  /**/
-  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:
+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
-  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: