% (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 BLOCKINGIO}}

The {\tt BLOCKINGIO} environment variable determines whether the
interpreter blocks for terminal IO.  If BLOCKINGIO is set (its value
is irrelevant), then the interpreter will block whenever any process
requests input from the terminal.  If BLOCKINGIO is not set, then the
interpreter will not block when waiting for I/O.  The disadvantage of
using blocking I/O is that the whole system (all the processes running
in a given interpreter) will hang whenever one process requires input.
The disadvantage of using non-blocking I/O is that it is currently
implemented using polling and therefore degrades system performance.

{\bf Note:} The implementation of non-blocking terminal I/O is
currently very buggy.  We recommend that you always leave your
BLOCKINGIO environment variable set when running Hermes programs.
We hope to fix non-blocking I/O and redesign it so that polling is not
required in the near future.

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

\item[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[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[7.]All messages sent to or received from remote interpreters are
logged.

\item[15.]

\begin{itemize}

\item When an {\tt OTHERS} handler is invoked for a process,
the process' status is displayed as described below.

\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[20.]{\tt malloc\_debug(1)} is issued, to cause extra checking to
be performed by {\tt malloc} and related routines.  ({\em Sun only})

\item[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{enumerate}

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

Normally, the {\tt hermes}, {\tt hparse}, and {\tt hsh} shell scripts
will attempt to run binary executable programs of the same names 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 installed a set of optimized executables in
the directory {\tt{\em hermes-root}/mbin/{\em arch}/opt}, you could set
{\tt HALTSYS} to {\tt opt} in order to use the optimized programs
rather than the standard set.

\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.
When the interpreter terminates normally (not if it is interrupted,
e.g. because you type $\langle$control$\rangle$C at the terminal),
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.

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.

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

\section{Using the Hermes shell and cache}
\label{shell}

Executing every Hermes command from the Unix command line performs
poorly because Hermes must reads many object modules from Unix files.
This is true even if a very simple program is executed, since the
initialization perfomred 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, watching all the load messages that are
produced before your program is loaded.} To improve performance we
provide the Hermes shell and cache, which together provide an
environment in which you can efficiently load and run many Hermes
programs.  We recommend that you use the cache and the shell.

The easiest way to operate in this mode is by starting hermes via the
command {\bf hsh}.  You can run the same hermes commands, with the
same arguments, from the resulting prompt, as you can from the Unix
prompt via the {\bf hermes} command described earlier.  The
differences is that the interpreter need be started only once, and
Hermes object files are each loaded only once, even if they are
requested many times.  For example, to compile process module {\tt
foo}, you can use either of the following:

\begin{itemize}
\item[]{\tt hermes pcom foo}
\item[]{\em -- or --}
\item[]{\em hsh}\\{\tt shell: pcom foo}
\end{itemize}

In the second form, ``{\tt shell:}'' was printed by the Hermes shell
program.

The {\tt hsh} command is an abbreviation for {\tt hermes cache shell}.
The {\tt cache} can be ignored for now; it is explained below.

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.

Another utility provided with the Hermes system is a software cache.
It is invoked by a command like ``{\tt hermes cache foo},'' where {\tt
foo} is a Hermes program.  This will run the program {\tt foo }, and
will also cache all Hermes object modules loaded during the execution
of {\tt foo}.  Hence, if {\tt foo} requests that process {\tt bar} be
loaded many times, only the first request will result in {\tt bar}
actually being fetched from disk.  Subsequently {\tt bar} will be
loaded directly from the cache (assuming that the file {\tt bar.po}
has not been changed since it was first loaded).  For many
applications, the cache can significantly improve run-time
performance.

The best way to use the Hermes shell is in conjunction with the cache
by invoking the command ``{\tt hsh},'' which is an abbreviation for
``{\tt hermes cache shell}.''  This will create a shell with a
software cache.  Any modules loaded while running programs from the
shell will be cached.  For instance, when compiling many modules from
the cached shell, the compiler will be loaded on only the first
compile.  This dramatically improves compilation time on subsequent
compiles.

\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}
    main:  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:

\begin{verbatim}
    unwrap unix from args.rm.get("unix", "") {
      init, init(call), init(access), init(r_external), init(stdio),
      init(stdio.stdin), init(stdio.stdout), init(stdio.stderr),
      init(stdio.clearerr), init(stdio.ctermid), init(stdio.cuserid),
      ...
      };
\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 unix.stdio.clearerr} capability, then
the following {\tt unwrap} statement would suffice:

\begin{verbatim}
    unwrap unix from args.rm.get("unix", "") {
      init, init(stdio), init(stdio.clearerr)};
\end{verbatim}

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

\subsubsection{Unix Services}

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

This resource contains capabilities to a smattering of Unix library
and system call services.  It is a record containing four pieces, as
follows:

\begin{itemize}

\item{\em stdio}---This is a record containing a few dozen
capabilities to specific I/O related Unix services.  They are listed
in section~\ref{stdio} below.  The type of this component is
{\tt unix!stdio} and its wrapped typestate is {\tt \{full\}}.

\item{\em access}---This is a capability to perform {\tt access} Unix
system calls.  It is of type {\tt unix!access\_func} and its wrapped
typestate is {\tt {init}}.  You could use it to check whether a
particular file is writable, for instance, with the following code:

\begin{verbatim}
    ...
    unwrap unix from args.rm.get("unix", "") {init, init(access)};
    if (unix.access("/etc/passwd", 'write')) then
      ...
\end{verbatim}

\item{\em r\_external}---This is a capability to read certain global
external variables in the interpreter (i.e. the Unix process in which
the interpreter is running).  These variables are: {\tt errno}, {\tt
stdin}, {\tt stdout}, and {\tt stderr}.  The {\em r\_external}
component is of type {\tt unix!read\_external\_variablefunction}.  For
example, to find out why an open file operation failed, the following
code might be used:

\begin{verbatim}
    unwrap unix from args.rm.get("unix", "") {init, init(r_external)};
    result <- unix.r_external('errno');
    reveal result.int;
    errno <- result.int;
\end{verbatim}

\item{\em call}---This is a capability to make a call to one of the supported
Unix services.  Normally, this capability is not used directly;
instead, one of the capabilities in the {\em stdio} component is used.
The type of this component is {\tt unix!unixcall\_func}.

\end{itemize}

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

Technically, these interfaces should all mention the {\tt checked}
typestate attribute for the programs they load and store.  This
attribute is currently unimplemented, so it is left out of these
interface definitions temporarily.\footnote{For this reason, the
typestate checker currently does not complain when an unchecked
program is instantiated with a {\tt create of} or {\tt procedure of}
operation.}

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} environment variables 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
momentarily.  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}

\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{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.

\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 much 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.

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

\subsubsection{Functions For Which Hermes Wrappers Exist}

\cherm{Store Program}{objectio!writeobject\_func}{init}
\cherm{Read Object}{objectio!readobject\_func}{init}
\cherm{Write Object}{objectio!writeobject\_func}{init}
\cherm{Unix}{unix!unixcall\_func}{init}
\cherm{Access}{unix!access\_func}{init}
\cherm{Read External}{unix!read\_external\_variablefunction}{init}

The {\tt "Store Program"} capability is not meant to be used by normal
Hermes programs; it is used by the {\tt "store"} resource described
above.  The other capabilities listed above are all available from
standard resources listed in Section~\ref{resource-list}.
Specifically: the {\tt "Read Object"} and {\tt "Write Object"}
C-Hermes capabilities are available as the {\tt "readObj"} and {\tt
"writeObj"} resources, respectively.  The {\tt "Unix"}, {\tt
"Access"}, and {\tt "Read External"} C-Hermes capabilities are the
{\tt call}, {\tt access}, and {\tt r\_external} components of the
standard {\tt "unix"} resource.

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

\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.  This will hopefully change at some
point.

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

Notice that there is no facility for creating a file descriptor set up
for asynchronous I/O.  The {\tt Window} service described above does
this explicitly.  This is yet another reason to generalize the
asynchronous I/O support.

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

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}), and are not expected to 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}



\subsection{Unix Stdio Functions}

\label{stdio}

This section describes the capabilities available in the {\tt stdio}
component of the standard {\tt "unix"} resource.

{\em This section is not yet written.  For a list of the capabilities,
see the {\tt unix} definitions module in {\tt interface/unix.d}.  Most
of the capabilities have names corresponding fairly closely with
standard Unix system calls and library routines.  The actual
implementations are in a combination of the C-Hermes process code
({\tt cfunc/stdio.ch}), and a Hermes process wrapper that can be found
in {\tt hermes/io/stdio.pp}.  Good luck!}
