\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}%
  \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.@*
129 El Paseo Court@*
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, Brian J. Fox, Universal Access Inc.@*
Copyright @copyright{} 1996, Universal Access Inc.
@end titlepage


@iftex
@everyfooting @i{Meta-HTML Reference -- Version 1.2} @| @| 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 5.0.  It
should not be considered a definitive reference manual by any means,
as the target remains somewhat mobile.  While the functions described
in this manual will continue to operate as documented, there may be
new functions or enhancements which 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/demos}.

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
  <b>You are connected to ``<get-var ENV::SERVER_NAME>'' and
     reading text written by <get-var the-author>.</b>
@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
    <set-var foo=bar>

@end example

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

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

@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
    name=value

@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
    <with-open-database db "/phones.db" mode=<get-var db-mode>>
     ...
    </with-open-database>

@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
    <if <get-var "Space Name">
        <get-var "Space Name[space index]">
      <set-var space-name-present=false>>

@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
    <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 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}} {cgi-decode}  string  [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
FOO=bar&STRING=this+is+a+string%2C+other+chars
@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}  var1  [var2...]  [preserve-case=true] 

A CGI readable string is created from the names of
@var{var1 ... varn} 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.

Thus,
@example
<cgi-encode Foo-Var preserve-case=true>
@end example

  produces

@example
Foo-Var=Foo+%26+Value
@end example

@end deffn

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

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
   <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 example

@end deffn

@deffn {@i{Simple Tag}} {copy-var}  from-var  [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
   <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 example

@end deffn

@deffn {@i{Simple Tag}} {decrypt}  varname  password 

Decrypts the contents of the previously encrypted variable named by @var{varname} using @var{password}.

The contents of @var{varname} are modified -- this function has no return value.

This function only does something if Meta-HTML has been configured with the @code{ --with-des} option, currently only available to those sites which are physically located within the United States.

Also see @vref{encrypt}.

@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
<define-tag defvar>
  <if <not <get-var %0>> <set-var %0=%1>>
</define-tag>
@end example

@end deffn

@deffn {@i{Simple Tag}} {encrypt}  varname  password 

Encrypts the contents of the variable named by @var{varname} using @var{password}.

The contents of @var{varname} are modified -- this function has no return value.

This function only does something if Meta-HTML has been configured with the @code{ --with-des} option, currently only available to those sites which are physically located within the United States.

Also see @vref{decrypt}.

@end deffn

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

Returns (as a text string) the current value of the variables named by
the @var{name}s given.

@end deffn

@deffn {@i{Simple Tag}} {get-var-once}  [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.

@end deffn

@deffn {@i{Simple Tag}} {set-var}  [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.

@end deffn

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

Replaces all occurrences of @var{this} with @var{with-that} in the contents of the variable named @var{varname}.  Both @var{this} and @var{with-that} are evaluated before the replacement is done. @var{this} 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}} {unset-var}  [name...] 

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

@end deffn

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

@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
  <set-var foo=1 bar>
  <var-exists foo>       ==> true
  <var-exists bar>       ==> true
  <get-var bar>          ==>
  <unset-var foo>
  <var-exists foo>       ==>
@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
   foo[3]
@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
   <get-var foo[]>
@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  [caseless=true] 

Adds @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 

Adds @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
<foreach name allnames>
  <if <satifies-criteria <get-var name>>
     <array-append <get-var name> useful-names>>
</foreach>
@end example

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

@end deffn

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

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

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

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

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

@end deffn

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

Looks up (and returns) 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 

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.

Given the array:

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

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

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

and, a subsequent execution of   @b{@code{<array-shift -3 array>}} leaves @var{array}:

@example
   "1"
   "2"
@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  [start=x]  [end=x]  [step=x] 

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
<set-var array[]="0\n1\n2\n3\n4\n5\n6\n7\n8\n9">
@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  [sort-fun]  [caseless=true]  [sortorder=reverse]  [numeric=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
<set-var array[0] = 1
         array[1] = 2
         array[3] = 3
         array[4] = 4
         array[5] = 20>
@end example

then,

@example
<sort array>
<foreach x array> <get-var x> </foreach>
@end example

  produces

@example

 1  2  2  20  3  4  6  7  8  9 
@end example

while
@example
<sort array numeric=true>
<foreach x array> <get-var x> </foreach>
@end example

  produces

@example

 1  2  2  3  4  6  7  8  9  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.92)
  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
   FOO::BAR
@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
   <set-var foo::bar = "Hello">
@end example

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

@deffn {@i{Simple Tag}} {%%read-package-file}  filename 

Reads packages from @var{filename}.  @var{filename} should contain the binary representation of packages that were written out with @vref{%%write-package-file}, and nothing else.

Returns a number indicating the number of packages read from the file.

This is used internally by @vref{require}.

@end deffn

@deffn {@i{Simple Tag}} {%%write-package-file}  filename  [package-name...] 

Writes the binary representation of the packages specified by @var{package-name}s to the file specified by @var{filename}.

Returns the number of packages written.

The packages may be read back in with @vref{%%read-package-file}.  This command is used in the @code{mklib} program in the Meta-HTML distribution.

@end deffn

@deffn {@i{Simple Tag}} {alist-to-package}  alist  package-name 

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

@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}} {package-delete}  package-name  ... 

Remove the definition of the packages named by @var{package-name}, 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
  <set-var all-packages[]=<package-names>>
@end example

@end deffn

@deffn {@i{Simple Tag}} {package-to-alist}  package-name  [strip=true] 

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}  package-name  [strip=true] 

Returns a newline separated list of the fully qualified variable names found in the package named by @var{package-name}.  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

@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}} {if}  test  [then]  [else] 

First @var{test} is evaluated.  If the result is a non-whitespace only
string, the @var{then} clause is evaluated, otherwise, the
@var{else} clause 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
  <if <get-var foo bar>
      "Either FOO or BAR is present"
    "Neither FOO nor BAR is present">
@end example

@end deffn

@deffn {@i{Simple Tag}} {ifeq}  this  that  [then]  [else]  [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}} {redirect}  url 

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.

@end deffn

@deffn {@i{Complex Tag}} {server-push} 

This command will be made obsolete.

Its functionality is available other, cleaner ways, specifically through the use of @vref{with-open-stream} and the variable @code{*standard-output*}.

Just write it as a @vref{defmacro}.

@end deffn

@deffn {@i{Simple Tag}} {var-case}  [{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
<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 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

@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}} {%%eval}  [expression] 

Internal function which performs evaluation.

If you think that you need this in your program, you
probably are doing something wrong.

@end deffn

@deffn {@i{Simple Tag}} {%%read}  [expression] 

Internal function which performs Meta-HTML reading.

If you think that you need this in your program, you
probably are doing something wrong.

@end deffn

@deffn {@i{Simple Tag}} {concat}  [arg1]  [...]  [argn] 

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
 <concat <textarea name=label rows=10 cols=40>
         <get-var-once label>
         </textarea>>
@end example

@end deffn

@deffn {@i{Simple Tag}} {date}  [epoch-seconds] 

Returns the local date as a string of 24 characters.

The output looks like @code{Fri Jun 20 18:29:49 1997}.

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.

Also see the @vref{time} function.

@end deffn

@deffn {@i{Simple Tag}} {debugging-on}  [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 <@vref{DEBUGGING-OUTPUT}> somewhere in the page.

@end deffn

@deffn {@i{Simple Tag}} {DEBUGGING-OUTPUT} 

By placing the @code{@b{<DEBUGGING-OUTPUT>}} tag somewhere in the page, you mark the location at which the Meta-HTML engine, server, or standalone processer should place any debugging statements which have been collected during the processing of the statements in the current page.

Without the presence of this tag, no debugging information will be displayed as part of the final output.

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}} {page-debug}  body 

Cause @var{body} to be inserted into the debugger output.

This output shows up as the result of placing the special tag <@vref{DEBUGGING-OUTPUT}> somewhere in the page.

@end deffn

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

Returns the current process ID on those systems which have process ID's.

@end deffn

@deffn {@i{Simple Tag}} {prog}  code... 

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.

For example:

@example
<if <eq this that>
   <prog <h2> This is equal to That </h2>>
  <prog <h2> This is not equal to That </h2>>>

@end example

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

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

@end deffn

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

Returns information about the symbol @var{symbol}.

The information is two lines:

@enumerate
@item  The type of the symbol, either STRING, BINARY, or FUNCTION.
@item  The "size" of the symbol.
@end enumerate

For 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}} {SYSTEM-ERROR-OUTPUT} 

By placing the @code{@b{<SYSTEM-ERROR-OUTPUT>}} tag somewhere in the page, you mark the location at which the Meta-HTML engine, server, or standalone processer should place any error statements which have been collected during the processing of the statements in the current page.

Without the presence of this tag, no system error information will be displayed as part of the final output.

We recommend that you place this tag somewhere in the page while you are building and testing your application, or, if you are having confusing behavior from an existing application.

Commands which manipulate files may place information about the underlying cause of the error condition here.

@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
   <date> ==> Wed Jul  3 17:14:53 1996
   <date <add <time> <mul 60 <mul 10 60>>>>
          ==> Thu Jul  4 03:14:57 1996
@end example

@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 

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

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}} {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}} {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

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

@end deffn

@deffn {@i{Simple Tag}} {match}  string  regexp  [action=(report|delete|extract|startpos|endpos|length)] 

Matches @var{regexp} against @var{string} and then performs @var{action}. The default @var{action} is @code{report}; when the expression matches the string @code{match} returns the text @code{true}.

Here are some examples:

@example
  <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 example

@end deffn

@deffn {@i{Simple Tag}} {pad}  string  total-size  [align=(right|left|middle)]  [truncate] 

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 spaces to make the
input argument take the desired number of spaces (presumably for use
in a   @b{@code{<pre> ... </pre>}} statement).

The optional arg @code{TRUNCATE} 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
  <pad "Hello" 10>              ==> "     Hello"
  <pad "Hello" 10 align=left>   ==> "Hello     "
  <pad "Hello" 10 align=middle> ==> "  Hello   "
  <pad "  Heckle  " 4 truncate> ==> "Heck"
@end example

@end deffn

@deffn {@i{Complex Tag}} {plain-text}  [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}} {small-caps}  [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

@end deffn

@deffn {@i{Simple Tag}} {string-eq}  string1  string2  [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
   <string-eq "foo" "FOO">               ==>
   <string-eq "foo" "foo">               ==>true
   <string-eq <upcase "foo"> "FOO">      ==>true
   <string-eq "foo" "FOO" caseless=true> ==>true
@end example

@end deffn

@deffn {@i{Simple Tag}} {subst-in-string}  string  regexp  replacement  [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.

@example
   <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 example

@end deffn

@deffn {@i{Simple Tag}} {substring}  string  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
  <substring "Hello" 1 2> ==> "e"
@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}.

@end deffn

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

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

@example
<upcase "This is a list">
@end example

  produces

@example
THIS IS A LIST
@end example

Also see @vref{downcase} and @vref{capitalize}.

@end deffn

@deffn {@i{Simple Tag}} {word-wrap}  string  [width=charwidth] 

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.

@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
   <set-var total = <add <get-var subtotals[0]>
                         <get-var subtotals[current]>>>
@end example

can be written as:

@example
   <set-var total = <add subtotals[0] subtotals[current]>>
@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
  <div 10 3>    ==> 3
  <div 10.0 3>  ==> 3.33
@end example

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

Returns the sum of @var{arg1} and @var{arg2}.

@end deffn

@deffn {@i{Simple Tag}} {decrement}  varname  [by=amount] 

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

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

Also see @vref{increment}.

@end deffn

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

 Returns the quotient of @var{arg1} and @var{arg2}.

@example
    <div 12 2> ==> 6
    <div 10 3> ==> 3

@end example

@end deffn

@deffn {@i{Simple Tag}} {increment}  varname  [by=amount] 

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

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

Also see @vref{decrement}.

@end deffn

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

  Returns the remainder of @var{arg1} and @var{arg2}.

@example
    <mod 12 2> ==> 0
    <mod 10 3> ==> 1

@end example

@end deffn

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

 Returns the product of @var{arg1} and @var{arg2}.

@example
    <mul 12 2> ==> 24

@end example

@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%.

Also see @vref{randomize}.

@end deffn

@deffn {@i{Simple Tag}} {randomize}  [arg] 

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

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

@end example

@end deffn

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

  Returns the difference of @var{arg1} and @var{arg2}.

@example
    <sub 12 2> ==> 10

@end example

@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}  expr  [...] 

Evaluates the @var{expr}s until one of them results in the empty string, or they are all exhausted.

The result of this expression is the last value evaluated.

@end deffn

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

Returns the string @code{"true"} when the number value of @var{arg1} is equal to the number value of @var{arg2}.

@end deffn

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

Returns the string @code{"true"} when the numeric value of
@var{arg-1} is greater than the numeric value of @var{arg-2}.

@end deffn

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

Returns the string @code{"true"} when the numeric value of
@var{arg-1} is less than the numeric value of @var{arg-2}.

@end deffn

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

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

@example
  <when <not <get-var foo>>>
     <comment> Complain that FOO is missing. </comment>
  </when>
@end example

@end deffn

@deffn {@i{Simple Tag}} {or}  expr  [...] 

Evaluates the @var{expr}s until one of them results in a non-empty value, or they are all exhausted.

The result of this expression is the last value evaluated.

@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 streams, which may be connected to files or network data.

The functions allow you to @vref{include} the contents of, open, create, read, or write various data sources, or to replace the contents of 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.

Also see @mref{Stream Operators}.

@deffn {@i{Simple Tag}} {cgi-exec}  pathname  [arg1]  [...]  [argn]  [output=varname]  [errors=varname] 

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

If @var{output=varname} is supplied, then @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}} {directory-contents}  path  [package-name]  [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{path}, and
the value of each variable is the association list for that
file.

@end deffn

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

Return an association-list containing operating system information about the file or directory named by @var{path}. @var{path} 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:
          	@b{Member}
	@b{Value}
	@b{Description}

            	 @b{NAME}
	@i{welcome.mhtml}
		  The name of the file or directory, without any of the path
	  information.

      	@b{FULL-NAME}
	/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{@code{get-file-properties}}.

      	 @b{SIZE} 
	2188
		  The size of the file in bytes.

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

      		  @b{In addition to the above fields, the following fields appear
	  on Unix based systems.}

      	@b{CREATED}
	6 29 96 10 3 24
		  The date on which this file was created.  The value is an
	  array, with ordered values being: month, day, year, hours,
	  minutes, and seconds.

      	@b{WRITTEN}
	6 29 96 10 3 24
		  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.

      	@b{READ}
	6 30 96 19 27 51
		  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.

      	@b{CREATOR}
	bfox
		  The system identifier of the user who created this file.

@end deffn

@deffn {@i{Simple Tag}} {include}  filename  [alt=code]  [verbatim] 

    Insert the contents of the file named by @var{filename} into
    the document at the point where the @code{include} form was
    read.  If the positional argument @var{verbatim} 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{filename} 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} value is given, then that value is placed into the
    page instead.

@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

@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  [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
  <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 example

@end deffn

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

Reads the contents of the stream @var{stream} into the binary variable @var{var}.  You had better understand binary variables before you use this. However, you can easily use this in conjunction with @vref{stream-put-contents}, and @vref{coerce-var}.

@end deffn

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

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

@end deffn

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

Writes the contents of the binary variable @var{var} to @var{stream}.
You had better understand binary variables before you use this.
However, you can easily use this in conjunction with
@vref{stream-get-contents}.

@end deffn

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

Returns @code{"true"} if @var{stream} is an open stream which
was opened with a mode of @code{read} or
@code{read-write}, or nothing otherwise.

@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 @code{*standard-output*}, this can be used to close the HTTP connection to the client, and yet continue processing data.

@end deffn

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

Returns @code{"true"} if @var{stream} is an open stream which
was opened with a mode of @code{write}, @code{append},
@code{write-create} or @code{read-write}, or nothing
otherwise.

@end deffn

@deffn {@i{Complex Tag}} {with-open-stream}  var  name  [type=(file|tcp)]  [mode=open-mode] 

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}, or @code{TCP}, in which case it is an open network connection.  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}).  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

@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.

@deffn {@i{Complex Tag}} {define-container}  name  [named-parameter...]  [package=package-name]  [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  [named-parameter...]  [package=packname] 

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
<define-function factorial num>
   <if <lt num 2> 1
      <mul num <factorial <sub num 1>>>>
</define-function>

<factorial 5> ==> 120
@end example

@end deffn

@deffn {@i{Complex Tag}} {define-tag}  name  [named-parameter...]  [package=package-name]  [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{Complex Tag}} {defmacro}  name  [named-parameter...]  [package=package-name]  [whitespace=delete] 

A synonym for @vref{define-container}.

@end deffn

@deffn {@i{Complex Tag}} {defsubst}  name  [named-parameter...]  [package=package-name]  [whitespace=delete] 

A synonym for @vref{define-tag}.

@end deffn

@deffn {@i{Complex Tag}} {defun}  name  [named-parameter...]  [package=packname] 

A synonym for @vref{define-function}.

@end deffn

@deffn {@i{Complex Tag}} {defweakmacro}  macro-name 

@code{defweakmacro} is exactly like @vref{defmacro}, 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
<defweakmacro p>
  <verbatim><P></verbatim>
  <when %qbody> Look ma! %body See? </when>
  <verbatim></P></verbatim>
</defweakmacro>
@end example

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

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

produces

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

@end deffn

@deffn {@i{Simple Tag}} {function-def}  name 

Returns the Meta-HTML readable form of the function body stored in the user-defined function @var{name}.

User-defined functions are made using @vref{defmacro}, @vref{defsubst}, or @vref{defun}.

@end deffn

@deffn {@i{Simple Tag}} {undef}  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

@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} 

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.

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}} {page-insert}  offset  content 

Insert @var{content} directly into the current page at the offset specified by @var{offset}.

In most cases, there is never any need to do this.  For some very strange situations involving direct communication with both the Web server, and the connecting client, it is conceivably possible that you would use this command.

But I doubt it.

@end deffn

@deffn {@i{Simple Tag}} {page-search}  start-offset  regex  [end] 

Returns a number representing the number of characters from the start of the current page that @var{regex} appears.  If @var{start-offset} is not zero, then the search starts from that many characters from the beginning of the page.

The optional argument @var{end} says to return the position of the last character which matched @var{regex}, instead of the first.

Why would you use this?

@end deffn

@deffn {@i{Simple Tag}} {replace-page}  filename  [alt=code] 

Replace the entire contents of the current page with the contents of the file named by @var{filename}.  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 file is chosen are identical to those for @vref{include}.

@end deffn

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

Replaces all occurrences of @var{this} with @var{with-that} in the current page.  Both @var{this} and @var{with-that} are evaluated before the replacement is done.  @var{this} 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
  <subst-in-page %name% <get-var forms::FirstName>>
@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}



@defvr {@i{Page Variable}} {mhtml::current-doc}
The name of the current document, without any path information, query strings, etc.

If the current URL is:

@example
http://www.company.com/foo/bar/doc.mhtml?this=that
@end example

then @code{MHTML::CURRENT-DOC} is:

@example
doc.mhtml
@end example

@end defvr


@defvr {@i{Page Variable}} {mhtml::current-url}
A synonym for @code{mhtml::location}.

@end defvr


@defvr {@i{Page Variable}} {mhtml::current-url-sans-sid}
A synonym for @code{mhtml::location-sans-sid}.

@end defvr


@defvr {@i{Page 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{Page 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{Page 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{Page 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{Page Variable}} {mhtml::http-to-host}
A synonym for @code{mhtml::http-prefix}.

@end defvr


@defvr {@i{Page 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{Page 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{Page Variable}} {mhtml::relative-prefix}
The sub-portion of the document path which appears after @code{mhtml::include-prefix}.

If the document path was:

@i{/meta-html/manual/make-printable.mhtml}

then the value of @code{mhtml::relative-prefix} is:

@i{}

Useful when constructing new URLs based on the current URL.

@end defvr


@defvr {@i{Page 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{Page 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

@node Block Commands
@section Block Commands
The @b{block} commands operate on a specific area of the page, and tend to manipulate the interpreter pointer position as a result.
These commands differ from the commands in the <section-ref pages> section of this manual because their scope is limited only to the block of statements that they surround.

@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.

@end deffn

@deffn {@i{Complex Tag}} {verbatim}  [quote] 

Insert @var{body} verbatim, avoiding doing any processing on
the contents.  If the positional 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

@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 @code{set-session-timeout}, you can change this value. A special signal value of "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}  [var1[=missing-code]]  [...]  [varn=[missing-code]]  [alt=altcode]  [allow-multiple] 

Create a session, and place the session identifier in the variable @code{SID}.  The @i{key} for the session is created by concatenating the values of the @var{var}s together, separated by hyphens (@code{-}).  If a @var{var} doesn't have a value, 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 in the page (or have no @i{missing} action), and the session could not be created, then @var{altcode} is evaluated if it is present.

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

@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 @code{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-var}  [name...] 

Get the value for @var{name} from the session database record
associated with the current session.

@end deffn

@deffn {@i{Simple Tag}} {require-session}  [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
  <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 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
<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 example

For more detail on the built-in variables provided by the Meta-HTML
Server and CGI Engine, see @mref{Server Variables}.

@end deffn

@deffn {@i{Simple Tag}} {session-export}  package  [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  [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}} {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
  <set-var sids[]=<sessions-of-key "On-Line Shopping">>
@end example

@end deffn

@deffn {@i{Simple Tag}} {set-session-timeout}  value 

Make the current session time out after @var{VALUE} minutes.
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

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

Make @var{NAME}s have no value in the session database record associated with the current session.

@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 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}.

@deffn {@i{Simple Tag}} {dbm::first-key}  dbvar 

Returns the "first" key in the database referenced by @var{dbvar}.

@end deffn

@deffn {@i{Simple Tag}} {dbm::get-var}  dbvar  varname 

Returns the value associated with @var{varname} in the open database referenced by @var{dbvar}.

@end deffn

@deffn {@i{Simple Tag}} {dbm::next-key}  dbvar  afterkey 

Returns the "next" key in the database referenced by @var{dbvar} starting after the key @var{afterkey}.

@end deffn

@deffn {@i{Simple Tag}} {dbm::set-var}  dbvar  [name=value...] 

Sets the association for @var{name} to be @var{value} in the open database referenced by @var{dbvar}.  Multiple @var{name=value} pairs may be given.

@end deffn

@deffn {@i{Simple Tag}} {dbm::unset-var}  dbvar 

Deletes any association for @var{name} in the open database referenced by @var{dbvar}.

@end deffn

@deffn {@i{Complex Tag}} {dbm::with-open-database}  dbvar  dbname  [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.

Only the DBM commands are meaningful within this environment.  This function is designed to allow access to legacy dbm, gdbm, or ndbm databases; it won't work on anything else.

@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 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
<with-open-database db /tmp/file.db mode=write>
  <set-var deleted? = <database-delete-record db <get-var key>>>
</with-open-database>
@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  [prefix=package-name] 

Load the variables from the record specified by @var{key} in the database referenced by @var{dbvar}.  If @var{prefix=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
<with-open-database db /tmp/file.db mode=read>
  <set-var loaded? = <database-load-record db <get-var name>>>
</with-open-database>

<when <get-var loaded?>>
  The record was loaded successfully.
</when>
@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
<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 example

@end deffn

@deffn {@i{Simple Tag}} {database-query}  dbvar  expr  [format=fexpr]  [keys=varname]  [sort=field1[]  [field2...]]  [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
<with-open-database db "/www/data/employee.db" mode=read>
  <database-query db <match <get-var name> "Fox"> keys=dbkeys>
</with-open-database>
@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
<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 example

@end deffn

@deffn {@i{Simple Tag}} {database-save-package}  dbvar  key  package  [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
<set-var 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 mykey foo strip=true>
</with-open-database>
@end example

produces

@example
true
@end example

@end deffn

@deffn {@i{Simple Tag}} {database-save-record}  dbvar  key  [var1...varn]  [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
<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 example

@end deffn

@deffn {@i{Simple Tag}} {database-unique-key}  dbvar  [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  [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 Msql Database Extensions
@section MSQL Database Extensions
Meta-HTML can optionally be compiled with the MSQL
database interface library (by supplying @code{--with-msql} to the `@code{configure}' command).  These extensions allow true SQL database interaction at many levels, providing a clean and flexible abstraction to an MSQL database. 

@deffn {@i{Simple Tag}} {msql::cursor-get-column}  cursor  column-number 

This can be called with  a cursor which is the result from a call to database-exec-query.

It gets the data  from the current result set, in column numbered @var{column-number} (starting at column 0).

@end deffn

@deffn {@i{Simple Tag}} {msql::database-delete-record}  dbvar  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}.

You must supply @var{tablename} and @var{fieldname}, where <fieldname> is the name of the primary key field.

@end deffn

@deffn {@i{Simple Tag}} {msql::database-exec-query}  dbvar  query-string  [cursor=varname] 

Executes the SQL query in @var{query-string} The @var{query-string} can be any expression Meta-HTML expression which evaluates to
a valid SQL query or command string.

Returns a cursor object, which can be passed to 
@vref{msql::database-next-record}, @vref{msql::number-of-rows}, and
@vref{msql::set-row-position}.

If the @var{cursor} keyword arg is supplied, the returned cursor value is stored in the supplied variable name. 

@end deffn

@deffn {@i{Simple Tag}} {msql::database-exec-sql}  dbvar  query-string 

Executes the SQL query in QUERY-STRING The QUERY-STRING can be any  Meta-HTML expression which evaluates to a valid SQL query or command string.

Returns TRUE if there is no error executing the query. 

@end deffn

@deffn {@i{Simple Tag}} {msql::database-field-info}  dbvar  table  fieldname 

Returns an alist of properties of the specified column  @var{fieldname} in the SQL table named @var{table}:

@example
((name . "column_name") (length . "max byte length") (type . "sqlDatatype")
    (is_primary_key . "true") (is_not_null . "true"))
@end example

The returned sqlDatatype value is one of
@example
GSQL_CHAR
GSQL_NUMERIC
GSQL_DECIMAL
GSQL_INTEGER
GSQL_SMALLINT
GSQL_FLOAT
GSQL_REAL
GSQL_DOUBLE
GSQL_VARCHAR
@end example

@end deffn

@deffn {@i{Simple Tag}} {msql::database-load-record}  dbvar  key  [package=packagename]  [table=tablename]  [keyname=fieldname] 

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}} {msql::database-next-record}  cursorvar  [colnames=namelist]  [prefixtablenames]  [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 "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 these commas-separated list of names instead of the field names in the
   result set.

@example
<msql::database-next-record mydb cursor package=tmp
                colnames="a.name, a.partnum, b.name">
<get-var tmp::b.name>
<get-var tmp::a.name>
@end example

If <prefixtablenames> is non-null, or the database connection option 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}} {msql::database-query}  dbvar  expr  query  [colnames=namelist]  [prefixtablenames]  [query=query-string]  [format=fexpr]  [keys=varname]  [keyname=fieldname] 

Select and optionally format records in the database @var{db} according to the criterion in @var{fexpr}. 

@var{query} is an SQL query, which returns 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} is present, it is an expression to evaluate in the context of the database fields, (as with @var{expr}).

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 true, and all of the selection of 
records is done via the SQL query itself. The @var{expr} could be used to impose additional conditions to decide whether to invoke the format expression on a row.

@example
  <msql::with-open-database rdb database=rolodex
			    host=localhost>
  <table border=1>
    <tr><th>Name</th><th>Age</th></tr>
  <msql::database-query rdb true 
			query="SELECT * FROM people WHERE name like 'Washington' ORDER BY lastname"
			format=<prog <tr>
				 <td>
				 <get-var lastname>, <get-var firstname>
				 </td>
				 <td>
				 <get-var age>
				 </td>
				 </tr>>>
    </table>
  </msql::with-open-database>
@end example

If @var{keys} is specified, it is the simple name of a variable to receive the array of keys which satisfied @var{fexpr}. If you specify an argument for @var{keys}, you must
also specify which column to collect the values from, using
the @var{keyname} keyword argument.

If the optional argument @var{colnames} 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
<msql::database-query mydb true query=<get-var query>
                      colnames="foo.name, bar.name"
                      format=<prog FOO.NAME IS 
				<get-var foo.name> 
				BAR.NAME IS 
				<get-var bar.name>>>
@end example

If @var{prefixtablenames} is non-null, or the database
connection option 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}} {msql::database-save-package}  dbvar  key  package  [keyname=fieldname]  [table=tablename] 

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 fields. 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.

@code{msql::database-save-package} is implemented to
first attempt to do a SQL INSERT into the table, and if
that fails to try a UPDATE query, with @var{keyname=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

 <set-var baz::name="Kate Mulgrew" baz::age=45 baz::salary=34000 
    baz::dept=travel>

  <set-var result=<msql::database-save-package mydb 103 baz
					       table=employees keyname=id>>
@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}} {msql::database-save-record}  db  key  table  keyname  [var...]  [table=tablename]  [keyname=fieldname] 

Does an INSERT and UPDATE to try to store the data into @var{table} using the single key @var{keyname}, with value @var{key}.

NOTE: If the key field for table you are using is not configured as the @i{primary key}, then it is possible to create duplicate entries in the database.

   If you have a variable which does not match a field name
   in the table, that variable is silently ignored.

   If you try to save character data into a numeric field,
   the insert or update will fail, and you can check the
   error message in msql::msql-error-message[]

@end deffn

@deffn {@i{Simple Tag}} {msql::database-table-fields}  dbvar  tablename  [result=varname] 

List all the fieldnames for a table. This must be done with a database already open, i.e., within the scope of a   @b{@code{<msql::with-open-database>}}.

Returns an array of column names, or sets the value of @var{varname} if supplied.

@end deffn

@deffn {@i{Simple Tag}} {msql::database-tables}  dbvar  [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. This must be done with a database already open, i.e., within the scope of a   @b{@code{<with-open-database>}}.

@end deffn

@deffn {@i{Simple Tag}} {msql::host-databases}  [hostname]  [result=varname] 

Return the names of the databases available on @var{host} as a newline separated list of strings.  If @var{varname} is supplied, it is the name of a variable which should receive the values.

@end deffn

@deffn {@i{Simple Tag}} {msql::number-of-rows}  cursorvar 

Returns the number of rows which were found as a result of the last query issued for @var{cursorvar}.

@end deffn

@deffn {@i{Simple Tag}} {msql::set-row-position}  cursorvar  index 

Sets the current row number position in the result referenced by @var{cursorvar} to @var{index}.

Subsequent calls to   @b{@code{<msql::database-next-record>}} will begin with the record at @var{index}.

@end deffn

@deffn {@i{Simple Tag}} {msql::sql-transact}  dbvar  [action=COMMIT|ROLLBACK] 

  Perform transaction, to either commit or rollback all operations on
   the current database connection.

   ACTION can be one of COMMIT or ROLLBACK. 
   If unspecified, ACTION defaults to COMMIT.

NOTE: Transactions are not yet supported by MSQL.

@end deffn

@deffn {@i{Complex Tag}} {msql::with-open-database}  dbvar  [dsn=DSN]  [database=DBNAME]  [host=hostname] 

Create an environment in which other MSQL database commands can be given.  First, the database referenced by @var{dbname} is locked and opened, 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.

Example:

@example
 <msql::with-open-database rdb database=rolodex
			    host=localhost>
...
</msql::with-open-database>
@end example

For compatibility with ODBC, the host/database information
can optionally be given in a ODBC style DSN string.   
@example
DSN="host=localhost;database=rolodex"
@end example

@end deffn

@node Odbc Database Operators
@section ODBC Database Extensions
Meta-HTML PRO is optionally delivered with a complete ODBC compliant database module, providing a useful set of database commands for operating on commercial databases, such as ORACLE or SyBase. These extensions allow true SQL database interaction at many levels, providing a clean and flexible abstraction.
@deffn {@i{Simple Tag}} {odbc::cursor-get-column}  cursor  column-number 

This can be called with  a cursor which is the result from a call to database-exec-query.

It gets the data  from the current result set, in column numbered @var{column-number} (starting at column 0).

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-column-info}  dbvar  table  fieldname 

 Returns an alist of properties of a column of a table. Example:
((NAME . "realname")(LENGTH . "30")(TYPE . "GSQL_CHAR")(IS_UNIQUE . "")(IS_NULLABLE . "true")(QUALIFIER . "")(OWNER . "")(TYPENAME . "")(PRECISION . "0")(SCALE . "0")(RADIX . "0")(TABLE . "accounts"))

    This is actually implemented by fetching information on *all*
    columns and selecting the specified one. It is thus more
    efficient, if you are looking for info on several columns, to use
    database-columns-info, and get all the column information in a
    single array.

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-columns-info}  dbvar  table  [result=var] 

 Returns an array of alists of properties of the columns of a table. 

An example of one entry in the result array:

((NAME . "realname")(LENGTH . "30")(TYPE . "GSQL_CHAR")(IS_UNIQUE . "")(IS_NULLABLE . "true")(QUALIFIER . "")(OWNER . "")(TYPENAME . "")(PRECISION . "0")(SCALE . "0")(RADIX . "0")(TABLE . "accounts"))

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-delete-record}  dbvar  key  table  keyname  [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 DELETE query is issued which
will delete any record in the table named @var{table} whose
field named @var{keyname} matches the value of @var{key}.

You must supply @var{table} and @var{keyname}, where @var{keyname} is the name of the primary key field in table.

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-exec-query}  dbvar  query-string  [cursor=varname] 

Executes the SQL query in @var{query-string} The @var{query-string} can be any expression Meta-HTML expression which evaluates to
a valid SQL query or command string.

Returns a cursor object, which can be passed to 
@vref{odbc::database-next-record}, @vref{odbc::number-of-rows}, and
@vref{odbc::set-row-position}.

If the @var{cursor} keyword arg is supplied, the returned cursor value is stored in the supplied variable name. 

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-exec-sql}  dbvar  query-string 

Executes the SQL query in  QUERY-STRING, on the open
database connection specified by DBVAR.

Returns TRUE if no errors are encountered.

This function differs from  ODBC::DATABASE-EXEC-QUERY
in that it does not return any cursor, so 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

@end example

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-load-record}  dbvar  key  [package=packagename]  [table=tablename]  [keyname=fieldname] 

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}} {odbc::database-next-record}  cursorvar  [colnames=namelist]  [prefixtablenames]  [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 "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 these commas-separated list of names instead of the field names in the
   result set.

@example
<odbc::database-next-record mydb cursor package=tmp
                colnames="a.name, a.partnum, b.name">
<get-var tmp::b.name>
<get-var tmp::a.name>
@end example

If <prefixtablenames> is non-null, or the database
connection option 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}} {odbc::database-query}  dbvar  expr  query  [colnames=namelist]  [prefixtablenames]  [query=query-string]  [format=fexpr]  [keys=varname]  [keyname=fieldname] 

Select and optionally format records in the database @var{db} according to the criterion in @var{fexpr}. 

@var{query} is an SQL query, which returns 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} is present, it is an expression to evaluate in the context of the database fields, (as with @var{expr}).

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 true, and all of the selection of 
records is done via the SQL query itself. The @var{expr} could be used to impose additional conditions to decide whether to invoke the format expression on a row.

@example
  <odbc::with-open-database rdb database=rolodex
			    host=localhost>
  <table border=1>
    <tr><th>Name</th><th>Age</th></tr>
  <odbc::database-query rdb true 
			query="SELECT * FROM people WHERE name like 'Washington' ORDER BY lastname"
			format=<prog <tr>
				 <td>
				 <get-var lastname>, <get-var firstname>
				 </td>
				 <td>
				 <get-var age>
				 </td>
				 </tr>>>
    </table>
  </odbc::with-open-database>
@end example

If @var{keys} is specified, it is the simple name of a variable to receive the array of keys which satisfied @var{fexpr}. If you specify an argument for @var{keys}, you must
also specify which column to collect the values from, using
the @var{keyname} keyword argument.

If the optional argument @var{colnames} 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
<odbc::database-query mydb true query=<get-var query>
                      colnames="foo.name, bar.name"
                      format=<prog FOO.NAME IS 
				<get-var foo.name> 
				BAR.NAME IS 
				<get-var bar.name>>>
@end example

If @var{prefixtablenames} is non-null, or the database
connection option 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}} {odbc::database-query-info}  cursor  [result=varname] 

  Returns an array of alists of information about the columns of the
   given cursor's query result set.

This is similar to the format returned by 
database-columns-info. 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

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-save-package}  dbvar  key  package  [keyname=fieldname]  [table=tablename] 

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 fields. 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.

@vref{} is implemented to
first attempt to do a SQL INSERT into the table, and if
that fails to try a 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

 <set-var baz::name="Kate Mulgrew" baz::age=45 baz::salary=34000 
    baz::dept=travel>

  <set-var result=<odbc::database-save-package mydb 103 baz
					       table=employees keyname=id>>
@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}} {odbc::database-save-record}  db  key  table  keyname  [var...]  [table=tablename]  [keyname=fieldname] 

Does an INSERT and UPDATE to try to store the data into @var{table} using the single key @var{keyname}, with value @var{key}.

NOTE: If the key field for table you are using is not configured as the @i{primary key}, then it is possible to create duplicate entries in the database.

   If you have a variable which does not match a field name
   in the table, that variable is silently ignored.

   If you try to save character data into a numeric field,
   the insert or update will fail, and you can check the
   error message in odbc::odbc-error-message[]

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-set-options}  dbvar  [SQL-ESCAPE-CHARACTER-CODE=int]  [SQL-TRUNCATE-COLUMNS=boolean] 

Sets various database-specific options.

SQL-ESCAPE-CHARACTER-CODE sets the character which is used
to escape single quotes in strings.

If SQL-TRUNCATE-COLUMNS is non-null, then queries composed
by database-save-record and database-save-package will
have character string field data automatically truncated
to the max column width of the field being stored into, before
the query is ever sent to the SQL server.

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-tables}  dbvar  [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. This must be done with a database already open, i.e., within the scope of a @vref{odbc::with-open-database}.

@end deffn

@deffn {@i{Simple Tag}} {odbc::database-tables-info}  dbvar  [result=var]  [tabletype=expression]  [tablequalifier=expression]  [tablename]  [tableowner=expression] 

Returns an array of alists, one per table in the database.

   Each alist contains database-specific information about
the table, including at least
   the NAME of the table.
   ((name . "table_name"))

 The optional tablemumble args are ANSI SQL regexp patterns.

The optional RESULT argument specifies a variable to
put the result array into.

@end deffn

@deffn {@i{Simple Tag}} {odbc::get-connect-option}  dbvar  fInfoType 

Performs ODBC SQLGetConnectOption call.  Returns the requested
data value specified by @var{fInfoType}

Valid values for @var{fInfoType} are:

@example
SQL_ACCESS_MODE  	
SQL_AUTOCOMMIT		
SQL_LOGIN_TIMEOUT 	
SQL_OPT_TRACE 		
SQL_OPT_TRACEFILE 	
SQL_TRANSLATE_DLL 	
SQL_TRANSLATE_OPTION 	
SQL_TXN_ISOLATION 	
SQL_CURRENT_QUALIFIER 	
SQL_ODBC_CURSORS	
SQL_QUIET_MODE 		
SQL_PACKET_SIZE 	
@end example

@end deffn

@deffn {@i{Simple Tag}} {odbc::get-info}  dbvar  fInfoType 

Performs ODBC GetInfo call.  Returns the requested
data value specified by @var{fInfoType}

Valid values for @var{fInfoType} are:

@example
SQL_DRIVER_NAME
SQL_ODBC_VER
SQL_CURSOR_COMMIT_BEHAVIOR
SQL_CURSOR_ROLLBACK_BEHAVIOR
SQL_DEFAULT_TXN_ISOLATION
SQL_TXN_ISOLATION_OPTION
SQL_NON_NULLABLE_COLUMNS
SQL_DRIVER_HLIB
SQL_DRIVER_ODBC_VER
SQL_QUALIFIER_LOCATION
@end example

@end deffn

@deffn {@i{Simple Tag}} {odbc::number-of-rows}  cursorvar 

Returns the number of rows which were found as a result of the last query issued for @var{cursorvar}.

Cursors are created as the result of direct SQL queries by @vref{odbc::database-exec-query}.

@end deffn

@deffn {@i{Simple Tag}} {odbc::query-get-column}  column-number 

This can be only  be called within the scope of the  odbc::database-query function.

It gets the data from the current result set, in column numbered @var{column-number} (starting at column 0).

@end deffn

@deffn {@i{Simple Tag}} {odbc::set-connect-option}  dbvar  fInfoType  value 

Performs ODBC SQLSetConnectOption call.  Returns the requested
data value specified by @var{fInfoType}

Valid values for @var{fInfoType} are:

@example
SQL_ACCESS_MODE  	
SQL_AUTOCOMMIT		
SQL_LOGIN_TIMEOUT 	
SQL_OPT_TRACE 		
SQL_OPT_TRACEFILE 	
SQL_TRANSLATE_DLL 	
SQL_TRANSLATE_OPTION 	
SQL_TXN_ISOLATION 	
SQL_CURRENT_QUALIFIER 	
SQL_ODBC_CURSORS	
SQL_QUIET_MODE 		
SQL_PACKET_SIZE 	
@end example

@end deffn

@deffn {@i{Simple Tag}} {odbc::sql-transact}  dbvar  [action=COMMIT|ROLLBACK] 

  Perform transaction, to either commit or rollback all operations on
   the current database connection.

   ACTION can be one of COMMIT or ROLLBACK. 
   If unspecified, ACTION defaults to COMMIT.

NOTE: ODBC connections default to AUTOCOMMIT mode. See
@vref{} and @vref{}.

@end deffn

@deffn {@i{Complex Tag}} {odbc::with-open-database}  dbvar  [DSN=dsn-string] 

Create an environment in which other ODBC database commands can be given.  First, the database referenced by @var{dbname} is locked and opened, 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.

Example:

@example
 <odbc::with-open-database rdb DSN="DSN=oracle;host=localhost;database=test">
...
</odbc::with-open-database>
@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{Server 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{Server 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{Server 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{Server 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]> ==> /cgi-bin/
@end example

@end defvr


@defvr {@i{Server 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
  <set-var mhtml::cgi-extensions[0]=".pl">
@end example

@end defvr


@defvr {@i{Server 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{Server Variable}} {mhtml::error-log}
MHTML::ERROR-LOG is the full path to a file to which the server logs errors.

@example
    <get-var mhtml::error-log>
@end example

  produces

@example

@end example

@end defvr


@defvr {@i{Server 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{Server 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{Server 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{Server Variable}} {mhttpd::admin-port}
MHTTPD::ADMIN-PORT is the port number on which the Meta-HTML server should listen for administration requests.  The default port is generally set to 8008.

If no such port is specified, then the server will not listen for administration requests at all.

@example
    <get-var mhttpd::admin-port>
@end example

  produces

@example

@end example

@end defvr


@defvr {@i{Server Variable}} {mhttpd::admin-root}
MHTTPD::ADMIN-ROOT is the complete path to the directory which contains server administration pages.  Usually set to @code{".../conf/admin"}.

@example
    <get-var mhttpd::admin-root>
@end example

  produces

@example

@end example

@end defvr


@defvr {@i{Server 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{Server Variable}} {mhttpd::session-database-file}
The complete path to the file in which the server or engine stores session information, keyed by session ID.

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

@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
@code{<load-module>} function.

See the @code{modules} directory of the distribution for more details.
@deffn {@i{Simple Tag}} {load-module}  module-name 

Loads a module dynamically at runtime, adding the function definitions found therein to the global package of Meta-HTML functions.

@code{load-module} returns the string @code{"true"} if the module is loaded successfully, or places an error in @vref{system-error-output} if not.

@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.

Example:

@example
<set-var loaded? = <load-module /www/lib/example.so>>
@end example

@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
    (mkdir /usr/www)

@end example

  @item  Create   @b{@code{<wwwroot>/bin}},   @b{@code{<wwwroot>/docs}},   @b{@code{<wwwroot>/conf}}, and   @b{@code{<wwwroot>/logs}}.

@example
    (mkdir /usr/www/bin /usr/www/docs /usr/www/conf /usr/www/logs)

@end example

  @item  Copy @code{"Server/mhttpd"} and @code{"Utilities/*"} to
    @b{@code{<wwwroot>/bin}}.

@example
    (cp Server/mhttpd /usr/www/bin)

@end example

  @item  Copy @code{"Documentation"} to   @b{@code{<wwwroot>/docs}}.

@example
    (cp -r Documentation /usr/www/docs)

@end example

  @item  Copy @code{"Server/mhttpd.conf"} to   @b{@code{<wwwroot>/conf}}.

@example
    (cp Server/mhttpd.conf /usr/www/conf)

@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
    (cat Server/mhttpd.conf | sed -e "s/www.myhost.com/`hostname`/"
		>/usr/www/conf/mhttpd.conf)

@end example

  @item  As the superuser, start the server from the   @b{@code{  <wwwroot>}} directory:

@example
    (cd /usr/www; su -c bin/mhttpd)

@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
    <set-var mhtml::server-port = <if <get-var mhttpd::ssl-server> 443 80>>

@end example

  to read:

@example
    <set-var mhtml::server-port = 8080>

@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.1.1 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.1.1 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.1.1 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.1.1 source tree.

    @b{@item }
    Reconfigure the compilation of your server by typing
    @code{./Configure} from the @code{src} directory of
    your Apache 1.1.1 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
      http://yourhost.com/cgi-bin/nph-engine/your/url.mhtml

@end example

    you can use 

@example
      http://yourhost.com/your/url.mhtml

@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
      Init fn=load-modules shlib=/ns-home/nsapi/nsapi-dist/mhtml_nsapi.so funcs=handle-mhtml-sid,mhtml_fixup_path

@end example

    @item  Find the definitions in the "default" object:

    Look for the line

@example
      <Object name="default">

@end example

    Right after this, you should place a NameTrans call to handle_mhtml_sid:

@example
      NameTrans fn=handle-mhtml-sid 

@end example

    @item  Your obj.conf will have several PathCheck directives. Find
    the call to index-names:

@example
      PathCheck index-names ...    

@end example

    and replace it with the lines

@example
      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 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
      Service fn="send-cgi" type="magnus-internal/cgi"

@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 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
   <set-var env::path="/www/bin:/www/docs/cgi-bin">
@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]> ==> /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
  <set-var mhtml::cgi-extensions[0]=".pl">
@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
http://www.company.com/foo/bar/doc.mhtml?this=that
@end example

then @code{MHTML::CURRENT-DOC} is:

@example
doc.mhtml
@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>
    9 / 3.0 = <div 9 3.0>
   10 / 3.0 = <div 10 3.0>
    9 / 3   = <div 9 3>
   10 / 3   = <div 10 3>
    <unset-var mhtml::decimal-places>
    9 / 3.0 = <div 9 3.0>
   10 / 3.0 = <div 10 3.0>
    9 / 3   = <div 9 3>
   10 / 3   = <div 10 3>
@end example

  produces

@example

    9 / 3.0 = 3.0000000000
   10 / 3.0 = 3.3333333333
    9 / 3   = 3.0000000000
   10 / 3   = 3.3333333333

    9 / 3.0 = 3.00
   10 / 3.0 = 3.33
    9 / 3   = 3
   10 / 3   = 3
@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 logs errors.

@example
    <get-var mhtml::error-log>
@end example

  produces

@example

@end example

@end defvr


@defvr {@i{Variable}} {mhtml::exec-path}
MHTML::EXEC-PATH is what gets passed in the environment to CGI programs as PATH.  Choose carefully.

The default value of this variable in the @b{Mhttpd} server is:

@example
   <set-var mhtml::exec-path =
     <concat <get-var mhtml::server-root>/bin:/bin
             :<get-var mhtml::document-root>/cgi-bin
             :/usr/bin:/usr/local/bin:/usr/ucb>>
@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::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::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
    <a href="<get-var mhtml::referer>">
     <b>Back</b> to referring document.
    </a>
@end example

@end defvr


@defvr {@i{Variable}} {mhtml::relative-prefix}
The sub-portion of the document path which appears after @code{mhtml::include-prefix}.

If the document path was:

@i{/meta-html/manual/make-printable.mhtml}

then the value of @code{mhtml::relative-prefix} is:

@i{}

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
   <when <not <get-var e-mail>>>
     <set-var e-mail = <get-var mhtml::remote-ident>>
   </when>
@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.02
@end example

@end defvr


@defvr {@i{Variable}} {mhttpd::admin-port}
MHTTPD::ADMIN-PORT is the port number on which the Meta-HTML server should listen for administration requests.  The default port is generally set to 8008.

If no such port is specified, then the server will not listen for administration requests at all.

@example
    <get-var mhttpd::admin-port>
@end example

  produces

@example

@end example

@end defvr


@defvr {@i{Variable}} {mhttpd::admin-root}
MHTTPD::ADMIN-ROOT is the complete path to the directory which contains server administration pages.  Usually set to @code{".../conf/admin"}.

@example
    <get-var mhttpd::admin-root>
@end example

  produces

@example

@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 complete path to the file in which the server or engine stores session information, keyed by session ID.

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}
This variable contains the current session ID.

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}, etc.

@end defvr

@node Function Index
@appendix Function Index
@printindex fn

@node Variable Index
@appendix Variable Index
@printindex vr

@node Contents
@contents
@bye