% (C) Copyright International Business Machines Corporation 23 January 
% 1990.  All Rights Reserved. 
%  
% See the file USERAGREEMENT distributed with this software for full 
% terms and conditions of use. 
\section{Using Hermes under Unix}
\label{Unix}
\subsection{Storing Hermes modules in Unix files}

The Hermes language includes notions of definitions and process
modules.  In a fault-tolerant, non-terminating Hermes system, all
Hermes data would persist until discarded, and there would be no need
to explicitly save modules to disk storage.  The current
implementation is neither fault-tolerant, nor is it run for long periods
of time, typically.  For this reason we use the Unix filesystem as a
repository for Hermes program modules and other data values.  This
requires a set of well-defined rules for naming the files that contain
Hermes data, as well as facilities for loading and storing data.  This
section describes the naming conventions assumed by the compiler and
run-time system of the current implementation.
Section~\ref{resource-list} discusses the services available to the
Hermes programmer for managing Hermes data in the Unix filesystem.

Hermes programs consist of definition modules and process modules.  In
their source forms, these files should be named with extentions ``{\tt
.d}'' and ``{\tt .p}'', respectively.  For example, the source text
for a definitions module named foo should be placed in a file named
``{\tt foo.d}''.  Likewise, the source for a process module named
``{\tt bar}'' should go in a file called ``{bar.p}''.

When a Hermes source file is compiled, the compiled object form is
saved in a file with the same base name, but with the extension ``{\tt
.do}'' or ``{\tt .po}'', for a definitions or process module,
respectively.  Thus, compiling the source file ``{\tt foo.d}'' would
result in the creation of a file ``{\tt foo.do}'', and compiling
``{\tt bar.p}'' would produce ``{\tt bar.po}''.

The compiler always writes object files into the ``current
directory,'' which is normally the directory in which the Hermes
interpreter was started (but see the {\tt setCwd} service described
in Section~\ref{resource-list} for how to change this).

\subsection{Where Hermes looks for files}

To compile a module that imports another module, the compiler must read
the imported module's object file.
For instance, to compile a module {\tt bar} with {\tt foo} in its
{\tt using} list, the compiler must load the compiled definitions module
{\tt foo.do}.  Similarly, if process module {\tt boz}
statically links module {\tt zip}, then the compiler must load the
compiled process module {\tt zip.po} in order to
to compile {\tt boz}.  {\em This implies that imported or
statically linked modules must 
be compiled before any module that uses them.}

It is also sometimes necessary for compiled modules to be loaded
during the execution, rather than during the compilation, of a
program.  This is because programs are supplied with facilities for
dynamically loading programs and instantiating them into running
processes (see the description of the {\tt pathLoad} resource in
Section~\ref{resource-list}). 

Frequently, the modules that must be loaded either to compile or to
execute a Hermes program are to be found someplace other than the
current working directory.  They may be standard modules that
are provided as part of this Hermes system, or they may be modules
written by other individuals and kept in their own directories.

To accomodate these requirements, the compiler (and the standard resources
{\tt pathLoad} and {\tt pathReadObj} (see
Section~\ref{resource-list})) will search all of the directories specified
in the Unix environment variable {\tt HPATH} when looking for modules
to load.  The {\tt HPATH} variable, like the standard Unix {\tt PATH}
variable, should be a colon-separated list of directory path
specifications.  The default {\tt HPATH} value, if you leave it
undefined, is {\tt .:{\em hermes-root}/bin}, where {\em hermes-root}
is the directory in which Hermes has been installed on your system.
Paths beginning with ``{\tt \~{\em}/}'' or ``{\tt \~{\em user}/}'',
commonly understood by Unix shells, are not understood by Hermes.

The {\tt HPATH} environment variable is ``global'' for all processes
running in an interpreter and cannot be changed after the interpreter
has started.  (But look in the source file of the {\tt root} process,
in file {\tt hermes/root.pp},\footnote{This process module and others
in the Hermes distribution have a file extension of {\tt .pp} rather
than {\tt .p}.  They are special in that they must be run through the
C preprocessor program (cpp) before being compiled.  This processing
is necessary for many of the modules that are built early in the
Hermes bootstrapping process, which is a complex procedure that builds
a complete Hermes system from nothing but source files.} to see how
the {\tt pathLoad} and {\tt pathReadObj} resources are created, and
how customized versions that use different path specifications could
be constructed.)

\subsection{Other Unix environment variables}

This section lists assorted Unix environment variables in addition to
{\tt HPATH} that are meaningful to the Hermes system.  Like {\tt
HPATH}, they are global to all processors running in a single
interpreter, and cannot be altered once the interpreter has started.

\subsubsection{{\tt HDEBUG}}

The {\tt HDEBUG} environment variable is an integer that controls the
level of debugging information displayed by the Hermes interpreter.
The higher the value of {\tt HDEBUG} the more debugging information
displayed.  Higher {\tt HDEBUG} levels always imply all lower levels.
Currently defined debugging levels are as follows:\footnote{These are
very likely to change.}
\begin{description}

\item[{\em Level 1\/}:]~

\begin{itemize}

\item If an unhandled exception occurs (this should never happen for
programs parsed by the Hermes compiler), the offending process's
status info is displayed.

\item An error message is displayed when a Hermes object file cannot be opened
for reading.

\item An error message is displayed when a second attempt is made to set the
network linking port.

\end{itemize}

\item[{\em Level 2\/}:]A message is displayed every time a Hermes
object file is read.  This can be very useful for tracking down
problems related to incorrect HPATH settings, since the full pathname
of the object file is displayed.  The message says {\tt XDR Reading
'<full pathname>'}.

\item[{\em Level 5\/}:]A message is displayed every time an object
file (not a Hermes object; a Unix ``dot-oh'' file resulting from the
compilation of C source generated by the {\tt chcode} utility; see
Section~\ref{c-coded}) is dynamically loaded into the running
interpreter.   The message says {\tt Dynamically linking <full
pathname>}. 

\item[{\em Level 7\/}:]All messages sent to or received from remote
interpreters are logged.

\item[{\em Level 15\/}:]~

\begin{itemize}

\item When an {\tt OTHERS} handler is invoked for a process,
the process' status is displayed.  
\cb{08a}
An example of the display is as follows:

$$\hbox{\tt *R foo            3/8      DivideByZero          (Process)}$$

The asterisk indicates that this is the currently running process.
The next letter is either ``R,'' ``S,'' or ``K,'' indicating that the
process is ready to run, suspended (e.g. waiting for a callmessage to
be returned), or killed (and waiting to be reclaimed), respectively.
Next comes the name of program being run by the process.  The two
numbers separated by a slash indicate the current LI instruction
pointer and the size of the compiled LI code for the process.  Then
comes the most recent type of exception experienced by this process
(this is the exception being handled by the {\tt on (others)} handler
in the case of HDEBUG=15 output).  Finally, an internal process
instantiation type, which we won't explain here.\footnote{If you ever
think you need to use this information, you will almost certainly have
gotten deep enough into the sources to know what it means!}
\endcb{08a}

\item A message is generated when
an interface mismatch occurs.  The message includes the names of the
processes involved in the attempted create operation, as in:
$$\hbox{Interface mismatch: 'foo' can't create 'bar'}$$
\end{itemize}

\item[{\em Level 20\/}:]{\tt malloc\_debug(1)} is issued, to cause
extra checking to be performed by {\tt malloc} and related routines.
({\em Sun only}) 

\item[{\em Level 99\/}:]{\tt malloc\_debug(2)} is issued, to cause the
entire heap to be checked for consistency on every call to {\tt
malloc} and friends. ({\em Sun only})

\end{description}

\subsubsection{{\tt HROOTDIR}}

If this environment variable is set, it should identify the directory
where Hermes is installed in your system.  If it is not set, Hermes
will attempt to look up a user named ``{\tt hermes}'' on your system
and use that user's home directory.\footnote{System administrators: It
is not necessary for this ID to have a valid password or login shell.}
If neither of these situations holds, the Hermes interpreter cannot
run.

If your system administrator is unable or unwilling to create a user
ID named ``{\tt hermes}'', then you will need to set the {\tt
HROOTDIR} environment variable in order to run Hermes.

\subsubsection{{\tt HALTSYS}}

\cb{08a}
Normally, the {\tt hermes} shell script will attempt to run a binary
executable program of the same name in the directory {\tt{\em
hermes-root}/mbin/{\em arch}}, where {\em hermes-root} is the
directory where Hermes is installed on your system, and {\em arch} is
a name for your machine architecture (normally, whatever is printed by
the {\tt arch} command on your system).  If {\tt HALTSYS} is defined,
its value is appended to this directory when looking for the
executables.  For example, if your system administrator has created an
interpreter including C-language debugging information in the
directory {\tt{\em hermes-root}/mbin/{\em arch}/dbg}, you could set
{\tt HALTSYS} to {\tt dbg} in order to use that interpreter rather
than the standard one.
\endcb{08a}

\subsubsection{{\tt HROOTPROG}}

When the Hermes interpreter starts up, it initially creates a ``root''
program that is responsible for interpreting command line arguments and
spawning whatever other Hermes processes are required.  The root process
expects, on its initialization port, a message of type {\tt
root!rootInitMessage}.\footnote{Note that this is not a callmessage;
the root process should not attempt to return it.}  By default, the
root process is loaded from the file {\tt{\em
hermes-root}/bin/root.po}, regardless of the setting of the {\tt
HPATH} variable.  If you wish a different root process to be run,
specify its complete path name in {\tt HROOTPROG}.

\subsubsection{{\tt HLOADPATH} and {\tt HLINKPATH}}

There are actually two additional environment variables besides {\tt
HPATH} that can affect which directories are searched for program
modules.  If {\tt HLOADPATH} is set, it is used in preference to {\tt
HPATH} for the loading of {\em program modules only}.  If {\tt
HLINKPATH} is set, it is preferred over both {\tt HLOADPATH} and {\tt
HPATH} for program modules that are statically linked (i.e. they
appear in the {\tt linking()} list of a program module being
compiled).  {\tt HLINKPATH} will not affect the search for program
modules loaded dynamically via {\tt pathLoad}, and neither {\tt
HLOADPATH} nor {\tt HLINKPATH} will affect the search for definitions
modules or other Hermes values loaded via the {\tt pathReadObj}
facility.

{\tt HLOADPATH} and {\tt HLINKPATH} are required primarily for certain
phases of the Hermes bootstrapping procedure.  It is not expected that
they will be required for normal use.

\subsubsection{{\tt HTRACE}}

The {\tt HTRACE} environment variable can cause LI instructions (the
``assembly'' instructions of the Hermes interpreter) to be traced as
they are executed.  You will need to understand a great deal more
about the interpreter than can be explained in this document in order
to understand trace output in detail, but trace level 5 can be useful
even without a detailed understanding.

There are currently two trace levels that are important to the system:
5 and 10.  Level 5 shows only operations involved in message
communication and process creation and termination.  Level 10 shows
all instructions, and typically results in far more output than
anybody will ever want to see.

Level 5 trace output can be useful to see the sequence of
communications among the processes in your program.  The name of the
process issuing the traced instruction is shown at the far left of the
trace line, and the instruction display is indented according to the
current ``call level'' of the executing process.  A few factors make
it somewhat difficult to interpret this output in some situations.
First, since many processes may be runnable at any given time,
instructions from several processes may be interleaved in the trace
output.  Attempting to track a single process can be difficult.  In
addition, multiple instantiations of the same program will be traced
with the same process name and will therefore be indistinguishable in
the trace output.  Despite these problems, trace level 5 is sometimes
the most effective means of tracking down a problem with a Hermes
program.  We hope to develop more sophisticated tools in the future.

Tracing can be selectively turned on and off under program control as
well, by means of ``pragmas'' attached to statements.  In particular,
the following will cause level-5 trace output only during the
execution of the given block:

\begin{verbatim}
    ...
    pragma "trace=5"
    block begin
      ...
    end block;
    pragma "trace=0"
    ...
\end{verbatim}

Note, however, that the trace level is global throughout the
interpreter.  The above would cause tracing not only of the process in
which it appears, but also of all other processes currently executing.
In addition, if another process were to turn tracing off, tracing of
this process would stop as well.

\subsubsection{{\tt HPROF}, {\tt HPROFFILE}, and {\tt HPROFINTERVAL}}

A rudimentary profiling facility is available for Hermes.  If the {\tt
HPROF} environment variable is set to the value 1 or 2, the
interpreter will collect profile information about Hermes processes as
they are run.  If the {\tt HPROF} level is 1, every single instruction
is counted by the profiling support.  If {\tt HPROF} is 2, a
timer-based sampling scheme is used; every {\tt HPROFINTERVAL}
microseconds (100,000 if {\tt HPROFINTERVAL} is not defined), the
interpreter looks to see which instruction of which process is
currently executing, and bumps that instruction's frequency count.
\cb{08a}
When the interpreter terminates, it writes the profile data to the
file named in the {\tt HPROFFILE} environment variable, or to {\tt
hprof} if {\tt HPROFFILE} is not set.
\endcb{08a}

There are two Hermes programs that can help interpret profiling data:
{\tt profdetail} and {\tt profsum}.  The former displays individual
instruction counts for each instruction of every process, while the
latter simply shows totals for each process.  To invoke {\tt
profdetail}, issue the command {\tt profdetail {\em prof-file}} either
to the Hermes shell or on the command line when the interpreter is
invoked;  {\em prof-file} is the name of the file containing the
profile information, and defaults to {\tt hprof} if omitted.  {\tt
hprofsum} is invoked similarly.

\cb{08a}
\subsubsection{\tt HCOBJPATH}

A Hermes compiled process module ({\tt .po} file) that has been
c-coded (see Section~\ref{c-coded}) contains references to object
files produced by the C language compiler.  If these references are
via relative pathnames, Hermes uses path specified in the {\tt
HCOBJPATH} environment variable to resolve the reference to an
absolute path.  If the environment variable is not set, the default is
{\tt .:{\em hermes-root}/mchbin/{\em arch}}, where {\em hermes-root}
is the directory where Hermes is installed on your system, and {\em
arch} is the name of the platform on which you are running Hermes
(normally the string produced by the {\tt arch} command).

\subsubsection{{\tt HSOURCEPATH} and {\tt MKSCOPE}}

These environment variables, as well as {\tt HPATH}, {\tt HLOADPATH},
and {\tt HLINKPATH}, are used by the {\tt makehermes} tool to search
for build targets and dependencies.  They are fully described in
Section~\ref{makehermes-pathvars}.

\subsubsection{{\tt HPROMPT}}

This environment variable specifies the prompt string that should be
issued by the Hermes shell (see Section~\ref{shell}).  The prompt is
``{\tt shell: }'' by default.
\endcb{08a}

\section{Compiling and Executing Hermes Programs}
\label{compile}

To run a Hermes program {\tt bar} (stored in file {\tt bar.po}) from 
a Unix shell, issue the command: \\
$$\hbox{\tt hermes bar {\em args $\ldots$}}$$

{\tt hermes} is a shell script that invokes the Hermes interpreter.
You may need to check with your system administrator to find out where
the shell script has been installed, and add that to your Unix {\tt
PATH} environment variable.

The command, ``{\tt hermes bar {\em args $\ldots$}}'' starts a root
process that parses the command line and attempts to load and execute
the process module {\tt bar}.  Section \ref{mainIntf} below discusses
how the command line arguments {\em args $\ldots$} can be retrieved by
program {\tt bar}.

The Hermes program that compiles a Hermes definitions module is called
{\tt dcom}.  Hence to compile the definitions module {\tt foo}, issue
the command, ``{\tt hermes dcom foo}.''  {\tt dcom} will look for the
file {\tt foo.d} in the current working directory.  If you want to
compile a definitions module whose source file is in some other
directory, you'll need to specify a more complete pathname to as the
argument to {\tt dcom}, as in ``{\tt hermes dcom /hermes/defs/foo}.''
In either case, the compiled definitions module will be written to a
file {\tt foo.do} in the current directory.

The compiler {\tt dcom} has four phases: parsing, checking, and two
types of typestate rewriting.\footnote{The typestate rewriting phases
convert certain typestate constructions into the canonical form
required by the typestate checker.} A successful compilation of
definitions module {\tt foo} will generate the following output:

$${\tt parse[foo.d]\;fixabbrevs\;checkdefs\;shorten\;store[foo.do]}$$

Hermes process modules are compiled by the program {\tt pcom}, which
operates very much like {\tt dcom}.  The compiler {\tt pcom} has four
phases: parsing, type checking, typestate checking, and code
generation.  A successful compilation of module {\tt bar} will
generate the following output:

$${\tt parse[bar.p]\;typecheck\;typestate\;codegen\;store[bar.po]}$$

Both {\tt dcom} and {\tt pcom} may be given multiple module names on a
single command line; all the specified modules will be compiled in the
order given.  If either {\tt dcom} or {\tt pcom} detects any errors in
a module, it will print one or more error messages and then continue
with the next file.

\cb{08a}

\subsection{Transforming Compiled Hermes Programs Into C}
\input chcode

\endcb{08a}

\cb{08a}
\section{Using the Hermes shell}
\endcb{08a}
\label{shell}

Executing every Hermes command directly from the Unix command line
performs poorly because Hermes must read many object modules from Unix
files each time it starts up.  This is true even if a very simple
program is executed, since the initialization performed by the root
process requires the loading of many modules before the user's program
can be run.\footnote{You can see exactly what modules are required
during initialization by setting {\tt HDEBUG} to 2 or greater and
watching all the load messages that are produced before your program
is loaded.} To improve performance we
\cb{08a}provide the Hermes shell, which allows you to
efficiently load and run many Hermes programs.  We recommend
that you use the shell.\endcb{08a} 

\cb{08a}
If you invoke the {\tt hermes} shell script with no command line
arguments, the root process will automatically load and run the shell
for you (as if you had typed {\tt hermes shell}).  The shell issues a
prompt, from which you can run the same hermes commands, with the same
arguments, as you can from the Unix prompt.  The only difference is
that you leave off the initial {\tt hermes} that is required when
invoking your program from the Unix command line.  Because the
interpreter only starts up once, its initialization sequence is only
performed once, rather than for each Hermes command you execute.  In
addition, due to the built-in program caching mechanism, if you run
the same program more than once, it will be loaded only once.

As an example, suppose you wish to compile definitions modules {\tt
foo} and {\tt bar} and process module {\tt foo}.  You could do this
without the shell as follows:

\begin{verbatim}
% hermes dcom foo bar
foo: parse[foo.d] fixabbrevs checkdefs shorten store[foo.do]
bar: parse[bar.d] fixabbrevs checkdefs shorten store[bar.do]
% hermes pcom foo
foo: parse[foo.p] typecheck typestate codegen store[foo.po]
%
\end{verbatim}

In this case the Hermes interpreter is run twice, and so the startup
processing is performed twice.  Using the shell, this scenario would
look like the following:

\begin{verbatim}
% hermes
shell: dcom foo bar
foo: parse[foo.d] fixabbrevs checkdefs shorten store[foo.do]
bar: parse[bar.d] fixabbrevs checkdefs shorten store[bar.do]
shell: pcom foo
foo: parse[foo.p] typecheck typestate codegen store[foo.po]
shell:
\end{verbatim}

In the above example ``{\tt shell:}'' is the prompt issued by the
Hermes shell.
\endcb{08a}

The {\tt shell} is a program that is much like the shells you use to
execute Unix commands ({\tt /bin/sh}, {\tt /bin/csh}, etc.)  It enters
a simple loop in which it accepts a command typed at its prompt, and
then executes the command, just as if it had been typed from the Unix
shell as command line arguments to the {\tt hermes} command.

Besides running Hermes programs, the shell supports a limited number of
built-in commands.  To change
directories from the shell, issue the command {\tt cd {\em pathname}},
where {\em pathname} is a complete Unix path.  For example, to connect
to {\tt /distributed/computing/lib} from {\tt /distributed/computing},
issue the command ``{\tt cd /distributed/computing/lib}.''  The {\tt
pwd} command displays the current directory, and {\tt exit}
causes the shell to terminate.


\section{The Standard Main Interface}
\label{mainIntf}

When a Hermes program starts up, the Hermes run-time system provides
initial capabilities (e.g., to load in additional modules, to print to
the terminal, etc.) to the program.  This is done by making a call to
the program on its initialization port.  The interface for this call
is the {\tt main} interface, and is defined in the file {\tt
interface/main.d}.

The main interface comprises the following types: {\tt main!main} (the
callmessage type), {\tt main!mainQ} (an inport for receiving {\tt
main!main} callmessages), and {\tt main!mainFn} (an outport for
sending {\tt main!main} callmessages).  Any process that you wish to
run as a main Hermes program (e.g. from the shell) should import the
{\tt main} definitions module and declare its initialization port to
be of type {\tt mainQ}.\footnote{In general, we encourage adopting the
following naming conventions: if an callmessage type is named {\tt 
foo}, then an inport type for receiving {\tt foo} messages is {\t
fooQ} and an outport type for connecting to {\tt fooQ} inports is
named {\tt fooFn}.  Much old Hermes code in the current distribution
uses various different conventions, sometimes even within a single
definitions module!}

All definitions modules referred to in the following can be found in
the {\tt interface} directory in the Hermes installation.

There are three components to the main interface:

\begin{itemize}

\item{\em argv}---An ordered table of character strings, comprising
the words typed on the command line that was used to invoke the
program.  An additional word, conventionally the name of the invoking
program, is prepended to this list.  Thus if you type {\tt foo 1
hello} to the shell, the {\tt foo} program will receive four strings
in its {\tt argv} argument: {\tt "shell"}, {\tt "foo"}, {\tt "1"}, and
{\tt "hello"}.  The {\tt argv} component is of type {\tt
charstringList} as defined in the definitions module {\tt common}.

\item{\em terminal}---A record containing five capabilities (output
ports) that can be used to perform input and output to the user's
terminal:
\begin{itemize}
\item{\tt putChar(c)} prints the character {\tt c}.
\item{\tt putString(s)} prints the string {\tt s}.
\item{\tt putLine(s)} prints the string {\tt s} followed by a newline.
\item{\tt getChar(c)} returns the next character typed by the user in
{\tt c}.
\item{\tt getString(s)} returns the next line of text typed by the
user (without the terminating newline character) in string {\tt s}.
\end{itemize}

The {\tt terminal} argument is of type {\tt terminalFunctions} as
defined in module {\tt terminalIO}.  This module also defines all the
interfaces for the individual terminal functions.

\item{\em rm}---A {\em resource manager} that provides access to many
other useful capabilities and values.  The resource manager facility
is described fully in Section~\ref{resource}.  We identify the current
set of resources provided by the system to main programs in
Section~\ref{resource-list}.
\end{itemize}

The shortest Hermes {\em hello-world} program is as follows:
\begin{verbatim}
    helloWorld:  using(main) process(Init: mainQ)
      declare  
        Parms: main; 
      begin 
        receive Parms from init;
        call Parms.terminal.putLine("Hello, World!");
        return Parms;
      end process 
\end{verbatim}

The resource manager always returns resources wrapped in polymorphs.
You must unwrap the resource in order to make use of it.  For example:

\begin{verbatim}
    foo: using (main, load) process (init: mainQ)
    declare
      parms: main;
      pathLoad: load_func;
      bar: barFn;
      ...
    begin
      receive parms from init;
      unwrap pathLoad from args.rm.get("pathLoad", "") {init};
      bar <- create of pathLoad("bar");
      ...
    end process
\end{verbatim}

When specifying typestates on {\tt unwrap} statements, remember that
the current implementation does not support the {\tt full}
abbreviation except in definitions modules.  This has the unfortunate
effect of sometimes requiring lengthy typestate specifications on {\tt
unwrap} statements, as in:

\cb{08a}

\begin{verbatim}
    unwrap stdio from args.rm.get("stdio", "") {
      init, init(stdin), init(stdout), init(stderr),
      init(stdin.getc), init(stdin.gets), ...,
      init(stdout.getc), init(stdout.gets), ...,
      init(stderr.getc), init(stderr.gets), ...,
      init(fopen), init(fdopen), init(popen), init(tmpfile),
      init(clearerrno, init(ctermid), init(cuserid), init(tmpnam),
      init(access), init(readErrno)
      ...
      };
\end{verbatim}

In such cases, one useful technique is to include only those portions
of the typestate specifications that are actually required for your
program to compile.  In the above example, if the program were only
going to make use of the {\tt stdio.fopen} and {\tt stdio.stdin.getc}
capabilities, then the following {\tt unwrap} statement would suffice:

\begin{verbatim}
    unwrap stdio from args.rm.get("stdio", "") {
      init, init(fopen), init(stdin), init(stdin.getc)};
\end{verbatim}

\endcb{08a}

Because the resource is actually fully initialized when provided by
the resource manager, the above code fragment would cause most of the
record to be coerced away at runtime as a result of the unwrap
operation.\footnote{Actually, this effect is not yet implemented; the
record will be left fully initialized by the current implementation,
though the typestate checker will treat it as if it had been coerced
down.} If the program never references these portions of the record,
this coercion will cause no problems.

\subsection{Standard Resources}
\label{resource-list}

This section describes the resources that are currently made available
to Hermes main programs.  All of these resources are currently given
without restriction to any process that requests them from the
resource manager.  For each resource, we give the resource name, its
type, and a short description.  The typenames are all given in {\em
modulename!typename} form.  For example type {\tt foo!bar} is the type
{\tt bar} defined in definitions module {\tt foo}; you would look in
the file {\tt interface/foo.d} to see the type definition.  Note that
resource names must be given {\em precisely} as shown; case is
important.  The wrapped typestate of every resource listed here is
{\tt \{full\}}, which in most cases translates directly into {\tt
\{init\}}.  As mentioned above, it is possible to unwrap these
resources into typestates that are lower than their wrapped
typestates. 

\def\resource#1#2#3{\relax
  \hbox{\strut\qquad\hbox to 0.4\textwidth{Name: {\tt #1}\hfill}\relax
    Type: {\tt #2}}}

\subsubsection{Environment variables}

\resource{environ}{root!environ}{init}

This resource is a table of pairs of character strings, corresponding
to the Unix environment definitions in place when you started the
Hermes interpreter.  For example, if you wish to examine the value of
the {\tt PATH} environment variable, your hermes program might look
like this:

\begin{verbatim}
    ...
    unwrap environ from args.rm.get("environ", "") {init};
    inspect pathentry in environ["PATH"] begin
      path := pathentry.value;
    end inspect;
\end{verbatim}

\subsubsection{C-Hermes Processes}
\label{cloader}
\resource{CLoader}{CLoad!CLoadFn}{init}

There are a number of ``processes'' that are implemented in C and made
available by the interpreter itself.  Capabilities to these so-called
``C-Hermes'' processes are obtained by means of the CLoader
capability, which in turn is obtained from the resource manager.  For
example, if your program needed to obtain the current time of day, you
would need access to the {\tt "date and time"} C-Hermes process.  Your
code might look something like this:

\begin{verbatim}
    ...
    unwrap CLoad from args.rm.get("CLoader", "") {init};
    unwrap time from CLoad("date and time") {init};
    call time(...);
    ...
\end{verbatim}

The C-Hermes processes are listed and described in
Section~\ref{cloader-list}.

\cb{08a}
\subsubsection{Unix Standard I/O Services}

\resource{stdio}{unix!stdio}{full}

This resource contains capabilities to a smattering of Unix library
and system call services.  The capabilities are described fully in
Section~\ref{stdio}.  The components of the record are:

\begin{itemize}

\item {\em stdin, stdout, stderr\/}: Each of these is a record of type
{\tt unix!stream}.  Streams are described fully in
Section~\ref{stdio-streams}.  These three streams correspond to the standard
Unix streams provided to the interptreter when it starts.  Normally,
they all refer to the terminal or window from which Hermes is invoked.

\item {\em fopen, fdopen, popen, tmpfile\/}: These capabilities
provide four ways to create new streams.

\item {\em clearerrno, ctermid, cuserid, tmpnam, access, readErrno\/}:
These capabilities perform miscellaneous functions related to the Unix
environment in which the Hermes interpreter is running.  They are
described fully in Section~\ref{stdio}.

\end{itemize}

\endcb{08a}

\subsubsection{Program Loading and Storing}

\nopagebreak
\resource{load}{load!load\_func}{init}
\nopagebreak
\resource{pathLoad}{load!load\_func}{init}
\nopagebreak
\resource{store}{load!storeFunc}{init}
\nopagebreak
\resource{libStore}{load!storeFunc}{init}

These resources are capabilities to load and store compiled program
modules, using the Unix filesystem as a repository.  Most Hermes
programs will only ever need to load programs; programs that build
other programs, like the Hermes compiler, use the store capabilities
as well.

The most basic load and store capabilites are called {\tt "load"} and
{\tt "store"}.  They should normally be used only with absolute
pathnames, since relative pathnames will be interpreted relative to
the directory from which the interpreter was started.

The more useful capabilities are {\tt "pathLoad"} and {\tt
"libStore"}.  The pathLoad capability searches all the directories
listed in the {\tt HPATH} or {\tt HLOADPATH} environment variable for
the requested program.  Currently there is no easy way to change this
path from within the interpreter, but by copying the relevant portion
of the {\tt hermes/root.pp} module, a new pathLoad capability can be
constructed that follows a different path.  The {\tt "libStore"}
capability resolves relative pathnames according to the current
working directory as maintained by the {\tt getCwd} process, described
in Section~\ref{cwd}.  The current working directory can be changed
by a call to the {\tt setCwd} capability described below.

An example of loading and running a program named {\tt foo} from a
file called {\tt foo.po} somewhere in the {\tt HPATH} environment
variable is:

\begin{verbatim}
    declare
      foo: fooFn;
    begin
    ...
    unwrap pathLoad from args.rm.get("pathLoad", "") {init};
    foo <- create of pathLoad("foo");
    call foo(...)
    ...
\end{verbatim}

\subsubsection{Reading and Writing Arbitrary Hermes Values}

\resource{readObj}{objectIO!readobject\_func}{init}
\resource{pathReadObj}{objectIO!readobject\_func}{init}
\resource{writeObj}{objectIO!writeobject\_func}{init}
\resource{libWriteObj}{objectIO!writeobject\_func}{init}

These resources provide capabilities to store and retrieve arbitrary
Hermes values in the Unix filesystem.  They work much like the load
and store capabilities described above, except they read and write
values wrapped in polymorphs, rather than program values.

Since the Hermes prototype does not currently support persistance
through fault-tolerance, you may wish to write an appointment
scheduler that would maintain schedules in a file on disk called {\tt
"appointments"}.  The following code fragment could be used to
retrieve the value stored in this file into a Hermes variable:

\begin{verbatim}
    unwrap pathReadObj from args.rm.get("pathReadObj", "") {init};
    block begin
      unwrap appts from pathReadObj("appointments") {init};
    on (readobject_func.file_not_found)
      -- no saved appointments... start with an empty calendar
      new appts;
    on (polymorphMismatch, readobject_func.file_not_readable)
      -- unexpected exceptions
      ...
    end block;
\end{verbatim}

\subsubsection{Current Working Directory}
\label{cwd}

\resource{getCwd}{cwd!getCwdFn}{init}
\resource{setCwd}{cwd!setCwdFn}{init}

These resources allow an application to maintain the notion of a
working directory that is separate from the working directory of the
Hermes interpreter as maintained by Unix.  Initially, the working
directory is the same as the Unix working directory, but later {\tt
setCwd} calls can alter it, thereby changing the behavior of
subsequent calls to {\tt libStore} and {\tt libWriteObj}.  Note that
each {\tt setCwd} is interpreted relative to the interpreter's current
workign directory as maintained by Unix.  For example, if the
interpreter is invoked while connected to the directory {\tt
/u/joe/programs}, then issuing {\tt setCwd} with the argument {\tt
"foo"} would set the current working directory to {\tt
/u/joe/programs/foo}.  A subsequent {\tt setCwd} call with the
argument {\tt "bar"} would result in a working directory of {\tt
/u/joe/programs/bar}, not {\tt /u/joe/programs/foo/bar}.

\subsubsection{User Name}

\resource{username}{common!charstring}{init}

This resource can be requested from a ``filtered'' resource manager to
find out what user name is being supplied on resource requests.
When the root process creates a filtered resource manager, it looks
for the environment variable {\tt USER} to figure out a user name to
use.  If {\tt USER} is undefined, it next tries {\tt LOGNAME}.  If
that fails, it uses {\tt "anonymous"}.

\subsubsection{Simple Standard I/O}

\resource{stdin}{stdio!stdin}{full}
\resource{stdout}{stdio!stdout}{full}

These resources contain copies of capabilities appearing in the {\em
terminal} component of the {\tt main} interface.  They are posted as
resources, mostly because of the conventions used by programs meant to
be run under the ``piping shell'' (see the {\tt tools/pipe} and {\tt
tools/pshell} directories).  It is unfortunate that there are two
conflicting conventions for acquiring these capabilities.  One or the
other may disappear in future releases.

\cb{08a}
\subsubsection{Checking Modules}

\resource{checker}{check!checkFn}{init}
\resource{definitionschecker}{check!checkDefinitionsFn}{init}

These resources serve as a temporary alternative to the {\tt
assert(checked)} and {\tt checkdefinitions} statements which are
currently unimplemented.  

The {\tt checker} resource turns an unchecked program into a checked
program, which can then be instantiated into running processes.  If
checking fails, the interface provides for the return of specific
error information.

Similarly, the {\tt definitionschecker} resource turns an unchecked
definitions module into a checked definitions module, given a
collection of existing checked definitions modules with which to
resolve references to imported modules.  Note that the module id of
the module being checked is changed to a new unique id, as a
side-effect of the checking process.  As with the {\tt checker}
resource, the interface provides for error information to be returned
should checking fail.

{\em N.B.} The {\tt checker} resource cannot handle ill-formed Hermes
programs (e.g. programs that reference variables out of scope or refer
to clauses that do not exist).  All program values produced by the
parser will be well-formed, but programs that construct program values
can easily build ill-formed programs.  The definitions module checker
will check any definitions module that can be constructed, including
ill-formed modules that could never be produced by the parser.

\endcb{08a}

\cb{08a}
\subsection{Unix Stdio Functions}
\label{stdio}

This section describes the capabilities available in the standard {\tt
"stdio"} resource.  The capabilities are described in three sections.
First Section~\ref{stdio-open} describes capabilities that result in
open ``streams'' available for I/O.  Section~\ref{stdio-streams} describes
the resulting streams in detail.  Section~\ref{stdio-misc} describes
additional miscellaneous functions available in the {\tt stdio}
resources.  In the descriptions that follow, each capability is listed
with its component name and type.  The component names are relative to
either the {\tt stdio} resource record itself (of type {\tt
unix!stdio}) or a stream record (of type {\tt unix!stream}), as
appropriate.

\def\capa#1#2{\relax
  \hbox{\strut\qquad\hbox to 0.4\textwidth{Name: {\tt #1}\hfill}\relax
    Type: {\tt #2}}}

In addition to the capabilities described in the following section,
the {\tt stdio} resource includes the following three components,
which represent pre-built Hermes streams corresponding to the standard
Unix streams made available to the Hermes interpreter:

\capa{stdin}{unix!stream}
\capa{stdout}{unix!stream}
\capa{stderr}{unix!stream}

Note that all the I/O functions performed by the services described in
this section are non-blocking and asynchronous, except I/O involving
the {\tt stderr} stream.  The latter exception is made because there
are various points within the interpreter itself where diagnostic
messages are written to stderr, and where the possibility of an {\tt
EWOULDBLOCK} error is not considered.  To ensure that these diagnostic
messages are not lost, output to {\tt stderr} is allowed to block.

\subsubsection{Opening Streams}
\label{stdio-open}
\capa{fopen}{fopenFn}
\capa{fdopen}{fdopenFn}
\capa{popen}{popenFn}
\capa{tmpfile}{tmpfileFn}

The {\tt fopen} capability opens a file and builds a Hermes stream to
operate on the file.  If a relative pathname is specified, it is
interpreted relative to the current working directory at the time the
Hermes interpreter was invoked regardless of the use of the {\tt
setCwd} resource.  The following ``open types'' (of type {\tt
unix!openType}) can be specified:

\begin{tabular}{l|l}
\multicolumn{1}{c|}{Type}&\multicolumn{1}{c}{Effect}\\
\hline
'read'&Open for reading at beginning of file\\
'write'&Truncate the file, then open for writing at beginning\\
'append'&Open for writing at current end of file\\
'updateRead'&Open for reading and writing at beginning of file\\
'updateWrite'&Truncate and open for reading and writing at beginning of file\\
'updateAppend'&Open for reading and writing at current end of file\\
\end{tabular}

The {\tt fdopen} capability creates a stream from an open Unix file
descriptor.  The same open types can be used with {\tt fdopen} as with
{\tt fopen}, though the open type must be compatible with the mode in
which the file descriptor was originally opened.

{\tt Popen} runs a Unix command in a child process and creates a
stream connected to either stdin or stdout of the child.  Two open
types are defined for use in the {\tt popen} interface:

\begin{tabular}{l|p{0.8\textwidth}}
\multicolumn{1}{c|}{Type}&\multicolumn{1}{c}{Effect}\\
\hline
'read'&The resulting stream can be used to read output sent to stdout
of the child process.\\
'write'&The resulting stream can be used to write data to be read from
stdin by the child process.\\
\end{tabular}

The {\tt tmpfile} capability creates a new temporary file and returns
a stream that can be used for both reading and writing the file.  When
the stream is closed, the file is removed from the filesystem.

\subsubsection{Stream Operations}
\label{stdio-streams}

This section describes the capabilities provided in every {\tt stream}
record.

The following capabilities can be used to perform input and output
operations on a stream.  Note that if a stream is opened for read-only
access, operations that would output to the stream will fail.
Similarly for input operations on write-only streams.

\capa{getc}{terminalIO!getCharFunc}
\capa{gets}{terminalIO!getStringFunc}
\capa{fgets}{terminalIO!getBoundedStringFunc}
\capa{fread}{terminalIO!getBoundedStringFunc}
\capa{getw}{terminalIO!getWordFunc}
\capa{putc}{terminalIO!putCharFunc}
\capa{puts}{terminalIO!putStringFunc}
\capa{fputs}{terminalIO!putStringFunc}
\capa{fwrite}{terminalIO!putSubStringFunc}
\capa{putw}{terminalIO!putWordFunc}

The operations performed by these functions are summarized in the
table below.  The column labeled ``Count'' indicates how much data is
read or written by the function; ``---'' in this column indicates
either no limit for input operations, or the size of the data string
for output operations.  The column labeled ``Newline'' specifies
special handling of newline characters: ``terminate'' indicates that a
newline character causes the input operation to stop; ``discard'' or
``keep'' indicates whether a terminating newline character is returned
as part of the input data; ``append'' means the output operation
writes a newline character following the argument data.

\begin{tabular}{l|c|c|c}
Function&Direction&Count&Newline\\
getc&input&1 char&---\\
gets&input&---&terminate, discard\\
fgets&input&$n$ chars&terminate, keep\\
fread&input&$n$ chars&---\\
getw&input&1 word&---\\
\hline
putc&output&1 char&---\\
puts&output&---&append\\
fputs&output&---&---\\
fwrite&output&$n$ chars&---\\
putw&output&1 word&---\\
\end{tabular}

The following capabilities are used to close a stream.  Closing a
stream causes all the capabilities associated with the stream to
become disconnected.

\capa{fclose}{unix!fcloseFn}
\capa{pclose}{unix!pcloseFn}

The {\tt fclose} function should be used for streams created by {\tt
fopen}, {\tt fdopen}, or {\tt tmpfile}.  {\tt Pclose} should be used
for streams created by {\tt popen}.\footnote{There's no good reason
for both capabilities to exist; a single {\tt close} capability that
would perform the correct type of close operation could be provided
easily.  This will probably happen in a future release.}  Note that
discarding a stream automatically closes it, using whichever type of
close operation is appropriate.

The following operations query and manipulate status information on
streams:

\capa{ferror}{unix!ferrorFn}
\capa{clearerr}{unix!clearerrFn}
\capa{ferrno}{unix!ferrnoFn}
\capa{feof}{unix!feofFn}

The {\tt ferror} capability queries whether any operation on the
stream has failed since the most recent {\tt clearerr} operation.
Note that a successful operation on a steram {\em does not} clear the
error status of the stream; only the {\tt clearerr} operation does
that.  {\tt Ferrno} returns the value of the Unix {\tt errno} variable
resulting from the most recent failing operation on the stream.  The
{\tt feof} function indicates whether or not an ``end of file''
condition is present on the stream.

The following capabilities query and set the current file position of
the stream.  The current file position determines the byte offset
within the file where the next input or output operation will begin.

\capa{fseek}{unix!fseekFn}
\capa{rewind}{unix!rewindFn}
\capa{ftell}{unix!ftellFn}

{\tt Fseek} sets the file position for the next input or output
operation on the stream.  Its {\tt offset} argument, which may be
negative, is interpreted relative to either the beginning of the file,
the current file position, or the end of the file, according to the
value of the {\tt seekType} argument.  {\tt Rewind} seeks to the
beginning of the file.  {\tt Ftell} returns the current file position.

The remaining stream operations are as follows:

\capa{fflush}{unix!fflushFn}

This operation forces buffered output data to be physically written to
the file or output device associated with the stream.

\capa{fstat}{unix!fstatFn}

This function returns various pieces of information about the file
associated with the stream, including protection bits, owning user id,
file size, last access and modification times, etc.  See the interface
definition for the complete list of information returned.

\capa{fileno}{unix!filenoFn}

This function returns the Unix file descriptor associated with the
stream.

\capa{setlinebuf}{unix!setlinebufFn}

This capability sets an output stream for line-buffered operation, in
which the stream is automatically flushed whenever (a) a newline
character is written, (b) the internal buffer fills, or (c) an input
operation is performed.

\capa{freopen}{unix!freopenFn}

This capability can be used to reassociate a stream with a different
file.  Following this operation, the stream behaves as if it had just
been created via the {\tt fopen} capability.  The underlying Unix file
descriptor previously associated with the stream is closed.  All
of the existing stream capabilities remain connected and usable, but
now they perform their operations on a different file.
\endcb{08a}

\subsubsection{Miscellaneous {\tt Stdio} Capabilities}
\label{stdio-misc}

The following capabilities query and set the Unix {\tt errno}
variable, which indicates error codes encountered by system operations
performed by the Hermes interpreter.  \footnote{Note that it is
unlikely that the value of this variable could be correlated
meaningfully with statements in a Hermes program, since the
interpreter frequently accesses operating system services in patterns
that are neither predictable nor likely to remain consistent in later
releases.  The capabilities may be removed in future releases.  The
stream-specific {\tt ferrno} capabilities are far more useful, as it
returns error codes encountered when operating on the associated
streams, rather than by the interpreter in general.}

\capa{readErrno}{unix!readErrnoFn}
\capa{clearerrno}{unix!clearerrnoFn}

The {\tt readErrno} function returns the current value of the Unix
{\tt errno} variable.  The {\tt clearerrno} capability clears the {\tt
errno} variable.

The remaining {\tt stdio} capabilities are:

\capa{ctermid}{unix!ctermidFn}

This capability produces a path name for the controlling terminal
device associated with the Unix process in which the Hermes
interpreter is running.

\capa{cuserid}{unix!cuseridFn}

This capability produces the login name of the user logged in on the
Hermes interpreter's controlling terminal.

\capa{tmpnam}{unix!tmpnamFn}

This capability creates a unique pathname suitable for opening a
temporary file.

\capa{access}{unix!fileAccessFn}

This function determines whether the permission bits associated with
the given file would permit its being opened or otherwise accessed in
the manner indicated by the {\tt mode} argument.  The recognized modes
are:

\begin{tabular}{l|l}
\multicolumn{1}{c|}{Mode}&\multicolumn{1}{c}{Tested Access}\\
\hline
'read'&The file can be opened for reading\\
'write'&The file can be opened for writing\\
'execute'&The file can be executed as a Unix command\\
'exists'&The file exists\\
\end{tabular}

\endcb{08a}

\subsection{C-Hermes Functions}
\label{cloader-list}

This section lists the capabilities currently available from the {\tt
CLoader} service described in Section~\ref{cloader}.  The functions
will be described in the same fashion as were the resources
listed in Section~\ref{resource-list}.  The CLoader is much like the
resource manager in that it retrieves capabilities based on names
supplied by the callers.  Unlike the resource manager, there is no
second argument required in these requests.  As with the resource
manager, the names supplied in the requests must be precisely as shown
below; letter case and spaces are significant.

One current implementation bug is especially important for those who
will be making direct calls to C-Hermes processes: these processes are
not capable of returning the exceptions defined on their interfaces.
When a C-Hermes process detects a situation in which a user-defined
exception return should be made, its only recourse is to discard the
callmessage, thereby causing the {\tt discarded} exception associated
with the call interface in the caller.  In addition, C-Hermes
processes are implemented in C, which is not a secure language.  The
implementations of these processes are generally fragile.  We are
currently working on better integration between Hermes and C, and when
this has been achieved these processes will be made more robust.

\cb{08a}
For those who wish to extend the interpreter with additional C-Hermes
processes, the Hermes distribution includes a document titled, {\em
How to Write C-Hermes Processes}, by Willard Korfhage of Brooklyn
Polytechnique.  It is in the file {\tt doc/chermes.ps} in the
distribution.
\endcb{08a}

\def\cherm#1#2#3{\relax
  \hbox{\strut\qquad\hbox to 0.4\textwidth{Name: {\tt #1}\hfill}\relax
    Type: {\tt #2}}}

\cb{08a}
\subsubsection{The C-Hermes Process Loader}

\cherm{C Load}{cload!cloadFn}{init}

This is precisely the capability provided via the {\tt CLoader}
resource described in Section~\ref{cloader}.
\endcb{08a}

\cb{08a}
\subsubsection{Support For {\tt stdio} Resource}

The following C-Hermes processes open Unix streams and return
Unix-style stream handles (values of type {\tt FILE *}, cast as
integers for transmission across Hermes interfaces).  The higher-level
resources described in Section~\ref{stdio} build Hermes-style streams
around these Unix stream handles.

\cherm{fopen}{unixint!fopenxFn}{init}
\cherm{fdopen}{unixint!fdopenxFn}{init}
\cherm{popen}{unixint!popenxFn}{init}
\cherm{tmpfile}{unixint!tmpfilexFn}{init}

Each of the following C-Hermes processes provides a single piece of
functionality for a specific stream.  The init ports all conform to an
interface that accepts a Unix stream handle (cast as an integer) and
gives back a capability that can be used to perform the indicated
operation on that stream.

\cherm{clearerr}{unixint!clearerrInitFn}{init}
\cherm{ferror}{unixint!ferrorInitFn}{init}
\cherm{ferrno}{unixint!ferrnoInitFn}{init}
\cherm{feof}{unixint!feofInitFn}{init}
\cherm{fileno}{unxint!filenoInitFn}{init}
\cherm{fflush}{unixint!fflushInitFn}{init}
\cherm{fseek}{unixint!fseekInitFn}{init}
\cherm{rewind}{unixint!rewindInitFn}{init}
\cherm{ftell}{unixint!ftellInitFn}{init}
\cherm{setlinebuf}{unixint!setlinebufInitFn}{init}
\cherm{fstat}{unixint!fstatInitFn}{init}
\cherm{fclose}{unixint!fcloseInitFn}{init}
\cherm{pclose}{unixint!pcloseInitFn}{init}
\cherm{freopen}{unixint!freopenInitFn}{init}
\cherm{readword}{unixint!readWordInitFn}{init}
\cherm{writeword}{unixint!writeWordInitFn}{init}

The following two capabilities provide generic support for reading and
writing bytes on a stream.  They are the basis for several of the
stream capabilities, including {\tt getc}, {\tt gets}, {\tt fgets},
{\tt fread}, {\tt putc}, {\tt puts}, {\tt fputs}, and {\tt fwrite}.

\cherm{readstream}{unixint!readStreamInitFn}{init}
\cherm{writestream}{unixint!writeStreamInitFn}{init}

The following capability can be called to return the Unix stream
handles for {\tt stdin}, {\tt stdout}, and {\tt stderr}.
\cherm{stdstreams}{unixint!stdstreamsFn}{init}

The following capabilities provide underlying support for the
corresponding {\tt stdio} capabilities as described in
Section~\ref{stdio}.

\cherm{clearerrno}{unix!clearerrnoFn}{init}
\cherm{ctermid}{unix!ctermidFn}{init}
\cherm{cuserid}{unix!cuseridFn}{init}
\cherm{tmpnam}{unix!tmpnamFn}{init}
\cherm{Access}{unix!fileAccessFn}{init}
\cherm{read errno}{unix!readErrnoFn}{init}
\endcb{08a}

\cb{08a}
\subsubsection{Unix Filesystem as a Hermes Data Repository}

\cherm{Read Object}{objectio!readobject\_func}{init}
\cherm{Write Object}{objectio!writeobject\_func}{init}

These two capabilities provide the low-level functionality required
for the {\tt readObj} and {\tt writeObj} resources described in
Section~\ref{resource-list}.  They are not intended to be used
directly by Hermes programs.

\endcb{08a}

\subsubsection{Windows}

\cherm{Window}{CWindow!CWindowFn}{init}

This function provides some very rudimentary window support.  It
causes the interpreter to fork off a program that will manage a window
for the purpose of displaying and reading text.  The interpreter and
the window program communicate via a pair of Unix pipes.  Whatever is
sent from the interpreter to the window program is displayed in the
window, and whatever the user types into the window is sent up the
pipe to the interpreter.

The call to create a window allows a label to be specified for the
window's title bar, and also allows some SunView-style options to be
specified, to determine foreground and background colors, sizes, etc.
The Unix file descriptors for the interpreter's ends of the two pipes
are returned.

Normally, you should not use this function directly.  Higher-level
support is described in Section~\ref{windows}.


\subsubsection{Asynchronous I/O for Window Support}

\cherm{FD Read}{fdhandlers!readInitFn}{init}
\cherm{FD Write}{fdhandlers!writeInitFn}{init}
\cherm{FD Close}{fdhandlers!closeInitFn}{init}

These functions were provided explicitly for our window support, and
their design is not very general.  
\cb{08a}
The window support should be modified to make use of the more general
facilities developed to suppor the new {\tt stdio} resources.  Thus
direct use of these facilities is discouraged, as they are likely to
disappear in the future.
\endcb{08a}

The {\tt FD Read} and {\tt FD Write} capabilities each take a file
descriptor and return a capability that can then be used to read from
or write to, respectively, that file descriptor.  The file descriptor
must have been set for asynchronous I/O.  When an I/O request is made,
the read or write process will attempt the operation and if the
operation would block (that is, would cause the entire Hermes
interpreter to block... not a good thing!), the C-Hermes process
blocks instead, and a signal handler for a SIGIO Unix signal is
established by the interpreter so the C-Hermes process can unblock
and retry at a later time.  Meanwhile, the Hermes process that
initiated the read or write call will block waiting for that call to
return.

The {\tt FD Close} operation takes two file descriptor and closes them
both.  This will cause any processes waiting to read or write to those
file descriptors to unblock and return with an exception.  The fact
that two file descriptors are given instead of just one relates to the
fact that this whole mechanism was designed to support asynchronous
I/O to windows, and windows are always managed with a pair of pipes.

\subsubsection{File Modification Time}

\cherm{File Modification Time}{unixStat!statMtimeFunc}{init}

This function takes a file name (relative path names interpreted
according to the interpreter's  working directory as a Unix process)
and returns the file modification timestamp as an integer.  
\cb{08a}
Similar functionality is available through the {\tt stdio} resource by
opening the file (via {\tt fopen}) and then using the {\tt fstat}
capability provided in the resulting stream.  However, the C-Hermes
process described here does not require opening the file.
\endcb{08a}

For example:

\begin{verbatim}
    ...
    unwrap MTime from CLoad("File Modification Time") {init};
    objFileModTime <- MTime(moduleName | ".po");
    srcFileModTime <- MTime(moduleName | ".p");
    if (objFileModTime < srcFileModTime) then
      -- recompilation needed
    ...
\end{verbatim}

\subsubsection{Current Date and Time}

\cherm{date and time}{time!getCurrentTimeFn}{init}

This capability returns information about the current date and time,
expressed in a number of convenient ways.  See the definitions module
{\tt time.d} to see exactly what is returned by this call.  A simple
way to print the current date and time is:

\begin{verbatim}
    ...
    unwrap getTime from CLoad("date and time") {init};
    currentTime <- getTime();
    call args.terminal.putLine("It is now " | currentTime.formattedTime);
    ...
\end{verbatim}

\subsubsection{Network Operations}
\label{low-level-distrib}

\cherm{start network}{distributed!startNetworkFn}{init}
\cherm{set linking port}{distributed!setLinkingPortFn}{init}
\cherm{get link}{distributed!getLinkeFn}{init}

The current Hermes implementation supports a somewhat awkward facility
for allowing two different Hermes interpreters to interoperate.
Higher level support for these facilities is described in
Section~\ref{distributed}.

In order to interoperate with other interpreters, each Hermes
interpreter must have a unique identity.  We use a combination of a
host address and an {\em interpreter number} for this purpose.  The
interpreter number is an integer, with the sole restriction being that
no two interpreters running on the same host may have the same
interpreter number.

The {\tt start network} operation supplies an interpreter with its
interpreter number.  Once this has been assigned, the interpreter is
able to register itself so that other interpreters can establish
communications with it.  The {\tt start network} operation can be
performed only once during the lifetime of an interpreter.  It must be
performed before either of the other network operations can be
performed.

The {\tt set linking port} operation identifies to the interpreter an
output port of type {\tt distributed!genericFn}, to which incoming
{\em linking calls} should be directed.  Linking calls are the means
by which other interpreters initially establish communication with
this interpreter.

The {\tt get link} operation returns an output port of type {\tt
distributed!genericFn} that can be used to make a linking call to a
process on another interpreter.  The output port that is returned is a
copy of the output port that was provided in the {\tt set linking
port} operation on the target interpreter.  Becuase the {\tt generic}
interface conveys polymorphs, the caller and callee can exchange
whatever information they choose, including additional ports that will
then operate across the network.

A program that provides a capability to print on some printer
to other interpreters around the network might include code like the
following:

\begin{verbatim}
    declare
      gQ: genericQ;
      gFn: genericFn;
      request: generic;
      printer: printFn;
      ...
    begin
    ...
    unwrap startNet from CLoad("start network") {init};
    call startNet(interpNo);
    new gQ;
    connect gFn to gQ;
    unwrap setLink from CLoad("set linking port") {init}
    call setLink(gFn);
    while ('true')
      receive request from gQ;
      wrap copy of printer as request.value;
      return request;
    end while;
    ...
\end{verbatim}

Correspondingly, a program on another host that prints on the
printer might look something like this:

\begin{verbatim}
    declare
      link: genericFn;
      printer: printFn;
      request: polymorph;
      empty: empty;
      ...
    begin
      ...
      unwrap startNet from CLoad("start network") {init};
      call startNet(interpNo);
      unwrap getLink from CLoad("start network") {init};
      link <- getLink(remoteHost, remoteInterpNo);
      wrap empty as request;
      call link(request);
      unwrap printer from request {init};
      call printer(file);
      ...
\end{verbatim}

This example is not terribly attractive because of the restriction
that only one linking port can be established for each interpreter.
In this case, because the linking port is being used to provide access
to a printer, it cannot be used for exchanging any other services.
The higher-level functions described in Section~\ref{distributed} make
use of resource managers to provide a more general facility.

\subsubsection{Parsing Hermes Programs}

\cherm{Parse Def}{initParse!initParseDefFn}{init}
\cherm{Parse Proc}{initParse!initParseProcFn}{init}

These functions are used to create processes which can parse Hermes programs
and return them in their abstract representations.  To create a
definitions module parser, for example, the {\tt Parse Def} C-Hermes
capability is retrieved, and an initialization call is made on it,
passing it a collection of capabilities it will need for loading and
storing Hermes object files, etc.  A capability is returned that can
be called with a Hermes definitions module (the source text, as a
character string) and module name, and returns a number of structures
resulting from the parsing of that module, including the value that
should be stored in an object file (a {\tt .do} file), various
mappings between various id's (nominals) and the textual names
appearing in the source file, and a list of errors.  The {\tt Parse
Proc} service operates similarly.

These functions are used by the Hermes compiler programs ({\tt dcom}
and {\tt pcom}); it is not expected that they will be used directly by
normal Hermes programs.

\subsubsection{Real Number Conversions}

\cherm{crtoa}{crtoa!ConvertRealToAsciiFn}{init}

This function accepts a {\tt printf}-style format specification and a
real number, and produces a character string displaying the number.
The function is written as a C-Hermes function rather than as a Hermes
process primarily for expediency.  It's a somewhat complicated
function to write, and it's already available via {\tt sprintf} for C
programs.  As an example, to print out a real number, left-justified
following a comment, with at most two digits folowing the decimal point:

\begin{verbatim}
    ...
    unwrap rtoa from CLoad("crtoa") {init};
    call putLine("The value is: " | rtoa("-10.2g", x));
    ...
\end{verbatim}


