summaryrefslogtreecommitdiff
path: root/reference/C/MAN/perlembed.htm
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/MAN/perlembed.htm')
-rw-r--r--reference/C/MAN/perlembed.htm885
1 files changed, 885 insertions, 0 deletions
diff --git a/reference/C/MAN/perlembed.htm b/reference/C/MAN/perlembed.htm
new file mode 100644
index 0000000..2609362
--- /dev/null
+++ b/reference/C/MAN/perlembed.htm
@@ -0,0 +1,885 @@
+<TITLE>perlembed</TITLE>
+<body background=/C_ref/GRAPHICS/bg1.gif>
+<hr>
+<pre>
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+<h3>NAME
+</h3> perlembed - how to embed perl in your C program
+
+<h3>DESCRIPTION
+</h3> PREAMBLE
+
+ Do you want to:
+
+ Use C from Perl?
+ Read the perlcall manpage and the perlxs manpage.
+
+ Use a UNIX program from Perl?
+ Read about backquotes and the system entry in the
+ perlfunc manpage and the exec entry in the perlfunc
+ manpage.
+
+ Use Perl from Perl?
+ Read about the do entry in the perlfunc manpage and
+ the eval entry in the perlfunc manpage and the use
+ entry in the perlmod manpage and the require entry in
+ the perlmod manpage.
+
+ Use C from C?
+ Rethink your design.
+
+ Use Perl from C?
+ Read on...
+
+ ROADMAP
+
+ the section on Compiling your C program
+
+ There's one example in each of the five sections:
+
+ the section on Adding a Perl interpreter to your C program
+
+ the section on Calling a Perl subroutine from your C
+ program
+
+ the section on Evaluating a Perl statement from your C
+ program
+
+ the section on Performing Perl pattern matches and
+ substitutions from your C program
+
+ the section on Fiddling with the Perl stack from your C
+ program
+
+ This documentation is UNIX specific.
+
+ Compiling your C program
+
+ Every C program that uses Perl must link in the perl
+ library.
+
+
+
+<h3>30/Jan/96 perl 5.003 with 1
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ What's that, you ask? Perl is itself written in C; the
+ perl library is the collection of compiled C programs that
+ were used to create your perl executable (/usr/bin/perl or
+ equivalent). (Corollary: you can't use Perl from your C
+ program unless Perl has been compiled on your machine, or
+ installed properly--that's why you shouldn't blithely copy
+ Perl executables from machine to machine without also
+ copying the lib directory.)
+
+ Your C program will--usually--allocate, "run", and
+ deallocate a PerlInterpreter object, which is defined in
+ the perl library.
+
+ If your copy of Perl is recent enough to contain this
+ documentation (5.002 or later), then the perl library (and
+ EXTERN.h and perl.h, which you'll also need) will reside
+ in a directory resembling this:
+
+ /usr/local/lib/perl5/your_architecture_here/CORE
+
+ or perhaps just
+
+ /usr/local/lib/perl5/CORE
+
+ or maybe something like
+
+ /usr/opt/perl5/CORE
+
+ Execute this statement for a hint about where to find
+ CORE:
+
+ perl -e 'use Config; print $Config{archlib}'
+
+ Here's how you might compile the example in the next
+ section, the section on Adding a Perl interpreter to your
+ C program, on a DEC Alpha running the OSF operating
+ system:
+
+ % cc -o interp interp.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
+ -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
+
+ You'll have to choose the appropriate compiler (cc, gcc,
+ et al.) and library directory (/usr/local/lib/...) for
+ your machine. If your compiler complains that certain
+ functions are undefined, or that it can't locate -lperl,
+ then you need to change the path following the -L. If it
+ complains that it can't find EXTERN.h or perl.h, you need
+ to change the path following the -I.
+
+ You may have to add extra libraries as well. Which ones?
+ Perhaps those printed by
+
+ perl -e 'use Config; print $Config{libs}'
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 2
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ Adding a Perl interpreter to youur C program
+
+ In a sense, perl (the C program) is a good example of
+ embedding Perl (the language), so I'll demonstrate
+ embedding with miniperlmain.c, from the source
+ distribution. Here's a bastardized, non-portable version
+ of miniperlmain.c containing the essentials of embedding:
+
+ #include &lt;stdio.h&gt;
+ #include &lt;EXTERN.h&gt; /* from the Perl distribution */
+ #include &lt;perl.h&gt; /* from the Perl distribution */
+
+ static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
+
+ int main(int argc, char **argv, char **env)
+ {
+ my_perl = perl_alloc();
+ perl_construct(my_perl);
+ perl_parse(my_perl, NULL, argc, argv, env);
+ perl_run(my_perl);
+ perl_destruct(my_perl);
+ perl_free(my_perl);
+ }
+
+ Now compile this program (I'll call it interp.c) into an
+ executable:
+
+ % cc -o interp interp.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
+ -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
+
+ After a successful compilation, you'll be able to use
+ interp just like perl itself:
+
+ % interp
+ print "Pretty Good Perl \n";
+ print "10890 - 9801 is ", 10890 - 9801;
+ &lt;CTRL-D&gt;
+ Pretty Good Perl
+ 10890 - 9801 is 1089
+
+ or
+
+ % interp -e 'printf("%x", 3735928559)'
+ deadbeef
+
+ You can also read and execute Perl statements from a file
+ while in the midst of your C program, by placing the
+ filename in argv[1] before calling perl_run().
+
+ Calling a Perl subroutine from yyour C program
+
+ To call individual Perl subroutines, you'll need to remove
+ the call to perl_run() and replace it with a call to
+ perl_call_argv().
+
+
+
+<h3>30/Jan/96 perl 5.003 with 3
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ That's shown below, in a program I'll call showtime.c.
+
+ #include &lt;stdio.h&gt;
+ #include &lt;EXTERN.h&gt;
+ #include &lt;perl.h&gt;
+
+ static PerlInterpreter *my_perl;
+
+ int main(int argc, char **argv, char **env)
+ {
+ my_perl = perl_alloc();
+ perl_construct(my_perl);
+
+ perl_parse(my_perl, NULL, argc, argv, env);
+
+ /*** This replaces perl_run() ***/
+ perl_call_argv("showtime", G_DISCARD | G_NOARGS, argv);
+ perl_destruct(my_perl);
+ perl_free(my_perl);
+ }
+
+ where showtime is a Perl subroutine that takes no
+ arguments (that's the G_NOARGS) and for which I'll ignore
+ the return value (that's the G_DISCARD). Those flags, and
+ others, are discussed in the perlcall manpage.
+
+ I'll define the showtime subroutine in a file called
+ showtime.pl:
+
+ print "I shan't be printed.";
+
+ sub showtime {
+ print time;
+ }
+
+ Simple enough. Now compile and run:
+
+ % cc -o showtime showtime.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
+ -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
+
+ % showtime showtime.pl
+ 818284590
+
+ yielding the number of seconds that elapsed between
+ January 1, 1970 (the beginning of the UNIX epoch), and the
+ moment I began writing this sentence.
+
+ If you want to pass some arguments to the Perl subroutine,
+ or you want to access the return value, you'll need to
+ manipulate the Perl stack, demonstrated in the last
+ section of this document: the section on Fiddling with the
+ Perl stack from your C program
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 4
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ Evaluating a Perl statement fr<h3>om your C program
+</h3>
+ NOTE: This section, and the next, employ some very brittle
+ techniques for evaluting strings of Perl code. Perl 5.002
+ contains some nifty features that enable A Better Way
+ (such as with the perl_eval_sv entry in the perlguts
+ manpage). Look for updates to this document soon.
+
+ One way to evaluate a Perl string is to define a function
+ (we'll call ours perl_eval()) that wraps around Perl's the
+ eval entry in the perlfunc manpage.
+
+ Arguably, this is the only routine you'll ever need to
+ execute snippets of Perl code from within your C program.
+ Your string can be as long as you wish; it can contain
+ multiple statements; it can use the require entry in the
+ perlmod manpage or the do entry in the perlfunc manpage to
+ include external Perl files.
+
+ Our perl_eval() lets us evaluate individual Perl strings,
+ and then extract variables for coercion into C types. The
+ following program, string.c, executes three Perl strings,
+ extracting an int from the first, a float from the second,
+ and a char * from the third.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 5
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ #include &lt;stdio.h&gt;
+ #include &lt;EXTERN.h&gt;
+ #include &lt;perl.h&gt;
+
+ static PerlInterpreter *my_perl;
+
+ int perl_eval(char *string)
+ {
+ char *argv[2];
+ argv[0] = string;
+ argv[1] = NULL;
+ perl_call_argv("_eval_", 0, argv);
+ }
+
+ main (int argc, char **argv, char **env)
+ {
+ char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" };
+ STRLEN length;
+
+ my_perl = perl_alloc();
+ perl_construct( my_perl );
+
+ perl_parse(my_perl, NULL, 3, embedding, env);
+
+ /** Treat $a as an integer **/
+ perl_eval("$a = 3; $a **= 2");
+ printf("a = %d\n", SvIV(perl_get_sv("a", FALSE)));
+
+ /** Treat $a as a float **/
+ perl_eval("$a = 3.14; $a **= 2");
+ printf("a = %f\n", SvNV(perl_get_sv("a", FALSE)));
+
+ /** Treat $a as a string **/
+ perl_eval("$a = 'rekcaH lreP rehtonA tsuJ'; $a = reverse($a); ");
+ printf("a = %s\n", SvPV(perl_get_sv("a", FALSE), length));
+
+ perl_destruct(my_perl);
+ perl_free(my_perl);
+ }
+
+ All of those strange functions with sv in their names help
+ convert Perl scalars to C types. They're described in the
+ perlguts manpage.
+
+ If you compile and run string.c, you'll see the results of
+ using SvIV() to create an int, SvNV() to create a float,
+ and SvPV() to create a string:
+
+ a = 9
+ a = 9.859600
+ a = Just Another Perl Hacker
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 6
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ Performing Perl pattern matche<h3>s and substitutions from
+</h3> your C program
+
+ Our perl_eval() lets us evaluate strings of Perl code, so
+ we can define some functions that use it to "specialize"
+ in matches and substitutions: match(), substitute(), and
+ matches().
+
+ char match(char *string, char *pattern);
+
+ Given a string and a pattern (e.g. "m/clasp/" or
+ "/\b\w*\b/", which in your program might be represented as
+ "/\\b\\w*\\b/"), returns 1 if the string matches the
+ pattern and 0 otherwise.
+
+ int substitute(char *string[], char *pattern);
+
+ Given a pointer to a string and an "=~" operation (e.g.
+ "s/bob/robert/g" or "tr[A-Z][a-z]"), modifies the string
+ according to the operation, returning the number of
+ substitutions made.
+
+ int matches(char *string, char *pattern, char **matches[]);
+
+ Given a string, a pattern, and a pointer to an empty array
+ of strings, evaluates $string =~ $pattern in an array
+ context, and fills in matches with the array elements
+ (allocating memory as it does so), returning the number of
+ matches found.
+
+ Here's a sample program, match.c, that uses all three:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 7
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ #include &lt;stdio.h&gt;
+ #include &lt;EXTERN.h&gt;
+ #include &lt;perl.h&gt;
+
+ static PerlInterpreter *my_perl;
+
+ int eval(char *string)
+ {
+ char *argv[2];
+ argv[0] = string;
+ argv[1] = NULL;
+ perl_call_argv("_eval_", 0, argv);
+ }
+
+ /** match(string, pattern)
+ **
+ ** Used for matches in a scalar context.
+ **
+ ** Returns 1 if the match was successful; 0 otherwise.
+ **/
+ char match(char *string, char *pattern)
+ {
+ char *command;
+ command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 37);
+ sprintf(command, "$string = '%s'; $return = $string =~ %s",
+ string, pattern);
+ perl_eval(command);
+ free(command);
+ return SvIV(perl_get_sv("return", FALSE));
+ }
+
+ /** substitute(string, pattern)
+ **
+ ** Used for =~ operations that modify their left-hand side (s/// and tr///)
+ **
+ ** Returns the number of successful matches, and
+ ** modifies the input string if there were any.
+ **/
+ int substitute(char *string[], char *pattern)
+ {
+ char *command;
+ STRLEN length;
+ command = malloc(sizeof(char) * strlen(*string) + strlen(pattern) + 35);
+ sprintf(command, "$string = '%s'; $ret = ($string =~ %s)",
+ *string, pattern);
+ perl_eval(command);
+ free(command);
+ *string = SvPV(perl_get_sv("string", FALSE), length);
+ return SvIV(perl_get_sv("ret", FALSE));
+ }
+
+ /** matches(string, pattern, matches)
+ **
+ ** Used for matches in an array context.
+
+
+
+<h3>30/Jan/96 perl 5.003 with 8
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ **
+ ** Returns the number of matches,
+ ** and fills in **matches with the matching substrings (allocates memory!)
+ **/
+ int matches(char *string, char *pattern, char **matches[])
+ {
+ char *command;
+ SV *current_match;
+ AV *array;
+ I32 num_matches;
+ STRLEN length;
+ int i;
+
+ command = malloc(sizeof(char) * strlen(string) + strlen(pattern) + 38);
+ sprintf(command, "$string = '%s'; @array = ($string =~ %s)",
+ string, pattern);
+ perl_eval(command);
+ free(command);
+ array = perl_get_av("array", FALSE);
+ num_matches = av_len(array) + 1; /** assume $[ is 0 **/
+ *matches = (char **) malloc(sizeof(char *) * num_matches);
+ for (i = 0; i &lt;= num_matches; i++) {
+ current_match = av_shift(array);
+ (*matches)[i] = SvPV(current_match, length);
+ }
+ return num_matches;
+ }
+
+ main (int argc, char **argv, char **env)
+ {
+ char *embedding[] = { "", "-e", "sub _eval_ { eval $_[0] }" };
+ char *text, **matches;
+ int num_matches, i;
+ int j;
+
+ my_perl = perl_alloc();
+ perl_construct( my_perl );
+
+ perl_parse(my_perl, NULL, 3, embedding, env);
+
+ text = (char *) malloc(sizeof(char) * 486); /** A long string follows! **/
+ sprintf(text, "%s", "When he is at a convenience store and the bill comes to some amount like 76 cents, Maynard is aware that there is something he *should* do, something that will enable him to get back a quarter, but he has no idea *what*. He fumbles through his red squeezey changepurse and gives the boy three extra pennies with his dollar, hoping that he might luck into the corre<h3>ct amount. The boy gives him back two of his own pennies and then the big shiny quarter that is his prize. -RICHH");
+</h3>
+ if (perl_match(text, "m/quarter/")) /** Does text contain 'quarter'? **/
+ printf("perl_match: Text contains the word 'quarter'.\n\n");
+ else
+ printf("perl_match: Text doesn't contain the word 'quarter'.\n\n");
+
+ if (perl_match(text, "m/eighth/")) /** Does text contain 'eighth'? **/
+ printf("perl_match: Text contains the word 'eighth'.\n\n");
+ else
+ printf("perl_match: Text doesn't contain the word 'eighth'.\n\n");
+
+ /** Match all occurrences of /wi../ **/
+
+
+
+<h3>30/Jan/96 perl 5.003 with 9
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ num_matches = perl_matches(text, "m/(wi..)/g", &matches);
+
+ printf("perl_matches: m/(wi..)/g found %d matches...\n", num_matches);
+ for (i = 0; i &lt; num_matches; i++)
+ printf("match: %s\n", matches[i]);
+ printf("\n");
+ for (i = 0; i &lt; num_matches; i++) {
+ free(matches[i]);
+ }
+ free(matches);
+
+ /** Remove all vowels from text **/
+ num_matches = perl_substitute(&text, "s/[aeiou]//gi");
+ if (num_matches) {
+ printf("perl_substitute: s/[aeiou]//gi...%d substitutions made.\n",
+ num_matches);
+ printf("Now text is: %s\n\n", text);
+ }
+
+ /** Attempt a substitution
+ if (!perl_substitute(&text, "s/Perl/C/")) {
+ printf("perl_substitute: s/Perl/C...No substitution made.\n\n");
+ }
+
+ free(text);
+
+ perl_destruct(my_perl);
+ perl_free(my_perl);
+ }
+
+ which produces the output
+
+ perl_match: Text contains the word 'quarter'.
+
+ perl_match: Text doesn't contain the word 'eighth'.
+
+ perl_matches: m/(wi..)/g found 2 matches...
+ match: will
+ match: with
+
+ perl_substitute: s/[aeiou]//gi...139 substitutions made.
+ Now text is: Whn h s t cnvnnc str nd th bll cms t sm mnt lk 76 cnts, Mynrd s wr tht thr s smthng h *shld* d, smthng tht wll nbl hm t gt bck qrtr, bt h hs n d *wht*. H fmbls thrgh hs rd s<h3>qzy chngprs nd gvs th by thr xtr pnns wth hs dllr, hpng tht h mght lck nt th crrct mnt. Th by gvs hm bck tw f hs wn pnns nd thn th bg shny qrtr tht s hs prz. -RCHH
+</h3>
+ perl_substitute: s/Perl/C...No substitution made.
+
+ =head2 Fiddling with the Perl stack from your C program
+
+ When trying to explain stacks, most computer science
+ textbooks mumble something about spring-loaded columns of
+ cafeteria plates: the last thing you pushed on the stack
+ is the first thing you pop off. That'll do for our
+ purposes: your C program will push some arguments onto
+ "the Perl stack", shut its eyes while some magic happens,
+ and then pop the results--the return value of your Perl
+
+
+
+<h3>30/Jan/96 perl 5.003 with 10
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ subroutine--off the stack.
+
+ First you'll need to know how to convert between C types
+ and Perl types, with newSViv() and sv_setnv() and newAV()
+ and all their friends. They're described in the perlguts
+ manpage.
+
+ Then you'll need to know how to manipulate the Perl stack.
+ That's described in the perlcall manpage.
+
+ Once you've understood those, embedding Perl in C is easy.
+
+ Since C has no built-in function for integer
+ exponentiation, let's make Perl's ** operator available to
+ it (this is less useful than it sounds, since Perl
+ implements ** with C's pow() function). First I'll create
+ a stub exponentiation function in power.pl:
+
+ sub expo {
+ my ($a, $b) = @_;
+ return $a ** $b;
+ }
+
+ Now I'll create a C program, power.c, with a function
+ PerlPower() that contains all the perlguts necessary to
+ push the two arguments into expo() and to pop the return
+ value out. Take a deep breath...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 11
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+ #include &lt;stdio.h&gt;
+ #include &lt;EXTERN.h&gt;
+ #include &lt;perl.h&gt;
+
+ static PerlInterpreter *my_perl;
+
+ static void
+ PerlPower(int a, int b)
+ {
+ dSP; /* initialize stack pointer */
+ ENTER; /* everything created after here */
+ SAVETMPS; /* ...is a temporary variable. */
+ PUSHMARK(sp); /* remember the stack pointer */
+ XPUSHs(sv_2mortal(newSViv(a))); /* push the base onto the stack */
+ XPUSHs(sv_2mortal(newSViv(b))); /* push the exponent onto stack */
+ PUTBACK; /* make local stack pointer global */
+ perl_call_pv("expo", G_SCALAR); /* call the function */
+ SPAGAIN; /* refresh stack pointer */
+ /* pop the return value from stack */
+ printf ("%d to the %dth power is %d.\n", a, b, POPi);
+ PUTBACK;
+ FREETMPS; /* free that return value */
+ LEAVE; /* ...and the XPUSHed "mortal" args.*/
+ }
+
+ int main (int argc, char **argv, char **env)
+ {
+ char *my_argv[2];
+
+ my_perl = perl_alloc();
+ perl_construct( my_perl );
+
+ my_argv[1] = (char *) malloc(10);
+ sprintf(my_argv[1], "power.pl");
+
+ perl_parse(my_perl, NULL, argc, my_argv, env);
+
+ PerlPower(3, 4); /*** Compute 3 ** 4 ***/
+
+ perl_destruct(my_perl);
+ perl_free(my_perl);
+ }
+
+
+ Compile and run:
+
+ % cc -o power power.c -L/usr/local/lib/perl5/alpha-dec_osf/CORE
+ -I/usr/local/lib/perl5/alpha-dec_osf/CORE -lperl -lm
+
+ % power
+ 3 to the 4th power is 81.
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 12
+</h3>
+
+
+
+
+<h3>PERLEMBED(1) Perl Programmers Reference Guide PERLEMBED(1)
+</h3>
+
+<h3>MORAL
+</h3> You can sometimes write faster code in C, but you can
+ always write code faster in Perl. Since you can use each
+ from the other, combine them as you wish.
+
+<h3>AUTHOR
+</h3> Jon Orwant &lt;orwant@media.mit.edu&gt;, with contributions from
+ Tim Bunce, Tom Christiansen, Dov Grobgeld, and Ilya
+ Zakharevich.
+
+ December 18, 1995
+
+ Some of this material is excerpted from my book: Perl 5
+ Interactive, Waite Group Press, 1996 (ISBN 1-57169-064-6)
+ and appears courtesy of Waite Group Press.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h3>30/Jan/96 perl 5.003 with 13
+</h3>
+
+</pre>
+<P>
+<hr>
+<p>
+<center>
+<table border="2" width="80%">
+<tr align=center>
+<td width="25%">
+<a href="../cref.html">Top</a>
+</td><td width="25%">
+<a href="../master_index.html">Master Index</a>
+</td><td width="25%">
+<a href="../SYNTAX/keywords.html">Keywords</a>
+</td><td width="25%">
+<a href="../FUNCTIONS/funcref.htm">Functions</a>
+</td>
+</tr>
+</table>
+</center>
+<p>
+<hr>
+
+This manual page was brought to you by <i>mjl_man V-2.0</i>