\input texinfo.tex
@tex
\global\def\mref#1{\begingroup
  \def\printednodename{\ignorespaces #1}%
  \printednodename \space \turnoffactive \ii{(p.\tie\refx{#1-pg})}{}%
\endgroup}
\global\def\vref#1{\begingroup
  \def\printednodename{\ignorespaces #1}%
  \code{\printednodename} \space \turnoffactive \ii{(p.\tie\refx{#1-pg})}{}%
\endgroup}
\global\defaultparindent = 0pt
\global\parindent = \defaultparindent
@end tex

@setfilename metahtml.info
@setchapternewpage odd
@settitle The Meta-HTML Reference Manual
@finalout

@titlepage
@title The Meta-HTML Reference Manual


@author Brian J. Fox, Universal Access Inc.


@page
		   This document describes the Meta-HTML Programming Language,
		   a language specifically designed for writing applications
		   for the World Wide Web.

Published by Universal Access Inc.@*
214-B State St.@*
Santa Barbara, CA 93101 USA

Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by Universal Access Inc.

@vskip 0pt plus 1filll
Copyright @copyright{} 1995, 1998 Brian J. Fox, Universal Access Inc.@*
Copyright @copyright{} 1996, 1998 Universal Access Inc.
@end titlepage


@iftex
@everyfooting @i{Meta-HTML Reference -- Version 1.4} @| @| Formatted on @today{}
@end iftex@c manual-prologue.texi: -*- Texinfo -*-  DESCRIPTIVE TEXT.

@c  Copyright (c) 1996 Brian J. Fox
@c  Author: Brian J. Fox (bfox@ai.mit.edu) Fri Nov  1 15:04:02 1996.

@ifinfo
@macro mref{node}
@xref{\node\}
@end macro

@macro vref{node}
@b{\node\}
@end macro
@end ifinfo

@node Welcome To Meta-HTML
@chapter Welcome To Meta-HTML

This document describes the Meta-HTML language, Version 6.05.  It should
be considered the definitive reference manual for this version of the
language, but the language target itself remains somewhat mobile.  While
the functions described in this manual will continue to operate as
documented, there may be new functions or enhancements appearing in
future versions of the language which will supersede the functionality
that the documented ones provide.

If you are really impatient, or you fancy yourself a wizard, I suggest
that you first look at the code examples at
@b{http://www.metahtml.com/examples}.

Comments and/or suggestions for improvement on this manual, the
language definition, or writing style(!!) should be sent to
@b{bug-manual@@metahtml.com}.

Although World Wide Web use of the Internet has been growing at a
phenomenal rate over the past 3 years, there remains a dearth of
interesting and useful client/server applications.  Traditional
programming languages do not provide an optimal environment for
programming such applications because of the syntactical and
paradigmatic distance between traditional languages and the target
output, namely @b{HTML}.

The stateless and dynamic nature of the WWW requires a level of
support from traditional programming languages which they are hard
pressed to provide.  Must each application programmer write his or her
own tool set to accomplish goals which are fundamentally similar
across applications?

Meta-HTML presents an alternative language choice for the design and
implementation of Web applications, and supplies three methods of
delivering the language.


@node The Purpose of Meta-HTML
@section The Purpose of Meta-HTML

@b{HTML} is a @i{description} layout language.  It describes in
general the placement and visual style of @i{elements} in a
page.  These elements are generally sequences of text, with an
occasional image thrown in for good measure.

Meta-HTML is an @i{interpreted} computer
language with dynamic variables and flow-control statements.  Although
it is not a complete general purpose computer language in the
traditional sense (i.e., you cannot write a version of a Meta-HTML
interpreter in Meta-HTML) it does perform processing and decision
making of and on data elements.

A quick example for the impatient is in order.  The text:

@b{You are connected to ``localhost.ua.com'' and reading
text written by Brian J. Fox.}

is produced in Meta-HTML by:

@example
@group
  <b>You are connected to ``<get-var ENV::SERVER_NAME>'' and
     reading text written by <get-var the-author>.</b>
@end group
@end example

As the WWW grows, more and more document providers are realizing that
stateless connections are only useful for retrieving documents full of
static information, and that, at times, it can be very useful to
remember state pertaining to the browser that is connecting.

The problem of keeping state for a particular browser user has been
resolved by various individuals; all of the solutions require
information to be passed back and forth between the browser and the
server.  For example, to play a WWW Blackjack game could involve the
passing back and forth of information including the current
wins/losses of the user, which cards have been dealt from the deck so
far, and so forth.  This information is most often passed to and fro
in the form of a "magic" URL.  The problems with passing information
in this way are two-fold:

@enumerate
  @item  The information can be modified by the user before sending it
       back, which might allow a user to put more money in his or her
       bank account, for example, and, less importantly,

  @item  The URL looks "ugly", since there is a large amount of
       information present which doesn't describe the essence of the
       location that the user is connecting to.

@end enumerate

Another mechanism can be taken advantage of when both the server and
browser being used support @b{HTTP Cookies}.  While this solves
the problem of "ugly" URLs, (this mechanism does not place information in the
URL) it generates a new problem: the user must be in possession of a
compliant browser, and be communicating with a compliant server.  In
addition, the information can be changed by the user before sending it
back.

Meta-HTML solves the problem of keeping state for a particular
session, and it does it in a server and browser independent manner.
Our method requires no additional CGI programs to be written.  You can
read about the technical details in the @mref{Session Operators}
section of this manual.


@node Implementation Design
@section Implementation Design

Initially, the vast majority of World Wide Web (@b{WWW})
documents consisted of static @i{pages} of text and images,
which were described using @b{HTML}, and displayed using a
@i{browser} which understood only the @b{HTML} language.  The
nature of a WWW connection is @i{stateless} by definition; each
request for information is not associated in any way with any previous
request for information, even when from the same source.

Connections are made from a browser to a WWW @i{server}, in
which the browser requests a particular item of data by specifying a
@i{Universal Resource Locator} (@b{URL}).  The
server looks up the URL, and then returns the data contained within.
While most URLs are static @b{HTML} documents, there exists a mechanism
in which a program can be run.  The output of such a program is an
@b{HTML} document, and  such programs are referred to as
@b{@i{Common Gateway Interface}}, or
@b{CGI} programs.

Meta-HTML is currently implemented as a CGI program which can be
executed every time the server is ready to retrieve a document.  As
before, the document to be retrieved can be a file of @b{HTML}, an
image, or a CGI program to be executed.  However, the document can
also be a file of Meta-HTML code, in which case the benefits of
dynamic variables and flow-control statements are fully realized.

Although this implementation method is not server-specific, you still
must make a couple of configuration changes to your HTTP server in
order to hide the Meta-HTML program from the user.  Details are in
the Installation Guide.


@node Language Syntax
@section Language Syntax

  A Meta-HTML document consists of plain text, @b{HTML} directives, and
  Meta-HTML statements.

  The syntax of the Meta-HTML language was designed to be as similar
  to @b{HTML} as possible, so as to not sacrifice readability of the total
  document.  All of the Meta-HTML statements are delivered as a form
  of @b{HTML} @i{tags}.  There are two types of Meta-HTML tags:
  @i{simple} and @i{complex}.

  A @i{simple tag} begins with an open angle bracket
  (@b{<}) and ends with a corresponding close angle bracket
  (@b{>}).  The text enclosed within the brackets is called the
  @i{body}; it can contain @i{assigned variables} and
  @i{positional arguments}.

  A @i{complex tag} begins with what looks exactly like a
  simple tag, continues throughout the body of the text, and ends with
  the a matching @i{closing tag}.  This is analogous to the use
  of tags within @b{HTML}.  The body of a complex tag is all of the text
  which appears between the opening tag and the closing tag, exclusive
  of those tags themselves.

  Here is an example of using the simple tag @code{set-var}:

@example
@group
    <set-var foo=bar>

@end group
@end example

  Here is an example of using the complex tag @code{when}:

@example
@group
    <when <get-var foo>>
      The value of `foo' is <get-var foo>.
    </when>

@end group
@end example

  Note that both the @code{set-var} and @code{when} forms
  have opening tags which contain additional material.  This
  material is used to supply information to the form.

  Additionally note that ``simple'' and ``complex'' do not refer to the
  complexity of the function performed; they simply refer to the syntax
  used to write the form in a document.  For example, the simple tag
  @vref{var-case} performs a complex operation based upon
  the arguments it is given.

  Variables assigned in the opening (or simple) tag have the form:

@example
@group
    name=value

@end group
@end example

  This gives the variable referred to as @code{name} a local value
  of @code{value}.  Variable assignments such as these give the
  Meta-HTML writer a way to pass dynamic arguments to a function.  For
  example, the @vref{with-open-database} form can open the
  requested database in one of 3 modes; you control which one by locally
  assigning the variable @code{mode} within the form:

@example
@group
    <with-open-database db "/phones.db" mode=<get-var db-mode>>
     ...
    </with-open-database>

@end group
@end example

  @subsubheading Quoting Syntax

  At times, you will need to quote the expressions that you pass to
  various Meta-HTML functions.  You do this with double quotes
  (@code{"}) and blackslashes (@code{\}).  Here is a   somewhat hairy example of quoting:

@example
@group
    <if <get-var "Space Name">
        <get-var "Space Name[space index]">
      <set-var space-name-present=false>>

@end group
@end example

  For most cases, quoting is unnecessary, because open braces are
  expected to match close braces, and doubles quotes are expected to
  come in pairs.  This is the usual case.  For example:

@example
@group
    <ifeq <get-var foo[index]> <get-var bar>
        <set-var array[index]=<get-var bar>-found>
      <set-var array[index]=<get-var bar>-missing>>

@end group
@end example

  In the above example, no quoting was required because the only
  whitespace which appeared in the expression was within a set of
  matched braces.


@node Essential Language Features
@chapter Essential Language Features

@node Variables
@section Variables
Meta-HTML provides a simple mechanism for the storage and retrieval
of variables during a single (possibly recursive) processing pass.  In
addition to this, functions are provided which test the value of a
variable, and conditionally execute other code based upon the result.

There is also a mechanism to group a set of variables using @mref{Packages}.@subsubheading Variable Types and Information

There are internal functions in Meta-HTML which create @i{binary}
variables.  Such variables cannot be used in the ordinary way, since
the data contained within them may not retain integrity once printed
out and read back in.  You can check to see what the type of a
particular variable is with the @vref{symbol-info}
function.

Many variables are predefined by Meta-HTML, and made available to
the page writer.  The @mref{Page Variables} section of this manual
documents those variables fully, while the @mref{Server Variables}
section contains more information on variables which control, or were
specifically created by, the web server.
@deffn {@i{Simple Tag}} {alist?}  string 

Return "t" if @var{string} is a representation of an association list.

@end deffn

@deffn {@i{Simple Tag}} {cgi-decode}  string &optional  [package] 

Decode @var{string} into @var{package}.

If @var{package} is not specified the current package is used.

@var{string} is a string that might have appeared in
@code{QUERY_STRING} or the contents of the data that was posted
to a document, such that it consists of name value pairs:

@example
@group
FOO=bar&STRING=this+is+a+string%2C+other+chars
@end group
@end example

@var{package} is the name of a package to bind the variables in.  So,
given the above example as the text in a variable called @var{string},
here is what you get:

@example
<set-var string="FOO=bar&STRING=a+string%2C+other+chars">
<cgi-decode <get-var string> mypack>
<get-var mypack::string>
@end example
  produces
@example
a string, other chars
@end example

Also see @vref{cgi-encode}.

@end deffn

@deffn {@i{Simple Tag}} {cgi-encode} &rest vars &key preserve-case=true strip=true

A CGI readable string is created from the names of the @var{var}s given,
and the associated values of those variables.  For example, if the
variable @code{FOO-VAR} has the value @code{"Foo &
Value"}, then the invocation

@example
<cgi-encode FOO-VAR>
@end example
  produces
@example
FOO-VAR=Foo+%26+Value
@end example

Given the optional keyword argument of @var{preserve-case=true},
@code{cgi-encode} encodes the variables preserving the case of
them as they were input.

@example
<cgi-encode Foo-Var preserve-case=true>
@end example
  produces
@example
Foo-Var=Foo+%26+Value
@end example

Finally, the keyword flag @var{strip=true}, when present, says to
strip off the package name of each variable before placing it in an
assignment statement (also see @vref{package-vars}).

@example
<set-var FOO::BAR=value>
<cgi-encode Foo::Bar preserve-case=true strip=true>
@end example
  produces
@example
Bar=value
@end example

@end deffn

@deffn {@i{Simple Tag}} {coerce-var}  varname &key  [type=(STRING|BINARY|ARRAY)] 

Coerces @var{varname}'s data to have the type specified by the
argument to @var{type}.  You can convert a binary object to a string
object, and vice-versa.

A binary variable might be created as the result of a call to @vref{stream-get-contents}, for example.  Once the data is
read, you might wish to perform some substitutions on it, or otherwise
get its value.  To do so, you call @code{coerce-var} on the
value:

@example
@group
<with-open-stream s /tmp/file mode=read>
  <stream-get-contents s foo>
</with-open-stream>

<coerce-var foo type=string>
<subst-in-string <get-var foo> "Hello" "Goodbye">
<get-var foo>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {content-length} 

 Return the length of the contents of @var{var}.
 If @var{var} is an array or string, returns the number of
 elements in the array.
 If @var{var} is a binary variable, returns the amount of data
 stored within.
 If @var{var} is a function, returns the empty string.

@example
@group
 <dir::read-file /etc/passwd myvar> ==> true
 <content-length myvar>             ==> 864

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {copy-var}  from-var &optional  [to-var...] 

Copies the variable @var{from-var} to each of the named @var{to-var}s.

Each @var{to-var} becomes the repository of a copy of the information already stored under @var{from-var}.  This is a @i{true} copy; not an alias to the original variable.

@example
@group
<set-var foo=bar>
<get-var foo>      ==> bar
<get-var new>      ==> 
<copy-var foo new> ==>
<get-var new>      ==> bar

<copy-var *meta-html*::get-var *meta-html*::foo>
<foo new>          ==> bar
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {decrement}  name &key  [by=amount] 

Subtract @var{amount} (default 1) from the contents of the variable named by @var{varname}.

@example
@group
   <set-var foo=1>
   <get-var foo> ==> 1
   <decrement foo>
   <get-var foo> ==> 0
@end group
@end example

Also see @vref{increment}.

@end deffn

@deffn {@i{Simple Tag}} {decrypt}  varname  key &key  [algorithm=[3des]] 

Decrypts the contents of @var{varname} using @var{algorithm}
(defaults to 3des).

The contents of @var{varname} are replaced with a decrypted version.
@var{key} is the cleartext key to use for decrypting the data.

Example:

@example
@group
<set-var foo="Hello">
<encrypt foo "secret password">
<get-var foo> ==> 3b743366228f5f37
<decrypt foo "secret password">
<get-var foo> ==> Hello
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {defvar}  name  value 

@b{DEF}ault the value of the @b{VAR}iable named by @var{name}
to @var{value}.

@code{defvar} assigns @var{value} to @var{name} if, and only if,
@var{name} has a non-empty value.

@code{defvar} could have been defined in Meta-HTML using
@vref{define-tag}:

@example
@group
<define-tag defvar var val>
  <if <not <get-var var>> <set-var <get-var var>=<get-var val>>>
</define-tag>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {encrypt}  varname  key &key  [algorithm=[3des]] 

Encrypts the contents of @var{varname} using @var{algorithm}
(defaults to 3des).

The contents of @var{varname} are replaced with an encrypted version.
@var{key} is the cleartext key to use for encrypting the data.

Example:

@example
@group
<set-var foo="Hello">
<encrypt foo "secret password">
<get-var foo> ==> 3b743366228f5f37
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {get-var} &optional  [name...] 

Return the value of the @var{name}s given.  Each @var{name} is a
variable name which has had a value assigned to it with @vref{set-var}, @vref{set-var-readonly}, or was
created implicity via @vref{alist-to-package} or @vref{coerce-var}.

The values are returned in the order in which the @var{name}s appear.

Examples:
@example
<set-var foo=Var-1 bar=Var-2>
<get-var foo>, <get-var bar>
@end example
  produces
@example
Var-1, Var-2
@end example

When multiple @var{name}s are given:
@example
<get-var foo bar foo>
@end example
  produces
@example
Var-1Var-2Var-1
@end example

@end deffn

@deffn {@i{Simple Tag}} {get-var-once} &optional  [name...] 

Returns the current value of the variables named by the @var{name}s
given.  The interpreter pointer is then moved to after the returned
data, thus preventing further interpretation of the data.

Example:

@example
@group
<set-var bar=HELLO>
<set-var-verbatim foo=<get-var bar>>
<get-var-once foo>   ==> <get-var bar>
@end group
@end example

but...

@example
@group
<get-var foo>        ==> HELLO
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {increment}  name &key  [by=amount] 

Add @var{amount} (default 1) to the contents of the variable named by
@var{varname}.

@example
@group
<set-var foo=1>
<get-var foo> ==> 1
<increment foo>
<get-var foo> ==> 2
@end group
@end example

Also see @vref{decrement}.

@end deffn

@deffn {@i{Simple Tag}} {set-var} &optional  [name=value...] 

Gives the variable @var{name} the value of @var{value} for the
current processing run.  Any number of name/value pairs may be given,
and whitespace is not significant.  Where @var{=value} is omitted, the
value is the empty string.

@example
@group
<set-var foo=bar bar=baz>
<get-var foo>              ==> bar
<get-var bar>              ==> baz
<get-var <get-var foo>>    ==> baz
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {set-var-readonly} &optional  [name=value...] 

For each @var{name} specified, if that name is not already assigned a
value with @code{set-var-readonly}, assigns the associated @var{value} to it, exactly in the way that @vref{set-var} would.

Once @var{name} has had a value assigned to it with
@code{set-var-readonly}, then that variable is @i{immutable},
i.e., its value cannot be changed using any Meta-HTML commands.

A useful construct for setting various site specific variables in your
@code{engine.conf} or @code{mhttpd.conf} file, this allows
one to create globally defined variables which cannot be changed by
the execution of Meta-HTML statements in a page.

Variables which can usefully benefit from this type of setting
include @code{mhtml::include-prefix} and @code{mhtml::relative-prefix} among others.

@end deffn

@deffn {@i{Simple Tag}} {set-var-verbatim} &optional  [name=value...] 

Gives the variable @var{name} the value of @var{value} for the
current processing run.  The difference between
@code{set-var-verbatim} and @vref{set-var} is that
in @code{set-var-verbatim} the right-hand side of assignments
are not evaluated.

Example:
@example
<set-var-verbatim foo=<get-var bar>>
<get-var-once foo>
@end example
  produces
@example
Var-2
@end example

@end deffn

@deffn {@i{Simple Tag}} {symbol-info}  symbol 

Returns information about the symbol @var{symbol}.

The information is two lines:

@itemize @bullet
@item  The type of the symbol, which is one of:

@enumerate
@item @code{STRING},
@item @code{BINARY},
@item @code{USER DEFUN},
@item @code{USER SUBST},
@item @code{USER MACRO},
@item @code{PRIM DEFUN}, or
@item @code{PRIM MACRO}.

@end enumerate
@item  The "size" of the symbol.

@end itemize

For @code{STRING}. variables, the size value is the number of
elements in the array.

For BINARY variables, the size value is the number of bytes of binary
data stored within.

The size value is zero for all other variable types.

@end deffn

@deffn {@i{Simple Tag}} {unset-var} &optional  [name...] 

Make @var{name}s be non-existent in the page environment.

This is different than   
@b{@code{<set-var foo="">}}
because the variable actually ceases to exist, rather than is given no
value.

Example:

@example
@group
<set-var foo="">
<var-exists foo>      ==> true
<get-var foo>         ==>
<unset-var foo>
<var-exists foo>      ==>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {var-exists}  name 

@code{var-exists} checks for the @i{existence} of
the variable named by @var{varname}, and returns @code{true} if that variable exists.

The existence of a variable has nothing to do with its value -- a variable exists if it has been created with @vref{set-var}, and doesn't exist after it has been unset with @vref{unset-var}.

@example
@group
  <set-var foo=1 bar>
  <var-exists foo>       ==> true
  <var-exists bar>       ==> true
  <get-var bar>          ==>
  <unset-var foo>
  <var-exists foo>       ==>
@end group
@end example

@end deffn


@node Arrays
@section Arrays
Meta-HTML allows the use of @i{array} variables as well as single element variables.  In fact, all string variables in Meta-HTML can be treated as array variables -- there is no special command for creating such variables.
Array variable values are referenced by placing the array index directly after the variable name, enclosed in square brackets (@b{[} and @b{]}).  Thus, a reference to the 3rd element of the array @var{foo} looks like:

@example
@group
   foo[3]
@end group
@end example

When an array reference is made without any containing index, the reference refers to the entire array.  So, to get the value of the entire array stored in @var{foo}, you would write:

@example
@group
   <get-var foo[]>
@end group
@end example

In order to ease the writing of array references which rely on a variable index, a variable name seen as an array reference index is automatically looked up as if you had written   
@b{@code{<get-var VAR>}}.  Finally, multiple values may be given in a @vref{set-var} command by separating those values with newline characters.  The following sequence of commands illustrates the typical use of array variables.

@example
<set-var array[] =
       "value-zero
        value-one
        value-two
        value-three">
    <set-var i=0>
    <while <get-var array[i]>>
      The value of array[<get-var i>] is `<get-var array[i]>'.<br>
      <increment i>
    </while>
@end example
  produces
@example

          The value of array[0] is `value-zero'.

          The value of array[1] is `value-one'.

          The value of array[2] is `value-two'.

          The value of array[3] is `value-three'.

@end example

@deffn {@i{Simple Tag}} {array-add-unique}  item  arrayvar &key  [caseless=true] 

Add @var{item} as the last array element of the contents
of @var{arrayvar} if, and only if, @var{item} is not already
a member of that array.

The comparison is a direct string-wise compare.  If @var{CASELESS} is
non-empty, then a caseless string compare is done.

See also @vref{array-append}.

@end deffn

@deffn {@i{Simple Tag}} {array-append}  item  arrayvar 

Add @var{item} as the last array element of the contents
of @var{arrayvar}.  This is especially useful in conjunction with
@vref{foreach} as a @i{collector}:

@example
@group
<foreach name allnames>
  <if <satifies-criteria <get-var name>>
     <array-append <get-var name> useful-names>>
</foreach>
@end group
@end example

See also @vref{array-add-unique}.

@end deffn

@deffn {@i{Simple Tag}} {array-concat}  receiver &optional  [contributor...] 

Appends the contents of each @var{contributor} array to the 
end of @var{receiver}.

Both @var{receiver} and each @var{contributor} are variable names whose
values are treated as arrays.

For a single @var{contributor}, @code{array-concat}
could have been defined as:

@example
@group
<defsubst array-concat>
  <foreach item %1>
     <array-append <get-var item> %0>
  </foreach>
</defsubst>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {array-delete-index}  index  arrayvar 

 Delete the element of @var{arrayvar} indicated by @var{index}.
 The remainder of the array after @var{index} is shifted back by one,
 so that the array ends up with one less element than it had before.

@end deffn

@deffn {@i{Simple Tag}} {array-member}  item  arrayvar &key  [caseless=true] 

Look up (and return) the index of @var{item} in the contents of the
array referenced by @var{arrayvar}.

If @var{item} is not found, then @code{array-member} returns the
empty string.

If @var{caseless} is non-empty, then the comparison is done without
regard to character case.  Otherwise, character case is significant in
the location of the item.

@example
<set-var array[] =
  <prog
     this
     another
     multi word
     thing>>
<array-member "multi word" array>
@end example
  produces
@example
2
@end example

@end deffn

@deffn {@i{Simple Tag}} {array-shift}  amount  arrayvar &key  [start] 

Shift the elements of @var{arrayvar} the indicated amount.

If @var{amount} is negative, the elements are shifted down
(i.e. towards zero), with the lowest number elements being lost.

If @var{amount} is positive, the elements are shifted up, with
no loss at all -- instead empty elements are used to fill the
created space.

If the keyword argument @var{start} is present, it indicates the
zero-based offset from which to start shifting.

Given the array:

@example
@group
<set-var array[] =
   <prog
       0
       1
       2>>
@end group
@end example

then after executing   
@b{@code{<array-shift 2 array>}}, 
the array looks like:

@example
@group
   ""
   ""
   "0"
   "1"
   "2"
@end group
@end example

and, a subsequent execution of

@b{@code{<array-shift -3 array>}} leaves @var{array}:

@example
@group
   "1"
   "2"
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {array-size}  arrayvar 

Returns the number of elements in the array referenced by the
variable @var{arrayvar}.

Examples:

@example
<set-var array[]="this">
<array-size array>
@end example
  produces
@example
1
@end example

and,

@example
<array-shift 4 array>
<array-size array>
@end example
  produces
@example
5
@end example

@end deffn

@deffn {@i{Complex Tag}} {foreach}  elementvar  arrayvar &key  [start=x]  [end=x]  [step=x]  [iter=var] 

Perform @var{body} with @var{elementvar} bound to successive memebers
of @var{arrayvar}, starting with the element at @var{start} (default
0), and ending at @var{end} (default   
@b{@code{<array-size
ARRAYVAR>}}), advancing by @var{step} (default 1).

The @code{foreach} command is the basic array looping device in
Meta-HTML.  It is guaranteed to iterate over each element that you
specify, whether that element is the empty string or not.

Starting with the simple array:

@example
@group
<set-var array[]="0\n1\n2\n3\n4\n5\n6\n7\n8\n9">
@end group
@end example

we can print out the odd numbers of this array by using values for
both @var{start} and @var{step}:

@example
<foreach x array start=1 step=2> <get-var x>, </foreach>
@end example
  produces
@example
 1,  3,  5,  7,  9, 
@end example

or, we can produce a "countdown" with a negative value for @var{step}:

@example
<foreach x array step=-1> <get-var x>, </foreach> BOOM!
@end example
  produces
@example
 9,  8,  7,  6,  5,  4,  3,  2,  1,  0,  BOOM!
@end example

@end deffn

@deffn {@i{Simple Tag}} {sort}  arrayvar &optional  [sort-fun] &key  [caseless=true]  [sortorder=[ascending|descending]]  [number=true] 

Sort the contents of the array @var{arrayvar}.

The elements are sorted in place -- this function has no return value.

If @var{caseless=true} is given, then the comparison of the elements of the array is done without regards to case.

If @var{sortorder=reverse} is given, then the results are returned in descending order, instead of ascending order.  The default is to order the elements in ascending order.

If @var{numeric=true} is given, then the elements of @var{arrayvar} are treated as numeric entities, whether they are or not.  The default is to treat the elements as character strings, which can have unexpected results when sorting numeric quantities ("11" is less then "2" when sorting alphabetically!)

Finally, you may supply a sorting function, whose name is passed as @var{sort-fun}.  This function will be called on each element just before comparison, and the results of that function will be used for the comparison instead of the element itself.  This allows you to create a collating sort, or to sort on complex weighting features, or anything else that you can conceive of.

Examples:

Given the array:

@example
@group
<set-var array[0] = 1
         array[1] = 2
         array[3] = 3
         array[4] = 4
         array[5] = 20>
@end group
@end example

then,

@example
<sort array>
<foreach x array> <get-var x> </foreach>
@end example
  produces
@example
   1  2  20  3  4 
@end example
while
@example
<sort array numeric=true>
<foreach x array> <get-var x> </foreach>
@end example
  produces
@example
   1  2  3  4  20 
@end example

Sorting strings:
@example
<set-var array[]="a\nb\nc\nd\ne\nf\nA\nB\nC\nD\nE\nF">
<sort array sortorder=descending>
<foreach x array> <get-var x> </foreach>
@end example
  produces
@example
 f  e  d  c  b  a  F  E  D  C  B  A 
@end example

Without regards to case:
@example
<sort array caseless=true>
<foreach x array> <get-var x> </foreach>
@end example
  produces
@example
 a  A  b  B  c  C  d  D  e  E  f  F 
@end example

Finally, here is an example which sorts a list
of words based upon the percentage of vowels
present in each word, using a sort function
which calculates that value for each string:

@example
<defun vowel-percentage string>
  <set-var x =
    <subst-in-string <downcase <get-var string>> "([^aeiou])" "">>
  <percent <string-length <get-var x>>
           <string-length <get-var string>>>
</defun>

<set-var words[]=
  <prog
    Brian
    Fox
    sorts
    elegant
    strings
    beautifully>>

<sort words vowel-percentage numeric=true sortorder=descending>

<foreach word words>
  <get-var word> (<vowel-percentage <get-var word>>)<br>
</foreach>
@end example
  produces
@example

  beautifully (45.45)
  elegant (42.86)
  Brian (40.00)
  Fox (33.33)
  sorts (20.00)
  strings (14.29)
@end example

@end deffn


@node Packages
@section Packages
@i{Packages} are repositories which contain symbols and their values.

Each time a symbol is referenced, a package must first be found, and
then the symbol may be found within that package. You indicate which
package to look the symbol up in by supplying a package @i{prefix}.
When the prefix is not supplied, the symbol is looked up in the
current package.For example, a full reference to the symbol @var{bar} stored in the
@var{foo} package looks like: 

@example
@group
   FOO::BAR
@end group
@end example

There are very few commands specifically for dealing with packages,
because most of the operations are performed implicitly, rather than
explicitly.  To create a package, simply give the package name as part
of the symbol, in the place where the symbol is normally used.

@example
@group
   <set-var foo::bar = "Hello">
@end group
@end example

This has the effect of creating the package @var{foo} if it didn't
already exist.

The majority of the functions documented here perform package maintenance, as
opposed to variable manipulation.  There are functions for querying a package
about its contens, for deleting an entire package, for exporting and importing
packages to and from sessions, for copying the contents of packages, and for
converting packages from an internal representation to a printable
representation, called an @i{alist}.
@deffn {@i{Simple Tag}} {alist-defvar}  alistvar  name  value 

@b{DEF}ault the value of the @b{VAR}iable named by @var{name}
to @var{value}, in the association list referenced by <alistvar>.

@code{defvar} assigns @var{value} to @var{name} if, and only if,
@var{name} has a non-empty value.

@end deffn

@deffn {@i{Simple Tag}} {alist-get-var}  alistvar &optional  [name...] 

Return the value of the @var{name}s given from the association list
specified by @var{alistvar}.  Each @var{name} is a
variable name which has had a value assigned to it with @vref{alist-set-var}, or was created implicity via
@vref{alist-to-package}.

The values are returned in the order in which the @var{name}s appear.

@end deffn

@deffn {@i{Simple Tag}} {alist-set-var}  alistvar &optional  [name=value...] 

Gives the variable @var{name} the value of @var{value} in the association
list specified by @var{alistvar}. Any number of name/value pairs may be given,
and whitespace is not significant.  Where @var{=value} is omitted, the
value is the empty string.

@example
@group
<alist-set-var myalist foo=bar bar=baz>
<alist-get-var myalist foo>    ==> bar
<alist-get-var myalist bar>    ==> baz
<alist-get-var myalist <alist-get-var myalist foo>>    ==> baz
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {alist-to-package}  alist &optional  [package] 

Takes the textual list representation of a package, and creates (or
modifies) the package named by @var{package-name}.

@code{alist-to-package} is the inverse of the @vref{package-to-alist} function -- given an "alist" (short for
`association list') you can create a package, and vice-versa.  The
following expression is one way to copy all of the variables from the
package @code{FOO} into the package @code{BAR}:

@example
@group
<alist-to-package <package-to-alist foo> bar>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {alist-unset-var}  alistvar &rest names...

Make @var{name}s be non-existent in the association list specified
by @var{alistvar}.

@end deffn

@deffn {@i{Simple Tag}} {alist-var-exists}  alistvar  name 

@code{var-exists} checks for the @i{existence} of
the variable named by @var{varname}, in the association list specified by
@var{alistvar}, and returns @code{true} if that variable does in
fact exist.

The existence of a variable has nothing to do with its value -- a
variable exists if it is present within the list, whether or not it
has a value.

@end deffn

@deffn {@i{Simple Tag}} {copy-package}  src  dest 

 Copy the contents of the package @var{src} to the package @var{dest}.

@end deffn

@deffn {@i{Complex Tag}} {in-package}  package-name 

Evaluate @var{body} in an environment where variables which are not
specifically prefixed with a package name are looked up and stored
within @var{package-name}.

The special package name @code{"local"} creates an anonymous
package within which to work.  The contents of local packages are only
accessible within the expressions surrounded by the
@code{in-package} operator.

@end deffn

@deffn {@i{Simple Tag}} {make-alist} &rest args

 Return an alist from the name=value pairs passed.
 @example
 <make-alist foo=bar baz=this>

@end example
  produces
@example
 (("BAZ" . "this")("FOO" . "bar"))

@end example

@end deffn

@deffn {@i{Simple Tag}} {make-innocuous} &rest packages[]

 Causes each variable in the specified @var{packages} to have
 non-interpretable text.
 This is done by substituting HTML constructs for angle braces,
 among other things.

@end deffn

@deffn {@i{Simple Tag}} {package-delete}  package-name... 

Remove the definition of the packages named by @var{package-name}s,
and all of the variables defined within them.

@end deffn

@deffn {@i{Simple Tag}} {package-names} 

Returns a newline separated list of the all of the named packages
which are currently defined.  Because the list is newline separated,
the result can easily be assigned to an array variable:

@example
@group
<set-var all-packages[]=<package-names>>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {package-to-alist} &optional  [package] 

Returns a Lisp readable string containing the names and values of the variables in @var{package}.  If @var{strip=true} is supplied, the package name is removed from the variables before placing them in the list.  See the following code sequence:

@example
<set-var
  foo::bar=baz
  foo::array[0]=Elt-0
  foo::array[1]=Elt-1>

  The contents of Foo: <package-to-alist foo>
The stripped contents: <package-to-alist foo strip=true>
@end example
  produces
@example
  The contents of Foo: (("FOO::BAR" . "baz")("FOO::ARRAY" "Elt-0" "Elt-1"))
The stripped contents: (("BAR" . "baz")("ARRAY" "Elt-0" "Elt-1"))
@end example

@end deffn

@deffn {@i{Simple Tag}} {package-vars} &optional  [package-name] &key  [strip=true] 

Returns a newline separated list of the fully qualified variable
names found in the package named by @var{package-name}, or in the
current package if @var{package-name} is not given.  When @var{strip=true} is supplied, the returned variable names have the package
prefix stripped off, making them @i{not} fully qualified.  The
names are not returned in any significant order.  Because the list is
newline separated, the results can easily be assigned to an array
variable:

@example
<set-var foo::bar=baz>
<set-var foo::baz=bar>
<set-var names[]=<package-vars foo>>
<get-var names[1]>
@end example
  produces
@example
FOO::ARRAY
@end example

@end deffn

@deffn {@i{Complex Tag}} {with-local-package} 

Shorthand for   
@b{@code{<in-package local> <i>body</i>
</in-package>}}

@end deffn


@node Flow Control
@section Flow Control
Meta-HTML contains commands for controlling which of a set
of statements will be executed, and for repetitive execution of a set
of statements.

Such commands constitute what is called @i{flow control}, since
they tell the Meta-HTML interpreter where or what the next statement
to interpret resides.

All of the flow control operators in Meta-HTML take a test and some
additional statements; the closest thing to a @b{goto} statement in
Meta-HTML is the @vref{redirect} command.
@deffn {@i{Simple Tag}} {break} 

Unconditionally and immediately stop the execution of the nearest
surrounding @vref{while} or @vref{foreach}.

Example usage:

@example
@group
<while true>

  <if <file-newer? <get-var foo.c> <get-var foo.o>>
    <break>>

  <process-chunk <get-var chunk-num>>
  <increment chunk-num>
</while>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {concat} &rest args

Concatenate all of the arguments given, creating a single token with no
intervening whitespace. This is quite useful for those situations where
intervening whitespace would look bad in the output, but the input source
would be unreadable without any.

For example:

@example
@group
<concat <textarea name=label rows=10 cols=40>
        <get-var-once label>
        </textarea>>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {group} &rest args

Combine all of the material passed into a single Meta-HTML statement.
This is the primitive for grouping multiple statements where only a
single statement is expected.  Whitespace within the group is preserved,
making this command useful for assigning to array variables.

Some examples:

@example
@group
<set-var array[] =
  <group this is element 0
         this is element 1
         this is element 2>>
@end group
@end example

@example
@group
<if <eq this that>
    <group <h2> This is equal to That </h2>>
   <group <h2> This is NOT equal to That </h2>>>
@end group
@end example

Although @code{group} is a primitive in Meta-HTML, it could
have been defined as:

@example
@group
  <defsubst group>%body</defsubst>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {if}  test &optional  [then]  [else] 

First @var{test} is evaluated. If the result does not contain only
whitespace characters the @var{then} clause is evaluated, otherwise,
the @var{else} clause is evaluated. Although Meta-HTML has the
relational operator @vref{or}, you can
efficiently test for the presence of any of a group of variables
with code similar to the following:

@example
@group
<if <get-var foo bar>
   "Either FOO or BAR is present"
  "Neither FOO nor BAR is present">
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {ifeq}  this  that &optional  [then]  [else] &key  [caseless=true] 

The @var{this} and @var{that} clauses are evaluated.
If the results are text-wise identical, then the @var{then}
clause is evaluated, otherwise, the @var{else} clause is
evaluated.  If @var{caseless=true} is given, the text-wise
comparison of the values is done with no regard to upper and lower
case distinctions.

@end deffn

@deffn {@i{Simple Tag}} {ifneq}  this  that &optional  [then]  [else] &key  [caseless=true] 

The @var{this} and @var{that} clauses are evaluated.
If the results are not text-wise identical, then the @var{then}
clause is evaluated, otherwise, the @var{else} clause is
evaluated.  If @var{caseless=true} is given, the text-wise
comparison of the values is done with no regard to upper and lower
case distinctions.

@end deffn

@defvr {@i{Variable}} {mhtml::iteration-limit}
The use of this variable has been deprecated.  @vref{while}
loops last until either the @var{test-clause} is met, or a
@vref{break} statement is seen.
@end defvr

@deffn {@i{Simple Tag}} {prog} &rest args

Synonym for @vref{group}.

@end deffn

@deffn {@i{Simple Tag}} {return} &rest args

Unconditionally and immediately stop the execution of the current
function, macro, @vref{while} or @vref{foreach} statement, and return the evaluated @var{args}.

Example usage:
@example
<define-function countdown start stop>
  <if <eq start stop>
      <return BlastOff!>>
  <get-var start>, 
  <countdown <sub start 1> <get-var stop>>
</define-function>
<countdown 10 4>
@end example
  produces
@example
10, 9, 8, 7, 6, 5, BlastOff!
@end example

@end deffn

@deffn {@i{Simple Tag}} {var-case} &optional  [name=value]  [consequent...]  [default]  [default-consequent] 

For each @var{name=value} pair, the value of @var{name} is
string-wise compared with @var{value}.  If they are identical, then
the corresponding @var{consequent} code is performed, and its value is
the return value of the   
@b{@code{<var-case>}} form.

If none of the clauses match, and there is a @code{default}
clause, then the @var{default-consequent} is evaluated, and its return
value is the return value of the   
@b{@code{<var-case>}}
form.

@code{var-case} is especially useful as a `traffic
switch' to select one of several actions based on a user button
press.

For example:

@example
@group
<var-case
   action="Save Files"      <save-files <get-var posted::files[]>>
   action="Delete Files"    <delete-files <get-var posted::files[]>>
   action="Rename Files"    <redirect
                                 rename-files.mhtml?<cgi-encode files>>>
@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {when}  test 

Evaluate @var{test}.  If the result is a non-empty string,
then execute the @var{body} statements.  This is a cleaner way to
handle optional multiple statement execution rather than dealing with
quoting everything inside of an @vref{if} form.

@end deffn

@deffn {@i{Complex Tag}} {while}  test 

@var{test} is evaluated.  If the result is a non-empty string, then
the @var{body} statements are evaluated, and the process is repeated.

@end deffn

@deffn {@i{Complex Tag}} {with} &optional  [var=val...] 

Execute @var{body} in an environment where @var{var} has the value
@var{val}.  Execution takes place in the current package.  After
execution, the value of @var{var} is restored to the value that it
had before encountering the @code{with} macro.

@example
<set-var x=hello>
<with x=1 z=<get-var foo>> <get-var x> </with>
<get-var x>
@end example
  produces
@example
 1 
hello
@end example

@end deffn


@node Language Operators
@section Convenience Primitives
Meta-HTML provides various functions and
variables which are used to operate on or within the language
environment itself, rather than within the application environment.

Such constructs make it possible to create self-modifying code, to
change the way in which a builtin function operates, and other such
language dependent features.
@deffn {@i{Simple Tag}} {bootstrapper::system-initialize} 

 Defined in libmhtml/standard.mhtml, this function is called immediately
 @i{after} the tagsets in libmhtml/tagsets have been initialized by the
 system on bootstrap.  You probably don't know what this means, so just
 forget about it.

 Suffice to say, here is the first user-defined function run by Meta-HTML
 for every invocation of the server, engine, debugger, or standalone
 processor (excepting when that program is called with "-z").

 I cannot think of a reason why or how you would modify this function,
 unless you are modifying the behaviour of Meta-HTML in general.  If you
 think that you need to modify this, perhaps you really want something
 like @vref{%%after-page-return}.

@end deffn

@deffn {@i{Complex Tag}} {comment} 

Simply discard the @var{body}.  No processing is done, and no output
is produced.

A shorthand for commenting source on a single line exists; when the
sequence of 3 semicolon character is seen
(@code{;}@code{;;}), then the text from this sequence to 
the end of the line inclusive is discarded.

Example:

@example
@group
<comment>
  This text is simply ignored.

  All of it.
</comment>

;; But NOT this line -- it only has two semi-colons on it.
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {make-identifier}  limit 

Create an identifier that is @var{limit} characters in length.
The identifier characters are taken from the string MI::ALPHABET.
MI::ALPHABET defaults to uppercase letters and numbers excluding
"I", "O", zero, and one.

@end deffn

@defvr {@i{Variable}} {mhtml::inhibit-comment-parsing}
When this variable is set to
a non-empty value, the triple semi-colon comment feature is disabled.

You may need this for complex applications where you are deliberately
shipping the source of a Meta-HTML document to the client.
@end defvr

@defvr {@i{Variable}} {mhtml::version}
Contains the version identification of the
currently running interpreter.  This variable is available whereever
the interpreter is running, including the Meta-HTML server, Engine,
and in @code{mdb}.

@example
<get-var mhtml::version>
@end example
  produces
@example
6.07
@end example
@end defvr

@deffn {@i{Simple Tag}} {parser::change-brackets}  bracket-pair 

Add the matched open and close bracket characters to the special
characters that are understood by the Meta-HTML parser.  For example,
calling this function like this:

@example
@group
<parser::change-brackets "@@{@@}">
@end group
@end example

causes the character "@{" to be in the same syntax class as "<", such
that an expression @{get-var foo@} would return the value of @var{foo}.

This function is only available after loading the @b{parser} module:

@example
@group
<load-module parser> ==> /www/lib/parser.so
@end group
@end example

For more information on loading dynamic modules in Meta-HTML, please see
the documentation for @vref{load-module}.

@end deffn

@deffn {@i{Simple Tag}} {pid} 

Returns the process ID of the currently executing Meta-HTML
interpreter, on those systems which have process IDs.

@end deffn

@deffn {@i{Complex Tag}} {with-safe-environment} 

 Execute @var{body} in an environment where commands that could
 affect the file system are disabled.  In addition, commands
 which can define or undefine functions are disabled.

 This command is especially useful when filtering input from an
 external source, such as a third party Web page.

@end deffn


@node Strings and Numbers
@chapter Strings and Numbers

@node String Operators
@section String Operators
There is a single function in Meta-HTML which performs pattern
matching, substring extraction, and substring deletion.  For
convenience, a blind substring extraction function is supplied as
well.  Three functions perform the three most common case changes.
Finally, the @vref{pad} function allows
alignment of fixed-width text.  
@deffn {@i{Simple Tag}} {base64decode}  string &optional  [varname] 

Performs the translation operation commonly known as @i{Base64
Decoding} on @var{STRING}, and returns the results of that
decoding.

If the optional @var{varname} is supplied, the results of decoding are
placed into the binary variable named @var{varname} instead of being
returned in the page.  This allows random binary data to be decoded,
and perhaps written to the output stream using @vref{stream-put-contents}.

Base64 encoding is a common transfer encoding for binary data and for
Basic Authorization values -- this function can be used to turn such
strings into their original, pre-encoded state.

@example
<set-var the-data = "YmZveDpmcm9ibml0eg==">
<base64decode <get-var the-data>>
@end example
  produces
@example
bfox:frobnitz
@end example

@end deffn

@deffn {@i{Simple Tag}} {base64encode}  varname &key  [shortlines=[true|value]] 

Performs the translation operation commonly known as @i{Base64
Encoding} on the contents of the binary variable referenced by @var{varname}, and returns the results of that encoding.

Base64 encoding is a common transfer encoding for binary data and for
Basic Authorization values -- this function can be used to turn data
from its original pre-encoded state to an encoded one.

If the keyword argument @var{shortlines=value} is supplied, then the result
of encoding is broken up into lines containing @var{value} characters
each, rounded up to the nearest multiple of 4.  This format is
commonly implemented by many base 64 encoding programs.  A value of
@code{true} uses the Meta-HTML default value of 64.  If the
argument is not supplied, the data is returned in a single line of data.

The following code reads a GIF image into a binary variable, and then
displays the base64 encoded version:

@example
@group
<with-open-stream s /tmp/image.gif mode=read>
  <stream-get-contents s gif>
</with-open-stream>
<base64encode gif>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {capitalize}  string 

Changes the case of each character in @var{string} to uppercase or
lowercase depending on the surrounding characters.

@example
<capitalize "This is a list">
@end example
  produces
@example
This Is A List
@end example

Also see @vref{downcase}, and
@vref{upcase}.

@end deffn

@deffn {@i{Simple Tag}} {char-offsets}  string  ch &key  [caseless] 

Return an array of numbers,  each one representing the offset from the
start of @var{string} of @var{ch}.  This function is useful for finding
candidate locations for word-wrapping, for example.
Here is a complete example:
@example
<char-offsets "This is a list" " ">
@end example
  produces
@example
4
7
9
@end example

@end deffn

@deffn {@i{Simple Tag}} {downcase}  string 

Converts all of the uppercase characters in @var{string} to
lowercase.

@example
<downcase "This is Written in Meta-HTML">
@end example
  produces
@example
this is written in meta-html
@end example

@end deffn

@deffn {@i{Simple Tag}} {encrypted-password}  pass  salt 

 Provided for backwards compatability only.  See
 @vref{unix::crypt}.

@end deffn

@deffn {@i{Simple Tag}} {match}  string  regex &key  [action=[delete]  [|]  [extract]  [|]  [report]  [|]  [startpos]  [|]  [endpos]  [|]  [length]] 

Matches @var{regexp} against @var{string}, and then performs the
indicated @var{action}.  The default for @var{action} is "report".

When action is "report" (the default), returns "true" if @var{regex} matched.

When action is "extract", returns the substring of @var{string}
matching @var{regex}.

When action is "delete", returns @var{string} with the matched
substring removed.

When action is "startpos", returns the numeric offset of the start of
the matched substring.

When action is "endpos", returns the numeric offset of the end of the
matched substring.

@var{regexp} is an extended Unix regular expression, the complete syntax of
which is beyone the scope of this document.  However, the essential
basics are:

@itemize @bullet
@item  A period (@code{.}) matches any one character.
@item  An asterisk (@code{*}) matches any number of occurrences of
the preceding expression, including none.
@item  A plus-sign matches one or more occurrences of the preceding expression.
@item  Square brackets are used to enclose lists of characters which may
match.  For example, "[a-zA-Z]+" matches one or more occurrences of
alphabetic characters.
@item  The vertical bar is used to separate alternate expressions to
match against.  For example, "foo|bar" says to match either "foo"
@i{or} "bar".
@item  A dollar-sign (@code{$}) matches the end of @var{STRING}.
@item  Parenthesis are used to group subexpressions.

@end itemize

Here are a few examples:

@example
@group
  <match "foobar" ".*">                 ==> "true"
  <match "foobar" "foo">                ==> "true"
  <match "foobar" "foo" action=extract> ==> "foo"
  <match "foobar" "oob" action=delete>  ==> "far"
  <match "foobar" "oob" action=startpos>==> "1"
  <match "foobar" "oob" action=endpos>  ==> "4"
  <match "foobar" "oob" action=length>  ==> "3"
  <match "foobar" "[0-9]+">             ==> ""
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {pad}  string  width &key  [align=[left|right|middle]]  [truncate=true]  [pad-char=x] 

Pads @var{string} to a length of @var{total-size}.  @var{align} can
be one of @code{LEFT}, @code{MIDDLE}, or
@code{RIGHT} (the default).

@code{PAD} inserts the correct number of @var{pad-char}acters to
make the input argument take the desired number of spaces (presumably
for use in a   
@b{@code{<pre> ... </pre>}} statement).  The
default value for @var{pad-char} is a space character.

If keyword argument @var{truncate=true} is given, it  says to force
the string to be the specified length.

Before any padding is done, leading and trailing whitespace is removed
from @var{string}.

Examples:

@example
@group
  <pad "Hello" 10>              ==> "     Hello"
  <pad "Hello" 10 align=left>   ==> "Hello     "
  <pad "Hello" 10 align=middle> ==> "  Hello   "
  <pad "  Heckle  " 4 truncate> ==> "Heck"
@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {plain-text} &key  [first-char=expr]  [nobr=true] 

Performs the following steps:

@enumerate
  @item  Replace occurrences of pairs of newline characters with a
  single   
@b{@code{<P>}} tag.

  @item  Applies the function @var{expr} to the first character of every
  paragraph, and inserts the closing tag after that character.

@end enumerate

The output will start with a   
@b{@code{<P>}} tag, unless the
optional argument @var{nobr=true} is given.

@example
<plain-text first-char=<font size="+1"> nobr=true>
This is line 1.

This is line 2.
</plain-text>
@end example
  produces
@example
This is line 1.

This is line 2.
@end example

@end deffn

@deffn {@i{Simple Tag}} {string-compare}  string1  string2 &key  [caseless] 

Compare the two strings @var{string1} and @var{string2}, and return
a string which specifies the relationship between them.  The
comparison is normall case-sensitive, unless the keyword argument @var{caseless=true} is given.

The possible return values are:

@enumerate
@item  equal

The two strings are exactly alike.
@item  greater

@var{string1} is lexically greater than @var{string2}.
@item  less

@var{string1} is lexically less than @var{string2}.

@end enumerate

Examples:

@example
@group
<string-compare "aaa" "aab">               ==> less
<string-compare "zzz" "aab">               ==> greater
<string-compare "zzz" "ZZZ">               ==> greater
<string-compare "zzz" "ZZZ" caseless=true> ==> equal
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {string-eq}  string-1  string-2 &key  [caseless=true] 

Compare @var{string1} to @var{string2} and return the string
@code{"true"} if they are character-wise identical.

The optional keyword argument @var{caseless=true} indicates that no
consideration should be given to the case of the characters during
comparison.

@example
@group
<string-eq "foo" "FOO">               ==>
<string-eq "foo" "foo">               ==>true
<string-eq <upcase "foo"> "FOO">      ==>true
<string-eq "foo" "FOO" caseless=true> ==>true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {string-length}  string 

Returns the number of characters present in @var{string}.

@example
<string-length "This is an interesting string">
@end example
  produces
@example
29
@end example

@end deffn

@deffn {@i{Simple Tag}} {string-neq}  string-1  string-2 &key  [caseless=true] 

Compare @var{string1} to @var{string2} and return the string
@code{"true"} if they are NOT character-wise identical.

The optional keyword argument @var{caseless=true} indicates that no
consideration should be given to the case of the characters during
comparison.

@example
@group
<string-neq "foo" "FOO">               ==>true
<string-neq "foo" "foo">               ==>
<string-neq <upcase "foo"> "FOO">      ==>
<string-neq "foo" "FOO" caseless=true> ==>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {string-to-array}  string  arrayvar 

 Create an array in @var{arrayvar} which is made of of the individual
 characters of @var{string}.  Given the following:

@example
@group
 <set-var s="This is a string.">
 <string-to-array <get-var-once s> chars>

@end group
@end example

 Then,   
@b{@code{<get-var chars[3]>}} returns @code{s}.

@end deffn

@deffn {@i{Simple Tag}} {strings::both-trim}  varname 

 Trims whitespace from both the "left" and "right" -hand sides
 of the string stored in @var{varname}, replacing the contents of
 that variable with the trimmed string.
 @example
 <set-var foo="    string with whitespace on left and right     ">
 String: [<get-var-once foo>]
 <strings::both-trim foo>
 String: [<get-var-once foo>]

@end example
  produces
@example

 String: [    string with whitespace on left and right     ]

 String: [string with whitespace on left and right]

@end example

@end deffn

@deffn {@i{Simple Tag}} {strings::left-trim}  varname 

 Trims whitespace from the "left-hand" side of the string stored
 in @var{varname}, replacing the contents of that variable with
 the trimmed string.
 @example
 <set-var foo="    string with whitespace on the left">
 String: [<get-var-once foo>]
 <strings::left-trim foo>
 String: [<get-var-once foo>]

@end example
  produces
@example

 String: [    string with whitespace on the left]

 String: [string with whitespace on the left]

@end example

@end deffn

@deffn {@i{Simple Tag}} {strings::right-trim}  varname 

 Trims whitespace from the "right-hand" side of the string stored
 in @var{varname}, replacing the contents of that variable with
 the trimmed string.
 @example
 <set-var foo="string with whitespace on the right     ">
 String: [<get-var-once foo>]
 <strings::right-trim foo>
 String: [<get-var-once foo>]

@end example
  produces
@example

 String: [string with whitespace on the right     ]

 String: [string with whitespace on the right]

@end example

@end deffn

@deffn {@i{Simple Tag}} {strings::trim}  varname 

 Trims whitespace from both the "left" and "right" -hand sides
 of the string stored in @var{varname}, replacing the contents of
 that variable with the trimmed string.
 @example
 <set-var foo="    string with whitespace on left and right     ">
 String: [<get-var-once foo>]
 <strings::both-trim foo>
 String: [<get-var-once foo>]

@end example
  produces
@example

 String: [    string with whitespace on left and right     ]

 String: [string with whitespace on left and right]

@end example

@end deffn

@deffn {@i{Simple Tag}} {subst-in-string}  string &rest regexp replacement

Replaces all occurrences of @var{regexp} with @var{replacement} in
@var{string}.

@var{regexp} can be any regular expression allowed by POSIX extended
regular expression matching.

In the replacement string, a backslash followed by a number @var{n} is
replaced with the contents of the @var{n}th subexpression from @var{regexp}.

@example
@group
<set-var foo="This is a list">
<subst-in-string <get-var foo> "is" "HELLO">
     ==> "ThHELLO HELLO a lHELLOt"

<subst-in-string "abc" "([a-z])" "\\1 "> ==> "a b c "
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {subst-in-var}  varname &optional  [this-string]  [with-that] 

Replaces all occurrences of @var{this-string} with @var{with-that} in the
contents of the variable named @var{varname}.  Both @var{this-string} and
@var{with-that} are evaluated before the replacement is done. @var{this-string} can be any regular expression allowed by the POSIX extended
regular expression matching.  This command can be useful when parsing
the output of @vref{cgi-exec}.

@end deffn

@deffn {@i{Simple Tag}} {substring}  string &key  [start]  [end] 

Extracts the substring of @var{string} whose first character starts
at offset @var{start}, and whose last character ends at offset
@var{end}. The indexing is zero-based, so that:

@example
@group
  <substring "Hello" 1 2> ==> "e"
@end group
@end example

This function is useful when you know in advance which part of the
string you would like to extract, and do not need the pattern matching
facilities of @vref{match}.

If you wish to index through each character of a string, the most direct
way is to convert it to an array first using
@vref{string-to-array}, and then use the
@vref{foreach} function to iterate over the members.
@example
<set-var s="This is a string.">
<string-to-array <get-var-once s> chars>
<foreach character chars><get-var character>-</foreach>
@end example
  produces
@example
T-h-i-s- -i-s- -a- -s-t-r-i-n-g-.-
@end example

@end deffn

@deffn {@i{Simple Tag}} {unix::crypt}  string &optional  [salt] 

Return @var{string} encrypted using the local system's @code{crypt()}
function with the salt @var{salt}.

@var{salt} is a two character string -- if you wish to compare the
cleartext value that a user has entered against a Unix-style encrypted
password, such as one from @code{/etc/passwd}, or from a
@code{.htaccess} file, use the first two characters of the
existing encrypted password as the salt, and then compare the
resulting strings.

For example, if the variable @var{existing-pass} contains a previously
encypted password, and the variable @var{entered-pass} contains the
cleartext that the user has just entered, you may encrypt the user's
password and compare it with the existing one with the following code:

@example
@group
<set-var encrypted-pass =
   <unix::crypt <get-var entered-pass>
                <substring <get-var existing-pass> 0 2>>>

<when <string-eq <get-var encrypted-pass>
                 <get-var existing-pass>>>
   <set-session-var logged-in=true>
   <redirect members-only.mhtml>
</when>

<h3>Please enter your password again.  It didn't match.</h3>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {upcase}  string 

Converts all of the lowercase characters in @var{string} to
uppercase.

@example
<upcase "This is Written in Meta-HTML">
@end example
  produces
@example
THIS IS WRITTEN IN META-HTML
@end example

@end deffn

@deffn {@i{Simple Tag}} {word-wrap}  string &key  [width=charwidth]  [indent=indentation]  [skip-first=true] 

Produce paragraphs of text from the string @var{string} with the text
filled to a width of @var{charwidth}.

This is provided for convenience only, and is of use when you need to
present some free form text in pre-formatted fashion, such as when
sending an E-mail message, or the like.

If the keyword @var{indent=indentation} is supplied, it says to indent
each line in the output by @var{indentation}, using space characters.

If the keyword @var{skip-first=true} is given, it says not to indent
the first line of the output -- just each successive line.  For
example:
@example
<set-var text =
   <concat "This is provided for convenience only, and is of use "
           "when you need to present some free form text in "
           "pre-formatted fashion, as in this example.">>
<pre>
Title Topic: <word-wrap <get-var text> 40 indent=13 skip-first=true>
</pre>
@end example
  produces
@example
@example
Title Topic: This is provided for convenience only, and is of use when
             you need to present some free form text in pre-formatted
             fashion, as in this example. 
@end example
@end example

@end deffn


@node Arithmetic Operators
@section Arithmetic Operators
Meta-HTML contains a small set of commands for operating on
numerical quantities.

All of the arithmetic operators described in this section can accept a
number, or simply the name of a variable, which is then looked up as
if it had been written with   
@b{@code{<get-var ...>}}.

That is to say:

@example
@group
   <set-var total = <add <get-var subtotals[0]>
                         <get-var subtotals[current]>>>
@end group
@end example

can be written as:

@example
@group
   <set-var total = <add subtotals[0] subtotals[current]>>
@end group
@end example

The binary arithmetic operators always expect two arguments, and will
produce a warning message in @vref{DEBUGGING-OUTPUT}
when given too few arguments.

You can perform floating point arithmetic if one or both of the
arguments is already a floating point number:

@example
@group
  <div 10 3>    ==> 3
  <div 10.0 3>  ==> 3.33
@end group
@end example

@deffn {@i{Simple Tag}} {acos}  x 

Return the arc cosine of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {acosh}  x 

Return the inverse hyperbolic cosine of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {add}  arg1  arg2 &rest more-args

Returns the summation of all of the arguments passed.

Examples:

@example
@group
<add 1 2>        ==> 3
<add -1 2 2 1>   ==> 4
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {asin}  x 

Return the arc sin of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {asinh}  x 

Return the inverse hyperbolic sine of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {atan}  x &optional  [y] 

Return the arc tangent of @var{x}.
If @var{y} is supplied, then this returns the arg tangent of @var{y/x},
using the signs of both arguments to determine the quadrant of the result.

@end deffn

@deffn {@i{Simple Tag}} {atanh}  x 

Return the inverse hyperbolic tangent of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {avg} &rest nums[]

 Returns the average of all of the arguments passed.
 Examples:

@example
@group
 <avg 3 4 5>    ==> 4
 <avg 4 9 3.2>  ==> 5.40

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cbrt}  x 

Return the cube root of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {ceiling}  x 

Round @var{x} upwards to the nearest integer.

@end deffn

@deffn {@i{Simple Tag}} {comma-separated-digits}  num 

 Produce NUM in standard human readable format, inserting commas
 where appropriate.

 Example:
 @example
 <comma-separated-digits 98342367.09>

@end example
  produces
@example
 98,342,367.09

@end example

@end deffn

@deffn {@i{Simple Tag}} {cos}  x 

Return the cosine of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {cosh}  x 

Return the hyperbolic cosine of @var{x},
i.e., (exp (@var{x}) + exp (@var{-x})) / 2.

@end deffn

@deffn {@i{Simple Tag}} {div}  arg1  arg2 &rest more-args

Returns the quotient of all of the arguments passed.

Examples:

@example
@group
<div 100 5>      ==> 20
<div 5 100>      ==> 0
<div 5.0 100.0>  ==> 0.05
<div 100 5 2>    ==> 10
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {eq}  arg1  arg2 

Returns "true" if the numeric value of @var{arg1} is exactly equal to
the numeric value of @var{arg2}.  Just as with the arithmetic
functions (@mref{Arithmetic Operators}), the arguments
may be the names of variables containing numeric values, and not just
the values themselves.  In that case, @code{eq} performs an
implicit call to   
@b{@code{<get-var ...>}} in order to get
the value to operate on.

Examples:

@example
@group
<eq 3 4>              ==> 
<eq 3 3>              ==> true
<eq 3.0 3>            ==> true
<set-var x=3.01>
<eq <get-var x> 3.01> ==> true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {exp}  x 

Return the value of @i{e} (the base of natural logarithms), raised 
to the power of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {factorial}  x 

 Computes the factorial of @var{x}.
 Example:
 @example
 <factorial 12>

@end example
  produces
@example
 0.00

@end example

@end deffn

@deffn {@i{Simple Tag}} {float} 

 Returns the floating point representation of @var{x}.
 @var{x} may be an integer, a floating point number, or a variable
 containing an integer or floating point number.
 @example
 <set-var foo=7>
 <float foo>
 <float 3>
 <float 3.0>

@end example
  produces
@example

 7.00
 3.00
 3.00

@end example

@end deffn

@deffn {@i{Simple Tag}} {floor}  x 

Round @var{x} downwards to the nearest integer.

@end deffn

@deffn {@i{Simple Tag}} {gt}  arg1  arg2 &rest more-args...

Returns "true" if the numeric value of @var{arg1} is greater than
the numeric value of @var{arg2} (which is greater than @var{more-args}.  Just as with the arithmetic functions (@mref{Arithmetic Operators}), the arguments may be the names of
variables containing numeric values, and not just the values
themselves.  In that case, @code{gt} performs an implicit call
to   
@b{@code{<get-var ...>}} in order to get the value to
operate on.

Examples:

@example
@group
<gt 4 3>            ==> true
<set-var x=3.4 y=3.5>
<gt x y>            ==>
<gt y x>            ==> true
<gt <get-var y> x>  ==> true

<defun between? item high low>
  <gt high item low>
</defun>

<between? 7 8 6>    ==> true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {integer?}  string &key  [base[=10]] 

Returns "true" if @var{string} is the string representation of an integer
value in base @var{base} (default @code{10}).  This function is useful
for checking the validity of user input to a form.

You call this function with the actual value -- you may not pass the name
of a variable instead.

Some examples:

@example
@group
<set-var x=123>
<integer? -90>          ==> true
<integer? <get-var x>>  ==> true
<integer? 2.3>          ==>
<integer? FEFE base=16> ==> true
<integer? 874 base=8>   ==>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {log}  x 

Return the natural logarithm of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {log10}  x 

Return the base-10 logarithm of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {logb}  x 

Return the base-2 logarithm of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {lt}  arg1  arg2 &rest more-args

Returns "true" if the numeric value of @var{arg1} is less than
the numeric value of @var{arg2} (which is less than @var{more-args}.
Just as with the arithmetic functions (@mref{Arithmetic Operators}),
@var{arg1} and @var{arg2} may be the names of variables containing
numeric values, and not just the values themselves.  In that case,
@code{lt} performs an implicit call to   
@b{@code{<get-var ...>}} in order to get the value to operate on.

Examples:

@example
@group
<lt 3 4>            ==> true
<lt 4 3>            ==> 
<set-var x=3.4 y=3.5>
<lt x y>            ==> true
<lt y x>            ==> 
<lt x <get-var y>>  ==> true
<lt 4 5 6>          ==> true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {max}  arg1  arg2 &rest more-args

Returns the largets of all of the arguments passed.

Examples:

@example
@group
<max 2 2>        ==> 2
<max 2.3 8 7>    ==> 8.00
<max 4 10 -4>    ==> 10
@end group
@end example

@end deffn

@defvr {@i{Variable}} {mhtml::decimal-places}
Controls the number of decimal places which arithmetic functions
produce.  The default value of this variable is @code{2}, but
for times when you need greater resolution in your calculations, you
may wish to set it higher.
@example
<set-var mhtml::decimal-places = 10>
To 10 places: <div 1 .34567>
<unset-var mhtml::decimal-places>
To  2 places: <div 1 .34567>
@end example
  produces
@example
To 10 places: 2.8929325657

To  2 places: 2.89
@end example
@end defvr

@deffn {@i{Simple Tag}} {min}  arg1  arg2 &rest more-args

Returns the smallest of all of the arguments passed.

Examples:

@example
@group
<min 2 2>        ==> 2
<min 2.3 8 3>    ==> 2.30
<min 3 -4 10>    ==> -4
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {mod}  arg1  arg2 &rest more-args

Returns the remainder of all of the arguments passed.

Examples:

@example
@group
<mod 100 10>    ==> 0
<mod 101 10>    ==> 1
<mod 89 9 3>    ==> 2
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {mul}  arg1  arg2 &rest more-args

Returns the product of all of the arguments passed.

Examples:

@example
@group
<mul 2 2>        ==> 4
<mul 2.3 8 3>    ==> 55.20
<mul -4 10>      ==> -40
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {neq}  arg1  arg2 

Returns "true" if the numeric value of @var{arg1} is NOT equal to
the numeric value of @var{arg2}.  Just as with the arithmetic
functions (@mref{Arithmetic Operators}), the arguments
may be the names of variables containing numeric values, and not just
the values themselves.  In that case, @code{eq} performs an
implicit call to   
@b{@code{<get-var ...>}} in order to get
the value to operate on.

Examples:

@example
@group
<neq 3 4>              ==> true
<neq 3 3>              ==> 
<neq 3.0 3>            ==> 
<set-var x=3.01>
<neq <get-var x> 3.00> ==> true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {number?}  arg &key  [base] 

 Returns "true" if @var{arg} is the string representation of an integer
 in base @var{base} (default @code{10}), or the string
 representation of a floating point number in base 10.

 For integer checks, the special value of zero (@code{0}) for
 @var{base} allows the common radixes of decimal, octal, and hexadecimal
 to be understood.  That is to say:

@example
@group
 <number? <get-var x> base=0>

@end group
@end example

 is equivalent to:

@example
@group
 <or <integer? <get-var x> base=8>
     <integer? <get-var x> base=10>
     <integer? <get-var x> base=16>
     <real?    <get-var x>>>

@end group
@end example

 Some examples:

@example
@group
 <number? 10>          ==> true
 <number? .9>          ==> true
 <number 0xEF base=16> ==> true

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {pi} 

Returns PI to 20 decimal places.

@end deffn

@deffn {@i{Simple Tag}} {raise}  x  y 

Returns @var{x} raised to the @var{y} power.

@end deffn

@deffn {@i{Simple Tag}} {random}  arg 

Returns a pseudo-random number between 0 and @var{arg} -1.  The
distribution is pretty good; calling   
@b{@code{<random
2>}} returns 0 50% of the time, and 1 the other 50%.

Examples:

@example
@group
  <random 100> ==> 87
  <random 100> ==> 44

  <b>I'm thinking of a number between 1 and 10:</b>
  <set-var guess = <add 1 <random 10>>>
@end group
@end example

Also see @vref{randomize}.

@end deffn

@deffn {@i{Simple Tag}} {randomize} &optional  [seed] 

Sets the pseudo-random number generator seed to @var{seed}.  The next
call to @vref{random} uses this seed value to
find the next pseudo-random number.  There is no return value.

Examples:

@example
@group
  <randomize 10>
  <random 100> ==> 28
  <random 100> ==> 15
  <randomize 10>
  <random 100> ==> 28
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {real?}  string 

Returns "true" if @var{string} is the string representation of
a real number.Useful for checking the validity of user input to a form.

You call this function with the actual value -- you may not pass the name
of a variable instead.

Some examples:

@example
@group
<set-var pi=3.141569>
<real? <get-var pi>>    ==> true
<real? 45>              ==> 
<real? 2.3>             ==> true
<real? "This">          ==>
<real? -.087e4>         ==> true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {round}  x 

Round @var{x} to the nearest integer.

@end deffn

@deffn {@i{Simple Tag}} {set-output-radix}  new-radix 

Set the output radix for numbers produced by arithmetic operations to
@var{new-radix}, which is specified in decimal.  Returns the value of
the previous output radix.  Note that there is no corresponding function
for setting the input radix.  If the value of @var{new-radix} is a number
between  2 and 32 decimal, inclusive, then the output radix is set to that
value.  @var{new-radix} can also be the name of a function of one argument,
which should be called to produce the appropriate output.

If the argument to @b{<set-output-radix>} does not fall between 2 and 32
inclusive, and is not the name of a defined function, then the output radix
remains unchanged, and @b{<set-output-radix>} produces no output.

Examples:

@example
@group
<set-output-radix 16>                ==> 10
<add 0x3e 1>                         ==> 0x3f
<set-output-radix 10>                ==> 16
<set-output-radix number-to-english> ==> 10
<add 23.4 32.32>                     ==> Fifty-Five point Seven Two
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {sin}  x 

Return the sin of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {sinh}  x 

Return the hyperbolic sine of @var{x},
i.e. (exp(@var{x}) - exp(@var{-x}) / 2.

@end deffn

@deffn {@i{Simple Tag}} {sqrt}  x 

Return the sqaure root of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {sub}  arg1  arg2 &rest more-args

Returns the difference of all of the arguments passed.

Examples:

@example
@group
<sub 2 1>        ==> 1
<sub 6 2 1>      ==> 3
<sub -1 -2>      ==> 1
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {tan}  x 

Return the tangent of @var{x}.

@end deffn

@deffn {@i{Simple Tag}} {tanh}  x 

Return the hyperbolic tangent of @var{x},
i.e. sinh(@var{x}) / cosh(@var{x}).

@end deffn


@node Relational Operators
@section Relational Operators
@i{Relational operators} in Meta-HTML return information about the
relationship between two items.  There are three logical operators,
@vref{and}, @vref{or},  and @vref{not}.

There are several other operators which compare numeric values; the
section @mref{Arithmetic Operators} cover those in detail.
@deffn {@i{Simple Tag}} {and} &rest expr...

@code{and} evaluates each @var{expr} given until one of them
evaluates to the empty string, or until they are all exhausted.  The
result is the result of the last evaluation.  Evaluating just   
@b{@code{<and>}} returns @code{"true"}.

Examples:

@example
@group
<and>                    ==> true
<and this that>          ==> that
<unset-var foo>
<and <get-var foo> this> ==>
<and this <get-var foo>> ==>
<set-var foo=bar>
<and this long list <get-var foo>> ==> bar
@end group
@end example

@b{<and>} could have been defined in Meta-HTML as follows:

@example
@group
<define-tag and &unevalled &rest expressions[] whitespace=delete>
  <set-var result=true>
  <foreach :expr expressions>
    <set-var result = <get-var :expr>>
    <if <not <get-var-once result>>
      <return>>
  </foreach>
  <get-var-once result>
</define-tag>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {not} &optional  [body] 

@var{body} is evaluated.  If the result is the empty string, then the
string "true" is returned, otherwise nothing is returned.  @var{body}
is simply the entire contents of the simple tag, with the word "not"
in it.  Thus, in typical usage one might write:

@example
@group
<when <not <get-var foo>>>
  Hey!  You didn't set the variable FOO.
</when>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {or} &rest expr...

@code{or} evaluates each @var{expr} given until one of them
evaluates to a non-empty string, or until they are all exhausted.  The
result is the result of the last evaluation.  Evaluating just   
@b{@code{<or>}} returns the empty string.

Examples:

@example
@group
<or>                    ==> 
<or this that>          ==> this
<unset-var foo>
<or <get-var foo> this> ==> this
<or this <get-var foo>> ==> this
<set-var foo=bar>
<or <get-var foo> this> ==> bar
@end group
@end example

@b{<or>} could have been defined in Meta-HTML as follows:

@example
@group
<define-tag or &unevalled &rest expressions[] whitespace=delete>
  <foreach :expr expressions>
    <set-var result = <get-var :expr>>
    <if <get-var-once result>
        <break>>
  </foreach>
  <get-var-once result>
</define-tag>
@end group
@end example

@end deffn


@node Input and Output
@chapter Input and Output

@node File Operators
@section File Operators
There are several types of commands in Meta-HTML for dealing with files.

Some of these commands operate directly on an open files, while others
operate on @i{streams} (see @mref{Stream Operators}), which may be
connected to files or network data.

The functions allow you to @vref{include} the
contents of, open (@vref{with-open-stream}), create,
read, or write various data sources, or to replace the contents of a page
(@vref{replace-page}) with another file.Commands such as @vref{get-file-properties} may
return additional information on some systems; this is documented with
each function where that is the case.
@deffn {@i{Simple Tag}} {cgi-exec}  pathname &optional  [arg...] &key  [output=varname]  [errors=varname]  [timeout=seconds]  [nowait=true] 

Execute the system function named by @var{pathname}, perhaps passing
it arguments @var{arg ... argn}.

If @var{output=varname} is supplied, then the variable referenced by
@var{varname} receives the output of the command.  Otherwise, the
resultant output is placed in the page.

If @var{errors=varname} is supplied, then @var{varname} receives the
error output of the command. Otherwise, the resultant output is placed
in @vref{SYSTEM-ERROR-OUTPUT}.

@end deffn

@deffn {@i{Simple Tag}} {dir::basename}  pathname 

 Return the "basename" of @var{pathname}.  This simply returns the last
 component of @var{pathname}.

 Example:
 @example
 <dir::basename /foo/bar/baz.dtd>

@end example
  produces
@example
 baz.dtd

@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::canonicalize-pathname}  path 

 Make @var{path} be absolute in the file system.

 If @var{path} starts with a "/", then do nothing, otherwise, prefix
 it with @code{mhtml::include-prefix} and
 @code{mhtml::relative-prefix}.

 Given an empty @var{path}, return the full path to the directory that
 this page resides in.

 Example:
 @example
 <dir::canonicalize-pathname foo.mhtml>

@end example
  produces
@example
 ./foo.mhtml

@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::dir-table} &optional  [webpath]  [regexp] &key  [show-icons=true]  [icon-dir=pathname]  [sort=sort-op]  [link=URL] 

Synopsis:

@example
@group
  <set-var loaded? = <load-module directory>>
  <dir::dir-table>
@end group
@end example

Produces a clickable listing of the files in @var{webpath} limited to
those which match @var{regexp}, displaying icons found in @var{icon-dir}.

@var{webpath} defaults to the directory containing this page.

@var{regexp}  defaults to @code{"(^[^.].*[^~]$)|(^\.\.$)|(^\.$)"},
i.e., files which do not begin with a dot, and files which do not end with
a tilde, and the two special directories, @code{`.'} and @code{`..'}.

@var{icon-dir} defaults to /images/icons -- each file is associated with an
icon file named by file extension (e.g, mhtml.gif, html.gif, etc.)
Icons are only shown if @var{show-icons} is set.

Possible values for @var{sort-op} are:

@itemize @bullet
@item  @code{size}: Order by size of file,
@item  @code{name}: Order alphabetically by name,
@item  @code{type}: Order by directory .vs. file, and filename extension,
@item  @code{created}: Order by creation date,
@item  @code{accessed}: Order by last access time, and
@item  @code{modified}: Order by last modification time.

@end itemize

@var{sort-op} defaults to @code{name}.

Note that this function is only available from the @b{directory}
module -- it is not a builtin part of Meta-HTML.

@example
@group
<set-var library-loaded? = <load-module directory>>
<when <get-var library-loaded?>>
   <dir::dir-table>
</when>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::dirname}  pathname 

 Return the directory part of @var{pathname}.  This simply
 returns everything but the last component of @var{pathname}.

 Example:
 @example
 <dir::dirname /foo/bar/baz.dtd>

@end example
  produces
@example
 /foo/bar

@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::filename-extension}  filename 

 Return the filename extension of @var{filename}, without the leading
 period.  Returns the empty string if @var{filename} doesn't have an
 extension.

@example
@group
 <dir::filename-extension /images/foo.gif>       ==> gif
 <dir::filename-extension /downloads/foo.tar.gz> ==> gz
 <dir::filename-extension /data/file>            ==>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::filename-sans-extension}  filename 

 Return @var{filename} without its extension part.
 @example
 <dir::filename-sans-extension /www/bin/foo.lib>

@end example
  produces
@example
 /www/bin/foo

@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::handle-dots}  path 

 Return @var{path}, resolving any "./" or "../" found within.
 Example:
 @example
 <dir::handle-dots /foo/bar/../baz/./../below-foo>

@end example
  produces
@example
 /foo/below-foo

@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::names-in-dir} &optional  [dir]  [type]  [matching] 

 Return an array of the fully qualified pathnames in @var{dir} which
 are of type @var{type} (either "@code{FILE}" or
 "@code{DIRECTORY}") and which satisfy the regular
 expression @var{matching}.

 @var{dir} defaults to the directory of the currently executing page.

 @var{type} defaults to "@code{FILE}".

 @var{matching} defaults to all possible filenames.

@end deffn

@deffn {@i{Simple Tag}} {dir::read-file}  filename &optional  [varname] 

 Read in the contents of the file named by FILENAME and return them.
 If the optional variable @var{varname} is given, it is the name of
 a binary variable to receive the contents of the file.  In that case,
 the word "true" is returned if the file was successfully read, or the
 empty string otherwise.

@example
@group
 <dir::read-file /tmp/foo.gif gifdata> ==>true
 <set-var hosts[]=<dir::read-file /etc/hosts>>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {dir::write-file}  filename  varname 

 Write the contents of the variable named by VARNAME to the file
 named by FILENAME.  Returns "true" if the file was written, and
 the empty string otherwise.

@end deffn

@deffn {@i{Simple Tag}} {directory-contents}  pathname &optional  [package-name] &key  [matching=pattern] 

Returns a newline separated list of association lists for
the files matching @var{pattern}.

When @var{package-name} is supplied, each variable in
@var{package-name} is the name of a file in @var{pathname}, and
the value of each variable is the association list for that
file.

@end deffn

@deffn {@i{Simple Tag}} {directory-p}  var 

 Treat the argument @var{var} as the name of a variable which contains
 an alist produced by @vref{get-file-properties} or
 @vref{directory-contents}, and return "true" if
 the referenced file object is a directory, as opposed to a file.

@end deffn

@deffn {@i{Simple Tag}} {directory?}  pathname 

 Return "true" if @var{pathname} is a directory, or "" if not.

@end deffn

@deffn {@i{Simple Tag}} {file-exists}  pathname 

Returns "true" if @var{pathname} is an existing file or directory.

@var{pathname} is absolute, that is to say that it is looked up in
absolute file system space, not in Web space.  To find out if a file
@code{foo} in the current directory exists, use:

@example
@group
<file-exists <thisdir>/foo>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {file-newer?}  file1  file2 

 Return "true" if @var{file1} has been written more recently than
 @var{file2}.

 Both @var{file1} and @var{file2} are fully qualified pathnames.

@end deffn

@deffn {@i{Simple Tag}} {get-file-properties}  pathname 

Return an association-list containing operating system information
about the file or directory named by @var{path}. @var{pathname} must be
given fully; it is @i{not} relative to Web space in any way.

If the file exists and is accessible, the members of the returned
association-list which are guaranteed to be present are:

@itemize @bullet
@item  @b{NAME}: @i{welcome.mhtml}

The name of the file or directory, without any of the path information.

@item  @b{FULL-NAME}: @i{/www/site/docs/welcome.mhtml}

The name of the file or directory, with full path
information.  This should be identical to @var{PATH} as
received by @b{<get-file-properties>}.

@item  @b{SIZE}: @i{ 2188 } 

The size of the file in bytes.

@item  @b{TYPE}: @i{FILE}

The @i{type} of the file.  This will either be
@code{FILE} or @code{DIRECTORY}.

@end itemize

In addition to the above fields, the following fields appear on Unix
based systems:

@itemize @bullet
@item  @b{CREATED}: @i{6 29 96 10 3 24 897595648}

The date on which this file was created.  The value is an
array, with ordered values being: month, day, year, hours,
minutes, and seconds, and then the number of seconds since
Jan 1st, 1970.

@item  @b{WRITTEN}: @i{6 29 96 10 3 24 897595648}

The date on which this file was last written.  The value is an
array, with ordered values being: month, day, year, hours,
minutes, and seconds, and then the number of seconds since
Jan 1st, 1970.

@item  @b{READ}: @i{6 30 96 19 27 51 897595648}

The date on which this file was last read.  The value is an
array, with ordered values being: month, day, year, hours,
minutes, and seconds, and then the number of seconds since
Jan 1st, 1970.

@item  @b{CREATOR}: @i{bfox} 

The system identifier of the user who created this file.

@end itemize

A example calling sequence:
@example
<dump-alist <get-file-properties />>
@end example

@end deffn

@deffn {@i{Simple Tag}} {make-directories}  path &optional  [mode-string] 

 Create all of the directories in @var{path} (a fully qualified path to
 a directory) if they are not already present.

@end deffn

@defvr {@i{Variable}} {mhtml::exec-path}
A colon-seperated list of directories in which Meta-HTML searches
for executables when executing the @vref{cgi-exec} tag.
@end defvr

@deffn {@i{Simple Tag}} {path::find-executable}  basename 

 Return the fully qualified path to the program which would be
 executed by CGI-EXEC for BASENAME.

 Example:

@example
@group
 <path::find-executable ls> ==> /bin/ls

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {require}  stem 

@code{require} tries hard to locate the source or library file
specified by @var{stem}, and then loads that file if it hasn't already
been loaded.

If the variable @code{mhtml::require-directories} is present, then
it is an array of directory names (without trailing slashes) relative
to Web space that should be searched through, in the order that they
appear in the array.

@code{require} understands the following extensions:

@itemize @bullet
@item  @b{.mhtml}, or @b{.src}: A Meta-HTML source file.

@item  @b{.lib}: A Meta-HTML library file.

@end itemize

@code{require} loads the newest version of the file that it
finds, and records the complete pathname of the loaded file in the
array variable @code{mhtml::require-loaded}.

@end deffn

@deffn {@i{Simple Tag}} {unix::mkfifo}  filename &optional  [mode-bits] 

Create a named pipe on unix systems that support named pipes.

The pipe is named @var{filename} and is created with the access mode
specified by @var{mode-bits}, an octal permissions mask.

@var{mode-bits} defaults to 0666 if not specified.

After a named pipe is created, it can be written to and read from
in the normal manner for writing and reading file streams.

UNIX::MKFIFO returns "true" if the named pipe could be created, or
the empty string if not.  In the case of an error, the human readable
text of the error message appears in SYSTEM-ERROR-OUTPUT.

@end deffn

@deffn {@i{Simple Tag}} {webpath-exists}  document-path 

 Returns "true" if the specified @var{document-path} exists with
 "/" being equal to the document root directory.

@end deffn


@node Stream Operators
@section Stream Operators
A @i{stream} is a data object upon which various input
and output operations may be performed.

Meta-HTML provides commands for creating, opening, reading from, and
writing to, stream objects.  The referenced underlying object may
either be a file or a network connection.There are three special
names which can be used with @vref{with-open-stream}, these are @code{*standard-input*},
@code{*standard-output*}, and @code{*standard-error*}.

@code{*standard-input*} always names the stream that from which
input was being read at the time the engine, server, or
@code{mhc} invoked.  @code{*standard-output*} always names
the stream to which output is being written by the engine, server or
@code{mhc}.

@code{*standard-error*} always names the stream where error
output will appear -- this stream could be the same as the one named
by @code{*standard-output*}, but this does not have to be the
case.
@deffn {@i{Simple Tag}} {stream-get}  stream &key  [stop-at=character] 

Reads a chunk of data from @var{stream} and returns it. @var{stream}
is read until the character value specified by @var{character}
(defaulting to a newline) is reached, and that data upto and including
the final @var{character} is returned. One way to read all of the
available data is to supply the empty string as the value of @var{stop-at}: 

@example
@group
<with-open-stream stream www.ua.com:80 type=tcp mode=read-write>
  <stream-put stream "GET /welcome.mhtml HTTP/1.0\n\n">
  <set-var the-page = <stream-get stream stop-at="">>
</with-open-stream>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {stream-get-contents}  stream  var &key  [chunk-size=size]  [stop-at=character] 

Reads the contents of the stream @var{stream} into the binary
variable @var{var}.  You can easily use this in conjunction with
@vref{stream-put-contents} and @vref{coerce-var}.

If @var{stop-at} is supplied, it is a character at which the function
should stop reading data from the stream.  Unlike
@code{stream-get}, @var{stop-at} defaults to the empty
character, thus causing the entire stream to be read.

If @var{chunk-size} is supplied, it is the amount to read at one
time.  This is useful for when you have an unbounded amount of data to
read, and you would like to process it in manageable chunks.

For example, the following code copies data from an open network
stream to a file on the local disk, without using more than 32k of
memory:

@example
@group
<with-open-stream src data-server.ua.com:2345 type=tcp mode=read>
  <with-open-stream dst /tmp/datafile type=file mode=write-create>
    <while <stream-readable s>>
      <stream-get-contents src chunk chunk-size=32768>
      <stream-put-contents dst chunk>
    </while>
  </with-open-stream>
</with-open-stream>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {stream-info}  stream 

Return an association list providing information about @var{stream}.

@end deffn

@deffn {@i{Simple Tag}} {stream-put}  stream  string 

Writes @var{string} to the open @var{stream}.

@end deffn

@deffn {@i{Simple Tag}} {stream-put-contents}  stream  var 

Writes the contents of the binary variable @var{var} to the open @var{stream}.  Binary variables are generally created with @vref{stream-get-contents}, or when uploading a file from
a Web browser.

@end deffn

@deffn {@i{Simple Tag}} {stream-readable}  stream &key  [delay=seconds] 

Returns "true" if @var{stream} is an open stream which was opened
with a mode of read, or read-write, and which still has data pending.

The optional keyword @var{delay} is used to specify the amount of time
in seconds that @code{stream-readable} should wait for the
stream to become ready for reading.  The default value is zero seconds;
no waiting period is used.

@end deffn

@deffn {@i{Simple Tag}} {stream-shutdown}  stream 

Only for use with network streams, this tells the underlying
operating system (and the other end of the network connection) that no
additional input or output will be done using this object. In effect,
it immediately closes the stream.

When used in conjunction with a network stream opened on
@code{*standard-output*}, this can be used to close the
@code{HTTP} connection to the client, and yet continue
processing data.

@end deffn

@deffn {@i{Simple Tag}} {stream-writable}  stream &key  [delay=seconds] 

Returns "true" if @var{stream} is an open stream which was opened
with a mode of write, append, read-write, or write-create, and which
is available to have data written to it.

The optional keyword @var{delay} is used to specify the amount of time
in seconds that @code{stream-writable} should wait for the
stream to become ready for writing.  The default value is zero seconds;
no waiting period is used.

@end deffn

@deffn {@i{Complex Tag}} {with-open-stream}  var  name &key  [type=(FILE|TCP|PROG)]  [mode=OPEN-MODE]  [timeout=(value|NEVER)] 

Create an environment in which @var{var} is bound to the
@i{indicator} of an open stream, named by @var{name}.

The stream is either of type @code{FILE}, in which case it is a simple
file in the file system, of type @code{TCP},
in which case it is an open network connection, or of type @code{PROG},
in which case it is an open connection to a running process.

When @var{type} is @code{TCP}, @var{name} specifies the host and
port to connect to, in the form @code{Hostname:Port-Number}.
@var{port-number} can either be a symbolic name which is widely
recognized (e.g., @code{SMTP}), or the digits which make up the
port number, (e.g., @code{25}). Finally, the keyword argument
@var{notimeout=true} may be given, which indicates that the amount of
time that Meta-HTML should wait during IO operations on this stream
is infinite -- all processing will block until the stream is
successfully read from or written to.  The default timeout is
dependent on which specific operation is being performed, and the
amount of data which is being read or written, but is generally
suitable for writing data at about 14.4kbps.

The possible values for @var{mode} are:

@itemize @bullet
  @item  @code{READ}:

  The stream is opened for reading only.  The underlying object must
already exist.

  @item  @code{WRITE}:

  The stream is opened for writing only.  The underlying object must
already exist.

  @item  @code{READ-WRITE}:

  The stream is opened for both reading and writing.  The underlying
object must already exist.

  @item  @code{APPEND}:

  The stream is opened for writing only.  If the underlying object did
not already exist, it is created.  Information written to this stream
appears after any information that was already present in the
underlying object.

  @item  @code{WRITE-CREATE}:

  The stream is opened for writing only.  The underlying object is
created fresh, even if it had already existed.

@end itemize

When one is opening, reading to, or writing from a network stream, the 
amount of time it can take to finish the operation is indeterminate.  So,
the keyword argument @var{timeout=value} can be used to specify the maximum
amount of time (in seconds) that these operations may take.  If the value
is specified as "never", then these operations can take "forever".
If the value isn't specified, then the operations calculate the maximum
wait time dynamically, based upon the amount of information to be read
or written.  Any other value specifies an absolute maximum number of
seconds.

@end deffn


@node Defining New Tags
@chapter Defining New Tags

@node Macro Commands
@section Macro Commands
Meta-HTML contains a powerful @i{macro} facility, which allows
you to define your own commands.  Such commands are first-class
objects in Meta-HTML; they may even supersede the compiled in
definitions.

There are two types of macros that you can define.  One type is a
@i{complex-tag}; it consists of an opening tag, a body, and a
closing tag.  The other type is a @i{simple-tag}; it only has an
opening tag.

You create a macro by using one of the macro-defining commands.  In
the body of the definition, special keywords can be placed, which
affect what is produced when the macro is invoked.  As a macro writer,
you have logical access to the arguments passed to the macro in the
opening tag, and for complex-tags, you have access to the body which
appears between the opening and closing tags.  In the opening tag of the macro defining command, several special
@i{meta-arguments} may be used to affect the binding method used at
invocation time to bind the passed parameters to the formal arguments.

@itemize @bullet
 @item  @b{&optional}
 Indicates that the following named
parameter is optional, and does not have to be supplied.  While at
this time Meta-HTML does not complain if there are missing arguments
at invocation time, it is likely that the byte-compiler will require
function calls to match the formal parameters of the defined function.

@example
@group
<defun func x &optional y> <get-var x>, <get-var y> </defun>
@end group
@end example

@item  @b{&key}
 Indicates that the following named parameters
will be bound by the caller placing the name of the parameter followed
by an equals sign, and the value of that parameter in the opening tag
of the function call.  Thus, keyword arguments may appear in any order
in the calling function.  Here is an example of defining a tag called
@b{<image>} which will add the width and hieght if they are not
already present:

@example
@group
<defun image &key src width height>
  <if <or <not <get-var width>>
	  <not <get-var height>>>
      <find-image-xy <get-var src> width height>>
  <img src="<get-var src>" width=<get-var width> height=<get-var height>>
</defun>
@end group
@end example

@item  @b{&rest}
 Gobbles up any remaining arguments to the
function, collecting them in the named parameter which follows the
@i{&rest}.  The arguments may be gathered into a single string, or
into an array, with one argument per slot.  This is controlled by
writing the formal parameter name either with or without sqaure
braces: (i.e., @code{foo[]} or @code{foo}).

@example
@group
<defun func req-arg &rest rest-args[]>
  <ol>
    <foreach x rest-args>
      <li> <get-var x> </li>
    </foreach>
  </ol>
</defun>
@end group
@end example

@item  @b{&body}
 Causes the following named parameter to be bound
to the body of the invoked function or macro.  For @b{<defun>} and
@b{<defsubst>}, this is all of the material which appeared in the
opening tag, while for @b{<defmacro>} and @b{<defweakmacro>}, this is
all of the material that appeared between the opening and closing
tags.

@example
@group
<defmacro with-debugging-output &body body>
  <with-open-stream debug-stream /tmp/debug-output mode=append>
    <stream-put debug-stream <get-var body>>
  </with-open-stream>
</defmacro>
@end group
@end example

@item  @b{&unevalled}
 Modifies the binding rule of a formal
parameter such that the material which is bound is not evaluated
before the binding takes place.  This is almost equivalent to using
the @b{%0} ... @b{%9}, or @b{%body} textual substitutions,
but the arguments are bound to variables instead of pure textual
substitution.  Here is how one might write a function which takes an
expression, and produces the expression and the evaluation of the
expression as output:

@example
@group
<defun debug-expr &body &unevalled qbody &body body>
  <get-var-once qbody> EVALS TO: <get-var-once body>
</defun>
@end group
@end example

Such an invocation might look like:

@example
@group
  <set-var x=4 y=5>
  <debug-expr <add x y>>
@end group
@end example

which would produce:

@example
@group
  <add x y> EVALS TO: 9
@end group
@end example

@end itemize

Here is a ridiculous function, which uses all of the special
meta-parameters:

@example
@group
<defsubst func req &optional opt &key k1 &unevalled k2 &body b &rest args[]>
   REQ: <get-var-once req>,
   OPT: <get-var-once opt>
    K1: <get-var-once k1>
    K2: <get-var-once k2>
  BODY: <get-var-once b>
  REST: <foreach arg args><get-var-once arg> </foreach>
</defsubst>
@end group
@end example

And, here are examples of calling that function:

Example 1:

@example
@group
<set-var key-1-arg=key-1>
<func required k2="Unevalled" opt-arg k1=<get-var key-1-arg> rest0 rest1>
   REQ: required,
   OPT: opt-arg
    K1: key-1
    K2: Unevalled
  BODY: required k2="Unevalled" opt-arg k1=key-1 rest0 rest1
  REST: rest0 rest1
@end group
@end example

Example 2:

@example
@group
<func k2=<get-var k1> required rest0 rest1>
   REQ: required,
   OPT: rest0
    K1: 
    K2: <get-var k1>
  BODY: k2= required rest0 rest1
  REST: rest1
@end group
@end example

Notice how in the second example, our optional parameter @b{opt}
got bound to the second non-keyword argument @code{rest0}!
@deffn {@i{Complex Tag}} {define-container}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

Define @var{name} as a complex tag. At invocation time, various
substitutions are made within @var{body}.  Specifically, if the text
string is:

@itemize @bullet
@item @b{%0},@b{%1}, and so on, upto @b{%9} are replaced
with the exact text of the positional arguments that were found in
the opening tag of the invocation

@item @b{%attributes} is replaced by all of the arguments which
appeared in the opening tag.

@item @b{%body} is replaced with the exact text of the material
that appeared between the opening and closing tags

@item @b{%qbody} is similar to @b{%body}, but the string is
first surrounded by double quotes, and double quote characters which
appear in the string are escaped.

@item @b{%xbody} is replaced with the evaluation of the material
that appeared between the opening and closing tags

@end itemize

If any @var{named-parameter}s are supplied, the values that were
passed in the opening tag are evaluated and bound to the named
parameters.

A keyword argument of @var{package-name} wraps the entire body of the
macro in an @vref{in-package} statement.

The keyword argument @var{whitespace} can be set to the string
@code{delete} to remove whitespace from the starts and ends of
lines in the macro definition before it is stored.  This effectively
concatenates all of the lines of the macro definition into a single
long line.

@end deffn

@deffn {@i{Complex Tag}} {define-function}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

Define @var{name} as a simple tag.

The only differences between @vref{define-function}
and @vref{define-tag} are:

@enumerate
@item  The @i{whitespace=delete} option is assumed.
@item  The @var{named-parameter}s are evaluated in the context of the
caller, not of the definition of the defun.
@item  By default, a local package is wrapped around the invocation of
the defined function.  This can be changed by the use of the @var{package=packname} keyword.

@end enumerate

@example
@group
<define-function factorial num>
   <if <lt num 2> 1
      <mul num <factorial <sub num 1>>>>
</define-function>

<factorial 5> ==> 120
@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {define-tag}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

Define @var{name} as a simple tag.  Within @var{body}, the values of
@code{%0...%9} are defined to be the positional arguments that
were found in the opening tag of the invocation, and
@code{%body} is all of that material in a single string.

If any @var{named-parameter}s are supplied, the values that were
passed in the opening tag are evaluated and bound to the named
parameters.

A keyword argument of @var{package-name} wraps the entire body of the
macro in an @vref{in-package} statement.

The keyword argument @var{whitespace} can be set to the string
@code{delete} to remove whitespace from the starts and ends of
lines in the subst definition before it is stored.  This effectively
concatenates all of the lines of the subst definition into a single
long line.

Also see @vref{define-function} and @vref{define-container}.

@end deffn

@deffn {@i{Simple Tag}} {defined?}  name 

 Returns "true" if @var{name} is defined as a Meta-HTML primitive or
 a user-defined function, or the empty string otherwise.

@end deffn

@deffn {@i{Complex Tag}} {defmacro}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

A synonym for @vref{define-container}.

@end deffn

@deffn {@i{Complex Tag}} {defsubst}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

A synonym for @vref{define-tag}.

@end deffn

@deffn {@i{Complex Tag}} {defun}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

A synonym for @vref{define-function}.

@end deffn

@deffn {@i{Complex Tag}} {defweakmacro}  name &optional  [named-parameters] &key  [package=packname]  [whitespace=delete] 

@code{defweakmacro} is exactly like @vref{define-container}, with one exception: at invocation time, the closing
tag does not have to be present -- in that case, the invocation is
treated as if the definition were a @vref{defsubst}.

This facility exists primarily to allow the redefinition of standard
HTML constructs which allow the closing tag to be missing, and yet,
still inexplicably operate correctly.

For example, the   
@b{@code{<p>}} tag is often used without
its closing counterpart of   
@b{@code{</p>}}.  If you
wished to redefine   
@b{@code{<p>}} to do something special
when a closing tag was found, you might write the following
definition:

@example
@group
<defweakmacro p>
  <verbatim><P></verbatim>
  <when %qbody> Look ma! %body See? </when>
  <verbatim></P></verbatim>
</defweakmacro>
@end group
@end example

then, a simple   
@b{@code{<P>}} would produce

@b{@code{<P></P>}}, while a complex invocation, such as:

@example
@group
<P> this is a list </P>
@end group
@end example

produces

@example
@group
  <P> Look ma!  this is a list See? </P>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {primitive?}  name 

 Returns "true" if @var{name} is defined as a Meta-HTML primitive, or
 the empty string otherwise.

@end deffn

@deffn {@i{Simple Tag}} {undef} &optional  [name...] 

Remove the definition of a user-defined @vref{defun},
@vref{defmacro} or @vref{defsubst}.  For every @var{name} that has been defined in this way, the definition is removed.

@end deffn

@deffn {@i{Simple Tag}} {user-function?}  name 

 Returns "true" if @var{name} is defined as a user function, or
 the empty string otherwise.

@end deffn


@node Managing the Page
@chapter Managing the Page

@node Page Operators
@section Page Operators
Meta-HTML contains a few commands which
operate on the entire @i{page} as it currently exists.

You may find, modify, or delete text which has already been looked at by the interpreter, as well as text which hasn't yet been looked at.

Most of the time, you won't need to use such commands.  They can make
it hard for other people to understand the sequence of code in your
page, and they can sometimes produce unexpected results which are
difficult to debug because much of the information has been modified.

@deffn {@i{Simple Tag}} {cleanup-whitespace} &optional  [varname] &key  [beautify] 

Reduces the amount of whitespace in the output page to the minimum
required.  This function carefully avoids the contents of   
@b{@code{<pre> ... </pre>}} constructs, as well as any material
appearing in a   
@b{@code{<textarea ...> ... </textarea>}}
construct.

Given @var{varname}, operates on the contents of that variable.

Placed as the last instruction on a page, it is an effective way to
reduce the amount of data sent back over the network to the connecting
browser.

@end deffn

@deffn {@i{Simple Tag}} {include}  webpath &key  [alt=altcode]  [verbatim=true] 

Insert the contents of the file named by @var{webpath} into the
document at the point where the @code{include} form was read.
If the keyword argument @var{verbatim=true} is given, then the contents
of the file are not executed, only inserted.  Otherwise, execution
resumes at the point where the file was inserted.

@var{webpath} can be given as an absolute pathname, or a relative
pathname.  If the path is relative, it is considered to be relative to
the location of the document which contains the @code{include}
form.  If the path given is not relative, it is appended to the
directory found in @b{MHTML::INCLUDE-PREFIX}.

If the named file could not be found on the server, and an @var{alt=altcode}
value is given, then that value is placed into the page instead.

@end deffn

@deffn {@i{Simple Tag}} {redirect}  url &key  [target] 

Immediately return the HTTP @b{Location} directive with @var{url}.
This command is extremely useful in conjunction with @vref{var-case}; in effect, that usage creates a dispatch table.

When a @code{redirect} tag is seen, the current page is
discarded, and the appropriate HTTP code is returned to the browser to
cause an immediate redirection to the specified page.

@var{url} may be expressed in relative terms, in absolute terms, or as
a complete URI specification.  For example, assume the current
document is located at

@b{@code{http://www.metahtml.com/subdir/doc.mhtml}}, and
the following redirections are seen:

@example
@group
  <redirect ../foo.mhtml>     ==> http://www.metahtml.com/foo.mhtml
  <redirect /bar/foo.mhtml>   ==> http://www.metahtml.com/bar/foo.mhtml
  <redirect http://www.bsdi.com> ==> http://www.bsdi.com
@end group
@end example

If the keyword argument @var{target=XXX} is supplied, it is the name of
the browser window in which to display the new page.  If one is working
with frames, this can be very useful: a target of "_top" removes all
frames, a target of "_new" creates a new window, etc.

@end deffn

@deffn {@i{Simple Tag}} {replace-page}  webpath &key  [alt=altcode] 

Replace the entire contents of the current page with the contents of
the page named by @var{webpath}.  You probably don't want to use this
command, use @vref{redirect} instead.  In that way, the
URLs give a consistent view to the user.  The rules for which @var{webpath} is chosen are identical to those for @vref{include}.

@end deffn

@deffn {@i{Complex Tag}} {server-push} &key  [type=mime-type] 

Writes the appropriate headers and HTTP information to the connected
browser, along with the data that you specify.

The functionality provided by this convenience function is available
other ways, specifically through the use of @vref{with-open-stream} and the variable @code{*standard-output*}.

@example
@group
<server-push>
  <html>
  <head><title>Just a Moment, please</title></head>
  <body>
  <h3>Please wait a moment, we are searching the entire Web...</h3>
  </body>
  </html>
</server-push>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {subst-in-page}  this-string  with-that 

Replaces all occurrences of @var{this-string} with @var{with-that} in the
current page.  Both @var{this-string} and @var{with-that} are evaluated
before the replacement is done.  @var{this-string} can be any regular
expression allowed by the POSIX extended regular expression matching.

This command can be useful when included as part of a footer
@code{include} file.  For example, you could replace all
occurrences of @code{%name%} with a the value of the variable
@code{FirstName} by writing:

@example
@group
  <subst-in-page %name% <get-var forms::FirstName>>
@end group
@end example

@end deffn


@node Page Variables
@section Page Variables
Several variables are predefined by
Meta-HTML, and made available to the page writer.  In addition to
the contents of the Unix environment (which includes the server-side
variables @code{ENV::SERVER_NAME}, @code{ENV::PATH_INFO}, etc.)
variables describing the location of the current document in various
ways are also defined.  The following short list is a quick look
at typical values of the most commonly referenced page variables.

When the URL is ``@i{http://localhost.ua.com/meta-html/manual/make-printable.mhtml}'', the following
variables are set to:

   @code{MHTML::PATH-INFO}: @i{}

   @code{MHTML::HTTP-TO-HOST}: @i{http://localhost.ua.com}

   @code{MHTML::CURRENT-DOC}: @i{make-printable.mhtml}

   @code{MHTML::INCLUDE-PREFIX}: @i{.}

   @code{MHTML::RELATIVE-PREFIX}: @i{}

   @code{MHTML::LOCATION}: @i{/meta-html/manual/make-printable.mhtml}

   @code{MHTML::LOCATION-SANS-SID}: @i{/meta-html/manual/make-printable.mhtml}

   @code{MHTML::FULL-URL}: @i{http://localhost.ua.com/meta-html/manual/make-printable.mhtml}

   @code{MHTML::FULL-URL-SANS-SID}: @i{http://localhost.ua.com/meta-html/manual/make-printable.mhtml}

   @code{MHTML::URL-TO-DIR}: @i{http://localhost.ua.com/meta-html/manual}

   @code{MHTML::URL-TO-DIR-SANS-SID}: @i{http://localhost.ua.com/meta-html/manual}

   @code{MHTML::HTTP-PREFIX}: @i{http://localhost.ua.com}

   @code{MHTML::HTTP-PREFIX-SANS-SID}: @i{http://localhost.ua.com}

@node Working with Sessions
@chapter Working with Sessions

@node Session Operators
@section Session Operators
Meta-HTML solves the problem of keeping state for a particular
session, and it does it in a server and browser independent
manner. Our method requires no additional CGI programs to be written,
and you don't have to be a programmer to take advantage of it.

The basic essence of sessions is the @i{session database}.  An
entry in the session database can have exactly one of three possible
states: @i{present}, @i{missing}, or @i{timed out}.Using the session commands, you can:

@itemize @bullet
@item 
@b{Create a session.}
 This generates a unique entry
in the session database, and returns that information as a session
identifier (@b{SID}).  You can associate a special
@i{key} with the session at creation time, and you can decide
whether the key must be unique or not.  Session information can be
located by either the SID or the key.

@item  @b{Delete a session.}

This removes the entry in the database associated with a specific SID,
thus placing the session in the "missing" state.

@item  @b{Change a session's timeout value.}

With each session there is an associated @i{timeout} value, which
is the number of minutes the session can live without any activity on
the part of the user.  When the session is created, a default timeout
is installed; currently this is five minutes.  Using
@vref{}set-session-timeout>, you can change this
value. A special signal value of "@code{0}" causes the session
to live forever (or until it is deleted with @vref{delete-session}).

@item  @b{Require a session to be present.}

Using the @vref{require-session} form allows you
to check the state of the session, and optionally execute code for the
cases where it is missing or timed out.

@item  @b{Manipulate persistent variables.}

Commands exist to associate a name with a value in the session
database, to retrieve the value associated with a name in the session
database, and to store and retrieve a group of associations at once
from the session database.

@end itemize
@deffn {@i{Simple Tag}} {create-session} &optional  [var=missing-code...] &key  [alt=altcode]  [allow-multiple] 

Create a session, and place the session identifier in the variable
@var{default::sid}. The key for the session is created by
concatenating the values of the @var{VAR}s together, separated by
hyphens (-). If a @var{VAR} doesn't have a value currently assigned in
the default package, but does have an optional @var{MISSING-CODE}
assignment, then the session is not created, and the @var{MISSING-CODE} for that variable is evaluated. If all of the variables
have values (or have no missing action), and the session could not be
created, then @var{ALTCODE} is evaluated if it is present.

Finally, if the keyword @var{ALLOW-MULTIPLE} is present, it indicates
that the key does not have to be unique; it is enough that the session
is created and a session ID returned.

Example:

@example
@group
<create-session
 USERNAME=<group <set-var ERROR-MESSAGE="You must supply a Username">
                 <include registration.html>>
 PASSWORD=<group <set-var ERROR-MESSAGE="You must supply a Password">
                 <include registration.html>>
      ALT=<group <set-var ERROR-MESSAGE="You are already signed on!">
                 <include begin.html>>>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {delete-session} 

Immediately end the current session. This never returns anything. The
current session is indicated by the value of the variable @var{default::sid}, so you can delete sessions other than your own by
setting that variable. Also see @vref{sessions-of-key}.

@end deffn

@deffn {@i{Simple Tag}} {get-session-data} &optional  [sid] 

Returns an association list representing all of the data in the
session database associated with @var{sid}.

If @var{sid} is not supplied, it defaults to the value of @var{default::sid} (i.e., the current session ID).

@end deffn

@deffn {@i{Simple Tag}} {get-session-var} &optional  [name...] 

Return the value of the @var{name}s given from the session data
associated with the current session.  Each @var{name} is a
variable name which has had a value assigned to it with @vref{set-session-var}, or was created implicity via
@vref{session-export}.

The values are returned in the order in which the @var{name}s appear.

Examples:

@example
@group
<set-session-var foo=Var-1 bar=Var-2>
<get-session-var foo>, <get-session-var bar>
@end group
@end example

produces
@example

Var-1, Var-2
@end example

Example of retrieving a single session variable from a session
package:

@example
@group
<set-var record::name="Brian Fox">
<set-var record::job="Programmer">
<session-export record record>
<get-session-var record::name> ==> Brian Fox
@end group
@end example

@end deffn

@defvr {@i{Variable}} {mhtml::sid-prefix}
When this variable is present, the
@code{PATH} component of a returned @code{Set-Cookie} MIME
header is set to its value.  Normally, the value of @code{MHTML::RELATIVE-PREFIX} is used.

If you need to use @code{MHTML::SID-PREFIX}, you probably have a
very complex directory structure, and the need for every page access
to have a cookie associated with it.  In this case, setting
@code{MHTML::SID-PREFIX} will have the effect of flattening your
directory structure in the browser's view.

Generally, correctly written Meta-HTML applications do not need to
use this variable, and it might be used in only the most complicated
of Web sites, with multiple sessions per connectee, etc.

The explanation of HTTP Cookies is beyond the scope of this document.
Reference information on Cookies can be found through  this
link.
@end defvr

@defvr {@i{Variable}} {mhttpd::session-database-file}
The fully qualified pathname to the
current session database.  Setting this variable only has meaning in the
@code{mhttpd.conf} or @code{engine.conf} files.

If this variable is not set, then the default value of
@code{"/tmp/sessions.db"} is used.

If the server or engine cannot access this file, no session state
information may be saved or retrieved.
@end defvr

@deffn {@i{Simple Tag}} {require-session} &key  [missing=missing-code]  [timeout=timeout-code] 

Check that the current session is valid and not timed out.  If either
of those things are true, the respective code is evaluated.  Usually,
the targets of @var{TIMEOUT} and @var{MISSING} are a @vref{redirect} command which points to a page explaining the
problem.

You could force an anonymous session with the following code:

@example
@group
  <set-var anonymous="Anonymous Session">
  <require-session
    missing="<create-session anonymous allow-multiple>
             <redirect <get-var SID>/<get-var mhtml::current-doc>"
    timeout=<redirect /timed-out.mhtml>>
@end group
@end example

In the real world, additional care should be taken when returning new
URLs.  The variable @var{mhtml::cookie-compatible} is
@code{true} when the attached browser/server combination is
capable of handling HTTP Cookies.  In this case, it is preferable to
use the HTTP Cookie handling facilities instead of returning the
session ID in the URL.  Here is how one might write the above example
to handle both cases:

@example
@group
<set-var anonymous="Anonymous Session" session-timeout=60>
<require-session
 missing = <prog
             <create-session anonymous allow-multiple>
             <set-session-timeout <get-var session-timeout>>
             <when <not <get-var mhtml::cookie-compatible>>>
             <redirect <concat
                        <get-var mhtml::http-to-host>/
                        <get-var SID><get-var mhtml::relative-prefix>/
                        <get-var mhtml::current-doc>>>
             </when>>
 timeout = <prog
             <set-var SID="">
             <if <get-var mhtml::cookie-compatible>
                 <replace-page
                  <get-var mhtml::relative-prefix>/timedout.mhtml>
               <redirect
                <get-var mhtml::url-to-dir-sans-sid>/timedout.mhtml>>>>
@end group
@end example

For more detail on the built-in variables provided by the Meta-HTML
Server and CGI Engine, see the section @mref{Server Variables}.

@end deffn

@deffn {@i{Simple Tag}} {session-destroy-package}  package 

 Delete all of the variables referenced by @var{package} in the
 current session.  Also see @vref{session-export}.

@end deffn

@deffn {@i{Simple Tag}} {session-export}  package &optional  [to-package] 

Save the package variables of @var{package} in the current session.
If @var{to-package} is supplied, it indicates a new  package name to
assign to each variable from @var{package} that is saved.

This function is quite useful when you wish to save all of the
variables that were @b{posted} from the previous  URL (presumably,
that URL contained a form whose @b{action} pointed to the current
URL) in the session database record for the current session.  For
example, if the previous URL posted the variables @code{FOO} and
@code{BAR}, then executing:

@b{@code{<session-export posted blue>}}

results in the session database containing values for
@code{blue::FOO} and @code{blue::BAR}.  These values can
either be looked up directly, or retrieved as a group (see @vref{session-import} for more information.

@end deffn

@deffn {@i{Simple Tag}} {session-import}  package &optional  [to-package] 

Get the values of the session variables which belong to @var{package}
and set their values in the current package. If @var{to-package} is
supplied, it is the name of the package which will receive the
variable values. Thus, if the session data for the current session
contains:

@b{@code{((BLUE::FOO . bar))}}

and then at a later time in the same session the command:

@b{@code{<session-import blue>}}

is given, then the variable @code{FOO} in the current package
will be set to @code{bar}.  This is extremely useful when
bouncing back and forth between forms, see @vref{session-export}.

@end deffn

@deffn {@i{Simple Tag}} {session::initialize} &optional  [timeout]  [timeout-page] 

 Create or resume a session for the currently connected browser.
 @var{timeout} is the length of time this session should stick around
 in the session database expressed in minutes; it defaults to 200.

 If the variable @code{SESSION::INHIBIT-SESSION} is
 non-empty, then no session processing is done.

 If the session has timed out, (detected by the browser passing in a SID
 which doesn't exist in the session database), then a new session is
 created using that SID, and the variable @var{session::restarted} is
 set to "true".

 If a new session had to be created, either because the browser had
 a SID which was timed out, or because the browser didn't have a SID,
 then the variable @var{session::new-arrival} is set to "true".

 If you supply @var{timeout-page}, and the session was timed out,
 then the browser is redirected to @var{timeout-page}, and the
 session is not instantiated in the session database (although the
 aforementioned variables are still set).

@end deffn

@deffn {@i{Simple Tag}} {session::reset-cookie} 

 Place this at the end of a page which is supposed to timeout the
 user's session.  It sends the browser a Set-Cookie header which
 makes the cookie go away.

@end deffn

@deffn {@i{Simple Tag}} {sessions-of-key}  key 

Returns a newline separated list of the session ID's whose key
matches @var{key}.

If @var{key} is not specified, or if it contains only whitespace, all
session ID's in the session database are returned. Since the list is
newline separated, it is suitable for assignment to an array, as in:

@example
@group
<set-var sids[]=<sessions-of-key "On-Line Shopping">>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {set-session-data}  alist &optional  [sid] 

Sets all of the session data associated with the session ID @var{sid}
to the contents of the association list @var{alist}.  If @var{sid} is
not supplied, it defaults to the value of @var{default::sid}.

This construct is really of use only for those programs which deal
directly with the session database, such as a backend tool for viewing
and manipulating session data.  For all other applications, the use of
@vref{set-session-var} and @vref{session-export} should be more than sufficient.

@end deffn

@deffn {@i{Simple Tag}} {set-session-db}  pathname 

Dynamically change the location of the file used to store session information.
You probably don't need this in your programs -- it is used within the server
and engine configuration files to specify the location of your session
database.

@end deffn

@deffn {@i{Simple Tag}} {set-session-encryption-key}  keystring 

With non-empty argument @var{keystring}, turns on the triple-DES
encryption of data saved to the session database.  The data is
encrypted and decrypted using @var{key}.

This could usefully be placed in the "mhttpd.conf" or "engine.conf"
file with a statement similar to the following:

@example
@group
  <set-session-encryption-key <make-identifier 128>>
@end group
@end example

Don't turn this on unless you really have to, as it (obviously) affects
the performance of the session database.  (Each access to the database
results in a full call to triple ECB DES encryption, using the entire
contents of the session, and encrypting/decryption with a random 128-bit
key.)

@end deffn

@deffn {@i{Simple Tag}} {set-session-timeout}  minutes 

Make the current session time out after @var{minutes} minutes have
transpired since the last access to that session.

You cannot supply the value of (@code{0}); that is accomplished
with @vref{delete-session}.

@end deffn

@deffn {@i{Simple Tag}} {set-session-var}  name=value... 

Give the @var{name}s the associated @var{value}s in the session
database record associated with the current session.

@end deffn

@defvr {@i{Variable}} {sid}
The current session ID, as set by the function
@vref{session::initialize}.

The session ID is passed to and from the browser by either the use of
HTTP Cookies, or in the URL, as the first element of the path.

Normally, you never need to reference this variable directly, since
the various internal functions which deal with sessions know how to
set, get, and/or modify it without your help.

Related functions: @vref{create-session},
@vref{delete-session}, @vref{set-session-var}.
@end defvr

@deffn {@i{Simple Tag}} {unset-session-var} &optional  [name...] 

Analogous to @vref{unset-var}, @code{unset-session-var}
removes the variables named by the given @var{name}s from the session
data associated with the current session.

@example
@group
<set-session-var foo=bar>
<get-session-var foo>     ==> bar
<unset-session-var foo>
<get-session-var foo>     ==>
@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {with-locked-session} 

Executes @var{body} in an environment where access to the current
session is blocked. This allows concurrency (such as might be required
when multiple @code{GET}s are being processed for a single user)
to take place without introducing any race conditions for access to
the current session record of the session database.

@end deffn


@node Working with Databases
@chapter Working with Databases

@node Generic Sql Interface
@section The Generic SQL Interface
With the plethora of ANSI SQL compatible databases present on the
marketplace, Meta-HTML provides a single comprehensive interface which
may be used to access any of those which are supported.

Such databases include @code{mSQL}, @code{mySQL},
@code{Oracle}, @code{SyBase}, @code{Informix}, and
many other ODBC compliant databases.

Using the Meta-HTML Generic SQL Interface (GSQL), you can more rapidly
develop and inexpensively prototype your application -- then migrate
to full-blown production scale without writing a single line of code!

For example, you might build an in-house HR application using the
mySQL database.  Once you are happy with the application flow and GUI,
you can port the application to Oracle by changing two lines of code:

@example
@group
<sql::set-database-type mysql>
<set-var app::dsn = "host=localhost;database=hr">
    ...
<sql::set-database-type odbc>
<set-var app::dsn = "HOST=production;database=HR;SVT=Oracle 71;...">
@end group
@end example
The Meta-HTML Generic SQL Interface works by providing all of the
underlying functionality for each specific database type at a generic
top-level interface which never has to change.  You specify which type
of database that you would like to use with a single function call,
using @vref{sql::set-database-type}.

Although there are specific low-level functions implementing the
database connectivity, the higher-level routines transparently make
extremely efficient use of them to handle your requests.

Because the low-level functions exist, you can easily write code which
copies data from one type of database (say mSQL) to another type (say
an Oracle ODBC database).
@deffn {@i{Simple Tag}} {sql::admin-prog} 

 Returns the complete path of the executable program which is used to
 perform administration functions on the undrlying SQL database.
 For example, @code{/usr/local/Hughes/bin/msqladmin}, or
 @code{/usr/local/bin/mysqladmin}.

@end deffn

@deffn {@i{Simple Tag}} {sql::affected-rows}  cursor 

 Return the number of rows affected by the last SQL query execution,
 associated with the database referenced indirectly by @var{cursor}.
 This may be completely unrelated to the query which created the
 cursor object, depending on the underlying database which is in
 use.

@end deffn

@deffn {@i{Simple Tag}} {sql::allow-system-tables} &optional  [allow?] 

 For those underlying database engines which keep information
 about the database structure within the database itself, a
 request to   
@b{@code{<sql::host-databases ...>}}
 can return a great deal of information, most of which is
 uninteresting to an application.  Call this function with an
 argument of "true" to allow such system tables to be returned,
 or with no argument to disallow them.

@end deffn

@deffn {@i{Simple Tag}} {sql::cursor-get-column}  cursor  column-number 

 Called with a @var{cursor} (the result from a call to
 @vref{sql::database-exec-query}),
 which has been filled in by at least one call to
 @vref{sql::database-next-record},
 this function returns the data from the current result set,
 in the column numbered @var{column-number} (starting at column 0).

 If there is no result set, or if the result set is empty, the
 empty string is returned.

@example
@group
 <sql::with-open-database db dsn="host=localhost;database=admin">
   <set-var query="select * from users">
    <sql::database-exec-query db <get-var query> cursor=row>
    <set-var any? = <sql::database-next-record row>>
    <when <get-var any?>>
      Result: <sql::cursor-get-column row 0>
    </when>
 </sql::with-open-database>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {sql::database-column-info}  dbvar  table  fieldname 

 Returns an association list of properties on the specified
 @var{column} in the table @var{table}.

 Example:
 @example
 ((NAME . realname)
  (LENGTH . 30)
  (TYPE . GSQL_CHAR)
  (IS_UNIQUE . "")
  (IS_NULLABLE . true)
  (QUALIFIER . "")
  (OWNER . "")
  (TYPENAME . "")
  (PRECISION . 0)
  (SCALE . 0)
  (RADIX . 0)
  (TABLE . accounts))

@end example

 This is actually implemented by fetching information on @i{all}
 columns and selecting the specified one.  This means that you should
 use the command
 @vref{sql::database-columns-info} if you
 are looking for information on several columns, as opposed to
 the specific column mentioned by @var{column}.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-columns}  dbvar  tablename &key  [result=varname] 

 Returns a newline separated list of the columns present in @var{tablename} in the open SQL database referenced by @var{dbvar}.

 The keyword @var{result=varname} argument specifies the name of
 a variable to put the result array into; if not present, the
 array is returned to the caller.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-columns-info}  dbvar  table &key  [result=varname] 

 Analogous to @vref{sql::database-column-info},
 this function returns an @i{array} of association lists where
 each entry in the array is the information about a single column.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-delete-record}  dbvar  key &key  [table=tablename]  [keyname=fieldname] 

 Deletes the specified record in the database referenced by
 @var{dbvar}. The record to delete is specified by @var{key} and
 @var{keyname}. An SQL @code{DELETE} query is issued which
 will delete all records in the table named @var{table} whose column
 named @var{fieldname} matches the value of @var{key}.

 You must supply values for @var{table} and @var{keyname}.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-exec-query}  dbvar  query-string &key  [cursor=varname] 

 Executes the SQL query in @var{query-string} by sending it to
 the open database connection referenced by @var{dbvar}.

 @var{query-string} can be any Meta-HTML expression which
 evaluates to a valid SQL query or command string.

 Returns a cursor object, which can be passed to
 @vref{sql::database-next-record},
 @vref{sql::number-of-rows}, or
 @vref{sql::set-row-position}.

 If the keyword argument @var{cursor=varname} is given, the
 returned cursor value is stored in @var{varname}.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-exec-sql}  dbvar  query-string 

 Executes the SQL query in @var{query-string}, on the open
 database connection specified by @var{dbvar}.

 Returns TRUE if no errors are encountered.

 This function differs from
 @vref{sql::database-exec-query} in that
 it does not return any cursor; i.e., there is no way to get
 results back from the execution of your SQL command. Thus, it is
 most useful for sending commands which expect no return values,
 such as a SQL DELETE statement:

@example
@group
 <sql::database-exec-sql 
    db "DELETE FROM maillists WHERE list = '<get-var listname>'">

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {sql::database-load-record}  dbvar  key &key  [table=tablename]  [keyname=fieldname]  [package=packagename] 

 Load variable values from the database referenced by @var{dbvar}
 and @var{key} into the package specified by @var{packagename}
 (defaulting to the current package if not supplied).

 @var{tablename} and @var{fieldname} must be supplied -- they
 specify the table and primary key field to be operated on.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-next-record}  cursor &key  [colnames=namelist]  [prefixtablenames=true]  [package=packagename] 

 Fill the variables in @var{packagename} (defaulting to the
 current package if not supplied) with the values of the next
 record which last satisfied the search referenced by @var{cursorvar}.

 Each subsequent call gets a subsequent record from the list of
 results, until all of the results are exhausted.

 Returns @code{true} if there are any records left in the
 search results, or the empty string if not.

 If @var{colnames} is supplied, then the column values of this
 result are bound sequentially to the comma-separated list of
 names in @var{namelist} instead of the field names in the result
 set.

@example
@group
 <sql::database-next-record db cursor package=tmp
             colnames="a.name, a.partnum, b.name">
 <get-var tmp::b.name>
 <get-var tmp::a.name>

@end group
@end example

 If @var{colnames} is non-null, or the database connection option
 @code{SQL-PREFIX-TABLENAMES} is non-null, then for each
 column in the result set, use the column's table name, if it
 exists, as a prefix to the column name as the variable name.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-query}  dbvar  query &key  [colnames=namelist]  [prefixtablenames=true]  [format=fexpr]  [keys=varname]  [keyname=fieldname] 

 Select and optionally format records in the database referenced
 by @var{dbvar} according to the criterion in @var{fexpr}.

 @var{query} is an SQL query, which is expected to return a list of rows.

 For each result row, @var{expr} is then evaluated, with the
 column values of each row bound to their corresponding column
 name. If the result of that evaluation is not an empty string,
 then that record is selected for further processing by either
 @var{format}, @var{keys}, or to return in plain text the list of
 keys. If @var{format=fexpr} is present, @var{fexpr} is an
 expression to evaluate in the context of the database fields,
 (as with @var{expr}).

 The value of "true" for @var{expr} is specially optimized to
 for those queries where no additional processing is necessary.

 The example below shows an SQL query which is formatted as rows
 of an HTML table. In this case, the @var{expr} is simply the
 constant @code{true}, and all of the selection of records
 is done via the SQL query itself. (Note that @var{expr} could be
 used to impose additional conditions to decide whether to invoke
 @var{fexpr} on a row.

@example
@group
 <table border=1>
   <tr> <th>Name</th> <th>Age</th> </tr>
   <sql::with-open-database db dsn="DATABASE=ROLO;HOST=localhost">
     <sql::database-query db true
         "SELECT * FROM people
          WHERE name like 'Washington' ORDER BY lastname"
         format=<group <tr>
                       <td> <get-var lastname>, <get-var firstname> </td>
                       <td> <get-var age> </td>
                       </tr>>>
   </sql::with-open-database>
 </table>

@end group
@end example

 If @var{keys=varname} is given, then @var{varname} is the name
 of a variable to receive the array of keys which satisfied
 the query.  If you specify an argument for @var{keys}, you must
 also specify which column to collect the values from, using the
 @var{keyname=fieldname} keyword argument.

 If the optional argument @var{colnames=namelist} is supplied,
 then for each row, column values are bound sequentially to these
 comma separated names instead of the column names in the result set.

@example
@group
 <sql::database-query db true <get-var query>
    colnames="foo.name, bar.name"
    format=<group FOO.NAME IS <get-var foo.name> 
                  BAR.NAME IS <get-var bar.name>>>

@end group
@end example

 If @var{prefixtablenames} is non-null, or the database
 connection option @code{SQL-PREFIX-TABLENAMES} is
 non-null, then for each column in the result set, use that
 column's table name as a prefix to the column name as the
 variable name.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-query-info}  cursor &key  [result=varname] 

 Returns an array of association lists giving information about
 each column in the result set specified by @var{cursor}.

 If the keyword argument @var{result=varname} is given, the
 resultant array is placed into that variable -- otherwise it is
 simply returned.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-save-package}  dbvar  key  package &key  [table=tablename]  [keyname=fieldname] 

 Save the variables in @var{package} associated with the value
 @var{key} in column @var{keyname} in the table @var{tablename}
 of the database referenced by @var{dbvar}.

 This only saves variables which have names matching existing
 table column names. Package prefixes are stripped from the
 variables, and the symbol name is used as the column name to
 store the data. Symbol names and column names are treated in a
 case-insensitive manner.

 The implementation is to first attempt to do a SQL
 @code{INSERT} into the table, and if that fails to try a
 @code{UPDATE} query, with @var{keyname} = @var{key}.

 Example: Say we want to save some information about employee
 Kate Mulgrew, in a table of employees, which has a primary key
 field named "id", and we want to save this record with id=103:

@example
@group
 <set-var record::name="Kate Mulgrew" record::age=45
          record::salary=34000 record::dept=travel>

 <set-var saved? =
    <sql::database-save-package db 103 record table=employees keyname=id>>

@end group
@end example

 If a variable in the package you are saving corresponds to a
 column with a numeric field type, and the value of the variable
 is the empty string, the system will attempt to store a NULL
 value into this field of the record. If the table does not
 support NULL values on that column, the operation will fail.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-save-record}  dbvar  key &optional  [var...] &key  [table=tablename]  [key=fieldname] 

 Write a record to the open SQL database connection referenced by
 @var{dbvar}, using @var{key} as the value of the primary key, on
 the table @var{table}.  The keyword argument @var{KEY} is the
 SQL column name of the column that you are specifying as the
 primary key.

 For each @var{var}, treat the name of @var{var} as a column
 name, and set that column's value to the value stored within
 @var{var}.

 An @code{UPDATE} is initially attempted to store the data.
 If the @code{UPDATE} fails, then an @code{INSERT} is
 attempted.

 NOTE: If the key field for table you are using is not configured
 as the primary key, then it is possible to create duplicate entries
 in the database.

 If you pass in a variable @var{var} which does not match a column
 name in @var{table}, that variable is silently ignored.

 If you try to save character data into a numeric field, the
 @code{INSERT} or @code{UPDATE} will fail.

 As always, the most recent query executed is available by
 calling the function @vref{sql::recent-query},
 and error messages may be retrieved by calling the function
 @vref{sql::sql-error-message}.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-set-options}  dbvar &key  [option-name=value] 

 Sets various database-specific options.

 Possible values for @var{option-name} are:

@itemize @bullet
 @item  @b{SQL-ESCAPE-CHARACTER-CODE}:
 The character which is used to escape single quotes in strings.
 @item  @b{SQL-TRUNCATE-COLUMNS}:
 When set to a non-empty string, queries composed by
 @vref{sql::database-save-record} and
 @vref{sql::database-save-package} will have
 character string field data automatically truncated to the maximum
 column width of the field being stored into, before the query is
 ever sent to the SQL server.
 @item  @b{SQL-PREFIX-TABLENAMES}:
 For @vref{sql::database-next-record} and
 @vref{sql::database-query}, prefix the names
 of symbols for column of the result set with the name table to which
 the column belongs.

@end itemize

@end deffn

@deffn {@i{Simple Tag}} {sql::database-table-info}  dbvar &optional  [tablename] &key  [result=varname]  [tabletype=regexp]  [tablequalifier=regexp]  [tableowner=regexp] 

 Returns an array of association lists, one per table in the
 open SQL database referenced by @var{dbvar}.

 Each alist contains database-specific information about the
 table, including at least the @i{name} of the table.

@example
@group
 ((name . "table_name"))

@end group
@end example

 The keyword arguments starting with
 @code{"table..."} are ANSI SQL regular expression
 patterns.  They are used if supplied, ignored if not.

 The keyword @var{result=varname} argument specifies the name of
 a variable to put the result array into; if not present, the
 array is returned to the caller.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-tables}  dbvar &key  [result=varname] 

 Return the names of the tables in the database referenced by
 @var{dbvar} as a newline separated list. If @var{varname} is
 supplied, it is the name of the variable to receive the table
 names.

@end deffn

@deffn {@i{Simple Tag}} {sql::database-tables-info}  dbvar &optional  [tablename] &key  [result=varname]  [tabletype=regexp]  [tablequalifier=regexp]  [tableowner=regexp] 

 Returns an array of association lists, one per table in the
 open SQL database referenced by @var{dbvar}.

 Each alist contains database-specific information about the
 table, including at least the @i{name} of the table.

@example
@group
 ((name . "table_name"))

@end group
@end example

 The keyword arguments starting with
 @code{"table..."} are ANSI SQL regular expression
 patterns.  They are used if supplied, ignored if not.

 The keyword @var{result=varname} argument specifies the name of
 a variable to put the result array into; if not present, the
 array is returned to the caller.

@end deffn

@deffn {@i{Simple Tag}} {sql::get-database-type} 

 Return the type of the underlying SQL database which will be accessed
 by the various SQL::... functions.  The possibilities are one of

@itemize @bullet
 @item  @b{msql}: The Minerva mSQL database from Hughes,
 @item  @b{mysql}: The mySQL database, or
 @item  @b{odbc}: A generic ODBC database, such as Oracle or Sybase.

@end itemize

@end deffn

@deffn {@i{Simple Tag}} {sql::host-databases} &optional  [host] 

 Return an array of the database names present on @var{host}
 (defaults to @code{localhost}.

 This command is only meaningful to the @code{mSQL} and
 @code{mySQL} database engines -- calling it on
 @code{odbc} databases always returns an empty array.

@end deffn

@deffn {@i{Simple Tag}} {sql::number-of-rows}  cursor 

 Return the number of rows SELECTed by the last SQL query execution,
 associated with the database referenced indirectly by @var{cursor}.

@end deffn

@deffn {@i{Simple Tag}} {sql::query-get-column} 

 Undocumented.

@end deffn

@deffn {@i{Simple Tag}} {sql::recent-query} 

 Returns the last SQL query statement that was sent to the underlying
 SQL database.  Can be useful in debugging.

@end deffn

@deffn {@i{Simple Tag}} {sql::search-form-params}  alist &key  [dsn]  [table]  [key]  [editurl]  [defcol]  [title] 

 Get or set the standard search form parameters.
 Always returns an association list of the current search form
 parameters, and can optionally set them to new values.  In
 typical usage, this function might be called as follows:

@example
@group
 <set-var orig-params =
    <sql::search-form-params DSN=<mydsn> table=CLIENTS>>
 <sql::standard-search-form posted>
 <set-var ignore = <sql::search-form-params <get-var-once orig-params>>>

@end group
@end example

 We have provided a simple but useful generic search form for use in
 your Meta-HTML pages.  Calling
 @vref{sql::standard-search-form} both produces
 the search form, and the results.

 You should set the following variables before calling
 @var{sql::standard-search-form}:

@itemize @bullet
 @item  sql::search-dsn -- The DSN string for the database.
 @item  sql::search-dbtable -- The name of the table in the database to search.
 @item  sql::search-keyname -- The name of the key field in the database.
 @item  sql::search-editurl -- The url of a single record editor.
 @item  sql::search-defcol -- The default column to display in the list.
 @item  sql::search-title -- The title to display in the input form.

@end itemize

 Optionally, you can specify columns that you would like not to be
 offered as columns that may be searched for, in the array
 sql::search-ignore-cols[].

@end deffn

@deffn {@i{Simple Tag}} {sql::set-database-type}  type 

 Create a command set called SQL::... which contains all of the functions
 normally used for accessing ODBC, mySQL, or mSQL databases.  This allows
 you to write a complete application using the mySQL database,
 @vref{sql::with-open-database} and
 friends, and then to painlessly "port" it to ODBC, simply by calling this
 function with an argument of @code{odbc}.

 The possible values for @var{type} are

@itemize @bullet
 @item  @b{msql}: The Minerva mSQL database from Hughes,
 @item  @b{mysql}: The mySQL database,
 @item  @b{pgsql}: The PostGres database, or
 @item  @b{odbc}: A generic ODBC database, such as Oracle or Sybase.

@end itemize

@end deffn

@deffn {@i{Simple Tag}} {sql::sql-error-message} 

 Return the current error message from recent SQL statements.

@end deffn

@deffn {@i{Simple Tag}} {sql::sql-transact} 

 Currently unimplemented.

@end deffn

@deffn {@i{Simple Tag}} {sql::standard-search-form} &optional  [package] &key  [fsize]  [href]  [title] 

 Display a complete form suitable for searching for a record from
 the database and table specified in @code{sql::search-dsn} and
 @code{sql::search-dbtable}.

 Optional keyword argument HREF specifies the destination page --
 it defaults to the current page if not supplied.
 Optional keyword FSIZE is the size of the font to use in the form --
 this has the effect of growing or shrinking the form.

 When this form is posted to, it gathers all of the
 columns which match the specified search criteria, and then
 displayes the results in a table, linking each to the
 sql::search-editurl.  When only one result is found, redirects
 to the page specified in @code{search::editurl}, providing a
 message in the session, displayable with
 @vref{show-message}, which explains why.

@end deffn

@deffn {@i{Simple Tag}} {sql::standard-search-handler}  package &key  [fsize]  [href] 

 Perform a database search on the search table using the criteria
 in PACKAGE.  Variables in PACKAGE must include:

@enumerate
 @item  csf-search   (simply must be set)
 @item  csf-column   (the name of the column to search on)
 @item  csf-operator (either "LIKE" "NOT LIKE" or "=")
 @item  csf-value    (the text to search for)

@end enumerate

 Produces a table with the contents of the specified column linked
 with an href to sql::search-defurl?.

 You can overide the information which is displayed for each record
 that matches the search criteria by creating a function called
 @b{sql::search-result-name}.  If this function exists, it should
 take two arguments: the column name that was being searched for, and
 an association list representing the data of the current record.

 An example might be to always display the last and first name of
 any search where the column name to be searched contained the
 string "name":

@example
@group
 <defun sql::search-result-name col alist>
   <if <match <get-var-once col> "name" caseless=true>
       <concat <alist-get-var alist last_name>
               ", "
               <alist-get-var alist first_name>>
     <alist-get-var alist <get-var-once col>>>
 </defun>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {sql::translate-column}  col 

 Return a pretty version of the column name specified in @var{col},
 by translating it through the array @var{sql::column-translations}.
 Each member of that array is a column name followed by a colon,
 followed by a pretty version of that column name.
 If @var{col} doesn't appear in the list of possible names, then
 it is simply capitalized.

@end deffn

@deffn {@i{Complex Tag}} {sql::with-open-database}  dbvar &key  [dsn=dsn-string]  [nolock=true] 

 Opens the database specified by DSN (database service name)
 string, and stores a referent to it in @var{dbvar}.  If the
 connection fails, the value of @var{dbvar} is the empty string.

 @var{DSN} should contain a minimum of
 "HOST=hostname;DATABASE=dbname" in order to connect successfully
 to an mSQL database.  Although the older @var{HOST=host} @var{DATABASE=dbname} keyword arguments are still supported, they
 have been deprecated, and the @var{DSN=dsn-string} form is
 preferred.

 If @var{nolock=true} is supplied, then no lock file on the server is
 created.  This is useful when you don't want to block other processes
 from accessing the database for the duration of the
 @code{sql::with-open-database} form.

@end deffn


@node Database Commands
@section GDBM Based Records
Meta-HTML contains commands for performing operations on a
database. A database created by Meta-HTML contains @i{records}
stored by @i{key}, where each record consists of a set of
@i{name/value} pairs.

There is a single command for specifying which database you will be
operating on: @vref{with-open-database}.  All of
the remaining database commands only have an effect when executed
within the scope of this function.

@vref{database-query} is the command used to
perform queries on a database, or to simply select a range of records
to operate on.

Functions which load, store, or delete a record as a single atomic
operation, return the string @code{"true"} when they succeed,
and store an error message in @vref{SYSTEM-ERROR-OUTPUT} when they do not.
@deffn {@i{Simple Tag}} {database-delete-record}  dbvar  key 

Remove the record associated with @var{key} from the database
referenced by @var{dbvar}.  This functions returns the string
@code{true} upon success.

@example
@group
<with-open-database db /tmp/file.db mode=write>
  <set-var deleted? = <database-delete-record db <get-var key>>>
</with-open-database>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-first-key}  dbvar 

Return a string representing the "first" key found in the database
referenced by @var{dbvar}.  The key is suitable for input to any of
the database functions which takes a key as input.  The order in which
keys are returned appears random, but the return value is always a
suitable argument to @vref{database-next-key}.

@end deffn

@deffn {@i{Simple Tag}} {database-load-record}  dbvar  key &key  [package=package-name] 

Load the variables from the record specified by @var{key} in the
database referenced by @var{dbvar}.  If @var{package=package-name} is
given, the record variables are stored into the specified package,
instead of the current package.

Upon success, this function returns the string @code{"true"}.

@example
@group
<with-open-database db /tmp/file.db mode=read>
  <set-var loaded? = <database-load-record db <get-var name> package=foo>>
</with-open-database>

<when <get-var loaded?>>
  The record was loaded successfully, and the
  value of NAME is <get-var foo::name>.
</when>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-next-key}  dbvar  after-key 

Return the "next" key in the database.  The key is found by looking
at @var{after-key}, which makes this function suitable for calling in
a loop.  For example, the following code iterates over an entire
database.

@example
@group
<with-open-database db /file.db mode=read>
  <set-var key=<database-first-key db>>
  <while <get-var key>>
    <package-delete record>
    <set-var loaded? =
      <database-load-record db <get-var key> package=record>>
    Key: <get-var key>, Name: <get-var record::name>
    <set-var key = <database-next-key db <get-var key>>>
  </while>
</with-open-database>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-query}  dbvar  expr &key  [format=fexpr]  [keys=varname]  [sort=field...]  [sortorder=reverse] 

Select records from the database referenced by @var{dbvar}, based on
@var{expr}, perhaps sorting them based on the data in @var{FIELD}s,
and optionally formatting them with the Meta-HTML expression in @var{fexpr}.

Both @var{expr} and @var{fexpr} are evaluated with the fields of the
database as the current package, so references to variables which are
not part of the record structure must be fully qualified (i.e., by
prefixing them with a package name. See @mref{Packages} for more
information.) If the result of evaluating @var{expr} is not the empty
string, then the record is selected for further processing by either
@var{format}, @var{keys}, or to be returned in a  plain text list of
keys. 

The order of evaluation is as follows:

First, the database is queried, and an internal list of selected
records is created.  Then, if @var{sort=field1,field2...} is present,
the records are sorted using the values of the specified fields.  The
order of the sort can be reversed by passed @var{sortorder=reverse}. 

Next, if @var{format=fexpr} is present, @var{fexpr} is executed for
each record, in an environment where the current package consists of
bindings for each field's name to each field's value, and the special
binding of @code{key} to the key of that record.  Finally, if
@var{keys=varname} is present, @var{varname} is the name of a variable
into which the matched keys are stored as an array.

The @var{sort} parameters indicates which fields to sort the resultant
keys on; the field names @var{field1,field2...} are separated by
commas.

Examples:

This simple query stores the key of every record in the database whose
@b{name} field contains "Fox" into the variable named
@b{dbkeys}:

@example
@group
<with-open-database db "/www/data/employee.db" mode=read>
  <database-query db <match <get-var name> "Fox"> keys=dbkeys>
</with-open-database>
@end group
@end example

This more complex query formats an alphabetical list of all the
members of the database who are employed as carpenters, and are
between the ages of 20 and 45, by creating links to a page which will
(presumably) get a more detailed listing of the individual record:

@example
@group
<with-open-database db "employee.db" mode=read>
  <database-query db sort=LastName
    <and <match <get-var job> "carpent">
         <gt age 20>
         <lt age 45>>
    format = <prog
               <a href="detail-display.mhtml?<cgi-encode key>">
               <get-var LastName>, <get-var FirstName>
               </a>: <get-var Job>, <get-var Age>>>
</with-open-database>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-save-package}  dbvar  key  package &key  [strip=true] 

Save the variables from the package @var{package} in the database
referenced by @var{dbvar} in the record specified by @var{key}.

If @var{strip=true} is supplied, then the names of the variables
written to the database have their package prefix removed as they are
written.

Upon success, this function returns the string @code{true}.

@example
@group
<set-var mykey="The Key" foo::x=x foo::array[0]=val0 foo::array[1]=val1>
<with-open-database db /tmp/file.db mode=write-create>
  <database-save-package db <get-var mykey> foo strip=true>
</with-open-database>
@end group
@end example

produces

@example
@group
true
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-save-record}  dbvar  key &optional  [var...] &key  [package=package-name] 

Save the variables @var{var1...varn} in the database referenced by
@var{dbvar} in the record specified by the key @var{key}.  If @var{package-name} is supplied, then the names of the variables written to
the database are written as if they belonged to that package.

Upon success, this function returns the string @code{true}.

Also see @vref{database-save-package}, and
@vref{database-load-record}.

@example
@group
<with-open-database db /tmp/file.db mode=write-create>
  <set-var saved? =
     <database-save-record db <get-var name> name age size>>
</with-open-database>

<when <get-var saved?>>
  The record was stored successfully.
</when>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-unique-key}  dbvar &optional  [suggestion] 

Return a key which is guaranteed to not already exist in the the
database referenced by @var{db}.  If @var{suggestion} is supplied,
that key is tried first, and then subsequent attempts are various
modifications to the suggestion.

@end deffn

@deffn {@i{Complex Tag}} {with-open-database}  dbvar  dbname &key  [mode=open-mode] 

Create an environment in which other database commands can be given.
First, the database referenced by @var{dbname} is locked and opened in
the mode specified by @var{open-mode}, and the resultant database
handle is bound to the variable named by @var{dbvar}.  Then, the @var{body} code is executed.  Finally, the database is closed, and further
references to @var{dbvar} are meaningless.

Please note that the file name specified by @var{dbname} should be a
full pathname; it is not relative to Web space in any way.

@var{open-mode} should evaluate to one of the following:

@itemize @bullet
  @item  @var{reader}

The caller wishes only to have read access to the specified database.

@item  @var{writer}

The caller wishes to have both read and write access to the specified
database.

@item  @var{write-create}

The caller wishes both read and write access to the specified
database.  If the database does not exist, it is created.

@end itemize

@end deffn


@node Direct Dbm Access
@section Database Commands
There are times when it is desirable to directly access DBM, NDBM, or
GDBM databases, for example, when reading or writing values to a
database created with a different tool, such as Perl or TCL.

Meta-HTML provides low-level access primitives for such databases in
addition to a higher-level, more generally useful abstraction
(which is detailed in @mref{Database Commands}).
@node Debugging Your Programs
@chapter Debugging Your Programs
@node Debugging Commands
@section Debugging Commands
Debugging a CGI application executing under a running Web server can be
quite problematic.  Meta-HTML provides the following functions, macros,
and variables in an effort to alleviate the problems associated with this
situation.In addition to the functions and variables above, Meta-HTML has a complete
source language debugger called @code{mdb}, which can be used to
interactively execute expressions, to place breakpoints in files and then
run them examining local and global variables, and to single-step through
source code that you have written in Meta-HTML.  Instructions on the
use of the debugger is beyong the scope of @i{this} manual -- please see
@b{MDB: A User's Guide to Debugging Meta-HTML Programs} for more
information specific to the debugger.
@deffn {@i{Simple Tag}} {debugging-on} &optional  [function-name=level...] 

Turns on debugging for the @var{function-name}s mentioned, setting
the level of output to @var{level}.  @var{level} is a number between
@code{0} (the least amount of debugging info) and
@code{10} (the maximum amount of debugging info).

The output is placed into the Meta-HTML internal debugger buffer, and
can be placed into an output page by simply placing the tag
@b{<DEBUGGING-OUTPUT>} somewhere in the page, or can be explicity
retrieved using   
@b{@code{<debugging-output retrieve>}}.

@end deffn

@deffn {@i{Simple Tag}} {debugging-output} &optional  [action...] 

Meta-HTML stores debugging information in an internal buffer.  You
may directly place information into this buffer using the @vref{page-debug} command, and you may retrieve or clear
this buffer using   
@b{@code{<debugging-output>}}.

Possible values for @var{action} are:

@itemize @bullet
@item  @b{retrieve}

Inserts the current contents of the debugging buffer into the page at
the current location.
@item  @b{clear}

Empties the debugging buffer of all stored information.

@end itemize

If you place    
@b{@code{<debugging-output>}} into your
page without passing any arguments, Meta-HTML treats this invocation
specially; it marks the location at which any debugging statements
which have been collected during the processing of the entire page
should be placed.

We recommend that you always place this tag somewhere in the output
page, whenever that output is an HTML document, as opposed to a
standalone script.

@end deffn

@deffn {@i{Simple Tag}} {dump-alist}  #alist &key  [recurse?] 

 Dump out the contents of @var{alist} in the same fashion as 
 @vref{dump-package} would.

@end deffn

@deffn {@i{Simple Tag}} {dump-all-packages} &key  [recurse?] 

 Call @vref{dump-package} on every defined package.
 If the keyword argument @var{recurse?} is supplied, it indicates
 that any association lists found as values in the package
 variables should be dumped out as well.

@end deffn

@deffn {@i{Simple Tag}} {dump-package} &key  [recurse?]  [text-mode?] &rest packages[]

 Dump the contents of the specified @var{packages} in a format
 suitable for including in @code{HTML} output.  If the
 keyword argument @var{RECURSE?} is non-empty, then recursively
 dump the contents of any alists found as values in @var{pack}.
 If the keyword argument @var{text-mode?} is non-empty, then
 dump the contents of the packages in a format suitable for
 placing within a <PRE> ... </PRE> construct.  This
 happens automatically when running under @b{mdb}.

@end deffn

@deffn {@i{Simple Tag}} {page-debug} &rest body

Cause @var{body} to be inserted into the debugger output.

The output is placed into the Meta-HTML internal debugger buffer, and
can be placed into an output page by simply placing the tag
@b{<DEBUGGING-OUTPUT>} somewhere in the page, or can be explicity
retrieved using   
@b{@code{<debugging-output retrieve>}}.

@end deffn

@deffn {@i{Simple Tag}} {system-error-output} &optional  [action...] 

Meta-HTML stores system error information in an internal buffer.
Such information may be the results of an error which occurred during
the execution of an external command (such as with @vref{cgi-exec}), or other information which is generated by
the inability of Meta-HTML to access a particular file (such as with
the @vref{require} command).

You may retrieve or clear this buffer using   
@b{@code{<system-error-output>}}.

Possible values for @var{action} are:

@itemize @bullet
@item  @b{retrieve}

Inserts the current contents of the system error buffer into the page at
the current location.
@item  @b{clear}

Empties the system error buffer of all stored information.

@end itemize

If you place    
@b{@code{<system-error-output>}} into your
page without passing any arguments, Meta-HTML treats this invocation
specially; it marks the location at which any system errors
which have been collected during the processing of the entire page
should be placed.

We recommend that you always place this tag somewhere in the output
page, whenever that output is an HTML document, as opposed to a
standalone script.

@end deffn


@node Dates And Times
@section Dates and Times
Meta-HTML provides a number of pre-defined functions for manipulating
date and time objects.  Along with the primitive builtins of @b{<date>}
and @b{<time>}, there are several functions defined with the prefix of
@code{date} which can be used to parse dates, convert between time
and date formats, format time strings in a variety of ways, and even
produce HTML-based calendars and the like.
@deffn {@i{Simple Tag}} {date} &optional  [seconds-since-epoch] &key  [gmt=true] 

Returns the local date as a string of 24 characters.

The output looks like @code{Mon Aug 17 13:07:40 1998}.

Given the optional argument @var{epoch-seconds}, this number is
treated as the number of seconds since 12 midnight, December 31st,
1969, and is converted into the current date.

When the keyword argument @var{gmt=true} is supplied, returns the date at
the meridian (Greenwich Mean Time) in the same format as used by HTTP headers,
such as the @b{Expires} header.

Examples:

@example
@group
<date>                  ==> Thu Nov 13 10:52:07 1997
<date gmt=true>         ==> Thu, 13 Nov 1997 18:52:07 GMT
<date <add <time> 60>>  ==> Thu Nov 13 10:53:07 1997
@end group
@end example

Also see the @vref{time} function.

@end deffn

@deffn {@i{Simple Tag}} {date::canonicalize}  date-string 

 Return the canonical version of DATE-STRING, in the format
 "MM/DD/YY HH:MM:SS".

 Example:
 @example
 <date::canonicalize <date>>

@end example
  produces
@example
 08/17/98 13:07:40

@end example

@end deffn

@deffn {@i{Simple Tag}} {date::days-in-month}  month 

 Return the number of days in @var{month}.
 @var{month} is the name of a month, such as "Apr" or "april".

@end deffn

@deffn {@i{Simple Tag}} {date::format-time}  format-string &optional  [time] 

 Return a string representation of the date from the time in @var{time}.
 If @var{time} is not supplied, it defaults to the current time.
 The format string consists of any characters you would like, with the
 following special sets being replaced by their corresponding elements
 of the date.  Please note that case is significant:

@itemize @bullet
 @item  @b{YY}:   Last two digits of the year.
 @item  @b{YYYY}: Four digits of the year.
 @item  @b{MM}:   Two digits of month, with January as @code{01}.
 @item  @b{MON}:  3 characters of month, as in @code{Jan}.
 @item  @b{MONTH}: The long name of the month, as in @code{March}
 @item  @b{DD}:   Two digits of day, as in @code{23}.
 @item  @b{DDD}:  3 character day of week, as in @code{Thu}.
 @item  @b{DAY}:  Full name of the weekday, as in @code{Tuesday}.
 @item  @b{hh}:   Hours, in 24 hour format, as in @code{17}.
 @item  @b{mm}:   Minutes, as in @code{43}.
 @item  @b{ss}:   Seconds, as in @code{04}.

@end itemize

 Example:
 @example
 <date::format-time "DAY, MONTH DD, YYYY (DD-MM-YY) at hh:mm:ss">

@end example
  produces
@example
 Monday, August 17, 1998 (17-08-98) at 13:07:40

@end example

@end deffn

@deffn {@i{Simple Tag}} {date::is-leap-year?}  year 

 Returns "true" if @var{year} is a leap year.

@end deffn

@deffn {@i{Simple Tag}} {date::long-month-name}  month 

 Return the canonical long name of @var{month}.
 @var{month} is the name of a month, such as "Apr" or "april".

@end deffn

@deffn {@i{Simple Tag}} {date::month-start-string}  time 

 Return a date string represent the first second of the month specified
 by @var{time}.
 @example
 <set-var now  = <time>>
 <set-var today= <date <get-var now>>>
 <set-var mstart = <date::month-start-string <get-var now>>>
 <pre>
  Now: <get-var today>
 Then: <get-var mstart>
 </pre>

@end example
  produces
@example

 @example
  Now: Mon Aug 17 13:07:40 1998
 Then: Sat Aug  1 00:00:01 1998

@end example

@end example

@end deffn

@deffn {@i{Simple Tag}} {date::month-table} &optional  [time] &key  [highlight-days[]]  [link-days[]]  [href]  [show-year]  [formatter] 

 Create a table representing the month found in @var{time}.

 Keyword argument @var{highlight-days} is an array of day numbers
 that you would like to have highlighted in the month display.

 Keyword argument @var{link-days} is an array of day numbers
 that should be linked to @var{href} in the month display.

 The arrays may have overlapping members.

 The keyword argument @var{href} is the document to go to when a linked
 day is clicked on -- it is passed the day, month, and year, as two
 digit fields in the POSTED package under the variable names
 @var{day}, @var{month}, and @var{year}.

 A example calling sequence:
@example
 <date::month-table
    highlight-days="3
8" link-days="18
8" href=<thisdoc>>

@end example

@end deffn

@deffn {@i{Simple Tag}} {date::month-table-centering-around} &optional  [time]  [count] &key  [bgcolor]  [formatter] 

 Display a table of @var{COUNT} months, centered around @var{TIME}.

 @var{TIME} defaults to the current time, while @var{COUNT} defaults
 to @code{3}.
 A example calling sequence:
@example
 <date::month-table-centering-around>

@end example

@end deffn

@deffn {@i{Simple Tag}} {date::parse-date}  string &optional  [pack] 

 Populates the package @var{pack} with the result of parsing
 @var{string}.

 If @var{string} is passed, that string is used instead of @b{<date>},
 and should be the date in human readable format, just as
 @vref{date} returns.

 If no @var{pack} is specified, returns an alist of the values instead.

@end deffn

@deffn {@i{Simple Tag}} {date::seconds-in-month}  month 

 Return the number of seconds in @var{month}.
 @var{month} is the name of a month, such as "Apr" or "april".

@end deffn

@deffn {@i{Simple Tag}} {date::seconds-since-epoch}  date-string 

 Return the number of seconds that have transpired between
 Jan 1, 1970 and @var{date-string}.

@end deffn

@deffn {@i{Simple Tag}} {date::short-month-name}  month 

 Return the canonical short name of @var{month}.
 @var{month} is the name of a month, such as "Apr" or "april".

@end deffn

@deffn {@i{Simple Tag}} {date::skip-days-backward}  count &optional  [time] 

 Return the seconds since the epoch representing the date which is
 exactly the first second of the day which is @var{count} days before
 the day represented by @var{time}.

 The @i{epoch} is defined as Jan 01, 1970, 00:00:00.

 @var{time} defaults to the current time.

@end deffn

@deffn {@i{Simple Tag}} {date::skip-days-forward}  count &optional  [time] 

 Return the seconds since the epoch representing the date which is
 exactly the first second of the day which is @var{count} days after
 the day represented by @var{time}.

 The @i{epoch} is defined as Jan 01, 1970, 00:00:00.

 @var{time} defaults to the current time.

@end deffn

@deffn {@i{Simple Tag}} {date::skip-months-backward}  count &optional  [time] 

 Return the seconds since the epoch representing the date which is
 exactly the first of month which is @var{count} months before the
 month represented by @var{time}.

 The @i{epoch} is defined as Jan 01, 1970, 00:00:00.

 @var{time} defaults to the current time.

@end deffn

@deffn {@i{Simple Tag}} {date::skip-months-forward}  count &optional  [time] 

 Return the seconds since the epoch representing the date which is
 exactly the first of month which is @var{count} months following the
 month represented by @var{time}.

 The @i{epoch} is defined as Jan 01, 1970, 00:00:00.

 @var{time} defaults to the current time.

@end deffn

@deffn {@i{Simple Tag}} {parse-date-string}  string 

 Deprecated.  Please use @vref{date::parse-date} instead.

@example
@group
 <parse-date-string> is equivalent to <date::parse-date <date> date>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {time} 

Returns the current local time, as measured in seconds since the
epoch (12 midnight, December 31, 1969).

This is often useful as input to the @vref{date}
operator.  Here is how one might find out the printable date for the
time 10 hours from now.

@example
@group
   <date> ==> Wed Jul  3 17:14:53 1996
   <date <add <time> <mul 60 60 10>>>
          ==> Thu Jul  4 03:14:57 1996
@end group
@end example

@end deffn


@node Working with the Server
@chapter Working with the Server

@node Server Variables
@section Server Variables
The Meta-HTML server (@code{mhttpd}) is configured by reading a
file of Meta-HTML code.  This allows arbitrary programming of the
server process, and means that you don't have to learn a new
configuration language in order to modify the server.

Included with the server is a set of administration pages; these pages
can be made accessible by telling the server where they are, and by
instructing the server to listen for requests on a specific port.

There are many variables which are important both to the engine and
the server.  Many of them are created on a per-page access basis by
either the engine or the server, and others are used to control the
server's behavior.

@defvr {@i{Variable}} {env::exec-path}
The list of directories that @vref{cgi-exec} will search when looking up the location of a
command.

Each component is a path to a directory, without the final trailing
slash, separated from its neighbors by a colon character
(@code{:}).

For example:

@example
@group
   <set-var env::path="/www/bin:/www/docs/cgi-bin">
@end group
@end example

@end defvr

@defvr {@i{Variable}} {env::http-authorization}
The @code{Basic Authorization}
string, as received by the server.  By the time that you see this
string, the user has already been authorized.
@end defvr

@defvr {@i{Variable}} {env::http-referer}
A synonym for @code{mhtml::referer}.
@end defvr

@defvr {@i{Variable}} {env::http-user-agent}
The name that the connecting client
browser passed as the value of the @code{User-Agent} MIME
header.

For example:

@example
You are connected using: <get-var env::http_user_agent>
@end example
  produces
@example
You are connected using: Mozilla/3.0 (X11; U; Linux 1.3.20 i386)
@end example
@end defvr

@defvr {@i{Variable}} {env::query-string}
The raw query string which was passed in
this URL.  In many cases, Meta-HTML can create variables in the
@code{POSTED} package based upon the contents of this string.
In some cases, the string doesn't contain any variable assignments
(e.g., when the URL is an imagemap target).  For such cases, you may
need direct access to the query string.

@example
<get-var env::query_string>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {env::remote-addr}
The Internet Protocol address of the
connecting client host, in "dot" notation.  You may wish to use
@code{env::remote_host} instead.

@example
<get-var env::remote_addr>
@end example
  produces
@example
127.0.0.1
@end example
@end defvr

@defvr {@i{Variable}} {env::remote-host}
The host name of the connecting client.  In
cases where the connecting client does not have a host name which can
be looked up by the use of DNS, this variable contains the host's
Internet Protocol address, in "dot" notation.

@example
<get-var env::remote_host>
@end example
  produces
@example
nirvana.datawave.net
@end example
@end defvr

@defvr {@i{Variable}} {env::server-port}
The port on which the current web server is
listening for connections.

@example
<get-var env::server_port>
@end example
  produces
@example
80
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::access-log}
The complete path to the file where the
MHTTPD server should keep the per-page access information.

The access log contains lines written in W3c's Common Logfile Format.
@end defvr

@defvr {@i{Variable}} {mhtml::cacheable}
The variable MHTML::CACHEABLE, when set to
a non-null value, indicates to the engine or server that the
expiration date of the current page should be in the future
(currently, about 10 days in the future).
@end defvr

@defvr {@i{Variable}} {mhtml::cgi-directories}
This array is a list of physical
paths relative to the document root which are directories containing
CGI programs.

The paths are checked @i{after} path translation has been
performed.  The final slash for each directory must be specified.

@example
<get-var mhtml::cgi-directories[0]>
@end example
  produces
@example
/cgi-bin/
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::cgi-extensions}
An array of file name extensions that
specifies to the MHTTPD server the file name extensions which indicate
that the file is really a CGI program to be executed.

@example
@group
  <set-var mhtml::cgi-extensions[0]=".pl">
@end group
@end example

@end defvr

@defvr {@i{Variable}} {mhtml::cookie-compatible}
Indicates whether or not the
current client/server pair can pass HTTP
Cookies back and forth.

When such communication is possible, this variable is set to
@code{"true"}.
@end defvr

@defvr {@i{Variable}} {mhtml::current-doc}
The name of the current document, without
any path information, query strings, etc.

If the current URL is:

@example
@group
http://www.company.com/foo/bar/doc.mhtml?this=that
@end group
@end example

then @code{MHTML::CURRENT-DOC} is:

@example
@group
doc.mhtml
@end group
@end example

@end defvr

@defvr {@i{Variable}} {mhtml::current-url}
A synonym for @code{mhtml::location}.
@end defvr

@defvr {@i{Variable}} {mhtml::current-url-sans-sid}
A synonym for @code{mhtml::location-sans-sid}.
@end defvr

@defvr {@i{Variable}} {mhtml::debug-log}
The complete path to the file where the
MHTTPD server should write server specific debugging information.
Generally, this only needs to be defined when you are debugging the
server itself.

@example
<get-var mhtml::debug-log>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::default-filenames}
An array specifying the file names
that should be looked up when the URL to fetch ends in a directory,
instead of a document specifier.  The files are searched for in the
order in which they appear in this array.

@example
<get-var mhtml::default-filenames[]>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::document-root}
The complete path to the directory from
which your documents are to be served.  The final slash should not be
present.

@example
<get-var mhtml::document-root>
@end example
  produces
@example
/www/localhost/docs
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::epilogue-document}
Specifies a per-connection file of
code to be appended to the page just before processing any Meta-HTML
document.

@example
<get-var mhtml::epilogue-document>
@end example
  produces
@example
/www/localhost/epilogue.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::error-log}
MHTML::ERROR-LOG is the full path to a file
to which the server (or engine) logs errors.

@example
<get-var mhtml::error-log>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::full-url}
The URL used to connect to the current
document, including protocol, host information, session ID,
path-information, and query strings.

@example
<get-var mhtml::full-url>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual/make-printable.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::full-url-sans-sid}
The URL used to connect to the
current document, including protocol, host information,
path-information, and query strings, but excluding the session ID.

@example
<get-var mhtml::full-url-sans-sid>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual/make-printable.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::http-prefix}
The portion of the current URL which
contains the protocol, host information, and the session ID.

@example
<get-var mhtml::http-prefix>
@end example
  produces
@example
http://localhost.ua.com
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::http-prefix-sans-sid}
The portion of the current URL
which contains the protocol, host information, but excluding the
session ID.

@example
<get-var mhtml::http-prefix-sans-sid>
@end example
  produces
@example
http://localhost.ua.com
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::http-to-host}
A synonym for @code{mhtml::http-prefix}.
@end defvr

@defvr {@i{Variable}} {mhtml::location}
The URL used to connect to the current
document, including path information and query strings, but without
the protocol or host information.

@example
<get-var mhtml::location>
@end example
  produces
@example
/meta-html/manual/make-printable.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::location-sans-sid}
The URL used to connect to the
current document, including path information and query strings, but
without the protocol, host information, or Session ID.

@example
<get-var mhtml::location-sans-sid>
@end example
  produces
@example
/meta-html/manual/make-printable.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::metahtml-extensions}
An array of file name extensions
which indicate that the document to be fetched contains Meta-HTML
code.

Normally, this variable is set in the server process.

@example
<get-var mhtml::metahtml-extensions[]>
@end example
  produces
@example
.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::mhttpd-pages}
MHTML::MHTTPD-PAGES is the directory
containing various pages used by the server for displaying error
conditions, directory files, etc.  This is a complete path to the
directory, without the trailing slash.

@example
<get-var mhtml::mhttpd-pages>
@end example
  produces
@example
/www/localhost/mhttpd-pages
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::prologue-document}
MHTML::PROLOGUE-DOCUMENT is a
per-connection file of code to be run just before processing any
Meta-HTML document.

@example
<get-var mhtml::prologue-document>
@end example
  produces
@example
/www/localhost/prologue.mhtml
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::raw-content-data}
Contains @i{exactly} what the
client browser sent in its @code{POST} request.

For wizard's use only!
@end defvr

@defvr {@i{Variable}} {mhtml::referer}
The value of the @code{HTTP}
@i{Referer} MIME header which the client browser sent along in its
request.

You might use this variable, if it is present, as the target of an
anchor:

@example
@group
<a href="<get-var mhtml::referer>">
  <b>Back</b> to referring document.
</a>
@end group
@end example

@end defvr

@defvr {@i{Variable}} {mhtml::relative-prefix}
The sub-portion of the document path
which appears after @code{mhtml::include-prefix}.

With @code{mhtml::include-prefix} equal to @code{/www/docs}, and a
document path of @i{/www/docs/admin/sections.mhtml} then the value
of @code{mhtml::relative-prefix} would be @i{/admin}.

Useful when constructing new URLs based on the current URL.
@end defvr

@defvr {@i{Variable}} {mhtml::remote-ident}
The value of the environment variable
@code{ENV::REMOTE_IDENT} as received by the server.

In the Meta-HTML server, you can turn on the feature of asking the
connecting host for the username of the individual running the client
browser by setting @code{MHTTPD::GET-REMOTE-IDENT}.

There is never any gaurantee that the client will allow the server to
find this information out, so you should not write code which relies
on the presence of this variable.  However, if it is present, it can
be useful to present a default value.  For example:

@example
@group
<when <not <get-var e-mail>>>
  <set-var e-mail = <get-var mhtml::remote-ident>>
</when>
@end group
@end example

@end defvr

@defvr {@i{Variable}} {mhtml::remote-user}
The value of the environment variable
@code{ENV::REMOTE_USER} as received by the server.

When @code{Basic Authorization} is supplied by a client, this
variable contains the username which the connected user supplied.  Do
NOT confuse this with ENV::REMOTE_IDENT!
@end defvr

@defvr {@i{Variable}} {mhtml::require-directories}
An array of directory names to be
searched through in order by @vref{require}.  The
directories should be specified without the trailing slash.
@end defvr

@defvr {@i{Variable}} {mhtml::require-loaded}
The list of pathnames which have
already been loaded through @vref{require}.
@end defvr

@defvr {@i{Variable}} {mhtml::server-name}
MHTML::SERVER-NAME is the name that this
server should advertise.  If you do not set it, the value of the
current host's name is used.  On Unix systems, this is the result of
calling @code{gethostname()}.

@example
<get-var mhtml::server-name>
@end example
  produces
@example
localhost.ua.com
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::server-port}
MHTML::SERVER-PORT is the port on which
this server should answer HTTP requests.  If you do not set it, the
value is @code{80}.

@example
<get-var mhtml::server-port>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::server-root}
MHTML::SERVER-ROOT is the root location
for your server.  You might store the configuration, logging, and
server specific files there, for example.  You currently cannot store
your CGIs there, because that directory must be underneath @code{MHTML::DOCUMENT-ROOT}.

The pathname should not end in a slash.

@example
<get-var mhtml::server-root>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::unparsed-headers}
When set to true, indicates to the
Meta-HTML Engine that the server is expecting the engine to produce
all of the @code{HTTP} results, and not just the
@code{HTML} results.

This variable is automatically set in the Meta-HTML server, and when
the Engine is run under a name beginning with @code{"nph-"}.

You can turn this variable on or off during the invocation of a
specific page to control the behavior of both the server and engine.

@example
<get-var mhtml::unparsed-headers>
@end example
  produces
@example

@end example
@end defvr

@defvr {@i{Variable}} {mhtml::url-to-dir}
The complete URL to the directory
containing the current document.  This includes protocol, host,
session ID, and relative prefix information.

@example
<get-var mhtml::url-to-dir>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual
@end example
@end defvr

@defvr {@i{Variable}} {mhtml::url-to-dir-sans-sid}
The complete URL to the directory
containing the current document.  This includes protocol, host, and
relative prefix information, but excludes the session ID if one were
present.

@example
<get-var mhtml::url-to-dir-sans-sid>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual
@end example
@end defvr

@defvr {@i{Variable}} {mhttpd::get-remote-ident}
MHTTPD::GET-REMOTE-IDENT, when set,
says to use the IDENT protocol to attempt to find out the username
associated with the connecting browser.  This only has a minor effect
on server performance, but isn't especially useful for non-Meta-HTML
sites.
@end defvr

@node Working with Modules
@chapter Working with Modules

@node Dynamic Modules
@section Dynamic Modules
You can now write C language code to implement your own built-in
Meta-HTML functions!  Such functions are first-class objects, and
can manipulate the Meta-HTML environment directly, easily reset the
parser pointer, manage hardware devices or talk on proprietery
networks, or anything else that you can do in C. 

It works by supplying you with the necessary Meta-HTML header files
and a Makefile for building modules on your system.  Using our
supplied Makefile provides you with a resultant @i{dynamically
loadable} module, which can be loaded into the Server, Engine, or a
single page with the @vref{load-module} function.

See the @code{modules} directory of the distribution for more
details.
@deffn {@i{Simple Tag}} {load-module}  module-name &key  [noinitialize]  [initfunc] 

Loads a module dynamically at runtime, adding the function
definitions found therein to the global package of Meta-HTML
functions.

@code{load-module} returns a non-empty string if the module is
loaded successfully, or places an error in @vref{system-error-output} if not.  The string returned is the fully
qualified pathname of the module just loaded.

@var{module-name} is searched for by looking in each directory
specified in the array @code{mhtml::module-directories}, or by
loading the module as if the name specified is the full pathname to
that file.

Once a module is loaded, the functions within it can be invoked just
as with any standard Meta-HTML command.

See the @code{examples.c} file in the @code{modules}
directory of your distribution for more information on writing
Meta-HTML modules.

The keyword argument @var{noinitialize} when set to "true" says
not to call the default initialization function of the module
(@i{module_initialize}).  This function is typically used to install
the function names of the Meta-HTML callable functions present within the
module.  When such initialization is not required (perhaps you are planning
to do this from within a different module), the use of this argument
prevents the attempted call.

The keyword argument @var{initfunc} may be set to the name of the
initialization function to call immediately after the module is
loaded.  If it is not set, or it is empty, the function
@b{module_initialize} is called.

Example:

@example
@group
<set-var loaded? = <load-module /www/lib/example.so>>
@end group
@end example

@end deffn

@defvr {@i{Variable}} {mhtml::loaded-modules}
An array of fully qualified pathnames to the modules which have been loaded
via the function @vref{load-module}.  Used internally
during the module search process.
@end defvr

@defvr {@i{Variable}} {mhtml::module-capable}
This value of this symbol is "true" when the system on which Meta-HTML
is running is capable of loading dynamic modules.  The value is determined
at the time Meta-HTML is compiled.
@end defvr

@defvr {@i{Variable}} {mhtml::module-directories}
An array of pathnames used to locate dynamic modules.

When @vref{load-module} is called with a non-fully qualified
pathname as an argument, the location of the file containing the module code
is searched for throughout the list of directories in
@var{mhtml::module-directories}.  The default list of directories includes at
least the following, and may have more dependent on your system type:

@example
@group
/www/lib, /www/bin, /www/metahtml/lib, /www/metahtml/bin,
/opt/lib, /opt/bin, /opt/metahtml/lib, /opt/metahtml/bin,
/usr/lib/mhtml, /home/mhttpd/lib, /usr/local/mhtml/lib,
and /www/src/metahtml/modules
@end group
@end example

@end defvr

@deffn {@i{Simple Tag}} {module-call-function}  module-name  function-name &rest args

Call the function @var{function-name} in the dynamically loaded module
@var{module_name} with character arguments of @var{args}.
It returns "true" if the function invocation took place.  More likely,
you will be crashing Meta-HTML without a way to debug it.

Up to ten arguments can be passed to the function.

It is so unlikely that you need this, that you will have to write me E-mail
or read the source to see exactly how this works.  If you are calling this
function, the called function should not produce any output at all, and,
in fact, there isn't a way for you to get output back from the function,
since you can't pass the address of a variable, etc.  This might be used to
re-initialize some internals of your module, but you should really just
provide an interface for that instead.

@end deffn

@deffn {@i{Simple Tag}} {module-function}  module-name  function-name 

Returns the address of @var{function-name} in @var{module-name} if
@var{module-name} is an already loaded dynamic module, and @var{function-name}
is a function defined within that module.

Otherwise, it returns the empty string.

@example
@group
<load-module example>                 ==> /www/lib/example.so
<module-function example pf_apropos>  ==> 0X0EF8C437C
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {unload-module}  module-name 

Unloads a previously loaded dynamic module.  You might want this if you
are running Meta-HTML as a FastCGI, and the module was temporarily needed
for some service, and was inordinately large.

Returns "true" if the module was successfully unloaded.

@end deffn


@node Installation Guide
@chapter Installation Guide

@node Installing the Server
@section Installing the Server

@subsubheading General Instructions for Installation

  There are distribution specific instructions located in the
  directories @b{Server}, @b{Engine}, and @b{Processor}.  You
  may have only one of these directories if you elected to obtain only
  the Server, Engine, or Stand-Alone Processor, or, you may have all
  of them if you received the Meta-HTML Tools Suite distribution.

@subsubheading Installing Your First Web Server

  Installing the Meta-HTML Server is quite straight-forward, and only
  requires you to have the most minimal knowledge of Unix-like systems.
  For those of you who can't wait, the following sequence is sufficient
  to install the Meta-HTML Server on a machine that is not already
  running a web server:

@enumerate
  @item  Choose a directory under which your server will be installed,
  say, "/usr/www".  We will call this directory   
@b{@code{<wwwroot>}}:

@example
@group
    (mkdir /usr/www)

@end group
@end example

  @item  Create   
@b{@code{<wwwroot>/bin}},   
@b{@code{<wwwroot>/docs}},   
@b{@code{<wwwroot>/conf}}, and   
@b{@code{<wwwroot>/logs}}.

@example
@group
    (mkdir /usr/www/bin /usr/www/docs /usr/www/conf /usr/www/logs)

@end group
@end example

  @item  Copy @code{"Server/mhttpd"} and @code{"Utilities/*"} to

@b{@code{<wwwroot>/bin}}.

@example
@group
    (cp Server/mhttpd /usr/www/bin)

@end group
@end example

  @item  Copy @code{"Documentation"} to   
@b{@code{<wwwroot>/docs}}.

@example
@group
    (cp -r Documentation /usr/www/docs)

@end group
@end example

  @item  Copy @code{"Server/mhttpd.conf"} to   
@b{@code{<wwwroot>/conf}}.

@example
@group
    (cp Server/mhttpd.conf /usr/www/conf)

@end group
@end example

  @item  Change @code{"www.myhost.com"} to the name of your host in the
  configuration file   
@b{@code{<wwwroot>/conf/mhttpd.conf}}.  You
  can do this by either editing the file with your favorite editor (say,
  emacs), or by @code{"sed"}ing the original file:

@example
@group
    (cat Server/mhttpd.conf | sed -e "s/www.myhost.com/`hostname`/"
		>/usr/www/conf/mhttpd.conf)

@end group
@end example

  @item  As the superuser, start the server from the   
@b{@code{  <wwwroot>}} directory:

@example
@group
    (cd /usr/www; su -c bin/mhttpd)

@end group
@end example

@end enumerate

  Congratulations, you are now running the Meta-HTML Server, and you
  have a Web site!  You can now go to your first URL:

  Start a browser, and connect to

@b{@code{"http://<your-host>/Documentation"}}, where
  @code{"<your-host>}" should be replaced with the name of
  your machine.

@subsubheading Co-habitating the Meta-HTML Server with an Existing Server

  You may run the Meta-HTML Server on a non-standard port (such as 8080), or
  under an aliased IP address for your machine.  The Server tightly binds to
  the address and port that it finds in the configuration file.  The newly
  installed server may serve the same documents that you are already serving
  with another server, or, may be configured to serve a different set of
  documents.

  If you are installing the Server with its own set of documents to serve, and
  its own IP address, simply follow the instructions given under `Installing
  Your First Web Server'.

  Otherwise, the intructions are almost identical; but you must manually
  edit the `mhttpd.conf' file and change the port number to 8080.  You
  do this by changing the line which reads:

@example
@group
    <set-var mhtml::server-port = <if <get-var mhttpd::ssl-server> 443 80>>

@end group
@end example

  to read:

@example
@group
    <set-var mhtml::server-port = 8080>

@end group
@end example

  Then start the server as described above.  The documents are served
  from the directory specified in `@code{MHTML::DOCUMENT-ROOT}'.


@node Configuring the Apache Server
@section Configuring the Apache Server

  There are three possibilities to choose from when configuring your
  Apache server to work with Meta-HTML files:

@enumerate
    @item  You can run every document on your
    server through the Meta-HTML CGI Engine.  While there is
    nothing horribly wrong with this, it is essentially equivalent to
    running the Meta-HTML server itself, so we do not highly
    recommend it.

    @item  You can run only Meta-HTML
    documents through the Meta-HTML CGI Engine, foregoing the
    ability to use statefull sessions with non-cookie capable
    browsers.  If you never use statefull sessions, or, if you only
    have cookie-capable clients connecting to your server (e.g.,
    Netscape, MSIE), this solution is completely reasonable, and
    totally painless.

    @item  You can run only Meta-HTML
    documents through the Meta-HTML CGI Engine, handling the
    case of non-cookie capable browsers co-existing with statefull
    sessions.  This is our recommended configuration.

@end enumerate

  @subsubheading Step 1: Install the Engine:
  In order for the Engine to operate under Apache, you must place it
  in your @code{cgi-bin} directory, and make it executable.  For
  example, if your @code{srm.conf} file contained:
  @example
   ScriptAlias /cgi-bin/ /www/htdocs/cgi-bin/
@end example
  then you would copy the Engine and its config file to that directory:
  @example
   user@@@@host$ cp engine/engine /www/htdocs/cgi-bin/nph-engine
   user@@@@host$ cp engine/engine.conf /www/htdocs/cgi-bin/
@end example

  @subsubheading Step 2: Edit the @code{engine.conf} file:
  Now edit the @code{engine.conf} file in
  @code{/www/htdocs/cgi-bin}, simply by reading the comments.
  For most installations, you won't actually need to change any of the
  parameters defined within -- the saavy site administrator may wish
  to add special behaviour, or to modify the existing behaviour.

  @subsubheading Step 3: Edit the Apache @code{srm.conf} file:
  Now edit the @code{srm.conf} for your Apache server.
  There are two possible edits:

@enumerate

    @b{@item Running Every Document Through the Engine}

    Add the following line before all of your other @code{ScriptAlias}
    lines:
    @example
     ScriptAlias / /cgi-bin/nph-engine

@end example

    @b{@item Running Only Meta-HTML Documents Through the Engine}

    Add the following lines to the @code{srm.conf} file, before
    all other @code{ScriptAlias} lines:
    @example
     AddType metahtml/interpreted .mhtml
     Action metahtml/interpreted /cgi-bin/nph-engine

@end example

@end enumerate

  @subsubheading Step 4: Compiling Apache 1.x With the Meta-HTML "mini-module":
  If you want to make sure that non-cookie capable browsers can have
  statefull sessions, you will need to recompile your 1.x server
  with the Meta-HTML mini-module installed.  Here is how to do that:

@enumerate
    @b{@item }
    Place the following line in @code{src/Configuration} (in
    your Apache 1.x source tree)
    @example
     Module mhtml_module           mod_mhtml.o
@end example

    @b{@item }
    Copy the @code{mod_mhtml.c} file to the @code{src}
    directory of your Apache 1.x source tree.

    @b{@item }
    Reconfigure the compilation of your server by typing
    @code{./Configure} from the @code{src} directory of
    your Apache 1.x source tree.

    @b{@item }
    Recompile the Apache server by typing @code{make}, and then
    copy the @code{httpd} file to whereever you have installed
    the previous version of the Apache server.

@end enumerate

  @subsubheading That's it!
  Congratulations!  You have configured the Meta-HTML Engine to work
  with your Apache server!

  So that you can see exactly what the mini-module does, I have
  included the source code below:

@example
  /* mod_mhtml.c: -*- C -*-  Apache mini-module code for Meta-HTML. */

  #include "httpd.h"
  #include "http_config.h"
  #include "http_request.h"
  #include "http_core.h"
  #include "http_protocol.h"
  #include "http_log.h"
  #include "http_main.h"
  #include "util_script.h"

  /* If the URI starts with a string of digits, leave them there, but
     make the filename be everything after it. */
  static int
  translate_filename (struct request_rec *req)
  @{
    register int i;
    int result = DECLINED;

    if ((req->uri != (char *)NULL) &&
        ((req->uri[0] == '/') && (isdigit (req->uri[1]))))
      @{
        for (i = 1; isdigit (req->uri[i]); i++);

        /* If the URI contains a cookie, then gobble it, stuff it into
           req->subprocess_env, and move along. */
        if (req->uri[i] == '\0' || req->uri[i] == '/')
          @{
            register int j;
            char *value = (char *)palloc (req->pool, 1 + i);
            table *page_env = req->subprocess_env;

            strncpy (value, req->uri + 1, i - 1);
            value[i - 1] = '\0';

            for (j = 0; req->uri[i] != '\0'; j++, i++)
              req->uri[j] = req->uri[i];

            req->uri[j] = '\0';

            /* Now stuff the value into a meaningful environment variable. */
            table_add (req->subprocess_env, "METAHTML_URL_COOKIE", value);
          @}
      @}

    return (result);
  @}

  module mhtml_module =
  @{
     STANDARD_MODULE_STUFF,
     NULL,                      /* initializer */
     NULL,                      /* dir config creater */
     NULL,                      /* dir merger --- default is to override */
     NULL,                      /* server config */
     NULL,                      /* merge server config */
     NULL,                      /* command table */
     NULL,                      /* handlers */
     translate_filename,        /* filename translation */
     NULL,                      /* check_user_id */
     NULL,                      /* check auth */
     NULL,                      /* check access */
     NULL,                      /* type_checker */
     NULL,                      /* fixups */
     NULL                               /* logger */
  @};
@end example


@node Configuring the Netscape Server
@section Configuring the Netscape Server

  At the time of this document, Netscape did not provide a way
  to use their browser based admin interface to configure either the
  Commerce or Communications server to execute the Meta-HTML
  Engine for every document reference (this is required to handle
  the passing of cookies to and from non-cookie capable browsers).

  In addition, calling technical support at Netscape resulted in the
  answer, "Oh, you can't do that."

  So, here is how you do it:

@itemize @bullet
    @item  Locate the configuration directory for the server in question.
    Let's say that this is
    @b{@code{/usr/ns-home/httpd-80.127.0.0.1/config}}

    @item  Locate the actual directory containing your WWW documents.
    Let's say it is @b{@code{/usr/www/docs}}

    @item  @b{@i{Manually}} edit the @b{obj.conf} file you
    found in the config directory, happily ignoring the warning not to
    do so at the top of the file.  Here is what you do:

@enumerate
      @item  Make sure that you have the @i{Object} which is named
      @b{cgi}.  The entry should look like this:

      @example
      <Object name="cgi">
      ObjectType fn="force-type" type="magnus-internal/cgi"
      Service fn="send-cgi"
      </Object>

@end example

      @item  In the @b{default} @i{Object}, add the following
      @b{NameTrans} line:

      @example
NameTrans from="" fn="pfx2dir" method=".*" dir="/usr/www/docs/cgi-bin/nph-engine" name="cgi"

@end example

      @item  Save this file.  Remember, you @i{have} manually edited
      this file, so it is probably wise to save at least one extra
      copy of it that won't be overwritten by the Netscape admin
      pages.

@end enumerate

    @item  Copy the Meta-HTML Engine to the file that you
    specified in the @b{NameTrans} entry:

    @code{ cp engine /usr/www/docs/cgi-bin/nph-engine }

    @item  Tell the Engine where the document root directory is.  You do
    this in the usual way, by placing the following into
    @code{/usr/www/docs/cgi-bin/engine.conf}:

    @code{<set-var mhtml::document-root = /usr/www/docs>}

    @item  Restart your server.

@end itemize

Here is a sample @b{obj.conf} file from a working site.

@example
# This file was automatically generated by the server.
# Edit at your own risk.

<Object name="default">
NameTrans fn="home-page" path="index.html"
NameTrans from="" fn="pfx2dir" method=".*" dir="/usr/www/docs/cgi-bin/nph-boxtop-engine" name="cgi"
NameTrans from="/mc-icons" fn="pfx2dir" dir="/usr/ns-home/mc-icons"
NameTrans from="/cgi-local" fn="pfx2dir" dir="/usr/www/docs/cgi-bin" name="cgi"
NameTrans from="/cgi-bin" fn="pfx2dir" dir="/www/cgi-bin" name="cgi"
NameTrans fn="unix-home" from="/~" subdir="public_html"
NameTrans root="/www/tvcopsdev/site" fn="document-root"
PathCheck fn="unix-uri-clean"
PathCheck fn="find-pathinfo"
PathCheck index-names="index.html,home.html" fn="find-index"
ObjectType fn="type-by-extension"
ObjectType fn="force-type" type="text/plain"
ObjectType fn="shtml-hacktype"
Service fn="imagemap" method="(GET|HEAD)" type="magnus-internal/imagemap"
Service fn="index-common" method="(GET|HEAD)" type="magnus-internal/directory"
Service fn="send-cgi" type="magnus-internal/cgi"
Service fn="parse-html" method="(GET|HEAD)" type="magnus-internal/parsed-html"
Service fn="send-file" method="(GET|HEAD)" type="*~magnus-internal/*"
<Client ip="*~204.119.208.*">
AddLog iponly="1" fn="common-log"
</Client>
</Object>

<Object name="cgi">
ObjectType fn="force-type" type="magnus-internal/cgi"
Service fn="send-cgi"
</Object>
@end example


@node Configuring the NSAPI Server
@section Configuring the NSAPI Server

  A sample obj.conf configuration has been supplied.

  The file @code{mhtml_nsapi.c} is an
  NSAPI module which provides a clean and more flexible way to call
  the Meta-HTML CGI Engine conveniently from the Netscape server.

  The following features are provided by this module:

@itemize @bullet
    @item  Configuration of the Netscape server to run only files which end in
    .mhtml (or the file-suffix of your choice) through the CGI engine.

    @item  Hiding of the location of the CGI Engine in your URL, so that
    instead of needing to use a URL such as:

@example
@group
      http://yourhost.com/cgi-bin/nph-engine/your/url.mhtml

@end group
@end example

    you can use 

@example
@group
      http://yourhost.com/your/url.mhtml

@end group
@end example

    @item  Passing of the correct PATH-INFO information from your URL to the
    Meta-HTML CGI Engine.

    @item  Backward compatibility with older non-cookie compatible browsers,
    for using session state features in the Meta-HTML Engine.

@end itemize

  @b{Compiling The NSAPI Module}

  If you did not receive a compiled binary shared library file of the
  NSAPI module, you will need to compile it. If you have the binary
  already, skip this section.

@enumerate
    @item  Copy the nsapi-dist directory into the nsapi directory of your
    Netscape server, typically ns-home/nsapi. (You can use "cp -r"
    to recursively copy the whole nsapi-dist directory.)

    @item  Edit the Makefile for your system, and type "make". 

@end enumerate

  The way you do the final link to create a shared library varies
  greatly on different Unix systems. Some hints are shown below:

             	@b{Options for Linking}

      	@b{System}
	 @b{Compile Options}

                 IRIX 
             ld -shared t.o u.o -o test.so

                 SunOS 
             ld -assert pure-text t.o u.o -o test.so

                 Solaris 
             ld -G t.o u.o -o test.so

                 OSF/1 
             ld -all -shared -expect_unresolved "*" t.o u.o -o test.so

                 HP-UX 
             ld -b t.o u.o -o test.so

      When compiling your code, you must also
      use the use the +z flag to the HP C compiler. 

                 AIX 
             cc -bM:SRE -berok t.o u.o -o test.so -bE:ext.exp -lc

      The ext.exp file must be a text file with the name of a 
      function that is externally accessible for each line. 

  @b{ Configuring Your Netscape Server's obj.conf File }

  Your Netscape Server has a directory of configuration files,
  containing at least obj.conf and magnus.conf. It is typically
  located in the directory ns-home/httpd-your-hostname/config

  The Meta-HTML NSAPI module defines several new functions, which
  you must add to your obj.conf file.

  Let's assume you have set up your web server with the following
  files in the following locations:

  @b{A.} The mhtml_nsapi.so file is in /ns-home/nsapi/nsapi-dist/mhtml_nsapi.so:

  @b{B.} Your web server document root is in /www/docs

  @b{C.} Your Meta-HTML CGI Engine is in /www/docs/cgi-bin/nph-engine

@enumerate
    @item  First, you must add a line which loads the mhtml_nsapi module

@example
@group
      Init fn=load-modules shlib=/ns-home/nsapi/nsapi-dist/mhtml_nsapi.so funcs=handle-mhtml-sid,mhtml_fixup_path

@end group
@end example

    @item  Find the definitions in the "default" object:

    Look for the line

@example
@group
      <Object name="default">

@end group
@end example

    Right after this, you should place a NameTrans call to handle_mhtml_sid:

@example
@group
      NameTrans fn=handle-mhtml-sid 

@end group
@end example

    @item  Your obj.conf will have several PathCheck directives. Find
    the call to index-names:

@example
@group
      PathCheck index-names ...    

@end group
@end example

    and replace it with the lines

@example
@group
      PathCheck index-names="index.html,home.html,index.mhtml,welcome.mhtml" fn="find-index" 
      PathCheck fn=mhtml_fixup_path document-root=/www/docs engine=/www/cgi-bin/nph-engine ext=".mhtml" 

@end group
@end example

    This will cause the following things to happen:

@enumerate
      @item  If you only specify a directory in a URL, the server will look for
      files named index.html,home.html,index.mhtml, or welcome.mhtml.

      @item  The Meta-HTML CGI Engine which is specified in the 'engine'
      parameter will be run on the indicated file

      @item  The 'document-root' portion of the physical (translated)
      URL path will be stripped off, and the remainder will be passed
      as the PATH-INFO CGI argument.

@end enumerate

    @item  Finally, you @i{must} add the line

@example
@group
      Service fn="send-cgi" type="magnus-internal/cgi"

@end group
@end example

    as the first Service directive in your obj.conf default object
    configuration.

    @item  Restart your server, and it will run any file ending with
    .mhtml through the Meta-HTML CGI Engine.

@end enumerate


@node Configuring the NCSA Server
@section Configuring the NCSA Server

@example
ScriptAlias / /usr/www/docs/cgi-bin/nph-engine/
@end example


@node Configuring the CERN Server
@section Configuring the CERN Server

In your server configuration file:
@example
Map	/*		/cgi-bin/nph-engine/*
Exec	/cgi-bin/*	<your-document-root>/cgi-bin/*
@end example

  @b{CERN/3.0A Bug}

  The Meta-HTML Engine tries hard to figure out where your document
  root is.  It starts out by looking in @code{argv[0]} to see
  which directory the program is running from.  By convention,
  programs which call @code{fork()} and @code{exec()}
  place the  @i{complete} path to the program to execute in
  @code{argv[0]}.

  But, does CERN do this?  No.  In fact, there are no variables in the
  environment, nor in @code{argv[]}, from which this information
  can be gleaned!

  So, the Meta-HTML Engine cannot find a local configuration file, and
  cannot determine the location of the document root directory from
  the information supplied by the CERN server.

  @b{Meta-HTML Workaround}

  There is a workaround for this bug in the CERN server.  If the
  Meta-HTML Engine cannot find a configuration file in the normal
  way, then it looks in the contents of the environment variable
  @code{METAHTML_ENGINE_CONFIG_FILE}, and tries to treat that
  value as the location for the configuration file.  If that fails,
  then finally the file @code{"/www/bin/engine.conf"} is looked
  for, and configuration is attempted from that file.

  Try copying the @code{engine.conf} file in your
  @code{/cgi-bin} directory to
  @code{/www/bin/engine.conf}, or start your server with the
  environment variable @code{METAHTML_ENGINE_CONFIG_FILE} set to
  the location of the @code{engine.conf} file that came with
  your distribution.


@node Configuring the PLEXUS Server
@section Configuring the PLEXUS Server

  This configuration material comes from Marc Tamsky
  (tamsky@@as.ucsb.edu).
  Although Marc is running the full Meta-HTML Server, he also likes to
  use the Plexus server, and placed the following lines in his
  @code{local.conf} file: 

@example
map     __get_default__  cgi.pl                           \
      @{                                                   \
        if ($path =~ m~\.mhtml$~)                         \
          @{                                               \
            local($tt) = 'mhtml';                         \
            if (length($path))                            \
              @{                                           \
                $tt = $tt . '/' . $path                   \
              @} ;                                         \
            &cgi'cgi('../mhtml/cgi-bin',$tt,$query);      \
          @}                                               \
        else                                              \
         @{                                                \
           &retrieve($path,$query);                       \
         @}                                                \
      @}

# Way-winning CGI
load    cgi.pl
map  mhtml   cgi.pl   &cgi'cgi('../mhtml/cgi-bin','engine/' .$rest,$query)
@end example


@node Networking With Meta-HTML
@appendix Networking With Meta-HTML

@node Network Appendix
@section Network Appendix
Meta-HTML contains several core functions for manipulating network
streams, such as @vref{with-open-stream}.  These
low level functions are exactly what is needed to allow the maximum
functionality and expressiveness in the language -- one might write a
complete Web based IMAP client using such primitives!  However, as is
often the case, it isn't always convenient to re-invent the wheel, and
so we have provided several tags in Meta-HTML PRO which deliver common
functionality in a general way.
@deffn {@i{Simple Tag}} {e-mail::parse-message}  msgvar 

 Given a complete RFC-822 E-mail message stored in @var{msgvar}, this
 function returns an alist describing the message in detail.
;
 The elements of the alist include the raw headers, and variables
 called @var{hdr_TO}, @var{hdr_FROM}, @var{hdr_SUBJECT}, @var{hdr_CC},
 and @var{hdr_DATE}, in additions to the variable @var{body}.

@end deffn

@deffn {@i{Simple Tag}} {e-mail::sendmail}  from  to[]  cc[]  bcc[]  headers[]  message 

 Send the mail message MESSAGE using a network stream from FROM to TO.

 The host used to connect to for SMTP defaults to the value of
 the variable E-MAIL::MAILHOST, or "localhost" if that variable is
 not defined.

 TO, CC, BCC and HEADERS are arrays containing elements of the indicated
 type.

@example
@group
 <e-mail::sendmail webmaster@@mysite.com bfox@@ua.com "" ""
    "Subject: Testing e-mail::sendmail
     Reply-to: nobody@@nobody.com"
    "This is the body of the message.">

@end group
@end example

 If the variable @var{e-mail::debug-sendmail-session} is non-empty,
 it says to populate the array e-mail::sendmail-session with the
 conversation that takes place between Meta-HTML and the SMTP
 server at @var{e-mail::mailhost}.

@end deffn

@deffn {@i{Simple Tag}} {http::get-document}  host  port  path &key  [strip-headers]  [var] &rest headers[]

 Get an HTTP document specified by @var{host}, @var{port} and @var{path}.

 If a redirection is necessary in order to get the final
 document, the variable @code{http::redirected-url} is set
 to the fully qualified URI of the document.

 If the document could not be retrieved, the variable
 @code{http::error-status} contains the word "NO-DATA", and
 the variable @code{http::explanation} contains an human
 readable string explaining the problem.

 If @var{strip-headers} is given, the HTTP protocol headers are
 stripped from the document before it is returned.

 If the keyword argument @var{var} is supplied, it is the
 name of variable that should receive the contents of the HTTP
 document verbatim -- by necessity, this variable is binary.
 You can use the @var{content-length} function to find out the
 length of the retrieved document.

 Finally, any extra headers that you would like to pass along may
 be written into the call, perhaps to set a cookie for example.

@example
@group
 <http::get-document www.metahtml.com 80 "/" "Cookie: SID=829389834">

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {http::host-part}  url 

 Return the hostname and port portion of the fully qualified @var{url}.
 @example
 <http::host-part http://www.metahtml.com/page.mhtml>

@end example
  produces
@example
 www.metahtml.com

@end example

@end deffn

@deffn {@i{Simple Tag}} {http::include}  url &key  [varname] &rest extra-headers[]

 Include the contents of the Web document referenced by @var{url}
 in the page.  If @var{varname} is supplied, it is the name of a
 binary variable which will receive the page contents.  Otherwise,
 the document is simply returned.

 @var{extra-headers} can be supplied, perhaps to pass a cookie to
 the server:

@example
@group
 <http::include http://www.foo.com/cgi-bin/foo.exe "Cookie: SID=10">

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {http::path-part}  url 

 Return the path portion of the fully qualified @var{url}.
 This is the part of @var{url} that is meaningful to the host.
 @example
 <http::path-part http://www.metahtml.com:8080/page.mhtml?foo=bar>

@end example
  produces
@example
 /page.mhtml?foo=bar

@end example

@end deffn

@deffn {@i{Simple Tag}} {http::port-part}  url 

 Return the port portion of the fully qualified @var{url}.
 If the @var{url} doesn't have a port specifier, the value "80" is
 returned.
 @example
 <http::port-part http://www.metahtml.com:8080/page.mhtml>

@end example
  produces
@example
 8080

@end example

@end deffn

@deffn {@i{Simple Tag}} {http::post}  url  pack &key  [user-agent] &rest http-headers

 POST the variables and values in @var{pack} to the server and page
 specified by @var{url}.  If the keyword argument @var{user-agent}
 is supplied, it overides the default value, which is either the
 value of @var{env::http_user_agent}, or the string
 @b{Mozilla/4.04 [en] (X11; I; Linux 2.0.27 i686)}.

@end deffn

@deffn {@i{Simple Tag}} {http::query-part}  url 

 Return the query portion of the fully qualified @var{url}.
 If @var{url} doesn't have a query string, the empty string
 is returned, otherwise, that portion of @var{url} following the
 first question-mark (@code{?}) is returned.
 @example
 <http::query-part http://www.metahtml.com:8080/page.mhtml?foo=bar>

@end example
  produces
@example
 foo=bar

@end example

@end deffn


@node HTML Color Manipulation
@appendix HTML Color Manipulation

@node Color Manipulation
@section Color Manipulation
Meta-HTML provides a few primitives for manipulating HTML color strings
and names.  You can convert from hexadecimal notation to decimal notation,
from color names to hex strings and back, create @code{SELECT}
widgets which allow the user to choose a color, and dynamically add new
colors to the (rather extensive) list of colors that Meta-HTML knows
about.
@deffn {@i{Simple Tag}} {color::add-color}  color  name &optional  [nickname] 

 Associate @var{color} with @var{name} and @var{nickname} in the system
 color tables and arrays.  @var{color} is the hexadecimal representation
 of the color, in standard RRGGBB format.  @var{name} is a pretty
 name of the color, as in "Antique White".

@end deffn

@deffn {@i{Simple Tag}} {color::color-name}  color 

 Given a string of hex digits (perhaps with a leading "#"), return
 the human readable name of that color as defined in our array of
 color names.  The color names are definitely suitable for Netscape,
 since I got the names off of their pages.

 @example
 <color::color-name #F5FFFA>

@end example
  produces
@example
 Mint Cream

@end example

@end deffn

@deffn {@i{Simple Tag}} {color::decimal-to-hex}  byte-value 

 Return the two hex characters which represent @var{byte-value},
 a decimal number between 0 and 255 inclusive.

 @example
 <color::decimal-to-hex 132>

@end example
  produces
@example
 84

@end example

@end deffn

@deffn {@i{Simple Tag}} {color::hex-value}  color 

 Given the human readable name of a color in @var{color}, return the
 color value as a string of 6 hex digits: RRGGBB.

 @example
 <color::hex-value "White Smoke">

@end example
  produces
@example
 F5F5F5

@end example

@end deffn

@deffn {@i{Simple Tag}} {color::opposite}  color 

 Return the "opposite" of COLOR in HTML format.  COLOR is supplied
 in HTML format as well.  For example:

@b{@code{<color::opposite #000000> ==> #FFFFFF}}

@end deffn

@deffn {@i{Simple Tag}} {color::parse-hex-pair}  hex-pair 

 Return the decimal value of @var{hex-pair}.
 @example
 <color::parse-hex-pair 84>

@end example
  produces
@example
 132

@end example

@end deffn

@deffn {@i{Simple Tag}} {color::parse-rgb}  rgb-string 

 Return an array of decimal values, one for each color in @var{rgb-string}.

 @example
 <color::parse-rgb #ff78e4>

@end example
  produces
@example
 255
120
228

@end example

@end deffn

@deffn {@i{Simple Tag}} {color::select-any-color}  varname 

 Create an HTML SELECTion pull-down menu containing the list of colors
 taken from the list of known colors in the system array
 @var{color::color-names}.  Assign the choice to @var{varname} when the
 containing form is POSTed.

@end deffn

@deffn {@i{Simple Tag}} {color::select-color}  varname 

 Create an HTML SELECTion pull-down menu containing a short list of
 colors including the primaries and hues.  Assign the choice to
 @var{varname} when the containing form is POSTed.

@end deffn


@node HTML Helper Tags
@appendix HTML Helper Tags

@node Html Helpers
@section Html Helpers
The following functions all produce HTML as output and are defined in
order to help with the creation of forms and tables.

@deffn {@i{Complex Tag}} {forms::multiple-instances}  session-pack &key  [modify-hook]  [create-hook]  [remove-hook]  [method]  [action]  [enctype] 

 Creates a repeating form, allowing multiple entries of data sets.
 The body of this macro is exactly whatever you might put in a
 standard FORM body.  What is needed here is examples, and there
 really isn't space for any.  Please see the file called
 multiple-instances.mhtml in the distribution for examples.

@end deffn

@deffn {@i{Simple Tag}} {forms::standard-buttons} &optional  [forms-index] 

 Display the standard buttons for input when performing
 @vref{forms::multiple-instances}.
 If there are no current instances of the form, this produces
 a language sensitive submit button with the name of "form-create" --
 if the instance that this function is called in already has values,
 then two submit buttons are produced, with names "form-modify" and
 "form-accept".

 If you would like to control the placement of these buttons, then
 you should set the variable @var{forms::no-submits}.  In this case,
 you are responsible for calling forms::standard-buttons yourself.

@end deffn

@deffn {@i{Simple Tag}} {incdir} 

 The Web based pathname to the directory containing the document which
 is currently being included with @b{<include>}.

@end deffn

@deffn {@i{Simple Tag}} {locale::iso-country-name-to-abbrev2}  country-name 

 Returns the two-letter abbreviation of the ISO-3166 country name
 passsed in @var{country-name}.  If @var{country name} isn't an
 ISO-3166 country name, then it is simply returned as is.

@end deffn

@deffn {@i{Simple Tag}} {locale::iso-country-name-to-abbrev3}  country-name 

 Returns the three-letter abbreviation of the ISO-3166 country name
 passsed in @var{country-name}.  If there isn't a three-letter
 abbreviation, but there is a two-letter one, then that is returned.
 If @var{country name} isn't an ISO-3166 country name, then it is
 simply returned as is.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-common-country}  postname &optional  [sitename] 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a country from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.
 @var{sitename} is the name of another variable which can contain the
 currently selected country.

 This differs from @vref{locale::select-country}
 only in the number of countries that are displayed.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-country}  postname &optional  [sitename] 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a country from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.
 @var{sitename} is the name of another variable which can contain the
 currently selected country -- this variable must be fully
 qualified with its package name (i.e., DEFAULT::FOO, or SITE::COUNTRY).

@end deffn

@deffn {@i{Simple Tag}} {locale::select-from-country}  postname  sitename  country-array 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a country from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.
 @var{sitename} is the name of another variable which can contain the
 currently selected country -- this variable must be fully
 qualified with its package name (i.e., DEFAULT::FOO, or SITE::COUNTRY).

@end deffn

@deffn {@i{Simple Tag}} {locale::select-iso-country}  postname &optional  [sitename] 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a country from a pull-down menu which
 includes all of the ISO-3166 country names.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.
 @var{sitename} is the name of another variable which can contain the
 currently selected country -- this variable must be fully
 qualified with its package name (i.e., DEFAULT::FOO, or SITE::COUNTRY).

@end deffn

@deffn {@i{Simple Tag}} {locale::select-iso-country-abbrev2}  postname &optional  [sitename] 

 Produce a selection widget suitable for placing in a form which
 allows the user to select an ISO-3166 country name from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.  The long name of the country is displayed,
 but the short, two-letter version of the country is returned.
 @var{sitename} is the name of another variable which can contain the
 currently selected country.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-iso-country-abbrev3}  postname &optional  [sitename] 

 Produce a selection widget suitable for placing in a form which
 allows the user to select an ISO-3166 country name from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.  The long name of the country is displayed,
 but the short, three-letter version of the country is returned.
 @var{sitename} is the name of another variable which can contain the
 currently selected country.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-province}  postname  sitename 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a province name from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.  The long name of the province is displayed,
 but the short, two- or three-letter version of the province is returned.
 @var{sitename} is the name of another variable which can contain the
 currently selected province.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-state}  postname  sitename 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a US state name from a pull-down menu.
 @var{postname} is the name of the variable which should be posted
 when the form is submitted.  The long name of the state is displayed,
 but the short, two-letter version of the state is returned.
 @var{sitename} is the name of another variable which can contain the
 currently selected state.

@end deffn

@deffn {@i{Simple Tag}} {locale::select-state-or-province}  postname  sitename 

 Produce a selection widget suitable for placing in a form which
 allows the user to select a US state or province name from a
 pull-down menu.  @var{postname} is the name of the variable
 which should be posted when the form is submitted.  The long
 name of the state or province is displayed, but the short, two-
 or three-letter version of the state or province is returned.
 @var{sitename} is the name of another variable which can contain the
 currently selected state or province.

@end deffn

@deffn {@i{Complex Tag}} {menu}  title &key  [nobr] 

 Create an HTML menu with title, text and links.

 Calling sequence:

@example
@group
 <menu "This Is The Title">
   This is link text: target.mhtml
   External Site:  http://www.external.com/welcome.mhtml
 </menu>

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {message} 

 Add BODY to the contents of the session variable "message".
 Also see @vref{show-message}.

@end deffn

@deffn {@i{Simple Tag}} {meta-html} 

 Produces the canonical form of the words "Meta-HTML".

@end deffn

@deffn {@i{Simple Tag}} {select-option}  varname  display &optional  [value] 

 Use instead of the   
@b{@code{<option>}} HTML tag within
 the select HTML tag.

 Creates a @i{option} item in the page in which @var{varname}
 is expected to contain the current value of the choice, or nothing,
 if no choice has been made.  If you supply the optional @var{value}
 argument, that value is returned instead of @var{display}.

 If @var{varname} contains @var{value}, then this option has the
 HTML @b{SELECTED} attribute turned on.

 Example:

@example
@group
 <select name=airport>
   <select-option airport Atlanta>
   <select-option airport Boston>
   <select-option airport Chicago>
   <select-option airport "Los Angeles">
   <select-option airport "New York">
   <select-option airport Miami>
   <select-option airport "San Francisco">
 </select>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {select-option-value}  varname  display &optional  [value] 

 Use instead of the   
@b{@code{<option>}} HTML tag within
 the select HTML tag.

 Creates a @i{option} item in the page in which @var{varname}
 is expected to contain the current value of the choice, or nothing,
 if no choice has been made.  If you supply the optional @var{value}
 argument, that value is returned instead of @var{display}.

 If @var{varname} contains @var{value}, then this option has the
 HTML @b{SELECTED} attribute turned on.

 Example:

@example
@group
 <select name=airport>
   <select-option airport Atlanta>
   <select-option airport Boston>
   <select-option airport Chicago>
   <select-option airport "Los Angeles">
   <select-option airport "New York">
   <select-option airport Miami>
   <select-option airport "San Francisco">
 </select>
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {show-message} 

 Display the contents of the session variable "message",
 and then remove that variable from the session.
 Also see @vref{message}.

@end deffn

@deffn {@i{Complex Tag}} {small-caps} &key  [upper=size]  [lower=size]  [other=size] 

Modify the characters in @var{body} raising lower-case
characters to upper-case, and changing the size of fonts as directed.

For example, this is how ``@sc{Hello
There}'' can be produced:

@example
  <small-caps lower=-1>Hello There</small-caps>
@end example
  produces
@example
  @sc{Hello There}
@end example

@end deffn

@deffn {@i{Simple Tag}} {source-link}  text 

 You write `Click here for source.'

@end deffn

@deffn {@i{Simple Tag}} {source-of}  web-path  highlight-keywords-p 

 Display the contents of @var{web-path} in @code{HTML}.
 Use sparingly.
 If @var{highlight-keywords-p} is non-empty, then make each
 Meta-HTML function in the displayed text be a link which will
 display the contents of the the manual page for that keyword.

@end deffn

@deffn {@i{Simple Tag}} {thisdir} 

 The fully qualified pathname to the directory containing the currently
 executing document.

@end deffn

@deffn {@i{Simple Tag}} {thisdoc} 

 The complete URL to this document, without the query string or
 path information.

@end deffn

@deffn {@i{Simple Tag}} {thisfile} 

 The fully qualified pathname to the document which is currently
 executing.

@end deffn

@deffn {@i{Simple Tag}} {thispage} 

 The local web-based URL to this document, without the query string
 or path information.

@end deffn

@deffn {@i{Simple Tag}} {verbatim} &key  [quote] 

Insert @var{body} verbatim, avoiding doing any processing on
the contents.  If the keyword argument @var{quote} is given,
occurrences of characters with special meaning to @b{HTML} are
replaced with the @b{HTML} code to produce that character in the
output page.

Contrast this with @vref{comment}.

@end deffn

@deffn {@i{Simple Tag}} {vertical-table}  array-name  width  link  extra-link-info 

 Lay out a table according to number of columns, but listing each
 item vertically.  The number of items to each column is determined
 by dividing the total number of items by the number of desired columns.

@end deffn


@node PAGECOUNT: Tracking Page Hits
@appendix PAGECOUNT: Tracking Page Hits

@node Pagecount Appendix
@section Pagecount Appendix
The PAGECOUNT::... functions allow you to place English language or
graphical page counters on any page in your site, simply by placing a
single tag on the page.

The counted pages are kept in a database (typically
@code{server-root/writable/pagecount.db}) so that you can write
your own programs to manipulate the collected data.
@deffn {@i{Simple Tag}} {count-this-page} &optional  [key] 

 Add the current hit on this page to the pagecounter database, and
 return the current number of hits.  The pagecounter database is
 only accessed if this is the first time that this function is
 called on this page.

 If @var{key} is not supplied, it defaults to the web-relative
 path to the current document.

@example
@group
   <count-this-page> ==> 2349

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {pagecount::available-fonts} 

 Return an array of the names of the fonts available on this system
 for displaying digit counters.

@end deffn

@deffn {@i{Simple Tag}} {pagecount::english-counter} 

 Produce an English text representation of the number of times
 this page has been accessed.  Implicitly calls the function
 @vref{count-this-page}.

@example
@group
 <pagecount::english-counter> ==> One Thousand Two Hundred and Fifty

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {pagecount::englith-counter} 

 Produce an English text representation of the number of times
 this page has been accessed.  Implicitly calls the function
 @vref{count-this-page}.

@example
@group
 <pagecount::english-counter> ==> One Thousandth Two Hundred and Fiftieth

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {pagecount::gif-counter}  fontname 

 Produce a sequence of GIFS representing the number of times this
 page has been accessed.  Implicitly calls count-this-page.
 The gifs are rendered using the font specified in FONTNAME.

@end deffn


@node Dynamic Image Creation
@appendix Dynamic Image Creation

@node 
@section 

@deffn {@i{Simple Tag}} {banner}  link  image-text  rotation 

 Return the HTML necessary to display a graphic image with
 @var{image-text} linked to @var{link}.

@end deffn

@deffn {@i{Simple Tag}} {banners::base-banner-image-file} 

 Returns the full pathname of the current base image for
 creating banners.  You don't need to call this function directly
 -- instead set the variable @code{banners::base-banner-image}
 to the name of a file in the directory
 @code{/System/images/base-images/banners}.

@end deffn

@deffn {@i{Simple Tag}} {banners::create-banner}  output-file  image-text  rotation 

 Create a "banner" image in OUTPUT-FILE using IMAGE-TEXT.
 The base image is taken from BANNERS::BASE-BANNER-IMAGE, which is
 the basename of the image file, and is looked for in
 /System/images/base-images/tabs.
 Other parameters, including HALIGN, VALIGN, FONT, FONT-SIZE, and
 FONT-COLOR are taken from their values in the BANNERS package.

@end deffn

@deffn {@i{Simple Tag}} {buttons::create-button}  output-file  image-text  italic? 

 Create a "button" image in @var{output-file} using @var{image-text}.
 The base image is taken from
 @code{BUTTONS::BASE-BUTTON-IMAGE}, which is
 the basename of the image file, and is looked for in
 /System/images/base-images/buttons.
 Other parameters, including HALIGN, VALIGN, FONT, FONT-SIZE, and
 FONT-COLOR are taken from their values in the BUTTONS package.

@end deffn

@deffn {@i{Simple Tag}} {image-builder::make-text-gif}  text  halign  valign  width  height  font  font-size  font-color  base-image 

 Make a gif from TEXT and BASE-IMAGE using the given parameters.

 HALIGN is horizontal alignment of the text in the image.  It can
 have one of the following values: Left, Center, Right.

 VALIGN is vertical alignment of the text in the image; it can have
 one of the following values:  Top, Middle, or Bottom.  Default: Middle.

 WIDTH and HEIGHT are the dimensions in pixels of the base image,
 if known.  Defaults are 468 and 60 respectively.

 FONT is the name of the Postscript font to use to render the text.
 FONT-SIZE is the size of the font, in points.
 FONT-COLOR is a 6 character RGB string specifying the color to draw
 the text in.

 Returns the full path of the generated GIF image.

@end deffn

@deffn {@i{Simple Tag}} {image-builder::select-font}  varname 

 Produce a   
@b{@code{<select ...> ... </select>}} tag
 displaying the fonts which are available on the current system.
 The displayed fonts may be used to create text on top of
 dynamically created banners, buttons, or tabs.

@end deffn

@deffn {@i{Simple Tag}} {navbar::create-client-side-imagemap}  name 

 Implicity uses the data in NAVBAR::IMAGEMAP-INFO.

@end deffn

@deffn {@i{Simple Tag}} {navbar::create-navbar}  name  navinfo[] 

 Undocumented by intent.  This interface is not complete yet.

@end deffn

@deffn {@i{Simple Tag}} {navbar::create-navbar-gif}  navinfo[]  map?  fname  fsize  fcolor  bgcolor  srgb 

 Create a navigation bar using the specified information.
 The full pathname of the created image is returned.
 If map? is non-empty, creates the array NAVBAR::IMAGEMAP-INFO, which
 is an array of alists, each one describing an area of the created
 navbar.

 The fields of each alist are: SHAPE, POINTS, LINK.

@end deffn

@deffn {@i{Simple Tag}} {navbar::create-server-side-imagemap}  name 

 Implicitly uses the data in NAVBAR::IMAGEMAP-INFO.

@end deffn

@deffn {@i{Simple Tag}} {navbar::use-navbar}  name  navinfo[] 

 Use a (perhaps) previously created navbar.
 Undocumented by intent.  This interface is not complete yet.

@end deffn

@deffn {@i{Simple Tag}} {site::dynamic-bg}  basename  border-width  lrgb  rrgb  force?  srgb 

 Dynamically create a background image with the given parameters,
 if one does not already exist.  Returns the full URL of the image.

@end deffn

@deffn {@i{Simple Tag}} {tab}  link  image-text  italic?  target 

 Return the HTML necessary to display a graphic image with @var{IMAGE-TEXT} in the left-hand border of the page, linked to @var{LINK}.

@end deffn

@deffn {@i{Simple Tag}} {tabs::create-tab}  output-file  image-text  italic?  rotation 

 Create a "tab" image in @var{output-file} using @var{image-text}.
 The base image is taken from @var{TABS::BASE-TAB-IMAGE}, which is
 the basename of the image file, and is looked for in
 /System/images/base-images/tabs.
 Other parameters, including HALIGN, VALIGN, FONT, FONT-SIZE, and
 FONT-COLOR are taken from their values in the TABS package.

@end deffn


@node PowerStrip System Tags
@appendix PowerStrip System Tags

@node Powerstrip System Tags
@section Powerstrip System Tags
The following functions are used in the implementation of the
PowerStrip System area (/System/*).

These functions are only useful to those persons who are adding
functionality to the PowerStrip system itself, or who need to
manipulate the underlying data structures and mechanisms of that
system.  
@deffn {@i{Simple Tag}} {acl-compose} 

@b{@code{ <acl-compose var &optional [packname]>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-decompose} 

@b{@code{<acl-decompose <var VAR> &optional [packname]>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-edit-table} 

@b{@code{<acl-edit-table VAR>}}

 Produces an editable   
@b{@code{<table>}} for values in ACL.

@end deffn

@deffn {@i{Simple Tag}} {acl-get-var} 

@b{@code{ <acl-get-var VAR name value>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-make-acl} 

 Create an ACL which has no values.

@end deffn

@deffn {@i{Simple Tag}} {acl-merge-acl} 

@b{@code{<acl-merge-acl into new>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-set-var} 

@b{@code{<acl-set-var VAR name value>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-table} 

@b{@code{<acl-table VAR>}}

 Produces a   
@b{@code{<table>}} of values in ACL.

@end deffn

@deffn {@i{Simple Tag}} {acl-test} 

@b{@code{ <acl-test VAR name> }}

@end deffn

@deffn {@i{Simple Tag}} {acl-unset-var} 

@b{@code{<acl-unset-var VAR name value>}}

@end deffn

@deffn {@i{Simple Tag}} {acl-zero} 

@b{@code{<acl-zero VAR>}}

@end deffn

@deffn {@i{Simple Tag}} {basic-auth::authorization-database}  filename  type 

 When passed FILENAME, sets the default authorization database
 file to be that fully qualified pathname.  When passed an empty
 FILENAME, returns the current pathname of the authorization
 database.

 The default authorization database used is the PowerStrip
 database.  Note that authorizing based on this method does
 not log the user into the PowerStrip system, it simply
 authenticates them against a database.

 If BASIC-AUTH::DATABASE-TYPE is set to "Meta-HTML", then the
 database is assumed to be a standard Meta-HTML/GDBM database,
 with a key value of the username, and a field called PASSWORD.
 If necessary, the password field will be decoded as a unix based
 password.

@end deffn

@deffn {@i{Simple Tag}} {basic-auth::get-auth-info} 

@end deffn

@deffn {@i{Simple Tag}} {basic-auth::powerstrip-login} 

@end deffn

@deffn {@i{Simple Tag}} {basic-auth::require-authorization}  for-realm  bad-login-page 

@end deffn

@deffn {@i{Simple Tag}} {defparam}  name  documentation &key  [type]  [value]  [choices[]] 

 Functions which allow the modification of a particular plugin's
 parameter set.

 Each plugin which can be installed in the System area of IBIS may
 have a file in its top-level directory called default.params, which
 contain the parameters for that application as shipped by the
 manufacturer.

 When such a file is present, the PowerStrip administrator can use the
 generic plugin parameter manipulation tools to modify the values.

@end deffn

@deffn {@i{Simple Tag}} {ibis::initialize} 

 Initialize the PowerStrip system.
 Should be called after defining any overriding variables for a specific
 page, such as layout::layout, etc.

@end deffn

@deffn {@i{Simple Tag}} {ibis::package-get}  package 

 Get the parameters for PACKAGE, storing them in PACKAGE.

@end deffn

@deffn {@i{Simple Tag}} {ibis::package-parameters}  package  into-array 

 Get the parameters for PACKAGE into the variable named by
 INTO-ARRAY, a fully qualified variable name.
 Each element of the returned array is an alist.

@end deffn

@deffn {@i{Simple Tag}} {ibis::parameter-input}  param-alist 

 Create a form entry for editing @var{param-alist}.

@end deffn

@deffn {@i{Simple Tag}} {ibis::standard-footer} 

 The corollary to @vref{ibis::standard-header}.

@end deffn

@deffn {@i{Simple Tag}} {ibis::standard-header} 

 Insert the standard PowerStrip header, including the
 system site header, and inserting the contents of the
 variable IBIS::HEAD-PARAMS in the

@b{@code{<HEAD> ... </HEAD>}} area.

 Also see @vref{ibis::standard-footer}.

@end deffn

@deffn {@i{Simple Tag}} {layout::clear-contents} 

 Discard any content that has been previously assigned to the
 left border, right border, or page contents areas.  Such content
 was presumably prepared using
 @vref{layout::left-border},
 @vref{layout::page}, or
 @vref{layout::right-border}.

 Please see @vref{layout::initialize}
 for more information.

@end deffn

@deffn {@i{Simple Tag}} {layout::default-header} 

 Produces the HTML which implements the appropriate table
 structure for the type of layout that you have specified by
 setting the variable @code{layout::layout}.
 Please see @vref{layout::initialize}.

@end deffn

@deffn {@i{Simple Tag}} {layout::initialize} 

 Call @code{layout::initialize} after loading this package,
 and after  setting the variables which define the type of layout
 that you would like.  Those variables are:

@itemize @bullet
   @item  @b{LAYOUT::LAYOUT}

	One of "plain", "bordered-left", "bordered-right", or
     "bordered-right-and-left".

   @item  @b{LAYOUT::LEFT-BORDER-WIDTH}

     An absolute number which determines the width of the left
     border.  Only has an effect when the layout actually contains
     a left border.

   @item  @b{LAYOUT::RIGHT-BORDER-WIDTH}

     An absolute number which determines the width of the right
     border.  Only has an effect when the layout actually contains
     a right border.

@end itemize

 Then, in the page itself, you can use:

@example
@group
          <layout::page> html </layout::page>
   <layout::left-border> html </layout::left-border>
  <layout::right-border> html </layout::right-border>

@end group
@end example

 Those tags place the HTML that you specify in the indicated region
 of the page.

 Finally, make sure that you call
 @vref{layout::resolve-contents} before
 the page returns.  A complete invocation might look like:

@example
@group
 <defvar layout::layout bordered-left>
 <layout::initialize>
 <layout::default-header>

 <layout::page>
   This is in the page.
 </layout::page>

 <layout::left-border>
   This is in the left border.
 </layout::left-border>

 <layout::resolve-contents>

@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {layout::left-border} 

 Append @var{body} to the portion of the resultant page which
 appears in the left border.
 Please see @vref{layout::initialize}
 for more information.

@end deffn

@deffn {@i{Complex Tag}} {layout::page} 

 Append @var{body} to the portion of the resultant page which
 appears between the left and the right borders.
 Please see @vref{layout::initialize}
 for more information.

@end deffn

@deffn {@i{Simple Tag}} {layout::resolve-contents} 

 Resolve the contents of the page according to the layout that
 you have specified by setting the variable
 @code{layout::layout}.  Please see @vref{layout::initialize}.

@end deffn

@deffn {@i{Complex Tag}} {layout::right-border} 

 Append @var{body} to the portion of the resultant page which
 appears in the right border.
 Please see @vref{layout::initialize}
 for more information.

@end deffn

@deffn {@i{Simple Tag}} {login::initialize} 

 Place before including the header, if, and only if, this page is to
 contain the login form generated by

@b{@code{<login::powerstrip-login>}}.

@end deffn

@deffn {@i{Simple Tag}} {login::powerstrip-login}  continue-link 

 Login, or present a login form, which authenticates based on the
 PowerStrip database of users.

@end deffn

@deffn {@i{Simple Tag}} {require-access}  name 

 Check to see if the current user has the access permission @var{name} present in their access control list.  If not, a
 redirection to @code{/access-denied.mhtml} is issued.

@end deffn

@deffn {@i{Simple Tag}} {signon-required} 

  This enforces a PowerStrip login before pages which contain sensitive
  information may be viewed.

@end deffn

@deffn {@i{Simple Tag}} {site::admin-body-value}  tag 

@b{@code{<site::admin-body-value text> ==> text="#000000"}}
 or nothing.

@end deffn

@deffn {@i{Simple Tag}} {site::body-value}  tag 

@b{@code{<site::body-value text> ==> text="#000000"}}
 or nothing.

@end deffn

@deffn {@i{Simple Tag}} {site::image}  name 

 Returns the full web-relative pathname of the image named by @var{name}.

@example
@group
 <site::image foo> ==> /System/images/site/foo.gif

@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {site::image-file}  url 

 Return the full pathname of the file representing the image in @var{url}.

@end deffn


@node Other Miscellaneous Tags
@appendix Other Miscellaneous Tags

@node 
@section 

@deffn {@i{Simple Tag}} {comma-separated}  arrayvar 

 Produce a human readable string of the elements in the array
 variable @var{arrayvar} separated by commas where appropriate,
 and with the word "and" after the penultimate item.

@end deffn

@deffn {@i{Complex Tag}} {form-to-database}  database &key  [dbname]  [key]  [redirect-to]  [action-name] 

 Used almost exactly like @code{FORM}, this stores the
 values entered into the form into the specified database.  Takes
 keyword arguments of @var{dbname}, @var{key}, @var{redirect-to},
 and @var{action-name}.

@itemize @bullet
 @item  @var{dbname}
 The name of the database to store the results in.  If it
 isn't supplied, "anonymous.db" is used.  The name of the
 database file is always relative to the current directory.

 @item  @var{key}
 The name of the input field which contains the unique key
 for this record.  For example, this might be "name" for a
 rolodex application which asked for that information field.

 @item  @var{redirect-to}
 The URL of the page to go to after the data is stored.
 If this is not specified, the user remains on the page
 containing this form.

 @item  @var{action-name}
 The text to place in the button which submits the form.
 Defaults to "Submit Form".

@end itemize

@end deffn

@deffn {@i{Simple Tag}} {forms::multiple-instance-resolve}  session-pack  dest-pack 

 DOC-SECTION (HTML-HELPERS)
 For every instance of a form in SESSION-PACK, append the
 elements in order to arrays in DEST-PACK.  Thus, if your
 form contained "name" and "age" input fields, and the user
 created multiple instances of this form, the output of
 calling (forms::multiple-instance-resolve mypack results)
 would be:
 RESULTS::NAME[0] ==> Brian
 RESULTS::NAME[1] ==> John
 ...
 RESULTS::AGE[0] ==> 38  (i.e., Brian's age)
 RESULTS::AGE[1] ==> 37  (i.e., John's age).

 You have to call FORMS::MULTIPLE-INSTANCE-RESOLVE for every form
 in your page which used FORMS::MULTIPLE-INSTANCES.  Since this
 requires the use of the session database, you can call
 FORMS::MULTIPLE-INSTANCE-RESOLVE from any page at any time to read
 the contents of the session data, and return the information.

@end deffn

@deffn {@i{Simple Tag}} {function-def}  fun 

 Return a human readable rendition of the function named by @var{fun}.

@end deffn

@deffn {@i{Simple Tag}} {lang} &key  [en]  [de]  [fr]  [it]  [es] 

 Provides an interface for selecting one of several phrases
 in different languages, based on the value of AUTHDATA::LANGUAGE.

 Use in the following situations:

@b{@code{ <input type=submit name=action value=<lang en=Now de=Jetzt>>
 }}

@end deffn

@deffn {@i{Simple Tag}} {lang-inform} &key  [en]  [de]  [fr]  [it]  [es] &rest info

 This function uses the value of authdata::language to select a
 language, and then calls @var{inform} with <info>.

@end deffn

@deffn {@i{Simple Tag}} {lang-message} &key  [en]  [de]  [fr]  [it]  [es] &rest message

 This function uses the value of authdata::language to select a
 language, and then calls @var{message} with that choice.

@end deffn

@deffn {@i{Simple Tag}} {mailable-address}  addr 

 Return "true" if ADDR appears to be a correctly formatted E-mail address.

@end deffn

@deffn {@i{Simple Tag}} {mhtml::engine-per-page-function} 

 Code that sets up the URL rewriter.  This has to be a per-page function
 because we haven't computed the URL of the document at the time
 the engine.conf file is read, so variables such as mhtml::http-prefix
 aren't set yet, and will be changed at the time the page location is
 computed.

@end deffn

@deffn {@i{Simple Tag}} {number-to-english}  value 

 Take the numeric value of VALUE and produce an English representation
 of it.  For example:
 @example
 <number-to-english 232>

@end example
  produces
@example
 Two Hundred and Thirty-Two

@end example

@end deffn

@deffn {@i{Simple Tag}} {number-to-englith}  value 

 Take the numeric value of VALUE and produce an English representation
 of it as a counting value.  For example:
 232 ==> Two Hundred and Thirty-Second.

@end deffn

@deffn {@i{Simple Tag}} {nummer-zum-deutsch}  nummer 

 Produziert die Wourter auf Deutsch, das den numerischen Wert des
 @var{nummer} darstellt.  Zum Beispiel:
 @example
 <nummer-zum-deutsch 232>

@end example
  produces
@example
 Zwei Hundert Zweiunddreizig

@end example

@end deffn

@deffn {@i{Simple Tag}} {nummer-zum-deutschte}  nummer 

 Produziert die Wourter auf Deutsch, das den numerischen Wert des
 @var{nummer} darstellt.  Zum Beispiel:
 @example
 <nummer-zum-deutschte 232>

@end example
  produces
@example
 Zwei Hundert Zweiunddreizigte

@end example

@end deffn


@node Misc. Meta-HTML Modules
@appendix Misc. Meta-HTML Modules

@node Csv Module
@appendixsec The Csv Module
The CSV module is useful for importing @b{C}omma @b{S}eperated
@b{V}alues from external programs which are capable of producing them.
Such programs include word processors, legacy database systems, spreadsheets,
and the like.
@deffn {@i{Simple Tag}} {csv::csv-to-array}  cvs-text  array-name &key  [sep=SEPARATOR] 

Returns an array of the values specified in the comma separated values
represented by @var{csv-text}.  The values are placed in @var{array-name}
in the order in which they are found.

@end deffn


@node Elsewhen Module
@appendixsec The Elsewhen Module
This module is provided for those programmers who feel more comfortable with
a balanced tag syntax for flow control over a balanced brace syntax.
Using the tags in this package will greatly reduce the number of
@vref{group}, or @vref{concat} tags, at the
slight cost of interpreter speed.  In many cases, the clarity of the code
is more important, so if you are one of those programmers that feel more
comfortable with the tag-based syntax, you might consider the use of this
module.
@deffn {@i{Complex Tag}} {cif}  test &optional  [then-clause]  [<else>]  [else-clause] 

First @var{test} is evaluated. If the result is a non-whitespace only string,
the statements between the @var{then-clause} and the @var{else-clause} are
evaluated.  Otherwise, if the the @var{else-clause} is present, it is
evaluated. Although Meta-HTML has an @code{or} function, you can
efficiently test for the presence of any of a group of variables with code
similar to the following:

@example
@group
<if <get-var foo bar>>
  "Either FOO or BAR is present"
<else>
  "Neither FOO nor BAR is present"
</if>
@end group
@end example

@end deffn

@deffn {@i{Complex Tag}} {whenelse}  test 

Evaluate @var{test}.  If the result is a non-empty string,
then execute the @var{body} statements.  If the tag <elsewhen>
appears in the body, then the commands between that tag and the closing
</whenelse> will be executed if, and only if, the @var{test} evaluates
to the empty string.  This is a cleaner way to handle optional multiple
statement execution rather than dealing with quoting everything inside
of an @vref{if} form.

@end deffn


@node Example Module
@appendixsec The Example Module
The functions in this module are simply here to demonstrate how to write
new dynamically loadable modules for Meta-HTML for your own application
needs, and don't really perform any services that couldn't be better 
performed in other ways.  However, the @b{<apropos>} function in this
module might be of use in an interactive Web page -- see @mref{Html Helpers}
for more information, as well as reading the source code in
@code{modules/example.c}.
@deffn {@i{Simple Tag}} {apropos}  regexp 

Search through all Meta-HTML symbols for @var{regexp}, and return a
newline separated list of those symbols which match.

Generally meant for interactive use.

Note that this is simply a long documentation comment in the source, to
demonstrate how to document new commands that you might write in a
Meta-HTML dynamically loadable module.

@end deffn


@node 
@appendixsec The Lisp Module

@deffn {@i{Simple Tag}} {caar}  list 

Returns the @vref{car} of the @vref{car} of
@var{list}.

@example
@group
<caar "(this that stuff)">     ==> 
<caar "((this that) stuff)">   ==> "this"
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cadr}  list 

Returns the @vref{car} of the @vref{cdr} of
@var{list}.

@example
@group
<cadr "(this that stuff)">     ==> "that"
<cadr "((this that) stuff)">   ==> "stuff"
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {car}  list 

Returns the first element of @var{list}.

@example
@group
<car "(this that and the other thing)"> ==> "this"
<car "((this that) and more stuff)">    ==> ("this" "that")
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cdar}  list 

Returns the @vref{cdr} of the @vref{car} of
@var{list}.

@example
@group
<cdar "(this that stuff)">     ==>
<cdar "((this that) stuff)">   ==> ("that")
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cddr}  list 

Returns the @vref{cdr} of the @vref{cdr} of
@var{list}.

@example
@group
<cddr "(this that stuff)">     ==> ("stuff")
<cddr "((this that) stuff)">   ==> ()
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cdr}  list 

Returns everything bu the first element of @var{list}.

@example
@group
<cdr "(this that stuff)">     ==> ("that" "stuff")
<cdr "((this that) stuff)">   ==> ("stuff")
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {cons} &optional  [car]  [cdr] 

Create a two element list with first element @var{car} and second element
@var{cdr}.  @var{car} and @var{cdr} default to the empty list "()" if not
specified.

Please see @vref{lisp-module-synopsis} for details of how
the arguments to this function are parsed.

@example
@group
<cons 'this 'that>            ==> ("this" . "that")
<cons 'this <cons 'that '()>> ==> ("this" "that")
@end group
@end example

@end deffn

@deffn {@i{Simple Tag}} {lisp-module-synopsis} 

The functions in this module treat their arguments substantially
differently than in the rest of Meta-HTML.  It is important to read
and understand the following paragraphs if you are to use this module.

If an argument begins with an open angle bracket ("<"), then it is
evaluated, and that is the argument that is passed to the lisp
function.  If an argument begins with a single quote ("'"), then the
value which immediately follows it is read using the lisp reader, and
the resultant value is passed to the lisp function.  Otherwise, the
argument is looked up as a variable name, and if it exists, the value
of that variable (either standard or binary) is what is passed to the
lisp function.  If the variable doesn't exist, then the variable name
is passed.

This is not optimal behavior (it allows for too much ambiguity), but
it can make writing programs which rely heavily on lisp-like syntax
much easier to read.

@end deffn

@deffn {@i{Simple Tag}} {list} &rest objects

Return a lisp list consisting of the objects passed.

Please see @vref{lisp-module-synopsis} for details of how
the arguments to this function are parsed.

@example
@group
<list 'this 'that '(the other thing)>  ==> (this that (the other thing))
@end group
@end example

@end deffn


@node Perl Module
@appendixsec The Perl Module
This module allows the evaluation of Perl statements directly from within
your Meta-HTML pages, and the evaluation of Meta-HTML statements, from within
that Perl code.

In order to use the @b{perl-eval} code, you must first load the
@b{modperl} module:

@example
@group
<load-module modperl> ==> /www/lib/modperl.so
@end group
@end example

@deffn {@i{Simple Tag}} {perl-eval}  perl-code 

Evaluates the Perl code in a scalar context and returns the result
as a string. If there is an error, sends it to page debugging log;
if you need to do something else with errors, eval @{@} your code
yourself!

@end deffn


@node Defined Meta-HTML Variables
@appendix Defined Meta-HTML Variables


@defvr {@i{Variable}} {env::exec-path}
The list of directories that @vref{cgi-exec} will search when looking up the location of a
command.

Each component is a path to a directory, without the final trailing
slash, separated from its neighbors by a colon character
(@code{:}).

For example:

@example
@group
   <set-var env::path="/www/bin:/www/docs/cgi-bin">
@end group
@end example

@end defvr


@defvr {@i{Variable}} {env::http-authorization}
The @code{Basic Authorization}
string, as received by the server.  By the time that you see this
string, the user has already been authorized.

@end defvr


@defvr {@i{Variable}} {env::http-referer}
A synonym for @code{mhtml::referer}.

@end defvr


@defvr {@i{Variable}} {env::http-user-agent}
The name that the connecting client
browser passed as the value of the @code{User-Agent} MIME
header.

For example:

@example
You are connected using: <get-var env::http_user_agent>
@end example
  produces
@example
You are connected using: Mozilla/3.0 (X11; U; Linux 1.3.20 i386)
@end example

@end defvr


@defvr {@i{Variable}} {env::query-string}
The raw query string which was passed in
this URL.  In many cases, Meta-HTML can create variables in the
@code{POSTED} package based upon the contents of this string.
In some cases, the string doesn't contain any variable assignments
(e.g., when the URL is an imagemap target).  For such cases, you may
need direct access to the query string.

@example
<get-var env::query_string>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {env::remote-addr}
The Internet Protocol address of the
connecting client host, in "dot" notation.  You may wish to use
@code{env::remote_host} instead.

@example
<get-var env::remote_addr>
@end example
  produces
@example
127.0.0.1
@end example

@end defvr


@defvr {@i{Variable}} {env::remote-host}
The host name of the connecting client.  In
cases where the connecting client does not have a host name which can
be looked up by the use of DNS, this variable contains the host's
Internet Protocol address, in "dot" notation.

@example
<get-var env::remote_host>
@end example
  produces
@example
nirvana.datawave.net
@end example

@end defvr


@defvr {@i{Variable}} {env::server-port}
The port on which the current web server is
listening for connections.

@example
<get-var env::server_port>
@end example
  produces
@example
80
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::access-log}
The complete path to the file where the
MHTTPD server should keep the per-page access information.

The access log contains lines written in W3c's Common Logfile Format.

@end defvr


@defvr {@i{Variable}} {mhtml::cacheable}
The variable MHTML::CACHEABLE, when set to
a non-null value, indicates to the engine or server that the
expiration date of the current page should be in the future
(currently, about 10 days in the future).

@end defvr


@defvr {@i{Variable}} {mhtml::cgi-directories}
This array is a list of physical
paths relative to the document root which are directories containing
CGI programs.

The paths are checked @i{after} path translation has been
performed.  The final slash for each directory must be specified.

@example
<get-var mhtml::cgi-directories[0]>
@end example
  produces
@example
/cgi-bin/
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::cgi-extensions}
An array of file name extensions that
specifies to the MHTTPD server the file name extensions which indicate
that the file is really a CGI program to be executed.

@example
@group
  <set-var mhtml::cgi-extensions[0]=".pl">
@end group
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::cookie-compatible}
Indicates whether or not the
current client/server pair can pass HTTP
Cookies back and forth.

When such communication is possible, this variable is set to
@code{"true"}.

@end defvr


@defvr {@i{Variable}} {mhtml::current-doc}
The name of the current document, without
any path information, query strings, etc.

If the current URL is:

@example
@group
http://www.company.com/foo/bar/doc.mhtml?this=that
@end group
@end example

then @code{MHTML::CURRENT-DOC} is:

@example
@group
doc.mhtml
@end group
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::current-url}
A synonym for @code{mhtml::location}.

@end defvr


@defvr {@i{Variable}} {mhtml::current-url-sans-sid}
A synonym for @code{mhtml::location-sans-sid}.

@end defvr


@defvr {@i{Variable}} {mhtml::debug-log}
The complete path to the file where the
MHTTPD server should write server specific debugging information.
Generally, this only needs to be defined when you are debugging the
server itself.

@example
<get-var mhtml::debug-log>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::decimal-places}
Controls the number of decimal places which arithmetic functions
produce.  The default value of this variable is @code{2}, but
for times when you need greater resolution in your calculations, you
may wish to set it higher.
@example
<set-var mhtml::decimal-places = 10>
To 10 places: <div 1 .34567>
<unset-var mhtml::decimal-places>
To  2 places: <div 1 .34567>
@end example
  produces
@example
To 10 places: 2.8929325657

To  2 places: 2.89
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::default-filenames}
An array specifying the file names
that should be looked up when the URL to fetch ends in a directory,
instead of a document specifier.  The files are searched for in the
order in which they appear in this array.

@example
<get-var mhtml::default-filenames[]>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::document-root}
The complete path to the directory from
which your documents are to be served.  The final slash should not be
present.

@example
<get-var mhtml::document-root>
@end example
  produces
@example
/www/localhost/docs
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::epilogue-document}
Specifies a per-connection file of
code to be appended to the page just before processing any Meta-HTML
document.

@example
<get-var mhtml::epilogue-document>
@end example
  produces
@example
/www/localhost/epilogue.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::error-log}
MHTML::ERROR-LOG is the full path to a file
to which the server (or engine) logs errors.

@example
<get-var mhtml::error-log>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::exec-path}
A colon-seperated list of directories in which Meta-HTML searches
for executables when executing the @vref{cgi-exec} tag.

@end defvr


@defvr {@i{Variable}} {mhtml::full-url}
The URL used to connect to the current
document, including protocol, host information, session ID,
path-information, and query strings.

@example
<get-var mhtml::full-url>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual/make-printable.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::full-url-sans-sid}
The URL used to connect to the
current document, including protocol, host information,
path-information, and query strings, but excluding the session ID.

@example
<get-var mhtml::full-url-sans-sid>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual/make-printable.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::http-prefix}
The portion of the current URL which
contains the protocol, host information, and the session ID.

@example
<get-var mhtml::http-prefix>
@end example
  produces
@example
http://localhost.ua.com
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::http-prefix-sans-sid}
The portion of the current URL
which contains the protocol, host information, but excluding the
session ID.

@example
<get-var mhtml::http-prefix-sans-sid>
@end example
  produces
@example
http://localhost.ua.com
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::http-to-host}
A synonym for @code{mhtml::http-prefix}.

@end defvr


@defvr {@i{Variable}} {mhtml::inhibit-comment-parsing}
When this variable is set to
a non-empty value, the triple semi-colon comment feature is disabled.

You may need this for complex applications where you are deliberately
shipping the source of a Meta-HTML document to the client.

@end defvr


@defvr {@i{Variable}} {mhtml::iteration-limit}
The use of this variable has been deprecated.  @vref{while}
loops last until either the @var{test-clause} is met, or a
@vref{break} statement is seen.

@end defvr


@defvr {@i{Variable}} {mhtml::loaded-modules}
An array of fully qualified pathnames to the modules which have been loaded
via the function @vref{load-module}.  Used internally
during the module search process.

@end defvr


@defvr {@i{Variable}} {mhtml::location}
The URL used to connect to the current
document, including path information and query strings, but without
the protocol or host information.

@example
<get-var mhtml::location>
@end example
  produces
@example
/meta-html/manual/make-printable.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::location-sans-sid}
The URL used to connect to the
current document, including path information and query strings, but
without the protocol, host information, or Session ID.

@example
<get-var mhtml::location-sans-sid>
@end example
  produces
@example
/meta-html/manual/make-printable.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::metahtml-extensions}
An array of file name extensions
which indicate that the document to be fetched contains Meta-HTML
code.

Normally, this variable is set in the server process.

@example
<get-var mhtml::metahtml-extensions[]>
@end example
  produces
@example
.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::mhttpd-pages}
MHTML::MHTTPD-PAGES is the directory
containing various pages used by the server for displaying error
conditions, directory files, etc.  This is a complete path to the
directory, without the trailing slash.

@example
<get-var mhtml::mhttpd-pages>
@end example
  produces
@example
/www/localhost/mhttpd-pages
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::module-capable}
This value of this symbol is "true" when the system on which Meta-HTML
is running is capable of loading dynamic modules.  The value is determined
at the time Meta-HTML is compiled.

@end defvr


@defvr {@i{Variable}} {mhtml::module-directories}
An array of pathnames used to locate dynamic modules.

When @vref{load-module} is called with a non-fully qualified
pathname as an argument, the location of the file containing the module code
is searched for throughout the list of directories in
@var{mhtml::module-directories}.  The default list of directories includes at
least the following, and may have more dependent on your system type:

@example
@group
/www/lib, /www/bin, /www/metahtml/lib, /www/metahtml/bin,
/opt/lib, /opt/bin, /opt/metahtml/lib, /opt/metahtml/bin,
/usr/lib/mhtml, /home/mhttpd/lib, /usr/local/mhtml/lib,
and /www/src/metahtml/modules
@end group
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::prologue-document}
MHTML::PROLOGUE-DOCUMENT is a
per-connection file of code to be run just before processing any
Meta-HTML document.

@example
<get-var mhtml::prologue-document>
@end example
  produces
@example
/www/localhost/prologue.mhtml
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::raw-content-data}
Contains @i{exactly} what the
client browser sent in its @code{POST} request.

For wizard's use only!

@end defvr


@defvr {@i{Variable}} {mhtml::referer}
The value of the @code{HTTP}
@i{Referer} MIME header which the client browser sent along in its
request.

You might use this variable, if it is present, as the target of an
anchor:

@example
@group
<a href="<get-var mhtml::referer>">
  <b>Back</b> to referring document.
</a>
@end group
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::relative-prefix}
The sub-portion of the document path
which appears after @code{mhtml::include-prefix}.

With @code{mhtml::include-prefix} equal to @code{/www/docs}, and a
document path of @i{/www/docs/admin/sections.mhtml} then the value
of @code{mhtml::relative-prefix} would be @i{/admin}.

Useful when constructing new URLs based on the current URL.

@end defvr


@defvr {@i{Variable}} {mhtml::remote-ident}
The value of the environment variable
@code{ENV::REMOTE_IDENT} as received by the server.

In the Meta-HTML server, you can turn on the feature of asking the
connecting host for the username of the individual running the client
browser by setting @code{MHTTPD::GET-REMOTE-IDENT}.

There is never any gaurantee that the client will allow the server to
find this information out, so you should not write code which relies
on the presence of this variable.  However, if it is present, it can
be useful to present a default value.  For example:

@example
@group
<when <not <get-var e-mail>>>
  <set-var e-mail = <get-var mhtml::remote-ident>>
</when>
@end group
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::remote-user}
The value of the environment variable
@code{ENV::REMOTE_USER} as received by the server.

When @code{Basic Authorization} is supplied by a client, this
variable contains the username which the connected user supplied.  Do
NOT confuse this with ENV::REMOTE_IDENT!

@end defvr


@defvr {@i{Variable}} {mhtml::require-directories}
An array of directory names to be
searched through in order by @vref{require}.  The
directories should be specified without the trailing slash.

@end defvr


@defvr {@i{Variable}} {mhtml::require-loaded}
The list of pathnames which have
already been loaded through @vref{require}.

@end defvr


@defvr {@i{Variable}} {mhtml::server-name}
MHTML::SERVER-NAME is the name that this
server should advertise.  If you do not set it, the value of the
current host's name is used.  On Unix systems, this is the result of
calling @code{gethostname()}.

@example
<get-var mhtml::server-name>
@end example
  produces
@example
localhost.ua.com
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::server-port}
MHTML::SERVER-PORT is the port on which
this server should answer HTTP requests.  If you do not set it, the
value is @code{80}.

@example
<get-var mhtml::server-port>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::server-root}
MHTML::SERVER-ROOT is the root location
for your server.  You might store the configuration, logging, and
server specific files there, for example.  You currently cannot store
your CGIs there, because that directory must be underneath @code{MHTML::DOCUMENT-ROOT}.

The pathname should not end in a slash.

@example
<get-var mhtml::server-root>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::sid-prefix}
When this variable is present, the
@code{PATH} component of a returned @code{Set-Cookie} MIME
header is set to its value.  Normally, the value of @code{MHTML::RELATIVE-PREFIX} is used.

If you need to use @code{MHTML::SID-PREFIX}, you probably have a
very complex directory structure, and the need for every page access
to have a cookie associated with it.  In this case, setting
@code{MHTML::SID-PREFIX} will have the effect of flattening your
directory structure in the browser's view.

Generally, correctly written Meta-HTML applications do not need to
use this variable, and it might be used in only the most complicated
of Web sites, with multiple sessions per connectee, etc.

The explanation of HTTP Cookies is beyond the scope of this document.
Reference information on Cookies can be found through  this
link.

@end defvr


@defvr {@i{Variable}} {mhtml::unparsed-headers}
When set to true, indicates to the
Meta-HTML Engine that the server is expecting the engine to produce
all of the @code{HTTP} results, and not just the
@code{HTML} results.

This variable is automatically set in the Meta-HTML server, and when
the Engine is run under a name beginning with @code{"nph-"}.

You can turn this variable on or off during the invocation of a
specific page to control the behavior of both the server and engine.

@example
<get-var mhtml::unparsed-headers>
@end example
  produces
@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::url-to-dir}
The complete URL to the directory
containing the current document.  This includes protocol, host,
session ID, and relative prefix information.

@example
<get-var mhtml::url-to-dir>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::url-to-dir-sans-sid}
The complete URL to the directory
containing the current document.  This includes protocol, host, and
relative prefix information, but excludes the session ID if one were
present.

@example
<get-var mhtml::url-to-dir-sans-sid>
@end example
  produces
@example
http://localhost.ua.com/meta-html/manual
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::version}
Contains the version identification of the
currently running interpreter.  This variable is available whereever
the interpreter is running, including the Meta-HTML server, Engine,
and in @code{mdb}.

@example
<get-var mhtml::version>
@end example
  produces
@example
6.07
@end example

@end defvr


@defvr {@i{Variable}} {mhttpd::get-remote-ident}
MHTTPD::GET-REMOTE-IDENT, when set,
says to use the IDENT protocol to attempt to find out the username
associated with the connecting browser.  This only has a minor effect
on server performance, but isn't especially useful for non-Meta-HTML
sites.

@end defvr


@defvr {@i{Variable}} {mhttpd::session-database-file}
The fully qualified pathname to the
current session database.  Setting this variable only has meaning in the
@code{mhttpd.conf} or @code{engine.conf} files.

If this variable is not set, then the default value of
@code{"/tmp/sessions.db"} is used.

If the server or engine cannot access this file, no session state
information may be saved or retrieved.

@end defvr


@defvr {@i{Variable}} {sid}
The current session ID, as set by the function
@vref{session::initialize}.

The session ID is passed to and from the browser by either the use of
HTTP Cookies, or in the URL, as the first element of the path.

Normally, you never need to reference this variable directly, since
the various internal functions which deal with sessions know how to
set, get, and/or modify it without your help.

Related functions: @vref{create-session},
@vref{delete-session}, @vref{set-session-var}.

@end defvr

@node Function Index
@appendix Function Index
@printindex fn

@node Variable Index
@appendix Variable Index
@printindex vr

@node Contents
@contents
@bye
