<!DOCTYPE HTML PUBLIC "-//SQ//DTD HTML 2.0 + all extensions//EN" "hmpro3.dtd">
<HTML>
<HEAD><LINK
HREF="mailto:drh@cs.princeton.edu" REV="made" TITLE="David R. Hanson">
<TITLE>Installing lcc</TITLE></HEAD>
<BODY>
<H1>Installing lcc</H1>
<P ALIGN="LEFT"><B><A HREF="http://www.research.microsoft.com/~cwfraser/">Christopher
W. Fraser</A> and <A HREF="http://www.research.microsoft.com/~drh/">David R.
Hanson</A>, <A HREF="http://www.research.microsoft.com/">Microsoft Research</A></B></P>
<H2>Contents</H2>
<DIR>
<LI><A HREF="#intro">Introduction</A></LI>
<LI><A HREF="#unix">Installation on UNIX
</A></LI>
<LI><A HREF="#driver">Building the Driver</A></LI>
<LI><A HREF="#rcc">Building the Compiler and Accessories</A></LI>
<LI><A HREF="#win32">Installation on Windows NT 4.0 and Windows 95</A></LI>
<LI><A HREF="#bugs">Reporting Bugs</A>
</LI>
<LI><A HREF="#mailinglist">Keeping in Touch</A></LI></DIR>
<H2><A NAME="intro">Introduction</A></H2>
<P><A HREF="http://www.cs.princeton.edu/software/lcc/">lcc</A> is the ANSI C
compiler described in our book
<CITE>A Retargetable C Compiler: Design and Implementation</CITE>
(Addison-Wesley, 1995, ISBN 0-8053-1670-1).</P>
<P>Extract the distribution into its own directory. All non-absolute paths
below are relative to this directory. The distribution holds the following
subdirectories.</P>
<BLOCKQUOTE>
<TABLE BORDER="0" CELLPADDING="1" CELLSPACING="1" WIDTH="80%">
<TR>
<TD><A HREF="pkg/src"><TT>src</TT></A></TD>
<TD></TD>
<TD>source code</TD></TR>
<TR>
<TD><A HREF="pkg/etc"><TT>etc</TT></A></TD>
<TD></TD>
<TD>driver, accessories</TD></TR>
<TR>
<TD><A HREF="pkg/lib"><TT>lib</TT></A></TD>
<TD></TD>
<TD>runtime library source code</TD></TR>
<TR>
<TD><A HREF="pkg/cpp"><TT>cpp</TT></A></TD>
<TD></TD>
<TD>preprocessor source code</TD></TR>
<TR>
<TD><A HREF="pkg/lburg"><TT>lburg</TT></A></TD>
<TD></TD>
<TD>code-generator generator source code</TD></TR>
<TR>
<TD><A HREF="pkg/doc"><TT>doc</TT></A></TD>
<TD></TD>
<TD>this document, man pages</TD></TR>
<TR>
<TD><TT><A HREF="pkg/include">include</A>/*/*</TT></TD>
<TD></TD>
<TD>include files</TD></TR>
<TR>
<TD><A HREF="pkg/tst"><TT>tst</TT></A></TD>
<TD></TD>
<TD>test suite</TD></TR>
<TR>
<TD><A HREF="pkg/alpha"><TT>alpha</TT></A><TT>/*/tst</TT></TD>
<TD></TD>
<TD>ALPHA test outputs</TD></TR>
<TR>
<TD><A HREF="pkg/mips"><TT>mips</TT></A><TT>/*/tst</TT></TD>
<TD></TD>
<TD>MIPS test outputs</TD></TR>
<TR>
<TD><A HREF="pkg/sparc"><TT>sparc</TT></A><TT>/*/tst</TT></TD>
<TD></TD>
<TD>SPARC test outputs</TD></TR>
<TR>
<TD><A HREF="pkg/x86"><TT>x86</TT></A><TT>/*/tst</TT></TD>
<TD></TD>
<TD>X86 test outputs</TD></TR></TABLE></BLOCKQUOTE>
<P><TT>doc/install.html</TT> is the HTML file for this document.
<A HREF="pkg/doc/4.html"><TT>doc/4.html</TT></A> describes the internal
differences between lcc 3.x and 4.0.</P>
<P>The installation makefile is designed so that lcc can be installed from a
read-only file system or directory, which is common in networked environments,
so the distribution can be unloaded on a central file server. <STRONG>You will
need an existing ANSI/ISO C compiler to build and install lcc.</STRONG></P>
<P>If you're installing lcc on a UNIX system, continue with the next section.
If you're installing lcc on a Windows NT 4.0 or Windows 95 system, read the next
three sections first, then follow the <A HREF="#win32">Windows NT/95
instructions</A>.</P>
<H2><A NAME="unix">Installation on UNIX</A></H2>
<P>The compilation components (the preprocessor, include files, and compiler
proper, etc.) are installed in a single <EM>build directory</EM>. On
multi-platform systems supported by a central file server, it's common to store
the build directory in a location specific to the platform and to the version of
lcc, and to point a symbolic link to this location. For example,</P>
<BLOCKQUOTE>
<PRE>% ln -s /usr/local/lib/lcc-4.0/sparc-solaris /usr/local/lib/lcc</PRE></BLOCKQUOTE>
<P>points <TT>/usr/local/lib/lcc</TT> to a build directory for lcc version 4.0
on the SPARC under Solaris. Links into <TT>/usr/local/lib</TT> are created for
the programs <TT>lcc</TT> and <TT>bprint</TT>. Thus, a new distribution can be
installed by building it in its own build directory and changing one symbolic
link to point to that directory. If these conventions or their equivalents are
followed, the host-specific parts of the driver program, <TT>lcc</TT>, can be
used unmodified.</P>
<P> Installation on a UNIX system involves the following steps. Below, the
build directory is referred to as <TT>BUILDDIR</TT>.</P>
<OL>
<LI>Create the build directory, using a version- and platform-specific naming
convention as suggested above, and record the name of this directory in the
<TT>BUILDDIR</TT> environment variable:
<BLOCKQUOTE>
<PRE>% setenv BUILDDIR /usr/local/lib/lcc-4.0/sparc-solaris
% mkdir -p $BUILDDIR</PRE></BLOCKQUOTE>Here and below, commands assume the C
shell. Also, you'll need a version of <TT>mkdir</TT> that supports the <TT>-p</TT>
option, which creates intermediate directories as necessary.</LI>
<LI>Copy the man pages to the repository for local man pages, e.g.,
<BLOCKQUOTE>
<PRE>% cp doc/*.1 /usr/local/man/man1</PRE></BLOCKQUOTE>Some users copy the man
pages to the build directory and create the appropriate symbolic links, e.g.,
<BLOCKQUOTE>
<PRE>% cp doc/*.1 $BUILDDIR
% ln -s $BUILDDIR/*.1 /usr/local/man/man1</PRE></BLOCKQUOTE></LI>
<LI>Platform-specific include files are in directories named
<TT>include/</TT><I>target</I><TT>/</TT><I>os</I>. Create the include
directory in the build directory,  and copy the include files for your platform
to this directory, e.g.,
<BLOCKQUOTE>
<PRE>% mkdir $BUILDDIR/include
% rcp -p include/sparc/solaris/*.h $BUILDDIR/include</PRE></BLOCKQUOTE>Again,
some users create a symbolic link to the appropriate directory in the
distribution instead of copying the include files. For example, at Princeton,
the distributions are stored under <TT>/proj/pkg/lcc</TT>, so the included
files are &quot;installed&quot; by creating one symbolic link:
<BLOCKQUOTE>
<PRE>% ln -s /proj/pkg/lcc/4.0/include/sparc/solaris $BUILDDIR/include</PRE></BLOCKQUOTE></LI>
<LI>The <A HREF="pkg/makefile"><TT>makefile</TT></A> includes the file named
by the <TT>CUSTOM</TT> macro; the default is <TT>custom.mk</TT>, and an empty
<TT>custom.mk</TT> is included in the distribution. If desired, prepare a
site-specification customization file and define <TT>CUSTOM</TT> to the path of
that file when invoking make in steps 5 and 6, e.g.,
<BLOCKQUOTE>
<PRE>make CUSTOM=/users/drh/solaris.mk</PRE></BLOCKQUOTE>You can, for example,
use customization files to record site-specific values for macros instead of
using environment variables, and to record targets for the steps in this list.</LI>
<LI>Build the host-specific driver, creating a custom host-specific part, if
necessary. See <A HREF="#driver"><EM>Building the Driver</EM></A>.</LI>
<LI>Build the preprocessor, compiler proper, library, and other accessories.
See
<A HREF="#rcc"><EM>Building the Compiler</EM></A>.</LI>
<LI>Plant symbolic links to the build directory and to the installed programs,
e.g.,
<BLOCKQUOTE>
<PRE>% ln -s $BUILDDIR /usr/local/lib/lcc
% ln -s /usr/local/lib/{lcc,bprint} /usr/local/bin</PRE></BLOCKQUOTE>Some users
copy
<TT>bprint</TT> and <TT>lcc</TT> into <TT>/usr/local/bin</TT> instead of
creating symbolic links. The advantange of creating the links for <TT>lcc</TT>
and <TT>bprint</TT> as shown is that, once established, they point indirectly
to whatever  <TT>/usr/local/lib/lcc</TT> points to; installing a new version of
lcc, say, 4.1, can be done by changing <TT>/usr/local/lib/lcc</TT> to point to
the 4.1 build directory.</LI></OL>
<H2><A NAME="driver">Building the Driver</A></H2>
<P>The preprocessor, compiler, assembler, and loader are invoked by a driver
program, <TT>lcc</TT>, which is similar to <TT>cc</TT> on most systems. It's
described in the man page
<TT>doc/lcc.1</TT>. The driver is built by combining the host-independent part,
<TT>etc/lcc.c</TT>, with a small host-specific part. Distributed host-specific
parts are named <TT>etc/</TT><I>os</I><TT>.c</TT>, where <I>os</I> is the
name of the operating system for the host on which <TT>lcc</TT> is being
installed. If you're following the installations conventions described above,
you can probably use one of the host-specific parts unmodified; otherwise, pick
one that is closely related to your platform, copy it to <I>whatever</I><TT>.c</TT>,
and edit it as described below. You should not have to edit <TT>etc/lcc.c</TT>.</P>
<P>We'll use <A HREF="pkg/etc/solaris.c"><TT>etc/solaris.c</TT></A> as an
example in describing how the host-specific part works. This example illustrates
all the important features. Make sure you have the environment variable <TT>BUILDDIR</TT>
set correctly, and build the driver with a <TT>make</TT> command, e.g.,</P>
<BLOCKQUOTE>
<PRE>% make HOSTFILE=etc/solaris.c lcc
cc -c -g -o /usr/local/lib/lcc-4.0/lcc.o etc/lcc.c
cc -c -g -o /usr/local/lib/lcc-4.0/host.o etc/solaris.c
cc -o /usr/local/lib/lcc-4.0/lcc -g /usr/local/lib/lcc-4.0/lcc.o /usr/local/lib/lcc-4.0/host.o</PRE></BLOCKQUOTE>
<P>The symbolic name <TT>HOSTFILE</TT> specifies the path to the host-specific
part, either one in the distribution or <I>whatever</I><TT>.c</TT>. Some
versions of make may require the <TT>-e</TT> option in order to read the
environment.</P>
<P>Here's <TT>etc/solaris.c</TT>:</P>
<BLOCKQUOTE>
<PRE>/* Sparcs running Solaris 2.5.1 at CS Dept., Princeton University */

#include &lt;string.h&gt;

static char rcsid[] = &quot; Id: solaris.c,v 1.9 1997/05/27 23:03:45 drh Exp $&quot;;

#ifndef LCCDIR
#define LCCDIR &quot;/usr/local/lib/lcc/&quot;
#endif
#ifndef SUNDIR
#define SUNDIR &quot;/opt/SUNWspro/SC4.0/lib/&quot;
#endif

char *suffixes[] = { &quot;.c&quot;, &quot;.i&quot;, &quot;.s&quot;, &quot;.o&quot;, &quot;.out&quot;, 0 };
char inputs[256] = &quot;&quot;;
char *cpp[] = { LCCDIR &quot;cpp&quot;,
	&quot;-D__STDC__=1&quot;, &quot;-Dsparc&quot;, &quot;-D__sparc__&quot;, &quot;-Dsun&quot;, &quot;-D__sun__&quot;, &quot;-Dunix&quot;,
	&quot;$1&quot;, &quot;$2&quot;, &quot;$3&quot;, 0 };
char *include[] = { &quot;-I&quot; LCCDIR &quot;include&quot;, &quot;-I/usr/local/include&quot;,
	&quot;-I/usr/include&quot;, 0 };
char *com[] = { LCCDIR &quot;rcc&quot;, &quot;-target=sparc/solaris&quot;,
	&quot;$1&quot;, &quot;$2&quot;, &quot;$3&quot;, 0 };
char *as[] = { &quot;/usr/ccs/bin/as&quot;, &quot;-Qy&quot;, &quot;-s&quot;, &quot;-o&quot;, &quot;$3&quot;, &quot;$1&quot;, &quot;$2&quot;, 0 };
char *ld[] = { &quot;/usr/ccs/bin/ld&quot;, &quot;-o&quot;, &quot;$3&quot;, &quot;$1&quot;,
	SUNDIR &quot;crti.o&quot;, SUNDIR &quot;crt1.o&quot;,
	SUNDIR &quot;values-xa.o&quot;, &quot;$2&quot;, &quot;&quot;,
	&quot;-Y&quot;, &quot;P,&quot; SUNDIR &quot;:/usr/ccs/lib:/usr/lib&quot;, &quot;-Qy&quot;,
	&quot;-L&quot; LCCDIR, &quot;-llcc&quot;, &quot;-lm&quot;, &quot;-lc&quot;, SUNDIR &quot;crtn.o&quot;, 0 };

extern char *concat(char *, char *);

int option(char *arg) {
	if (strncmp(arg, &quot;-lccdir=&quot;, 8) == 0) {
		cpp[0] = concat(&amp;arg[8], &quot;/cpp&quot;);
		include[0] = concat(&quot;-I&quot;, concat(&amp;arg[8], &quot;/include&quot;));
		ld[12] = concat(&quot;-L&quot;, &amp;arg[8]);
		com[0] = concat(&amp;arg[8], &quot;/rcc&quot;);
	} else if (strcmp(arg, &quot;-p&quot;) == 0) {
		ld[5] = SUNDIR &quot;mcrt1.o&quot;;
		ld[10] = &quot;P,&quot; SUNDIR &quot;libp:/usr/ccs/lib/libp:/usr/lib/libp:&quot;
			 SUNDIR &quot;:/usr/ccs/lib:/usr/lib&quot;;
	} else if (strcmp(arg, &quot;-b&quot;) == 0)
		;
	else if (strncmp(arg, &quot;-ld=&quot;, 4) == 0)
		ld[0] = &amp;arg[4];
	else
		return 0;
	return 1;
}</PRE></BLOCKQUOTE>
<P><TT>LCCDIR</TT> defaults to <TT>&quot;/usr/local/lib/lcc/&quot;</TT>
unless it's defined by a <TT>-D</TT> option as part of <TT>CFLAGS</TT> in the
make command, e.g.,</P>
<BLOCKQUOTE>
<PRE>% make HOSTFILE=etc/solaris.c CFLAGS='-DLCCDIR=\&quot;/v/lib/lcc/\&quot;' lcc</PRE></BLOCKQUOTE>
<P>Note the trailing slash; <TT>SUNDIR</TT> is provided so you can use
<TT>etc/solaris.c</TT> even if you have a different version of the Sun Pro
compiler suite. If you're using the gcc compiler tools instead of the Sun Pro
tools, see <A HREF="pkg/etc/gcc-solaris.c"><TT>etc/gcc-solaris.c</TT></A>.</P>
<P>Most of the host-specific code is platform-specific data and templates for
the commands that invoke the preprocessor, compiler, assembler, and loader. The
<TT>suffixes</TT> array lists the file name suffixes for C source files,
preprocessed source files, assembly language source files, object files, and
executable files. <TT>suffixes</TT> must be terminated with a null pointer, as
shown above. The initialization of <TT>suffixes</TT> in <TT><A
HREF="pkg/etc/solaris.c">etc/solaris</A></TT> are the typical ones for UNIX
systems. Each element of <TT>suffixes</TT> is actually a list of suffixes,
seperated by semicolons; <TT><A HREF="pkg/etc/win32.c">etc/win32.c</A></TT>
holds an example:</P>
<BLOCKQUOTE>
<PRE>char *suffixes[] = { &quot;.c;.C&quot;, &quot;.i;.I&quot;, &quot;.asm;.ASM;.s;.S&quot;, &quot;.obj;.OBJ&quot;, &quot;.exe&quot;, 0 };
</PRE></BLOCKQUOTE>
<P>When a list is given, the first suffix is used whenever lcc needs to
generate a file name. For example, with <TT><A HREF="pkg/etc/win32.c">etc/win32.c</A></TT>,
lcc emits the generated assembly code into <TT>.asm</TT> files.</P>
<P>The <TT>inputs</TT> array holds a null-terminated string of directories
separated by colons or semicolons. These are used as the default value of <TT>LCCINPUTS</TT>,
if the environment variable <TT>LCCINPUTS</TT> is not set; see the
<A HREF="http://www.cs.princeton.edu/software/lcc/cgi-bin/man2html.cgi?lcc+1">man
page</A>.</P>
<P>Each command template is an array of pointers to strings terminated with a
null pointer; the strings are full path names of commands, arguments, or
argument placeholders, which are described below. Commands are executed in a
child process, and templates can contain multiple commands by separating
commands with newlines. The driver runs each command in a new process.</P>
<P>The <TT>cpp</TT> array gives the command for running lcc's preprocessor,
<TT>cpp</TT>. Literal arguments specified in templates, e.g., <TT>&quot;-Dsparc&quot;</TT>
in the <TT>cpp</TT> command above, are passed to the command as given.</P>
<P>The strings <TT>&quot;$1&quot;</TT>, <TT>&quot;$2&quot;</TT>, and <TT>&quot;$3&quot;</TT>
in templates are placeholders for <EM>lists</EM> of arguments that are
substituted in a copy of the template before the command is executed.
<TT>$1</TT> is replaced by the <EM>options</EM> specified by the user; for the
preprocessor, this list always contains at least
<TT>-Dunix</TT> and <TT>-D__LCC__</TT>.
<TT>$2</TT> is replaced by the <EM>input</EM> files, and <TT>$3</TT> is
replaced by the <EM>output</EM> file.</P>
<P>Zero-length arguments after replacement are removed from the argument list
before the command is invoked. So, for example, if the preprocessor is invoked
without an output file,
<TT>&quot;$3&quot;</TT> becomes <TT>&quot;&quot;</TT>, which is removed from
the final argument list.</P>
<P>The <TT>include</TT> array is a list of <TT>-I</TT> options that specify
which directives should be searched to satisfy include directives. These
directories are searched in the order given. The first directory should be the
one to which the ANSI header files were copied as described in <A HREF="#unix">UNIX</A>
or <A HREF="#win32">Windows</A> installation instructions. The driver adds
these options to <TT>cpp</TT>'s arguments when it invokes the preprocessor,
except when <TT>-N</TT> is specified.</P>
<P><TT>com</TT> gives the command for invoking the compiler. This template can
appear as shown above in a custom host-specific part, but the option <TT>-target=sparc/solaris</TT>
should be edited to the <I>target</I><TT>/</TT><I>os</I> for your platform.
If <TT>com[1]</TT> includes the string &quot;<TT>win32</TT>&quot;, the driver
assumes it's running on Windows. lcc can generate code for <EM>all</EM> of the
<I>target</I><TT>/</TT><I>os</I> combinations listed in the file <TT>src/bind.c</TT>.
The <TT>-target</TT> option specifies the default combination. The driver's
<TT>-Wf</TT> option can be used to specify other combinations; the
<A HREF="http://www.cs.princeton.edu/software/lcc/cgi-bin/man2html.cgi?lcc+1">man
page</A> elaborates.</P>
<P><TT>as</TT> gives the command for invoking the assembler.</P>
<P><TT>ld</TT> gives the command for invoking the loader. For the other
commands, the list <TT>$2</TT> contains a single file; for <TT>ld</TT>, <TT>$2</TT>
contains all &quot;.o&quot; files and libraries, and
<TT>$3</TT> is <TT>a.out</TT>, unless the <TT>-o</TT> option is specified. As
suggested in the code above, <TT>ld</TT> must also specify the appropriate
startup code and default libraries, including the lcc library, <TT>liblcc.a</TT>.</P>
<P>The <TT>option</TT> function is described below; the minimal
<TT>option</TT> function just returns 0.</P>
<P>You can test
<TT>lcc</TT> with the options <TT>-v -v</TT> to display the commands that
would be executed, e.g.,</P>
<BLOCKQUOTE>
<PRE>% $BUILDDIR/lcc -v -v foo.c baz.c mylib.a -lX11
/usr/local/lib/lcc-4.0/lcc Id: lcc.c,v 4.8 1997/05/21 00:23:30 drh Exp $
foo.c:
/usr/local/lib/lcc/cpp -D__STDC__=1 -Dsparc -D__sparc__ -Dsun -D__sun__ -Dunix -D__LCC__ -I/usr/local/lib/lcc/include -I/usr/local/include -I/usr/include foo.c /tmp/lcc266290.i
/usr/local/lib/lcc/rcc -target=sparc/solaris -v /tmp/lcc266290.i /tmp/lcc266291.
s
/usr/ccs/bin/as -Qy -s -o /tmp/lcc266292.o /tmp/lcc266291.s
baz.c:
/usr/local/lib/lcc/cpp -D__STDC__=1 -Dsparc -D__sparc__ -Dsun -D__sun__ -Dunix -D__LCC__ -I/usr/local/lib/lcc/include -I/usr/local/include -I/usr/include baz.c /tmp/lcc266290.i
/usr/local/lib/lcc/rcc -target=sparc/solaris -v /tmp/lcc266290.i /tmp/lcc266291.s
/usr/ccs/bin/as -Qy -s -o /tmp/lcc266293.o /tmp/lcc266291.s
/usr/ccs/bin/ld -o a.out /opt/SUNWspro/SC4.0/lib/crti.o /opt/SUNWspro/SC4.0/lib/crt1.o /opt/SUNWspro/SC4.0/lib/values-xa.o /tmp/lcc266292.o /tmp/lcc266293.o mylib.a -lX11 -Y P,/opt/SUNWspro/SC4.0/lib/:/usr/ccs/lib:/usr/lib -Qy -L/usr/local/lib/lcc/ -llcc -lm -lc /opt/SUNWspro/SC4.0/lib/crtn.o
rm /tmp/lcc266293.o /tmp/lcc266290.i /tmp/lcc266291.s /tmp/lcc266292.o</PRE></BLOCKQUOTE>
<P>As the output shows, <TT>lcc</TT> places temporary files in <TT>/tmp</TT>;
if any of the environment variables <TT>TMP</TT>, <TT>TEMP</TT>, and <TT>TMPDIR</TT>
are set, they override this default (in the order shown) as does the <TT>-tempdir=</TT><EM>dir</EM>
option. The default can be changed by defining <TT>TEMPDIR</TT> in <TT>CFLAGS</TT>
when building the driver.</P>
<P>The <TT>option</TT> function is called for the options
<TT>-Wo</TT>, <TT>-g</TT>, <TT>-p</TT>, <TT>-pg</TT>, and <TT>-b</TT>
because these compiler options might also affect the loader's arguments. For
these options, the driver calls <TT>option(arg)</TT> to give the host-specific
code an opportunity to edit the <TT>ld</TT> command, if necessary.
<TT>option</TT> can change <TT>ld</TT>, if necessary, and return 1 to announce
its acceptance of the option. If the option is unsupported, <TT>option</TT>
should return 0.</P>
<P>For example, in response to <TT>-g</TT>, the <TT>option</TT> function
shown above accepts the option but does nothing else, because the <TT>ld</TT>
and <TT>as</TT> commands don't need to be modified on the SPARC. <TT>-g</TT>
will also be added to the compiler's options by the host-independent part of the
driver. The <TT>-p</TT> causes <TT>option</TT> to change the name of the
startup code and changed the list of libraries. The <TT>-b</TT> option turns on
lcc's per-expression profiling, the code for which is in <TT>liblcc.a</TT>, so
<TT>option</TT> need no nothing.</P>
<P>On SPARCs, the driver also recognizes <TT>-Bstatic</TT> and <TT>-Bdynamic</TT>
as linker options. The driver recognizes but ignores &quot;<TT>-target</TT>
<I>name</I>&quot; option.</P>
<P>The option <TT>-Wo</TT><I>arg</I> causes the driver to pass <I>arg</I> to
<TT>option</TT>. Such options have no other effect; this mechanism is provided
to support system-specific options that affect the commands executed by the
driver. As illustrated above, host-specific parts should support the <TT>-Wo-lccdir=</TT><EM>dir</EM>
option, which causes lcc's compilation components to be found in <EM>dir</EM>,
because this option is  used by the test scripts. The code above rebuilds the
paths to the include files, preprocessor, compiler, and library by calling <TT>concat</TT>,
which is defined in <TT>etc/lcc.c</TT>.</P>
<H2><A NAME="rcc">Building the Compiler and Accessories</A></H2>
<P>To build the rest of compilation components make sure <TT>BUILDDIR</TT> is
set appropriately and type &quot;<TT>make all</TT>&quot;. This command builds
<TT>librcc.a</TT> (the compiler's private library), 
<TT>rcc</TT> (the compiler proper), <TT>lburg</TT> (the code-generator
generator), <TT>cpp</TT> (the preprocessor), <TT>liblcc.a</TT> (the runtime
library), and <TT>bprint</TT> (the profile printer), all in <TT>BUILDDIR</TT>.
There may be warnings, but there should be no errors. If you're using an
ANSI/ISO compiler other than <TT>cc</TT>, specify its name with the <TT>CC=</TT>
option, e.g., &quot;<TT>make CC=gcc all</TT>&quot;. If you're running on a DEC
ALPHA, use &quot;<TT>make CC='cc -std1' all</TT>&quot;; the <TT>-std1</TT>
option is essential on the ALPHA. If you're on a DEC 5000 running Ultrix 4.3,
use &quot;<TT>make CC=c89 all</TT>&quot;.</P>
<P>Once <TT>rcc</TT> is built with the host C compiler, run the test suite to
verify that <TT>rcc</TT> is working correctly. If any of the steps below fail,
contact us (see <A HREF="#bugs"><EM>Reporting Bugs</EM></A>). The commands in
the makefile run the shell script
<TT>src/run.sh</TT> on each C program in the test suite, <TT>tst/*.c</TT>. It
uses the driver, <TT>$BUILDDIR/lcc</TT>, so you must have the driver in the
build directory before testing <TT>rcc</TT>. The <I>target</I><TT>/</TT><I>os</I>
combination is read from the variable <TT>TARGET</TT>, which must be specified
when invoking
<TT>make</TT>:</P>
<BLOCKQUOTE>
<PRE>% make TARGET=sparc/solaris test
mkdir -p /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/8q.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/array.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/cf.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/cq.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/cvt.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/fields.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/front.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/incr.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/init.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/limits.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/paranoia.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/sort.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/spill.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/stdarg.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/struct.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/switch.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/wf1.s:
/usr/local/lib/lcc-4.0/sparc-solaris/rcc -target=sparc/solaris /usr/local/lib/lcc-4.0/sparc-solaris/sparc/solaris/tst/yacc.s:</PRE></BLOCKQUOTE>
<P>Each line in the output above is of the form</P>
<BLOCKQUOTE>
<P><TT>$BUILDDIR/rcc -target=</TT><I>target</I><TT>/</TT><I>os</I><TT>$BUILDDIR/</TT><I>target</I><TT>/</TT><I>os</I><TT>/</TT><EM>X</EM><TT>.s:</TT></P></BLOCKQUOTE>
<P>where <EM>X</EM> is the base name of the C program <EM>X</EM><TT>.c</TT>
in the test suite. This output identifies the compiler and the target, e.g., &quot;<TT>$BUILDDIR/rcc</TT>
is generating code for a <TT>sparc</TT> running the
<TT>solaris</TT> operating system.&quot;</P>
<P>For each program in the test suite,
<TT>src/run.sh</TT> compiles the program, drops the generated assembly language
code in <TT>BUILDDIR</TT>/<I>target</I><TT>/</TT><I>os</I>, and uses <TT>diff</TT>
to compare the generated assembly code with the expected code (the code expected
for <TT>tst/8q.c</TT> on the SPARC under Solaris is in <TT>sparc/solaris/tst/8q.sbk</TT>,
etc.). If there are differences, the script executes the generated code with the
input given in <TT>tst</TT> (the input for <TT>tst/8q.c</TT> is in <TT>tst/8q.0</TT>,
etc.) and compares the output with the expected output (the expected output from
<TT>tst/8q.c</TT> on the SPARC under Solaris is in <TT>sparc/solaris/tst/8q.1bk</TT>,
etc.). The script also compares the diagnostics from the compiler with the
expected diagnostics.</P>
<P>On some systems, there may be a few differences between the generated code
and the expected code. These differences occur because the expected code is
generated by cross compilation and the least significant bits of some
floating-point constants differ from those bits in constants generated on your
system. There should be no differences in the output from executing the test
programs.</P>
<P>Next, run the &quot;triple test&quot;, which builds <TT>rcc</TT> using
itself:</P>
<BLOCKQUOTE>
<PRE>% make triple
/usr/local/lib/lcc-4.0/sparc-solaris/lcc -o /usr/local/lib/lcc-4.0/sparc-solaris/1rcc -d0.6 -Wo-lccdir=/usr/local/lib/lcc-4.0/sparc-solaris -B/usr/local/lib/lcc-4.0/sparc-solaris/  -Isrc src/*.c
src/alloc.c:
...
src/x86.c:
/usr/local/lib/lcc-4.0/sparc-solaris/lcc -o /usr/local/lib/lcc-4.0/sparc-solaris/1rcc -d0.6 -Wo-lccdir=/usr/local/lib/lcc-4.0/sparc-solaris -B/usr/local/lib/lcc-4.0/sparc-solaris/  -Isrc src/*.c
src/alloc.c:
...
src/x86.c:
strip /usr/local/lib/lcc-4.0/sparc-solaris/[12]rcc
dd if=/usr/local/lib/lcc-4.0/sparc-solaris/1rcc of=/usr/local/lib/lcc-4.0/sparc-solaris/rcc1 bs=512 skip=1
769+1 records in
769+1 records out
dd if=/usr/local/lib/lcc-4.0/sparc-solaris/2rcc of=/usr/local/lib/lcc-4.0/sparc-solaris/rcc2 bs=512 skip=1
769+1 records in
769+1 records out
if cmp /usr/local/lib/lcc-4.0/sparc-solaris/rcc[12]; then \
        mv /usr/local/lib/lcc-4.0/sparc-solaris/2rcc /usr/local/lib/lcc-4.0/sparc-solaris/rcc; \
        rm -f /usr/local/lib/lcc-4.0/sparc-solaris/1rcc /usr/local/lib/lcc-4.0/sparc-solaris/rcc[12]; fi</PRE></BLOCKQUOTE>
<P>This command builds <TT>rcc</TT> twice; once using the
<TT>rcc</TT> built by <TT>cc</TT> and again using the <TT>rcc</TT> built by
<TT>lcc</TT>. The resulting binaries are compared. They should be identical, as
shown at the end of the output above. If they aren't, our compiler is generating
incorrect code;
<A HREF="#bugs">contact</A> us.</P>
<P>The final version of <TT>rcc</TT> should also pass the test suite; that is,
the output from</P>
<BLOCKQUOTE>
<PRE>% make TARGET=sparc/solaris test</PRE></BLOCKQUOTE>
<P>should be identical to that from the previous <TT>make test</TT>.</P>
<P>The command &quot;<TT>make clean</TT>&quot; cleans up, but does not remove
<TT>rcc</TT>, etc., and &quot;<TT>make clobber</TT>&quot; cleans up and
removes <TT>lcc</TT>, <TT>rcc</TT>, and the other accessories. Test
directories under <TT>BUILDDIR</TT> are <EM>not</EM> removed; you'll need to
remove these by hand, e.g.,</P>
<BLOCKQUOTE>
<PRE>% rm -fr $BUILDDIR/sparc</PRE></BLOCKQUOTE>
<P>The code generators for the other targets can be tested by specifying the
desired <I>target</I><TT>/</TT><I>os</I> and setting an environment variable
that controls what <TT>src/run.sh</TT> does. For example, to test the MIPS code
generator, type</P>
<BLOCKQUOTE>
<PRE>% setenv REMOTEHOST noexecute
% make TARGET=mips/irix test</PRE></BLOCKQUOTE>
<P>As above, <TT>src/run.sh</TT> compares the MIPS code generated with what's
expected. There should be no differences. Setting <TT>REMOTEHOST</TT> to <TT>noexecute</TT>
suppresses the assembly and execution of the generated code. If you set <TT>REMOTEHOST</TT>
to the name of a MIPS machine to which you can <TT>rlogin</TT>,
<TT>src/run.sh</TT> will <TT>rcp</TT> the generated code to that machine and
execute it there, if necessary. See <TT>src/run.sh</TT> for the details.</P>
<P>You can use lcc as a cross compiler. The options <TT>-S</TT> and <TT>-Wf-target=</TT><I>target/os</I>
generate assembly code for the specified target, which is any of those listed in
the file
<TT>src/bind.c</TT>. For example,
</P>
<BLOCKQUOTE>
<PRE>% lcc -Wf-target=mips/irix -S tst/8q.c</PRE></BLOCKQUOTE>
<P>generates MIPS code for <TT>tst/8q.c</TT> in <TT>8q.s</TT>.</P>
<P>lcc can also generate code for a &quot;symbolic&quot; target. This target is
used routinely in front-end development, and its output is a printable
representation of the input program, e.g., the dags constructed by the front end
are printed, and other interface functions print their arguments. You can
specify this target with the option <TT>-Wf-target=symbolic</TT>. For example,</P>
<BLOCKQUOTE>
<PRE>% lcc -Wf-target=symbolic -S tst/8q.c</PRE></BLOCKQUOTE>
<P>generates symbolic output for <TT>tst/8q.c</TT> in <TT>8q.s</TT>. Finally,
the option <TT>-Wf-target=null</TT> specifies the &quot;null&quot; target for
which lcc emits nothing and thus only checks the syntax and semantics of its
input files.</P>
<H2><A NAME="win32">Installation on Windows NT 4.0 or Windows 95</A></H2>
<P>On Windows NT 4.0 and Windows 95, lcc is designed to work with Microsoft's
Visual C++ 5.0 (VC) and Microsoft's Assembler, MASM 6.11d. It uses the VC header
files, libraries, and command-line tools, and it uses MASM to assemble the code
it generates. If you have MASM 6.11, make sure you
<A HREF="http://www.microsoft.com/kb/articles/q138/9/83.htm">upgrade to 6.11d</A>,
because earlier 6.11 releases do not generate correct COFF object files.
<A HREF="pkg/makefile.nt"><TT>makefile.nt</TT></A> is written to use only
Microsoft's make, <TT>nmake</TT>, and the standard Windows NT/95 command
interpreter.</P>
<P>As on UNIX systems, the compilation components are installed in a single
<EM>build directory</EM>, and the top-level programs, <TT>lcc</TT> and <TT>bprint</TT>,
are installed in a directory on the PATH. If the conventions used below are
followed, the Windows-specific parts of the driver program, <TT>lcc</TT>, can
be used unmodified.</P>
<P> Installation on a Windows NT/95 system involves the following steps. Below,
the build directory is referred to as <TT>BUILDDIR</TT>, and the distribution
is in <TT>\dist\lcc\4.0</TT>.</P>
<OL>
<LI>Create the build directory, perhaps using a version- and platform-specific
naming convention as suggested in <A HREF="#unix"><EM>Installation on UNIX</EM></A>,
and record the name of this directory in the
<TT>BUILDDIR</TT> environment variable:
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;set BUILDDIR=\pkg\lcc-4.0
C:\dist\lcc\4.0&gt;mkdir %BUILDDIR%</PRE></BLOCKQUOTE></LI>
<LI><A HREF="pkg/etc/win32.c"><TT>etc\win32.c</TT></A> is the
Windows-specific part of the driver. It assumes that the VC header files are in
one of the standard places (<TT>\Program Files\devstudio\vc\include</TT> or
<TT>\msdev\include</TT>) and that the linker (<TT>link.exe</TT>) and the
assembler (<TT>ml.exe</TT>) are on the PATH. It also assumes that the macro
<TT>LCCDIR</TT> gives the build directory. If necessary, revise a copy of
<A HREF="pkg/etc/win32.c"><TT>etc\win32.c</TT></A> to reflect the conventions
on your computer (see <A HREF="#driver"><EM>Building the Driver</EM></A>),
then build the driver, specifying the default temporary directory, if necessary:
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;nmake -f makefile.nt TEMPDIR=\\temp HOSTFILE=etc/win32.c lcc

Microsoft (R) Program Maintenance Utility   Version 1.62.7022
Copyright (C) Microsoft Corp 1988-1997. All rights reserved.

        cl -nologo -Zi -MLd -Fd\pkg\lcc-4.0\ -c -DTEMPDIR=\&quot;\\temp\&quot; -Fo\pkg\lcc-4.0\lcc.obj etc/lcc.c
lcc.c
        cl -nologo -Zi -MLd -Fd\pkg\lcc-4.0\ -c -Fo\pkg\lcc-4.0\host.obj etc/win32.c
win32.c
        cl -nologo -Zi -MLd -Fd\pkg\lcc-4.0\ -Fe\pkg\lcc-4.0\lcc.exe \pkg\lcc-4.0\lcc.obj \pkg\lcc-4.0\host.obj</PRE></BLOCKQUOTE>If
you make a copy of <TT>etc\win32.c</TT>, specify the path of the copy as the
value of <TT>HOSTFILE</TT>. For example, if you copy <TT>etc\win32.c</TT> to
<TT>BUILDDIR</TT> and edit it, use the command
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;nmake -f makefile.nt TEMPDIR=\\temp HOSTFILE=%BUILDDIR%\win32.c lcc</PRE></BLOCKQUOTE></LI>
<LI>Build the preprocessor, compiler proper, library, and other accessories
(see
<A HREF="#rcc"><EM>Building the Compiler</EM></A>):
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;nmake -f makefile.nt all</PRE></BLOCKQUOTE>This command
uses the VC command-line tools <TT>cl</TT> and <TT>lib</TT> to build
<TT>bprint.exe</TT>, <TT>cpp.exe</TT>, <TT>lburg.exe</TT>, <TT>liblcc.lib</TT>,
<TT>librcc.lib</TT>, and <TT>rcc.exe</TT>, all in <TT>BUILDDIR</TT>. There
may be some warnings, but there should be no warnings.</LI>
<LI>Create a test directory and run the test suite:
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;mkdir %BUILDDIR%\x86\win32\tst
C:\dist\lcc\4.0&gt;nmake -f makefile.nt test</PRE></BLOCKQUOTE>This command
compiles each program in <A HREF="pkg/tst">tst</A>, compares the generated
assembly code and diagnostics with the expected assembly code and diagnostics,
executes the program, and compares the output with the expected output (using 
<TT>fc</TT>). For example, when the nmake command compiles
<A HREF="pkg/tst/8q.c"><TT>tst\8q.c</TT></A>, it leaves the generated assembly
code and diagnostic output in <TT>%BUILDDIR%\x86\win32\tst\8q.s</TT> and <TT>%BUILDDIR%\x86\win32\tst\8q.2</TT>,
and it compares them with the expected results in <TT>x86\win32\tst\8q.sbk</TT>.
It builds the executable program in  <TT>%BUILDDIR%\x86\win32\tst\8q.exe</TT>,
runs it, and redirects the output to <TT>%BUILDDIR%\x86\win32\tst\8q.1</TT>,
which it compares with
<TT>x86\win32\tst\8q.1bk</TT>. The output from this step is voluminous, but
there should be no differences and no errors.</LI>
<LI>Run the &quot;triple&quot; test, which compiles <TT>rcc</TT> with itself
and verifies the results:
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;nmake -f makefile.nt triple
...
\pkg\lcc-4.0\x86.c:
 Assembling: C:/TEMP/lcc2001.asm
        fc /b \pkg\lcc-4.0\1rcc.exe \pkg\lcc-4.0\2rcc.exe
Comparing files \PKG\LCC-4.0\1rcc.exe and \PKG\LCC-4.0\2RCC.EXE
00000088: A2 BE</PRE></BLOCKQUOTE>This command builds <TT>rcc</TT> twice; once
using the
<TT>rcc</TT> built by VC and again using the <TT>rcc</TT> built by
<TT>lcc</TT>. The resulting binaries are compared using <TT>fc</TT>. They
should be identical, except for one or two bytes of timestamp data, as shown at
the end of the output above. If they aren't, our compiler is generating
incorrect code;
<A HREF="#bugs">contact</A> us.</LI>
<LI>Copy <TT>lcc.exe</TT> and <TT>bprint.exe</TT> to a directory on your
PATH, e.g.,
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;copy %BUILDDIR%\lcc.exe \bin
        1 file(s) copied.

C:\dist\lcc\4.0&gt;copy %BUILDDIR%\bprint.exe \bin
        1 file(s) copied.</PRE></BLOCKQUOTE></LI>
<LI>Finally, clean up:
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;nmake -f makefile.nt clean</PRE></BLOCKQUOTE>This
command removes the derived files in <TT>BUILDDIR</TT>, but does not remove
<TT>rcc.exe</TT>, etc.; &quot;<TT>nmake -f makefile.nt clobber</TT>&quot;
cleans up and removes all executables and libraries. Test directories under
<TT>BUILDDIR</TT> are <EM>not</EM> removed; you'll need to remove these by
hand, e.g.
<BLOCKQUOTE>
<PRE>C:\dist\lcc\4.0&gt;rmdir %BUILDDIR%\x86 /s
\pkg\lcc-4.0\x86, Are you sure (Y/N)? y</PRE></BLOCKQUOTE></LI></OL>
<H2><A NAME="bugs">Reporting Bugs</A></H2>
<P>lcc is a large, complex program. We find and repair errors routinely. If you
think that you've found a error, follow the steps below, which are adapted from
the instructions in Chapter 1 of
<CITE>A Retargetable C Compiler: Design and Implementation</CITE>.</P>
<OL>
<LI>If you don't have a source file that displays the error, create one. Most
errors are exposed when programmers try to compile a program they think is
valid, so you probably have a demonstration program already.</LI>
<LI>Preprocess the source file and capture the preprocessor output. Discard the
original code.</LI>
<LI>Prune your source code until it can be pruned no more without sending the
error into hiding. We prune most error demonstrations to fewer than five lines.</LI>
<LI>Confirm that the source file displays the error with the
<EM>distributed</EM> version of lcc. If you've changed lcc and the error
appears only in your version, then you'll have to chase the error yourself, even
if it turns out to be our fault, because we can't work on your code.</LI>
<LI>Annotate your code with comments that explain why you think that lcc is
wrong. If lcc dies with an assertion failure, please tell us where it died. If
lcc crashes, please report the last part of the call chain if you can. If lcc is
rejecting a program you think is valid, please tell us why you think it's valid,
and include supporting page numbers in the ANSI Standard, Appendix A in
<CITE>The C Programming Language</CITE>, or the appropriate section in <CITE>C:
A Reference Manual</CITE>, 4th edition by S. B. Harbison and G. L. Steele, Jr.
(Prentice Hall, 1995). If lcc silently generates incorrect code for some
construct, please include the corrupt assembly code in the comments and flag the
incorrect instructions if you can.</LI>
<LI>Confirm that your error hasn't been fixed already. The latest version of
lcc is always available for anonymous <TT>ftp</TT> from
<TT>ftp.cs.princeton.edu</TT> in
<A HREF="ftp://ftp.cs.princeton.edu/pub/lcc"><TT>pub/lcc</TT></A>. A
<A HREF="ftp://ftp.cs.princeton.edu/pub/lcc/README"><TT>README</TT></A> file
there gives acquistion details, and a
<A HREF="ftp://ftp.cs.princeton.edu/pub/lcc/LOG"><TT>LOG</TT></A> file reports
what errors were fixed and when they were fixed. If you report a error that's
been fixed, you might get a canned reply.</LI>
<LI>Send your program by electronic mail to
<TT>lcc-bugs@cs.princeton.edu</TT>. Please send only valid C programs; put all
remarks in C comments so that we can process reports semiautomatically.</LI></OL>
<H2><A NAME="mailinglist">Keeping in Touch</A></H2>
<P>There is an lcc mailing list for general information about lcc. To be added
to the list, send a message with the 1-line body</P>
<BLOCKQUOTE>
<PRE>subscribe lcc</PRE></BLOCKQUOTE>
<P>to <TT>majordomo@cs.princeton.edu</TT>. This line must appear in the
message body; &quot;Subject:&quot; lines are ignored. To learn more about
mailing lists served by <TT>majordomo</TT>, send a message with the 1-word body
&quot;<TT>help</TT>&quot; to <TT>majordomo@cs.princeton.edu</TT>.  Mail sent
to <TT>lcc@cs.princeton.edu</TT> is forwarded to everyone on the mailing list.</P>
<P>There is also an <TT>lcc-bugs</TT> mailing list for reporting bugs;
subscribe to it by sending a message with the 1-line body
</P>
<BLOCKQUOTE>
<PRE>subscribe lcc-bugs</PRE></BLOCKQUOTE>
<P>to <TT>majordomo@cs.princeton.edu</TT>. Mail addressed to
<VAR>lcc-bugs@cs.princeton.edu</VAR> is forwarded to everyone on this list.</P>
<HR>
<ADDRESS><A HREF="http://www.research.microsoft.com/~cwfraser/">Chris Fraser</A> / <A
HREF="mailto:cwfraser@microsoft.com">cwfraser@microsoft.com</A><BR><A
HREF="http://www.research.microsoft.com/~drh/">David Hanson</A> / <A
HREF="mailto:drh@microsoft.com">drh@microsoft.com</A><BR>$Revision: 1.34 $ $Date: 1997/08/01 22:02:35 $</ADDRESS></BODY></HTML>
