1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
|
------------------------------
GUIDELINES FOR ZSH DEVELOPMENT
------------------------------
Zsh is currently developed and maintained by the Zsh Development Group.
This development takes place by mailing list. Check the META-FAQ for the
various zsh mailing lists and how to subscribe to them. The development
is very open and anyone is welcomed and encouraged to join and contribute.
Because zsh is a very large package whose development can sometimes
be very rapid, we kindly ask that people observe a few guidelines when
contributing patches and feedback to the mailing list. These guidelines
are very simple and hopefully should make for a more orderly development
of zsh.
Tools
-----
To develop (as opposed to just build) zsh, you'll need a few specialised
tools:
* GNU autoconf, version 2.50 or later. This version contained
significant enhancements and earlier versions will no
longer work.
* GNU m4. (Required by autoconf.)
* yodl.
* texi2html.
Patches
-------
* Send all patches to the mailing list rather than directly to me.
* Send only context diffs "diff -c oldfile newfile" or unified diffs
"diff -u oldfile newfile". They are much easier to read and
understand while also allowing the patch program to patch more
intelligently. Please make sure the filenames in the diff header
are relative to the top-level directory of the zsh distribution; for
example, it should say "Src/init.c" rather than "init.c" or
"zsh/Src/init.c". Git-style naming of diffs is also acceptable.
* Please put only one bug fix or feature enhancement in a single patch and
only one patch per mail message. This helps me to multiplex the many
(possibly conflicting) patches that I receive for zsh. You shouldn't
needlessly split patches, but send them in the smallest LOGICAL unit.
* If a patch depends on other patches, then please say so. Also please
mention what version of zsh this patch is for.
* Please test your patch and make sure it applies cleanly. It takes
considerably more time to manually merge a patch into the baseline code.
* By convention, patches should be sent with a Subject: line starting with
one of "PATCH:", "[PATCH]" or "[PATCH n/m]" (for a patch series).
Testing
-------
* Because zsh has a huge number of different options and interacts with
a wide range of human and artificial life, it is very difficult to
test the shell thoroughly. For this purpose, the Test subdirectory
exists. It consists of a driver script (ztst.zsh) and various test
files (*.ztst) in a format which is described in B01cd.ztst, which acts
as a template. It is designed to make it easy to provide input to
chunks of shell code and to test the corresponding standard output,
error output and exit status.
* There is not much there yet, but please don't let that put you off adding
tests for basic syntactic features, builtins, options etc. which you
know to be flakey or to have had difficulties in the past. Better
support for testing job control and interactive features is expected
to follow eventually.
* The directory is not part of the usual process of building and
installation. To run the tests, go to Test and `make check'. Please
report any errors with all the usual information about the zsh version
and the system you are using.
C coding style
--------------
* The primary language is ANSI C as defined by the 1989 standard, but the
code should always be compatible with late K&R era compilers ("The C
Programming Language" 1st edition, plus "void" and "enum"). There are
many hacks to avoid the need to actually restrict the code to K&R C --
check out the configure tests -- but always bear the compatibility
requirements in mind. In particular, preprocessing directives must
have the "#" unindented, and string pasting is not available.
* Conversely, there are preprocessor macros to provide safe access to some
language features not present in pure ANSI C, such as variable-length
arrays. Always use the macros if you want to use these facilities.
* Avoid writing code that generates warnings under gcc with the default
options set by the configure script. For example, write
"if ((foo = bar))" rather than "if (foo = bar)".
* Please try not using lines longer than 79 characters.
* The indent/brace style is Kernighan and Ritchie with 4 characters
indentations (with leading tab characters replacing sequences of
8 spaces). This means that the opening brace is the last character
in the line of the if/while/for/do statement and the closing brace
has its own line:
if (foo) {
do that
}
* Put only one simple statement on a line. The body of an if/while/for/do
statement has its own line with 4 characters indentation even if there
are no braces.
* Do not use space between the function name and the opening parenthesis.
Use space after if/for/while. Use space after type casts.
* Do not use (unsigned char) casts since some compilers do not handle
them properly. Use the provided STOUC(X) macro instead.
* If you use emacs 19.30 or newer you can put the following line to your
~/.emacs file to make these formatting rules the default:
(add-hook 'c-mode-common-hook (function (lambda () (c-set-style "BSD"))))
* Function declarations must look like this:
/**/
int
foo(char *s, char **p)
{
function body
}
There must be an empty line, a line with "/**/", a line with the
type of the function, and finally the name of the function with typed
arguments. These lines must not be indented. The script generating
function prototypes and the ansi2knr program depend on this format.
* Variable declarations must similarly be preceded by a
line containing only "/**/", for the prototype generation script.
The declaration itself should be all on one line (except for multi-line
initialisers).
* Preprocessor directives that affect the function/variable declarations must
also be preceded by a "/**/" line, so that they get copied into the
prototype lists.
* There are three levels of visibility for a function or variable. It can
be file-local, for which it must be marked with the keyword "static" at
the front of the declaration. It can be visible to other object files in
the same module, for which it requires no extra keyword. Or it can be
made available to the entire program (including other dynamically loaded
modules), for which it must be marked with the pseudo-keyword "mod_export"
at the front of the declaration. Symbols should have the least visibility
possible.
* Leave a blank line between the declarations and statements in a compound
statement, if both are present. Use blank lines elsewhere to separate
groups of statements in the interests of clarity. There should never
be two consecutive blank lines.
* Each .c file *must* #include the .mdh header for the module it is a
part of and then its own .pro file (for local prototypes). It may
also #include other system headers. It *must not* #include any other
module's headers or any other .pro files.
* The repository includes a `.editorconfig' file with whitespace/indent
control settings. Information about text editor plugins and this file
can be found at <http://editorconfig.org/>.
Modules
-------
Modules have hierarchical names. Name segments are separated by `/', and
each segment consists of alphanumerics plus `_'. Relative names are never
used; the naming hierarchy is strictly for organisational convenience.
Each module is described by a file with a name ending in `.mdd' somewhere
under the Src directory. This file is actually a shell script that will
sourced when zsh is built. To describe the module it can/should set the
following shell variables:
- name name of the module
- link `static', `dynamic' or `no', as described in INSTALL.
In addition, the value `either' is allowed in the .mdd
file, which will be converted by configure to `dynamic'
if that is available, else `static'.
May also be a command string, which will be run within
configure and whose output is used to set the value
of `link' in config.modules. This allows a
system-specific choice of modules. For example,
link='case $host in *-hpux*) echo dynamic; ;;
*) echo no; ;; esac'
- load `yes' or `no': whether the shell should include hooks
for loading the module automatically as necessary.
(This corresponds to an `L' in xmods.conf in the
old mechanism.)
- moddeps modules on which this module depends (default none)
- nozshdep non-empty indicates no dependence on the `zsh/main'
pseudo-module
- alwayslink if non-empty, always link the module into the executable
- autofeatures features defined by the module for autoloading,
a space-separated list. The syntax for features is as
for zmodload -F, e.g. b:mybin refers to the builtin
mybin. This replaces the previous mechanism with
separate variables for builtins, conditions, math
functions and parameters. Note the features are only
available in zsh's native mode, not in emulation modes.
- autofeatures_emu As autofeatures, but the features so presented are
available in modes that are *not* zsh's native mode.
The variable autofeatures must also be present.
- objects .o files making up this module (*must* be defined)
- proto .syms 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 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 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 structures 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; note also the pointers for the abstract features are not
initialised so setting them is mandatory any time there are any present.
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).
See below.
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 the features array, the area of the enables
array for abstract features is not even initialised by the main shell). 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 initial 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. Note that
`cleanup_' is called whenever `setup_' succeeded, so that `cleanup_'
must be prepared to handle any state resulting from a failed `boot_'
or initial call to `features_'. Note also that a return code of 1
from `cleanup_' will result in the module not being unloaded, so
usually `cleanup_' will return 0 even if it has to handle an unclean
state; if it does return 1, it must be prepared to be called again
in a future attempt to unload.
The last function, `finish_' is called when the module is actually unloaded
and should finalize all the data initialized in the `setup_'-function.
However, `finish_' is called even if `setup_' failed, so it should
not rely on the module successfully being set up.
The state from `finish_' module is currently ignored; it is called
too late to prevent the module from being unloaded.
*Note* in addition to freeing memory, variables associated with allocated
memory should be set to NULL or to indicate arrays are empty, etc. It
should not be assumed that the variables will automatically be zeroed if
the module is reloaded (though some configurations may do this).
In short, the `cleanup_'-function should undo what the `boot_'-function did
(together with handling any residual effects of `enables_'), but should
not rely on `boot_' having been successful, and the
`finish_'-function should undo what the `setup_'-function did, but
should not rely on `setup_' having been successful.
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 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 */
}
Within each individual table ("bintab", etc.), features should be listed
in ASCII order as no further sorting is performed by the shell when
features are listed.
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[] = {
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'). Passing NULL here disables
all flag handling, i.e. even "--".
- 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.
Conditions
----------
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, raw)
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. If the last argument is zero, the string
will also be 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 num'th string from the array taken
as a glob pattern matches the given string.
Parameters
----------
For defining parameters, a module can call `createparam()' directly or
use a table to describe them, e.g.:
static struct paramdef patab[] = {
PARAMDEF("foo", PM_INTEGER, NULL, get_foo, set_foo, unset_foo),
INTPARAMDEF("exint", &intparam),
STRPARAMDEF("exstr", &strparam),
ARRPARAMDEF("exarr", &arrparam),
};
There are four macros used:
- PARAMDEF() gets as arguments:
- the name of the parameter
- the parameter flags to set for it (from the PM_* flags defined
in zsh.h)
- optionally a pointer to a variable holding the value of the
parameter
- three functions that will be used to get the value of the
parameter, store a value in the parameter, and unset the
parameter
- the other macros provide simple ways to define the most common
types of parameters; they get the name of the parameter and a
pointer to a variable holding the value as arguments; they are
used to define integer-, scalar-, and array-parameters, so the
variables whose addresses are given should be of type `long',
`char *', and `char **', respectively
For a description of how to write functions for getting or setting the
value of parameters, or how to write a function to unset a parameter,
see the description of the following functions in the `params.c' file:
- `intvargetfn()' and `intvarsetfn()' for integer parameters
- `strvargetfn()' and `strvarsetfn()' for scalar parameters
- `arrvargetfn()' and `arrvarsetfn()' for array parameters
- `stdunsetfn()' for unsetting parameters
Note that if one defines parameters using the last two macros (for
scalars and arrays), the variable holding the value should be
initialized to either `NULL' or to a piece of memory created with
`zalloc()'. But this memory should *not* be freed in the
finish-function of the module because that will be taken care of by
the `deleteparamdefs()' function described below.
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 definitions in Src/Modules/parameter.c.
Math functions
--------------
Modules can also define math functions. Again, they are described
using a table:
static struct mathfunc mftab[] = {
NUMMATHFUNC("sum", math_sum, 1, -1, 0),
STRMATHFUNC("length", math_length, 0),
};
The `NUMMATHFUNC()' macro defines a math function that gets an array
of mnumbers (the zsh type for representing values in arithmetic
expressions) taken from the string in parentheses at the function
call. Its arguments are the name of the function, the C-function
implementing it, the minimum and maximum number of arguments (as
usual, the later may be `-1' to specify that the function accepts any
number of arguments), and finally an integer that is given unchanged
to the C-function (to be able to implement multiple math functions in
one C-function).
The `STRMATHFUNC()' macro defines a math function that gets the string
in parentheses at the call as one string argument (without the
parentheses). The arguments are the name of the function, the
C-function, and an integer used like the last argument of
`NUMMATHFUNC()'.
The C-functions implementing the math functions look like this:
/**/
static mnumber
math_sum(char *name, int argc, mnumber *argv, int id)
{
...
}
/**/
static mnumber
math_length(char *name, char *arg, int id)
{
...
}
Functions defined with `NUMMATHFUNC' get the name of the function, the
number of numeric arguments, an array with these arguments, and the
last argument from the macro-call. Functions defined with
`STRMATHFUNC' get the name of the function, the string between the
parentheses at the call, and the last argument from the macro-call.
Both types of functions return an mnumber which is a discriminated
union looking like:
typedef struct {
union {
zlong l;
double d;
} u;
int type;
} mnumber;
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.
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. 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:
static struct hookdef foohooks[] = {
HOOKDEF("foo", foofunc, 0),
};
The first argument of the macro is the name of the hook. This name
is used whenever the hook is used. The second argument is the default
function for the hook or NULL if no default function exists. The
last argument is used to define flags for the hook. Currently only one
such flag is defined: `HOOKF_ALL'. If this flag is given and more than
one function was added to the hook, all functions will be called
(including the default function). Otherwise only the last function
added will be called.
The functions that can be used as default functions or that can be
added to a hook have to be defined like:
/**/
static int
foofunc(Hookdef h, void *data)
{
...
}
The first argument is a pointer to the struct defining the hook. The
second argument is an arbitrary pointer that is given to the function
used to invoke hooks (see below).
The functions to register and de-register hooks look like those for
the other things that can be defined by modules:
/**/
int
boot_foo(Module m)
{
int ret;
ret = addhookdefs(m->nam, foohooks, sizeof(foohooks)/sizeof(*foohooks))
...
}
...
/**/
int
cleanup_foo(Module m)
{
deletehookdefs(m->nam, foohooks, sizeof(foohooks)/sizeof(*foohooks));
...
}
Modules that define hooks can invoke the function(s) registered for
them by calling the function `runhook(name, data)'. The first argument
is the name of the hook and the second one is the pointer given to the
hook functions as their second argument. Hooks that have the `HOOKF_ALL'
flag call all function defined for them until one returns non-zero.
The return value of `runhook()' is the return value of the last hook
function called or zero if none was called.
To add a function to a hook, the function `addhookfunc(name, func)' is
called with the name of the hook and a hook function as arguments.
Deleting them is done by calling `deletehookfunc(name, func)' with the
same arguments as for the corresponding call to `addhookfunc()'.
Alternative forms of the last three function are provided for hooks
that are changed or called very often. These functions,
`runhookdef(def, data)', `addhookdeffunc(def, func)', and
`deletehookdeffunc(def, func)' get a pointer to the `hookdef'
structure defining the hook instead of the name and otherwise behave
like their counterparts.
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:
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 clue 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 immediately 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 there 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
-------------
* Edit only the .yo files. All other formats (man pages, TeXinfo, HTML,
etc.) are automatically generated from the yodl source.
* Always use the correct markup. em() is used for emphasis, and bf()
for citations. tt() marks text that is literal input to or output
from the shell. var() marks metasyntactic variables.
* In addition to appropriate markup, always use quotes (`') where
appropriate. Specifically, use quotes to mark text that is not a part
of the actual text of the documentation (i.e., that it is being quoted).
In principle, all combinations of quotes and markup are possible,
because the purposes of the two devices are completely orthogonal.
For example,
Type `tt(xyzzy)' to let zsh know you have played tt(advent).
Saying `plugh' aloud doesn't have much effect, however.
In this case, "zsh" is normal text (a name), "advent" is a command name
occurring in the main text, "plugh" is a normal word that is being quoted
(it's the user that says `plugh', not the documentation), and "xyzzy"
is some text to be typed literally that is being quoted.
* For multiple-line pieces of text that should not be filled, there are
various models.
- If the text is pure example, i.e. with no metasyntactic variables etc.,
it should be included within `example(...)'. The text will be
indented, will not be filled and will be put into a fixed width font.
- If the text includes mixed fonts, it should be included within
`indent(...)'. The text is now filled unless `nofill(...)' is also
used, and explicit font-changing commands are required inside.
- If the text appears inside some other format, such as for example the
`item()' list structure, then the instruction `nofill(...)', which
simply turns off filling should be used; as with `indent(...)',
explicit font changing commands are required. This can be used
without `indent()' when no indentation is required, e.g. if the
accumulated indentation would otherwise be too long.
All the above should appear on their own, separated by newlines from the
surrounding text. No extra newlines after the opening or before the
closing parenthesis are required.
Module names
------------
Modules have hierarchical names. Name segments are separated by `/', and
each segment consists of alphanumerics plus `_'. Relative names are never
used; the naming hierarchy is strictly for organisational convenience.
Top-level name segments should be organisational identifiers, assigned
by the Zsh Development Group and recorded here:
top-level identifier organisation
-------------------- ------------
x_* reserved for private experimental use
zsh The Zsh Development Group (contact: <coordinator@zsh.org>)
Below the top level, naming authority is delegated.
Distribution of files
---------------------
zsh is distributed in two parts: a "src" distribution containing all
the source files (roughly, but not exactly, corresponding to the git
tree), and a "doc" distribution containing some pre-built files from
the documentation directory. All the files in the "doc" distribution
may be generated from files in the "src" distribution with appropriate
freely available tools.
To indicate which files should be distributed, each directory in the git
tree includes a file .distfiles that sets any number of a set of Bourne
shell (scalar) parameters. The value of the parameter is expanded as a
set of standard command line arguments. Basic globbing is allowed in the
values.
The following parameters are currently used:
- DISTFILES_SRC is a list of files from the directory for the "src"
distribution.
- DISTFILES_DOC is a list of files from the directory for the "doc"
distribution.
- DISTFILES_NOT is a list of files that will not be included in a
distribution, but that need to be present in the git tree. This
variable is not used by the zsh build process and is present for
the convenience of external checks.
Use of Git
----------
zsh has migrated from CVS to git for version control. We have so far
kept our workflow unchanged; to wit:
1. change is developed and posted to the zsh-workers mailing list
2. the zsh-workers list management software adds an X-Seq: header
3. an entry is added to ChangeLog with details, including the X-Seq:
header.
[Open Question: should the first 6 or so characters of the commit
fingerprint be included, so: "* 12345/deadbeef: frobbed the baz" ?]
4. this is committed to git as a second commit
5. this is pushed to the master server
Micro Git Tutorial:
% $VISUAL file1.c file2.c new-file3.c
% git add new-file3.c
% git commit -a
% git push
"git commit -a" automatically finds files which are tracked and have
been modified, but doesn't pick up new files; "git add" adds a file to
the index to be part of the next commit, and can be used for new files
or for existing files (commit -a is a shortcut for the latter)
"git push" assumes that you're on the master branch and the repository
was created by cloning it from some place, with default options.
Feature branch work:
% git checkout -b feature_foo
% $VISUAL path/to/files ...
% git commit -a
[lather, rinse, repeat]
% git push origin feature_foo
[ do mailing-list stuff here ]
[ Switch back to master: ]
% git checkout master
[ and get the most recent changes: ]
% git pull
[ make the branch content now be relative to *new* master tip ]
% git checkout feature_foo
% git rebase master
[ then bring in your changes: ]
% git checkout master
% git merge --ff-only feature_foo
% $VISUAL ChangeLog
% git commit -i ChangeLog
% git push
[ Cleanup: ]
% git branch -d feature_foo
% git push origin :feature_foo
Git further reading:
* git help tutorial
* git help tutorial-2
* git help gitcore-tutorial
* http://www-cs-students.stanford.edu/~blynn/gitmagic/
|