1.fp 5 CW
2.ds DT January 9, 2012  \" use troff -mm
3.nr C 3
4.nr N 2
5.SA 1  \"  right justified
6.TL "311466-6713" "49059-6"  \" charging case filing case
7Guidelines for writing \f5ksh-93\fP built-in commands
8.AU "David G. Korn" DGK FP 11267 8062 D-237 "(research!dgk)"
9.AF
10.TM  11267-930???-93  \"  technical memo + TM numbers
11.MT 4
12.AS 2   \" abstract start for TM
13One of the features of \f5ksh93\fP, the latest version of \f5ksh\fP,
14is the ability to add built-in commands at run time.
15This feature only works on operating systems that have the ability
16to load and link code into the current process at run time.
17Some examples of the systems that have this feature
18are Linux, System V Release 4, Solaris, Sun OS, HP-UX Release 8 and above,
19AIX 3.2 and above, and Microsoft Windows systems.
20.P
21This memo describes how to write and compile programs
22that can be loaded into \f5ksh\fP at run  time as built-in
23commands.
24.AE   \" abstract end
25.H 1 INTRODUCTION
26A built-in command is executed without creating a separate process.
27Instead, the command is invoked as a C function by \f5ksh\fP.
28If this function has no side effects in the shell process,
29then the behavior of this built-in is identical to that of
30the equivalent stand-alone command.  The primary difference
31in this case is performance.  The overhead of process creation
32is eliminated.  For commands of short duration, the effect
33can be dramatic.  For example, on SUN OS 4.1, the time to
34run \f5wc\fP on a small file of about 1000 bytes, runs
35about 50 times faster as a built-in command.
36.P
37In addition, built-in commands may have side effects on the
38shell environment.
39This is usually done to extend the application domain for
40shell programming.  For example, there is a group of X-windows extension
41built-ins that make heavy use of the shell variable namespace.
42These built-ins are added at run time and
43result in a windowing shell that can be used to write
44X-windows applications.
45.P
46While there are definite advantages to adding built-in
47commands, there are some disadvantages as well.
48Since the built-in command and \f5ksh\fP share the same
49address space, a coding error in the built-in program
50may affect the behavior of \f5ksh\fP; perhaps causing
51it to core dump or hang.
52Debugging is also more complex since your code is now
53a part of a larger entity.
54The isolation provided by a separate process
55guarantees that all resources used by the command
56will be freed when the command completes.
57Resources used by a built-in must be meticulously maintained and freed.
58Also, since the address space of \f5ksh\fP will be larger when built-in are loaded,
59it may increase the time it takes \f5ksh\fP to fork() and
60exec() non-built-in commands.
61It makes no sense to add a built-in command that takes
62a long time to run or that is run only once, since the performance
63benefits will be negligible.
64Built-ins that have side effects in the current shell
65environment have the disadvantage of increasing the
66coupling between the built-in and \f5ksh\fP, making
67the overall system less modular and more monolithic.
68.P
69Despite these drawbacks, in many cases extending
70\f5ksh\fP by adding built-in
71commands makes sense and allows reuse of the shell
72scripting ability in an application specific domain.
73This memo describes how to write \f5ksh\fP extensions.
74.H 1 "WRITING BUILT-IN COMMANDS"
75There is a development kit available for writing \f5ksh\fP
76built-ins as part of the AST (AT&T Software Technology) Toolkit.
77The development kit has three directories,
78\f5include\fP, \f5lib\fP, and \f5bin\fP.
79It is best to set the value of the environment variable
80\f5PACKAGE_ast\fP to the pathname of the directory
81containing the development kit.
82The \f5include\fP directory contains a sub-directory
83named \f5ast\fP that contains interface prototypes
84for functions that you can call from built-ins.  The \f5lib\fP
85directory contains the \f5ast\fP library
86and a library named \f5cmd\fP that contains a version
87of several of the standard POSIX\*(Rf
88.RS
89.I "POSIX \- Part 2: Shell and Utilities,"
90IEEE Std 1003.2-1992, ISO/IEC 9945-2:1993.
91.RF
92utilities that can be made run time built-ins.
93The \f5lib/ksh\fP directory contains shared libraries
94that implement other \f5ksh\fP built-ins.
95The \f5bin\fP directory contains build tools such as \f5nmake\fP\*(Rf.
96.RS
97Glenn Fowler,
98.IR "A Case for make" ,
99Software - Practice and Experience, Vol. 20 No. S1, pp. 30-46, June 1990.
100.RF
101To add built-ins at runtime, it is necessary to build a shared library
102containing one or more built-ins that you wish to add.
103The built-ins are then added by running \f5builtin \-f\fP \fIshared_lib\fP.
104Since the procedure for building share libraries is system dependent,
105it is best to use
106\f5nmake\fP
107using the sample nmake makefile below as a prototype.
108The AST Toolkit also contains some examples of built-in libraries under
109the \f5src/cmd/kshlib\fP directory.
110.P
111There are two ways to code adding built-ins.  One method is to replace
112the function \f5main\fP with a function
113\f5b_\fP\fIname\fP, where \fIname\fP is the name
114of the built-in you wish to define.
115A built-in command has a calling convention similar to
116the \f5main\fP function of a program,
117\f5int main(int argc, char *argv[])\fP.
118except that it takes a third argument of type \f5Shbltin_t*\fP which can
119be passed as \f5\s-1NULL\s+1\fP if it is not used.  The definition for
120\f5Shbltin_t*\fP is in \f5<ast/shcmd.h>\fP.
121Instead of \f5exit\fP, you need to use \f5return\fP
122to terminate your command.
123The return value will become the exit status of the command.
124The \f5open\fP built-in, installed in \f5lib/ksh\fP in the AST Toolkit, uses this method.
125The \f5Shbltin_t\fP structure contains a field named \f5shp\fP which is
126a pointer the the shell data that is needed for \f5shell\fP library callbacks.
127It also contains the fields, \f5shrun\fP, \f5shtrap\fP, \f5shexit\fP,
128and \f5shbltin\fP
129that are function pointers to the \f5shell\fP library functions \f5sh_run\fP, \f5sh_trap\fP
130\f5sh_exit\fP, and \f5sh_addbuiltin\fP, respectively. These functions
131can be invoked without the need for runtime symbol lookup when the
132shell is statically linked with \f5libshell\fP.
133.P
134The alternative method is to create a function \f5lib_init\fP and
135use the \f5Shbltin_t.shbltin()\fP function to add one or more built-ins.
136The \f5lib_init\fP function will be called with two arguments.  The
137first argument will be 0 when the library is loaded and the second
138argument will be of type \f5Shbltin_t*\fP.
139The \f5dbm_t\fP and \f5dss\fP shell built-ins use this method.
140.P
141No matter which way you add built-ins you should add the line
142\f5SHLIB(\fP\fIidentifier\fP\f5)\fP as the last line of one
143of the built-in source file, where \fIidentifier\fP is any C identifier.
144This line provides version information to the shell \f5builtin\fP command
145that it uses to verify compatibility between the built-in and \f5ksh\fP
146implementation versions. \f5builtin\fP fails with a diagnostic on version
147mismatch. The diagnostic helps determine whether \f5ksh\fP is out of
148date and requires an upgrade or the built-in is out of date and requires
149recompilation.
150.P
151The steps necessary to create and add a run time built-in are
152illustrated in the following simple example.
153Suppose you wish to add a built-in command named \f5hello\fP
154which requires one argument and prints the word hello followed
155by its argument.  First, write the following program in the file
156\f5hello.c\fP:
157.EX
158#include     <stdio.h>
159int b_hello(int argc, char *argv[], void *context)
160{
161        if(argc != 2)
162        {
163                fprintf(stderr,"Usage: hello arg\en");
164                return(2);
165        }
166        printf("hello %s\en",argv[1]);
167        return(0);
168}
169SHLIB(hello)
170.EE
171.P
172Next, the program needs to be compiled.
173If you are building with AT&T \f5nmake\fP use the following \f5Makefile\fP:
174.EX
175:PACKAGE: --shared ast
176hello plugin=ksh :LIBRARY: hello.c
177.EE
178and run \f5nmake install\fP to compile, link, and install the built-in shared library
179in \f5lib/ksh/\fP under \f5PACKAGE_ast\fP.
180If the built-in extension uses several \f5.c\fP files, list all of these on
181the \f5:LIBRARY:\fP line.
182.P
183Otherwise you will have to compile \f5hello.c\fP with an option
184to pick up the AST include directory
185(since the AST \f5<stdio.h>\fP is required for \f5ksh\fP compatibility)
186and options required for generating shared libraries.
187For example, on Linux use this to compile:
188.EX
189cc -fpic -I$PACKAGE_ast/include/ast -c hello.c
190.EE
191and use the appropriate link line.
192It really is best to use \f5nmake\fP because the 2 line Makefile above
193will work on all systems that have \f5ksh\fP installed.
194.P
195If you have several built-ins, it is desirable
196to build a shared library that contains them all.
197.P
198The final step is using the built-in.
199This can be done with the \f5ksh\fP command \f5builtin\fP.
200To load the shared library \f5libhello.so\fP from the current directory
201and add the built-in \f5hello\fP, invoke the command,
202.EX
203builtin -f ./libhello.so hello
204.EE
205The shared library prefix (\f5lib\fP here) and suffix (\f5.so\fP here) be omitted;
206the shell will add an appropriate suffix
207for the system that it is loading from.
208If you install the shared library in \f5lib/ksh/\fP, where \f5../lib/ksh/\fP is
209a directory on \fB$PATH\fP, the command
210.EX
211builtin -f hello hello
212.EE
213will automatically find, load and install the built-in on any system.
214Once this command has been invoked, you can invoke \f5hello\fP
215as you do any other command.
216If you are using \f5lib_init\fP method to add built-ins then no arguments
217follow the \f5\-f\fP option.
218.P
219It is often desirable to make a command \fIbuilt-in\fP
220the first time that it is referenced.  The first
221time \f5hello\fP is invoked, \f5ksh\fP should load and execute it,
222whereas for subsequent invocations \f5ksh\fP should just execute the built-in.
223This can be done by creating a file named \f5hello\fP
224with the following contents:
225.EX
226function hello
227{
228        unset -f hello
229        builtin -f hello hello
230        hello "$@"
231}
232.EE
233This file \f5hello\fP needs to be placed in a directory that is
234in your \fB\s-1FPATH\s+1\fP variable, and the built-in shared library
235should be installed in \f5lib/ksh/\fP, as described above.
236.H 1 "CODING REQUIREMENTS AND CONVENTIONS"
237As mentioned above, the entry point for built-ins must either be of
238the form \f5b_\fP\fIname\fP or else be loaded from a function named
239\f5lib_init\fP.
240Your built-ins can call functions from the standard C library,
241the \f5ast\fP library, interface functions provided by \f5ksh\fP,
242and your own functions.
243You should avoid using any global symbols beginning with
244.BR sh_ ,
245.BR nv_ ,
246and
247.B ed_
248since these are used by \f5ksh\fP itself.
249\f5#define\fP constants in \f5ksh\fP interface
250files use symbols beginning with \f5SH_\fP and \f5NV_\fP,
251so avoid using names beginning with these too.
252.H 2 "Header Files"
253The development kit provides a portable interface
254to the C library and to libast.
255The header files in the development kit are compatible with
256K&R C\*(Rf,
257.RS
258Brian W. Kernighan and Dennis M. Ritchie,
259.IR "The C Programming Language" ,
260Prentice Hall, 1978.
261.RF
262ANSI-C\*(Rf,
263.RS
264American National Standard for Information Systems \- Programming
265Language \- C, ANSI X3.159-1989.
266.RF
267and C++\*(Rf.
268.RS
269Bjarne Stroustroup,
270.IR "C++" ,
271Addison Wesley, xxxx
272.RF
273.P
274The best thing to do is to include the header file \f5<shell.h>\fP.
275This header file causes the \f5<ast.h>\fP header, the
276\f5<error.h>\fP header and the \f5<stak.h>\fP
277header to be included as well as defining prototypes
278for functions that you can call to get shell
279services for your builtins.
280The header file \f5<ast.h>\fP
281provides prototypes for many \fBlibast\fP functions
282and all the symbol and function definitions from the
283ANSI-C headers, \f5<stddef.h>\fP,
284\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP,
285and \f5<string.h>\fP.
286It also provides all the symbols and definitions for the
287POSIX\*(Rf
288.RS
289.I "POSIX \- Part 1: System Application Program Interface,"
290IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990.
291.RF
292headers \f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and
293\f5<unistd.h>\fP.
294You should include \f5<ast.h>\fP instead of one or more of
295these headers.
296The \f5<error.h>\fP header provides the interface to the error
297and option parsing routines defined below.
298The \f5<stak.h>\fP header provides the interface to the memory
299allocation routines described below.
300.P
301Programs that want to use the information in \f5<sys/stat.h>\fP
302should include the file \f5<ls.h>\fP instead.
303This provides the complete POSIX interface to \f5stat()\fP
304related functions even on non-POSIX systems.
305.P
306.H 2 "Input/Output"
307\f5ksh\fP uses \fBsfio\fP,
308the Safe/Fast I/O library\*(Rf,
309.RS
310David Korn and Kiem-Phong Vo,
311.IR "SFIO - A Safe/Fast Input/Output library,"
312Proceedings of the Summer Usenix,
313pp. , 1991.
314.RF
315to perform all I/O operations.
316The \fBsfio\fP library, which is part of \fBlibast\fP,
317provides a superset of the functionality provided by the standard
318I/O library defined in ANSI-C.
319If none of the additional functionality is required,
320and if you are not familiar with \fBsfio\fP and
321you do not want to spend the time learning it,
322then you can use \f5sfio\fP via the \f5stdio\fP library
323interface.  The development kit contains the header \f5<stdio.h>\fP
324which maps \f5stdio\fP calls to \f5sfio\fP calls.
325In most instances the mapping is done
326by macros or inline functions so that there is no overhead.
327The man page for the \f5sfio\fP library is in an Appendix.
328.P
329However, there are some very nice extensions and
330performance improvements in \f5sfio\fP
331and if you plan any major extensions I recommend
332that you use it natively.
333.H 2 "Error Handling"
334For error messages it is best to use the \f5ast\fP library
335function \f5errormsg()\fP rather that sending output to
336\f5stderr\fP or the equivalent \f5sfstderr\fP directly.
337Using \f5errormsg()\fP will make error message appear
338more uniform to the user.
339Furthermore, using \f5errormsg()\fP should make it easier
340to do error message translation for other locales
341in future versions of \f5ksh\fP.
342.P
343The first argument to
344\f5errormsg()\fP specifies the dictionary in which the string
345will be searched for translation.
346The second argument to \f5errormsg()\fP contains that error type
347and value.  The third argument is a \fIprintf\fP style format
348and the remaining arguments are arguments to be printed
349as part of the message.  A new-line is inserted at the
350end of each message and therefore, should not appear as
351part of the format string.
352The second argument should be one of the following:
353.VL .5i
354.LI \f5ERROR_exit(\fP\fIn\fP\f5)\fP:
355If \fIn\fP is not-zero, the builtin will exit value \fIn\fP after
356printing the message.
357.LI \f5ERROR_system(\fP\fIn\fP\f5)\fP:
358Exit builtin with exit value \fIn\fP after printing the message.
359The message will display the message corresponding to \f5errno\fP
360enclosed within \f5[\ ]\fP at the end of the message.
361.LI \f5ERROR_usage(\fP\fIn\fP\f5)\fP:
362Will generate a usage message and exit.  If \fIn\fP is non-zero,
363the exit value will be 2.  Otherwise the exit value will be 0.
364.LI \f5ERROR_debug(\fP\fIn\fP\f5)\fP:
365Will print a level \fIn\fP debugging message and will then continue.
366.LI \f5ERROR_warn(\fP\fIn\fP\f5)\fP:
367Prints a warning message. \fIn\fP is ignored.
368.H 2 "Option Parsing"
369The first thing that a built-in should do is to check
370the arguments for correctness and to print any usage
371messages on standard error.
372For consistency with the rest of \f5ksh\fP, it is best
373to use the \f5libast\fP functions \f5optget()\fP and
374\f5optusage()\fPfor this
375purpose.
376The header \f5<error.h>\fP includes prototypes for
377these functions.
378The \f5optget()\fP function is similar to the
379System V C library function \f5getopt()\fP,
380but provides some additional capabilities.
381Built-ins that use \f5optget()\fP provide a more
382consistent user interface.
383.P
384The \f5optget()\fP function is invoked as
385.EX
386int optget(char *\fIargv\fP[], const char *\fIoptstring\fP)
387.EE
388where \f5argv\fP is the argument list and \f5optstring\fP
389is a string that specifies the allowable arguments and
390additional information that is used to format \fIusage\fP
391messages.
392In fact a complete man page in \f5troff\fP or \f5html\fP
393can be generated by passing a usage string as described
394by the \f5getopts\fP command.
395Like \f5getopt()\fP,
396single letter options are represented by the letter itself,
397and options that take a string argument are followed by the \f5:\fP
398character.
399Option strings have the following special characters:
400.VL .5i
401.LI \f5:\fP
402Used after a letter option to indicate that the option
403takes an option argument.
404The variable \f5opt_info.arg\fP will point to this
405value after the given argument is encountered.
406.LI \f5#\fP
407Used after a letter option to indicate that the option
408can only take a numerical value.
409The variable \f5opt_info.num\fP will contain this
410value after the given argument is encountered.
411.LI \f5?\fP
412Used after a \f5:\fP or \f5#\fP (and after the optional \f5?\fP)
413to indicate the the
414preceding option argument is not required.
415.LI \f5[\fP...\f5]\fP
416After a \f5:\fP or \f5#\fP, the characters contained
417inside the brackets are used to identify the option
418argument when generating a \fIusage\fP message.
419.LI \fIspace\fP
420The remainder of the string will only be used when generating
421usage messages.
422.LE
423.P
424The \f5optget()\fP function returns the matching option letter if
425one of the legal option is matched.
426Otherwise, \f5optget()\fP returns
427.VL .5i
428.LI \f5':'\fP
429If there is an error.  In this case the variable \f5opt_info.arg\fP
430contains the error string.
431.LI \f50\fP
432Indicates the end of options.
433The variable \f5opt_info.index\fP contains the number of arguments
434processed.
435.LI \f5'?'\fP
436A usage message has been required.
437You normally call \f5optusage()\fP to generate and display
438the usage message.
439.LE
440.P
441The following is an example of the option parsing portion
442of the \f5wc\fP utility.
443.EX
444#include <shell.h>
445while(1) switch(n=optget(argv,"xf:[file]"))
446{
447	case 'f':
448		file = opt_info.arg;
449		break;
450	case ':':
451		error(ERROR_exit(0), opt_info.arg);
452		break;
453	case '?':
454		error(ERROR_usage(2), opt_info.arg);
455		break;
456}
457.EE
458.H 2 "Storage Management"
459It is important that any memory used by your built-in
460be returned.  Otherwise, if your built-in is called frequently,
461\f5ksh\fP will eventually run out of memory.
462You should avoid using \f5malloc()\fP for memory that must
463be freed before returning from you built-in, because by default,
464\f5ksh\fP will terminate you built-in in the event of an
465interrupt and the memory will not be freed.
466.P
467The best way to to allocate variable sized storage is
468through calls to the \fBstak\fP library
469which is included in \fBlibast\fP
470and which is used extensively by \f5ksh\fP itself.
471Objects allocated with the \f5stakalloc()\fP
472function are freed when you function completes
473or aborts.
474The \fBstak\fP library provides a convenient way to
475build variable length strings and other objects dynamically.
476The man page for the \fBstak\fP library is contained
477in the Appendix.
478.P
479Before \f5ksh\fP calls each built-in command, it saves
480the current stack location and restores it after
481it returns.
482It is not necessary to save and restore the stack
483location in the \f5b_\fP entry function,
484but you may want to write functions that use this stack
485are restore it when leaving the function.
486The following coding convention will do this in
487an efficient manner:
488.EX
489\fIyourfunction\fP()
490{
491        char	*savebase;
492        int	saveoffset;
493        if(saveoffset=staktell())
494        	savebase = stakfreeze(0);
495        \fR...\fP
496        if(saveoffset)
497        	stakset(savebase,saveoffset);
498        else
499        	stakseek(0);
500}
501.EE
502.H 1 "CALLING \f5ksh\fP SERVICES"
503Some of the more interesting applications are those that extend
504the functionality of \f5ksh\fP in application specific directions.
505A prime example of this is the X-windows extension which adds
506builtins to create and delete widgets.
507The \fBnval\fP library is used to interface with the shell
508name space.
509The \fBshell\fP library is used to access other shell services.
510.H 2 "The nval library"
511A great deal of power is derived from the ability to use
512portions of the hierarchal variable namespace provided by \f5ksh-93\fP
513and turn these names into active objects.
514.P
515The \fBnval\fP library is used to interface with shell
516variables.
517A man page for this file is provided in an Appendix.
518You need to include the header \f5<nval.h>\fP
519to access the functions defined in the \fBnval\fP library.
520All the functions provided by the \fBnval\fP library begin
521with the prefix \f5nv_\fP.
522Each shell variable is an object in an associative table
523that is referenced by name.
524The type \f5Namval_t*\fP is pointer to a shell variable.
525To operate on a shell variable, you first get a handle
526to the variable with the \f5nv_open()\fP function
527and then supply the handle returned as the first
528argument of the function that provides an operation
529on the variable.
530You must call \f5nv_close()\fP when you are finished
531using this handle so that the space can be freed once
532the value is unset.
533The two most frequent operations are to get the value of
534the variable, and to assign value to the variable.
535The \f5nv_getval()\fP returns a pointer the the
536value of the variable.
537In some cases the pointer returned is to a region that
538will be overwritten by the next \f5nv_getval()\fP call
539so that if the value isn't used immediately, it should
540be copied.
541Many variables can also generate a numeric value.
542The \f5nv_getnum()\fP function returns a numeric
543value for the given variable pointer, calling the
544arithmetic evaluator if necessary.
545.P
546The \f5nv_putval()\fP function is used to assign a new
547value to a given variable.
548The second argument to \f5putval()\fP is the value
549to be assigned
550and the third argument is a \fIflag\fP which
551is used in interpreting the second argument.
552.P
553Each shell variable can have one or more attributes.
554The \f5nv_isattr()\fP is used to test for the existence
555of one or more attributes.
556See the appendix for a complete list of attributes.
557.P
558By default, each shell variable passively stores the string you
559give with with \f5nv_putval()\fP, and returns the value
560with \f5getval()\fP.  However, it is possible to turn
561any node into an active entity by assigning functions
562to it that will be called whenever \f5nv_putval()\fP
563and/or \f5nv_getval()\fP is called.
564In fact there are up to five functions that can
565associated with each variable to override the
566default actions.
567The type \f5Namfun_t\fP is used to define these functions.
568Only those that are non-\f5NULL\fP override the
569default actions.
570To override the default actions, you must allocate an
571instance of \f5Namfun_t\fP, and then assign
572the functions that you wish to override.
573The \f5putval()\fP
574function is called by the \f5nv_putval()\fP function.
575A \f5NULL\fP for the \fIvalue\fP argument
576indicates a request to unset the variable.
577The \fItype\fP argument might contain the \f5NV_INTEGER\fP
578bit so you should be prepared to do a conversion if
579necessary.
580The \f5getval()\fP
581function is called by \f5nv_getval()\fP
582value and must return a string.
583The \f5getnum()\fP
584function is called by by the arithmetic evaluator
585and must return double.
586If omitted, then it will call \f5nv_getval()\fP and
587convert the result to a number.
588.P
589The functionality of a variable can further be increased
590by adding discipline functions that
591can be associated with the variable.
592A discipline function allows a script that uses your
593variable to define functions whose name is
594\fIvarname\fP\f5.\fP\fIdiscname\fP
595where \fIvarname\fP is the name of the variable, and \fIdiscname\fP
596is the name of the discipline.
597When the user defines such a function, the \f5settrap()\fP
598function will be called with the name of the discipline and
599a pointer to the parse tree corresponding to the discipline
600function.
601The application determines when these functions are actually
602executed.
603By default, \f5ksh\fP defines \f5get\fP,
604\f5set\fP, and \f5unset\fP as discipline functions.
605.P
606In addition, it is possible to provide a data area that
607will be passed as an argument to
608each of these functions whenever any of these functions are called.
609To have private data, you need to define and allocate a structure
610that looks like
611.EX
612struct \fIyours\fP
613{
614        Namfun_t	fun;
615	\fIyour_data_fields\fP;
616};
617.EE
618.H 2 "The shell library"
619There are several functions that are used by \f5ksh\fP itself
620that can also be called from built-in commands.
621The man page for these routines are in the Appendix.
622.P
623The \f5sh_addbuiltin()\fP function can be used to add or delete
624builtin commands.  It takes the name of the built-in, the
625address of the function that implements the built-in, and
626a \f5void*\fP pointer that will be passed to this function
627as the third agument whenever it is invoked.
628If the function address is \f5NULL\fP, the specified built-in
629will be deleted.  However, special built-in functions cannot
630be deleted or modified.
631.P
632The \f5sh_fmtq()\fP function takes a string and returns
633a string that is quoted as necessary so that it can
634be used as shell input.
635This function is used to implement the \f5%q\fP option
636of the shell built-in \f5printf\fP command.
637.P
638The \f5sh_parse()\fP function returns a parse tree corresponding
639to a give file stream.  The tree can be executed by supplying
640it as the first argument to
641the \f5sh_trap()\fP function and giving a value of \f51\fP as the
642second argument.
643Alternatively, the \f5sh_trap()\fP function can parse and execute
644a string by passing the string as the first argument and giving \f50\fP
645as the second argument.
646.P
647The \f5sh_isoption()\fP function can be used to set to see whether one
648or more of the option settings is enabled.
649