Index: /trunk/source/doc/src/Makefile.fedora
===================================================================
--- /trunk/source/doc/src/Makefile.fedora	(revision 8569)
+++ /trunk/source/doc/src/Makefile.fedora	(revision 8570)
@@ -71,5 +71,5 @@
 include makehtml
 
-install: $(HTMLFILES)
+install: $(HTMLFILES) distclean
 	cp $(HTMLFILES) ../HTML
 
@@ -81,5 +81,5 @@
 
 distclean: clean
-	-find . -type f -name "*~" | xargs rm
+	rm -f *~
 
 # All this rigamarole is to make the pathnames stored in the tarfile
Index: /trunk/source/doc/src/Makefile.macports
===================================================================
--- /trunk/source/doc/src/Makefile.macports	(revision 8569)
+++ /trunk/source/doc/src/Makefile.macports	(revision 8570)
@@ -22,5 +22,5 @@
 # (see below), and, if so, that its contents are correct.
 #EXTRAPARAMS= --load-trace
-EXTRAPARAMS=
+EXTRAPARAMS= --xinclude --nonet
 
 # The catalog file tells the translator where to find XSL stylesheets on the
@@ -55,7 +55,9 @@
 # Compute some targets.
 
-XMLFILES = $(shell find . -name "*.xml")
+#XMLFILES = $(shell find . -name "*.xml")
+XMLFILES = [0-9][0-9]-*.xml ccl-documentation.xml
 XSLFILES = $(shell find xsl -name "*.xsl")
-HTMLFILES = $(patsubst %.xml,%.html, $(XMLFILES))
+#HTMLFILES = $(patsubst %.xml,%.html, $(XMLFILES))
+HTMLFILES = ccl-documentation.html
 
 # Save the xsltproc version string for use in debugging.
Index: unk/source/doc/src/openmcl-documentation.xml
===================================================================
--- /trunk/source/doc/src/openmcl-documentation.xml	(revision 8569)
+++ 	(revision )
@@ -1,15693 +1,0 @@
-<?xml version="1.0" encoding="US-ASCII"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
-<!ENTITY rest "<varname>&amp;rest</varname>">
-<!ENTITY key "<varname>&amp;key</varname>">
-<!ENTITY optional "<varname>&amp;optional</varname>">
-<!ENTITY body "<varname>&amp;body</varname>">
-<!ENTITY aux "<varname>&amp;aux</varname>">
-<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
-]>
-<book lang="en">
- <bookinfo>
-  <title>OpenMCL Documentation</title>
- </bookinfo>
-
- <chapter><title>Obtaining, Installing, and Running OpenMCL</title>
-  
-  <sect1><title>Releases and System Requirements</title>
-   
-   <para>There are three active versions of OpenMCL.  Version 1.0 was
-   a stable release (released in late 2005); it is no longer under
-   active development.  Version 1.1 has been under active development
-   since shortly after 1.0 was released; it's been distributed as a
-   series of development "snapshots" and CVS updates.  1.1 snapshots
-   have introduced support for x86-64 platforms, internal use of
-   Unicode, and many other features, but have presented something of a
-   moving target.  Version 1.2 (being released in early 2008) is
-   intended to both a more stable and predictable release schedule and
-   to make it a bit easier for users who wish to track the "bleeding
-   edge" of development to do so.</para>
-
-      <para>Version 1.0 is available for three platform configurations:</para>
-      <itemizedlist>
-        <listitem>
-          <para>Linux on PowerPC (32-bit implementation)</para>
-        </listitem>
-        <listitem>
-          <para>Mac OS X on PowerPC (32-bit implementation)</para>
-        </listitem>
-        <listitem>
-          <para>Mac OS X on PowerPC (64-bit implementation)</para>
-        </listitem>
-      </itemizedlist>
-
-      <para>Versions 1.1 and 1.2 are available for five platform
-      configurations:</para>
-      <itemizedlist>
-        <listitem>
-          <para>Linux on PowerPC (32-bit and 64-bit implementations)</para>
-        </listitem>
-        <listitem>
-          <para>>Mac OS X on PowerPC (32-bit and 64-bit implementations)</para>
-        </listitem>
-        <listitem>
-          <para>Linux on X86-64 (64-bit implementation)</para>
-        </listitem>
-        <listitem>
-          <para>Mac OS X on X86-64 (64-bit implementation)</para>
-        </listitem>
-        <listitem><para>FreeBSD on X86-64 (64-bit implementation)</para></listitem>
-      </itemizedlist>
-
-      <para>A 64-bit version of OpenMCL requires a 64-bit processor
-      (obviously) running a 64-bit OS variant.</para>
-      
-      <para>There are ongoing efforts to port OpenMCL to the Windows
-      operating system and 32-bit x86 processors.</para>
-      
-      
-      <para>Additional platform-specific information is given in the
-      following subsections.</para>
-
-      <sect2><title>LinuxPPC</title> 
-        
-        <para>OpenMCL versions 1.0 and later run under relatively
-        recent versions of LinuxPPC. All versions of OpenMCL require
-        version 2.2.13 (or later) of the Linux kernel and version
-        2.1.3 (or later) of the GNU C library (glibc) at a bare
-        minimum.</para>
-      </sect2>
-
-      <sect2><title>LinuxX8664</title> 
-
-        <para>Version 1.1 and later of OpenMCL runs on relatively
-        recent Linux distributions for the x86-64 architecture.  It
-        requires a Linux with Thread Local Storage support in the
-        toolchain and standard libraries, and the New Posix Thread
-        Library (NPTL).  Fortunately, these features seem to be
-        present in all current Linux distributions for x86-64, though
-        there may be some problems with early Linux distributions for
-        x86-64.  (Some GCC versions older than 4.0 on Linux have been
-        known to have problems compiling some of the C code in the
-        kernel, some very old Linux distributions don't follow the
-        current ABI standards wrt segment register usage, some early
-        Linux kernels for x86-64 had problems mapping large regions of
-        the address space ... it's difficult to enumerate exactly what
-        versions of what Linux distributions have what problems.  A
-        rule of thumb is that - since much of the development of
-        OpenMCL for x86-64 took place in that time frame - Linux
-        distributions released earlier than early 2006 may have
-        problems running OpenMCL.) </para>
-      </sect2>
-
-      <sect2><title>FreeBSD-amd64</title>
-        <para>Versions 1.1 and later of OpenMCL runs on FreeBSD on
-        x86-64 (FreeBSD releases generally call the platform "and64")
-        OpenMCL should run under FreeBSD 6.0 or later; as of this
-        writing, FreeBSD 7.0 is about to be released and it may be
-        necessary for FreeBSD 7 users to install the "compat6x"
-        package in order to use a version of OpenMCL built on FreeBSD
-        6.x under FreeBSD 7.  .</para>
-      </sect2>
-
-      <sect2><title>DarwinPPC-MacOS-X</title>
-
-        <para> OpenMCL 1.0 runs on MacOS X versions 10.2, 10.3 and
-        10.4 on the PowerPC.</para>
-
-        <para>Current development on version 1.1 and later takes place
-        under OS X versions 10.4 and 10.5 and requires at least
-        version 10.3.9</para>
-
-        <para>The 64-bit DarwinPPC version of OpenMCL requires
-        functionality introduced in OSX 10.4 (namely, the ability to
-        run 64-bit binaries).  It also, obviously, requires a G5
-        processor.</para>
-
-        <para>OpenMCL hasn't been tested under Darwin proper, but
-        OpenMCL doesn't intentionally use any MacOS X features beyond
-        the Darwin subset and therefore it seems likely that OpenMCL
-        would run on PPC Darwin versions that correspond to recent OSX
-        versions.</para>
-      </sect2>
-
-      <sect2><title>Darwinx8664-MacOS-X</title>
-        <para>Versions 1.1 and later of OpenMCL runs on 64-bit
-        DarwinX86 (MacOS on Intel).</para>
-
-        <para>OpenMCL Darwinx8664/MacOS X requires a 64-bit processor.
-        All Macintoshes currently sold by Apple (as of early 2008) and
-        all Macintoshes introduced by Apple since August 2006 have
-        such processors.  However, the original MacBooks, MacBook Pros
-        and Intel iMacs (models introduced in early 2006) used 32-bit
-        Core Duo processors, and so OpenMCL will not (yet) run on
-        them.</para>
-
-      </sect2>
-    </sect1>
-
-    <sect1><title>Installation</title>
-      <para>Installing OpenMCL consists of</para>
-      <orderedlist> 
-        <listitem>
-          <para>Downloading an appropriate distribution of OpenMCL;</para>
-        </listitem>
-        <listitem>
-          <para>If necessary, extracting the archive somewhere on your
-          computer;</para>
-        </listitem>
-        <listitem>
-          <para>Configuring a shell script so OpenMCL can locate
-          necessary library files and other auxilliary files.</para>
-        </listitem>
-      </orderedlist>
-
-      <sect2><title>Downloading and untarring OpenMCL binary source
-      releases</title> <para> OpenMCL releases and snapshots are
-      distributed as tarballs (compressed tar archives).</para>
-
-      <para>Tarballs of version 1.0 for supported platforms are
-      available from the download page of the OpenMCL website.</para>
-
-      <para>Tarballs of the latest development snapshots of version
-      1.1, along with release notes, are available from the testing
-      directory on Clozure.com.</para>
-      <para>Both the release and snapshot archives contain a directory
-      named <literal>ccl</literal>, which in turn contains a number of
-      files and subdirectories.  The <literal>ccl</literal> directory
-      can reside anywhere in the filesystem, assuming appropriate
-      permissions. If you wanted the <literal>ccl</literal> directory
-      to reside in <literal>``~/openmcl/ccl''</literal> and the
-      directory <literal>``~/openmcl/''</literal> already existed, you
-      could do anything equivalent to:</para>
-      <programlisting>
-shell&gt; cd ~/openmcl
-shell&gt; tar xvzf <emphasis>path-to-downloaded-openmcl-archive.tar.gz</emphasis>
-      </programlisting>
-      <para><emphasis>Important Note for Macintosh Users:</emphasis>
-      Double-clicking the archive in the Finder may work, but it also
-      may have unintended side-effects.  In some versions of the Mac
-      OS double-clicking an archive will invoke Stuffit, which may try
-      to replace linefeeds with carriage returns as it extracts
-      files. Also, tar can be used to merge the archive contents into
-      an existing <literal>ccl</literal> directory, whereas
-      double-clicking in the Finder will create a new directory named
-      <literal>ccl 2</literal> (or <literal>ccl 3</literal>, or...)
-      Bottom line is that you're better off using tar from the
-      shell.</para>
-
-      <para>Once the <literal>ccl</literal> directory is installed,
-      it's necessary to install and configure a shell script
-      distributed with OpenMCL before using it.</para>
-      </sect2>
-
-      <sect2><title>The-openmcl-Shell-Script"</title>
-      <para>OpenMCL needs to be able to find the
-      <literal>ccl</literal> directory in order to support features
-      such as <literal>require</literal> and
-      <literal>provide</literal>, access to foreign interface
-      information (see ) and the lisp build process (see
-      ). Specifically, it needs to set up logical pathname
-      translations for the <literal>"ccl:"</literal> logical host.  If
-      this logical host isn't defined (or isn't defined correctly),
-      some things might work, some things might not... and it'll
-      generally be hard to invoke and use OpenMCL productively.</para>
-
-        <para>OpenMCL uses the value of the environment variable
-        <literal>CCL_DEFAULT_DIRECTORY</literal> to determine the
-        filesystem location of the <literal>ccl</literal> directory;
-        the openmcl shell script is intended to provide a way to
-        invoke OpenMCL with that environment variable set
-        correctly.</para>
-        <para>There are two versions of the shell script:
-        <literal>"ccl/scripts/openmcl"</literal> is used to invoke
-        32-bit implementations of OpenMCL and
-        <literal>"ccl/scripts/openmcl64"</literal> is used to invoke
-        64-bit implementations.</para>
-        <para>To use the script:</para>
-        <orderedlist>
-          <listitem>
-            <para>Edit the definition of
-            <literal>CCL_DEFAULT_DIRECTORY</literal> near the
-            beginning of theshell script so that it refers to your ccl
-            directory.  Alternately,set
-            <literal>CCL_DEFAULT_DIRECTORY</literal> in your .cshrc,
-            .tcshrc, .bashrc,.bash_profile, .MacOSX/environment.plist,
-            or wherever you usually set environment variables.  If
-            there is an existing definition of thevariable, the
-            openmcl script will not override it.The shell script sets
-            a local variable (<literal>OPENMCL_KERNEL</literal>) to
-            the standard name of the OpenMCL kernel approprate for the
-            platform (asdetermined by 'uname -s'.) You might prefer to
-            set this variable manually in the shell script</para>
-          </listitem>
-
-          <listitem>
-            <para>Ensure that the shell script is executable, for
-            example:<literal>$ chmod +x
-            ~/openmcl/ccl/scripts/openmcl64</literal>This command
-            grants execute permission to the named script. If you
-            areusing a 32-bit platform, substitute "openmcl" in place
-            of "openmcl64".
-            <warning>
-	      <para>The above command won't work if you are not the
-	      owner of the installed copy of OpenMCL. In that case,
-	      you can use the "sudo" command like this:</para>
-              <para><literal>$ sudo chmod +x
-              ~/openmcl/ccl/scripts/openmcl64</literal></para>
-              <para>Give your password when prompted.</para>
-              <para>If the "sudo" command doesn't work, then you are
-              not an administrator on the system you're using, and you
-              don't have the appropriate "sudo" permissions. In that
-              case you'll need to get help from the system's
-              administrator.</para>
-            </warning></para>
-          </listitem>
-          <listitem>
-            <para>Install the shell script somewhere on your shell's
-            search path</para>
-          </listitem>
-        </orderedlist>
-
-        <para>Once this is done, it should be possible to invoke
-        OpenMCL by typing <literal>openmcl</literal> at a shell
-        prompt:</para>
-        <programlisting>
-&gt; openmcl [args ...]
-Welcome to OpenMCL Version whatever (DarwinPPC32)!
-?
-</programlisting>
-        <para>The openmcl shell script will pass all of its arguments
-        to the OpenMCL kernel.  See <xref linkend="Invocation"/> for
-        more information about "args".  When invoked this way, the
-        lisp should be able to initialize the
-        <literal>"ccl:"</literal> logical host so that its
-        translations refer to the <literal>"ccl"</literal>
-        directory. To test this, you can call
-        <literal>probe-file</literal> in OpenMCL's read-eval-print
-        loop:</para>
-        <programlisting>
-? (probe-file "ccl:level-1;level-1.lisp")  ;will return the physical pathname of the file
-#P"/Users/alms/my_lisp_stuff/ccl/level-1/level-1.lisp"
-</programlisting>
-      </sect2>
-      <sect2 id="Invocation">
-	<title>Invocation</title>
-	<para>Assuming that the shell script is properly installed, it can be used to invoke OpenMCL from a shell prompt:
-	<programlisting>
-shell&gt;<replaceable>ccl</replaceable> <emphasis>args</emphasis>
-	</programlisting>
-	<literal>ccl</literal> will run a 32-bit session;
-	<literal>ccl64</literal> will run a 64-bit session.
-	</para>
-      </sect2>
-      <sect2 id="Personal-Customization-with-the-Init-File">
-	<title>Personal Customization with the Init File</title>
-        <para>By default OpenMCL will try to load the file
-        <literal>"home:openmcl-init.lisp"</literal> or the compiled
-	
-        <literal>"home:openmcl-init.fasl"</literal> upon starting
-        up. It does this by executing <literal>(load
-        "home:openmcl-init")</literal>.  If it is unable to load the
-        file (for example because it does not exist) no action is
-        taken; an error is not signalled.</para>
-        <para>The <literal>"home:"</literal> prefix to the filename is
-        a Common Lisp logical host, which OpenMCL initializes to refer
-        to your home directory, so this looks for either of the files
-        <literal>~/openmcl-init.lisp</literal> or
-        <literal>~/openmcl-init.fasl</literal>.</para>
-        <para>Since the init file is loaded the same way as normal
-        Lisp code is, you can put anything you want in it.  For
-        example, you can change the working directory, and load
-        packages which you use frequently.</para>
-        <para>To suppress the loading of this init-file, invoke OpenMCL with the
-<literal>--no-init</literal> option.</para>
-      </sect2>
-
-      <sect2 id="Some--hopefully--useful-options">
-	<title>Some (hopefully) useful options</title>
-        <para> The exact set of command-line arguments accepted by
-        OpenMCL may vary slightly from release to release;
-        <literal>openmcl --help</literal> will provide a definitive
-        (if somewhat terse) summary of the options accepted by the
-        current implementation and then exit. Some of those options
-        are described below.</para>
-	<itemizedlist>
-	  <listitem>
-	    <para>-S (or --stack-size). Specify the size of the initial process
-	    stack.</para>
-	  </listitem>
-
-	  <listitem>
-	    <para>-b (or --batch). Execute in &#34;batch mode&#34;. End-of-file
-	    from *STANDARD-INPUT* will cause OpenMCL to exit, as will attempts to
-	    enter a break loop.</para>
-	  </listitem>
-
-	  <listitem>
-	    <para>-n (or --no-init). If this option is given, the init file
-	    is not loaded.  This is useful if OpenMCL is being invoked by a
-	    shell script which should not be affected by whatever
-	    customizations a user might have in place.
-	    </para>
-	  </listitem>
-
-	  <listitem>
-	    <para>-e &#60;form&#62; (or --eval &#60;form&#62;). An expression is
-	    read (via READ-FROM-STRING from the string &#60;form&#62; and
-	    evaluated. If &#60;form&#62; contains shell metacharacters, it may be
-	    necessary to escape or quote them to prevent the shell from
-	    interpreting them.</para>
-	  </listitem>
-
-	  <listitem>
-	    <para>-l &#62;path&#62; (or --load &#60;path&#62;). Executes (load
-	    &#34;&#60;path&#62;&#34;).</para>
-	  </listitem>
-	</itemizedlist>
-
-        <para>The <literal>--load</literal> and
-        <literal>--eval</literal> options can each be provided
-        multiple times.  They're executed in the order specified on
-        the command line, after the init file (if there is one) is
-        loaded and before the toplevel read-eval-print loop is
-        entered.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Using-OpenMCL-with-GNU-Emacs-and-SLIME">
-      <title>Using OpenMCL with GNU Emacs and SLIME</title>
-      <para>A very common way to use OpenMCL is to run it within the
-      GNU Emacs editor, using a Lisp interface called SLIME ("Superior
-      Lisp Interaction Mode for Emacs"). SLIME is an Emacs package
-      designed to provide good support within Emacs for any of several
-      Common Lisp implementations; one of the supported
-      implementations is OpenMCL. This page describes how you can
-      download SLIME and set it up to work with your OpenMCL
-      installation.</para>
-      <para>Why use SLIME? With SLIME, you can do the following things from within
-an Emacs editing session:</para>
-      <itemizedlist>
-        <listitem><para>run and control Lisp</para></listitem>
-        <listitem><para>evaluate, compile, and load files or expressions</para></listitem>
-        <listitem><para>macroexpand expressions</para></listitem>
-        <listitem><para>fetch documentation and source code for Lisp symbols</para></listitem>
-        <listitem><para>autocomplete symbols and package names</para></listitem>
-        <listitem><para>cross-reference function calls</para></listitem>
-        <listitem><para>examine stack traces and debug errors</para></listitem>
-      
-      </itemizedlist>
-      <para>There is an excellent SLIME tutorial video available at
-Common-Lisp.net.  For
-complete information about SLIME, see the
-SLIME home page.</para>
-
-      <sect2 id="Assumptions-and-Requirements">
-	<title>Assumptions and Requirements</title>
-        <para>In order to simplify these instructions, we'll make
-        several assumptions about your system. Specifically, we
-        assume:</para>
-        <itemizedlist>
-          <listitem>
-	    <para>You have a working installation of GNU Emacs. If you
-	    don't have a working copy of GNU Emacs, see the web page on
-	    obtaining Emacs.  If you prefer to use XEmacs instead of
-	    GNU Emacs,these instructions should still work; SLIME
-	    supports XEmacs Version21. Mac OS X includes an Emacs
-	    installation.  If you want to look into different versions,
-	    you can check out theEmacsWiki, whichmaintains a
-	    page,EmacsForMacOS,that provides much more information
-	    about using Emacs on the Mac.
-            <warning>
-              <para>A popular version of Emacs among Mac users is
-              Aquamacs. This application is a version of GNU Emacs
-              with a number of customizations meant to make it behave
-              more like a standard Maciontosh application, with
-              windows, a menubar, etc.  Aquamacs includes SLIME; if
-              you like Aquamacs then you can use SLIME right away,
-              without getting and installing it separately. You just
-              need to tell SLIME where to find your installation of
-              OpenMCL. (See FIXTHIS.)</para>
-            </warning>
-	  </para>
-	  </listitem>
-          <listitem>
-            <para>You have a working copy of OpenMCL, installed in
-            <literal>"~/openmcl/ccl"</literal>If you prefer to install
-            OpenMCL in some directory other
-            than<literal>"~/openmcl/ccl"</literal> then these
-            instructions still work, but you must remember to use your
-            path to your ccl directory instead of theone that we give
-            here.</para>
-          </listitem>
-          <listitem>
-            <para>You install emacs add-ons in the folder
-            <literal>"~/emacs/site/"</literal>If this directory
-            doesn't exist on your system, you can just create it.If
-            you prefer to install Emacs add-ons in some place other
-            than<literal>"~/emacs/site/"</literal> then you must
-            remember to use your path toEmacs add-ons in place of
-            ours.</para>
-          </listitem>
-        
-        </itemizedlist>
-      </sect2>
-
-      <sect2 id="Getting_Slime"><title>Getting SLIME</title>       
-
-        <para>You can get SLIME from the SLIME Home Page. Stable
-        releases and CVS snapshots are available as archive files, or
-        you can follow the instructions on the SLIME Home Page to
-        check out the latest version from their CVS repository.</para>
-
-        <para>It's worth noting that stable SLIME releases happen very
-        seldom, but the SLIME developers often make changes and
-        improvements that are available through CVS updates. If you
-        asked the SLIM developers, they would most likely recommend
-        that you get SLIME from their CVS repository and update it
-        frequently.</para>
-
-        <para>Whether you get it from CVS, or download and unpack one
-        of the available archives, you should end up with a folder
-        named "slime" that contains the SLIME distribution.</para>
-      </sect2>
-
-      <sect2><title>Installing SLIME</title> 
-
-        <para>Once you have the "slime" folder described in the
-        previous section,installation is a simple matter of copying
-        the folder to the proper place. You can drag it into the
-        "~/emacs/site/" folder, or you can use a terminal command to
-        copy it there. For example, assuming your working directory
-        contains the unpacked "slime" folder:</para> <para><literal>$
-        cp -R slime ~/emacs/site/</literal></para> <para>That's all it
-        takes.</para>
-
-      </sect2>
-
-      <sect2 id="Telling-Emacs-About-SLIME">
-	<title>Telling Emacs About SLIME</title>
-        <para> Once SLIME and OpenMCL are installed, you just need to
-        add a line to your "~/.emacs" file that tells SLIME where to
-        find the script that runs OpenMCL:</para>
-        <para><literal>(setq inferior-lisp-program "~/openmcl/ccl/scripts/openmcl64")</literal></para>
-        <para>or</para>
-        <para><literal>(setq inferior-lisp-program "~/openmcl/ccl/scripts/openmcl")</literal></para>
-        <warning>
-          <para>Aquamacs users should add this line to the file "~/Library/Preferences/Aquamacs Emacs/Preferences.el".</para>
-        </warning>
-      </sect2>
-
-      <sect2 id="Running-OpenMCL-with-SLIME">
-	<title>Running OpenMCL with SLIME</title>
-        <para>Once the preparations in the previous section are
-        complete, exit Emacs and restart it, to ensure that it reads
-        the changes you made in your ".emacs" file (alternatively, you
-        could tell Emacs to reload the ".emacs" file). If all went
-        well, you should now be ready to run OpenMCL using
-        SLIME.</para>
-        <para>To run OpenMCL, execute the command "M-x slime". SLIME
-        should start an OpenMCL session in a new buffer.  (If you are
-        unfamiliar with the Emacs notation "M-x command", see the GNU
-        Emacs FAQ; specifically, take a look at questions 1, 2, and
-        128.)</para>
-      </sect2>
-
-      <sect2 id="What-if-a-New-Version-of-OpenMCL-Breaks-SLIME-">
-	<title>What if a New Version of OpenMCL Breaks SLIME?</title>
-	<para>Sometimes you'll get a new version of OpenMCL, set up
-	Emacs to use it with SLIME, and SLIME will fail. Most likely
-	what has happened is that the new version of OpenMCL has a
-	change in the output files produced by the compiler (OpenMCL
-	developers will say "the fasl version has changed." fasl
-	stands for &ldquo;fast load&rdquo; aka compiled files). This
-	problem is easy to fix: just delete the existing SLIME fasl
-	files. The next time you launch Emacs and start SLIME, it will
-	automatically recompile the Lisp files, and that should fix
-	the problem.</para>
-        <para>SLIME's load process stores its fasl files in a hidden
-        folder inside your home folder. The path is</para>
-        <para><literal>~/.slime/fasl</literal></para>
-        <para>You can use a shell command to remove the fasl files, or
-        remove them using your system's file browser.</para>
-        <screen><emphasis role="bold">Note for Macintosh Users:</emphasis> 
-	The leading "." character in the ".slime" folder's name
-	prevents the Finder from showing this folder to you. If you
-	use the "Go To Folder" menu item in the Finder's "Go" menu,
-	you can type in "~/.slime" and the Finder will show it to
-	you. You can then drag the "fasl" folder to the trash.
-	</screen>
-      </sect2>
-
-      <sect2 id="Known-Bugs">
-	<title>Known Bugs</title>
-	<para>SLIME has not been updated to account for recent changes
-	made in OpenMCL to support x86-64 processors. You may run into
-	bugs running on those platforms.</para>
-        <para>The SLIME backtrace sometimes shows incorrect information.</para>
-        <para><literal>return-from-frame</literal> and
-        <literal>apply-in-frame</literal> do not work reliably.  (If
-        they work at all, it's pure luck.)</para>
-        <para>Some versions of Emacs on the Macintosh may have trouble
-        finding the shell script that runs OpenMCL unless you specify
-        a full path to it. See the above section "Telling Emacs About
-        SLIME" to learn how to specify the path to the shell
-        script.</para>
-        <para>For more help with OpenMCL on Mac OS X, consult the
-        OpenMCL mailing lists.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Example-Programs">
-      <title>Example Programs</title>
-      <para>Beginning with release 0.9, a number (ok, a
-      <emphasis>small</emphasis> number, at least initially) of
-      example programs are distributed in the "ccl:examples;"
-      directory of the source distribution. See the
-      README-OPENMCL-EXAMPLES text file in that directory for
-      information about prerequisites and usage.</para>
-      <para>Some of the example programs are derived from C examples
-      in textbooks, etc.; in those cases, the original author and work
-      are cited in the source code.</para>
-      <para>It may be a stretch to imply that the examples have a
-      great deal of value as "intellectual property", but I might as
-      well say this: Unless the original author or contributor claims
-      other rights, you're free to incorporate any of this example
-      code or derivative thereof in any of you're own works without
-      restriction. In doing so, you agree that the code was provided
-      "as is", and that no other party is legally or otherwise
-      responsible for any consequences of your decision to use
-      it.</para>
-      <para>If you've developed OpenMCL examples that you'd like to
-      see added to the distribution, please send mail to let me
-      know. Any such contributions would be welcome and appreciated
-      (as would bug fixes and improvements to the existing
-      examples.)</para>
-    </sect1>
-  </chapter>
-
-  <chapter><title>Building OpenMCL from its Source Code</title>
-
-    <para>OpenMCL, like many other Lisp implementations, consists of a
-    kernel and a heap image.  The kernel is an ordinary C program, and
-    is built with a C compiler.  It provides very basic and
-    fundamental facilities, such as memory management, garbage
-    collection, and bootstrapping.  All the higher-level features are
-    written in Lisp, and compiled into the heap image.  Both parts are
-    needed to have a working Lisp implementation; neither the kernel
-    nor the heap image can stand on their own.</para>
-
-    <para>You may already know that, when you have a C compiler which
-    is written in C, to build the compiler, you need to already have a
-    C compiler available.  The heap image includes a Lisp compiler,
-    which is written in Lisp.  Therefore, you need a working Lisp
-    compiler in order to build the heap image!</para>
-    
-    <para>Where will you get a working Lisp compiler?  No worries; you
-    can use a precompiled copy of a (slightly older and compatible)
-    version of OpenMCL.  For help, read on.</para>
-
-    <para>In principle it would be possible to use another Lisp as the
-    host compiler, rather than an old OpenMCL; this would be a
-    challenging and experimental way to build, and is not described
-    here.</para>
-
-    <sect1 id="building-definitions"><title>building definitions</title>
-      <para>The following terms are used in subsequent sections; it
-      may be helpful to refer to these definitions.</para>
-
-      <para><indexterm><primary>fasl files</primary></indexterm> are
-      the object files produced by<literal>compile-file</literal>.
-      fasl files store the machine codeassociated with function
-      definitions and the external representationof other lisp objects
-      in a compact, machine-readable form. fasl is short for
-      &ldquo;<literal>FAS</literal>t
-      <literal>L</literal>oading&rdquo;.OpenMCL uses different
-      pathname types (extensions) to name faslfiles on different
-      platforms; see <xref
-      linkend="Platform-specific-filename-conventions"/> </para>
-
-      <para>The <indexterm><primary>lisp kernel</primary></indexterm> is
-      a C program (with a fair amount ofplatform-specific assembly
-      language code as well.)  Its basic job isto map a lisp heap
-      image into memory, transfer control to somecompiled lisp code
-      that the image contains, handle any exceptionsthat occur during
-      the execution of that lisp code, and provide variousother forms
-      of runtime support for that code.OpenMCL uses different
-      filenames to name the lisp kernel fileson different platforms;
-      see FIXTHIS.</para>
-
-      <para>A <indexterm><primary>heap image</primary></indexterm> is
-      a file that can be quickly mapped into aprocess's address space.
-      Conceptually, it's not too different from anexecutable file or
-      shared library in the OS's native format (ELF orMach-O/dyld
-      format); for historical reasons, OpenMCL's own heap images are in
-      their own (fairly simple) format.The term <literal>full heap
-      image</literal> refers to a heap image file thatcontains all of
-      the code and data that comprise OpenMCL.OpenMCL uses different
-      filenames to name the standard full heapimage files on different
-      platforms; see FIXTHIS .</para>
-
-      <para>A <indexterm><primary>bootstrapping
-      image</primary></indexterm> is a minimal heap image used in
-      the process of building OpenMCL itself.  The bootstrapping image
-      containsjust enough code to load the rest of OpenMCL from fasl
-      files.  It mayhelp to think of the bootstrapping image as the
-      egg and the full heapimage as the chicken...OpenMCL uses
-      different filenames to name the standardbootstrapping image
-      files on different platforms; see FIXTHIS .</para>
-
-      <para>Each supported platform (and possibly a few
-      as-yet-unsupported ones) has a uniquely named subdirectory of
-      <literal>ccl/lisp-kernel/</literal>; each such
-      <indexterm><primary>kernel build directory</primary></indexterm>
-      contains a Makefile and may contain some auxiliary files (linker
-      scripts, etc.) that are used to build the lispkernel on a
-      particular platform.The platform-specific name of the kernel
-      build directory is described in FIXTHIS.</para>
-
-      <sect2 id="filename_conventions">
-       <title>Platform-specific filename conventions</title>
-       <table id ="Platform-specific-filename-conventions">
-	 <title>Platform-specific filename conventions</title>
-	 <tgroup cols="6">
-	   <thead>
-            <row>
-                <entry>Platform</entry>
-                <entry>kernel</entry>
-                <entry>full-image</entry>
-                <entry>boot-image</entry>
-                <entry>fasl extension</entry>
-                <entry>kernel-build directory</entry>
-	    </row>
-	   </thead>
-	   <tbody>
-	     <row>
-	       <entry>DarwinPPC32</entry>
-                <entry>dppccl</entry>
-                <entry>dppccl.image</entry>
-                <entry>ppc-boot.image</entry>
-                <entry>.dfsl</entry>
-                <entry>darwinppc</entry>
-	     </row>
-	     <row>
-	       <entry>LinuxPPC32</entry>
-                <entry>ppccl</entry>
-		<entry>PPCCL</entry>
-                <entry>ppc-boot</entry>
-                <entry>.pfsl</entry>
-                <entry>linuxppc</entry>
-	     </row>
-	     <row>
-	       <entry>DarwinPPC64</entry>
-	       <entry>dppccl64</entry>
-	       <entry>dppccl64.image</entry>
-	       <entry>ppc-boot64.image</entry>
-	       <entry>.d64fsl</entry>
-	       <entry>darwinppc64</entry>
-             </row>
-              <row>
-		<entry>LinuxPPC64</entry>
-                <entry>ppccl64</entry>
-                <entry>PPCCL64</entry>
-                <entry>ppc-boot64</entry>
-                <entry>.p64fsl</entry>
-                <entry>linuxppc64</entry>
-              </row>
-	      <row>
-		<entry>LinuxX8664</entry>
-                <entry>lx86cl64</entry>
-                <entry>LX86CL64</entry>
-                <entry>x86-boot64</entry>
-                <entry>.lx64fsl</entry>
-                <entry>linuxx8664</entry>
-              </row>
-	      <row>
-		<entry>DarwinX8664</entry>
-		<entry>dx86cl64</entry>
-                <entry>dx86cl64.image</entry>
-                <entry>x86-boot64.image</entry>
-                <entry>.dx64fsl</entry>
-                <entry>darwinx8664</entry>
-              </row>
-	      <row>
-		<entry>FreeBSDX8664</entry>
-                <entry>fx86cl64</entry>
-                <entry>FX86CL64</entry>
-                <entry>fx86-boot64</entry>
-                <entry>.fx64fsl</entry>
-                <entry>freebsdx8664</entry>
-              </row>
-	   </tbody>
-	 </tgroup>
-       </table>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Setting-Up-to-Build">
-      <title>Setting Up to Build</title>
-      <para>There are currently three versions of OpenMCL that you
-      might want to use (and therefore might want to build from
-      source):</para>
-      <itemizedlist>
-        <listitem><para>Version 1.0 - the more stable version</para></listitem>
-        <listitem><para>Version 1.1 - the more recent version, which
-        runs on more platforms (including x86-64 platforms) and
-        supports Unicode</para></listitem>
-	<listitem><para>Version 1.2 - supports (at least) all of the
-	features and platforms as 1.1, but is distributed and updated
-	differently</para></listitem>
-      </itemizedlist>
-      <para>All versions are available for download from the OpenMCL
-      website in the form of archives that contain everything you need
-      to work with OpenMCL, including the complete sources, a full
-      heap image, and the foreign-function interface database.</para>
-      <para>Version 1.0 archives are named
-      <literal>openmcl-</literal><replaceable>platform</replaceable><literal>-all-1.0.tar.gz</literal>,
-      where <replaceable>platform</replaceable> is either
-      <literal>darwinppc</literal>, <literal>darwinppc64</literal>, or
-      <literal>linuxppc</literal>.  Because version 1.0 is no longer
-      undergoing active development, you won't ever need to update
-      these sources.</para>
-      <para>Version 1.1 archives are named
-      <literal>openmcl-</literal><replaceable>platform</replaceable><literal>-snapshot-</literal><replaceable>yymmdd</replaceable><literal>.tar.gz</literal>,
-      where <replaceable>platform</replaceable> is either
-      <literal>darwinppc</literal>, <literal>darwinx8664</literal>,
-      <literal>linuxppc</literal>, <literal>linuxx8664</literal>, or
-      <literal>freebsdx8664</literal>, and where
-      <replaceable>yymmdd</replaceable> is the year, month, and day
-      the snapshot was released.</para>
-      <para>Because version 1.1 is undergoing active development,
-      there may be times when you want to get sources that are more
-      recent than the most recent snapshot and use them to build
-      yourself a new bleeding-edge OpenMCL.  In that case, you should
-      download and install the latest snapshot, and then update your
-      sources via CVS.  At that point you can rebuild and you'll have
-      the latest and greatest OpenMCL.  The snapshot has CVS
-      working-copy information in it, so all you need to do to update
-      is</para>
-      <programlisting>
-$ cd ccl
-$ cvs login             # password is "cvs"
-                        # this step only needs to be done once,
-                        # that'll store the trivially encrypted
-                        # password in ~/.cvspas
-$ cvs update
-      </programlisting>
-      <para>Unless you tell it to, cvs won't delete ("prune") empty
-      directories or create new ones when the repository changes.
-      It's generally a good habit to use</para>
-      <programlisting>
-$ cvs update -d -P      # create dirs as needed, prune empty ones
-      </programlisting>
-      <para>Version 1.2 archives follow naming conventions that are
-      similar to those used by 1.0 (though more platforms are supported.)
-      However, rather than containing CVS working-copy information, the
-      1.2 (and, presumably, later) archives contain metainformation used
-      by the Subversion (svn) source-code control system.</para>
-      <para>Subversion client programs are pre-installed on OSX 10.5 and
-      later and are typically either pre-installed or readily available
-      on Linux and FreeBSD platforms.  The <ulink url="http://subversion.tigris.org">Subversion web page</ulink> contains links to subversion client programs
-      for many platforms; users of OSX versions 10.4 and earlier can also
-      install Subversion clients via Fink or MacPorts.</para>
-      
-    </sect1>
-
-    <sect1 id="Building-Everything">
-      <title>Building Everything</title>
-      <para>Given that you now have everything you need, do the
-      following in a running OpenMCL to bring your Lisp system
-      completely up to date.</para>
-      <programlisting>
-? (ccl:rebuild-ccl :full t)
-      </programlisting>
-      <para>That call to the function <literal>rebuild-ccl</literal>
-      will perform the following steps:</para>
-      <itemizedlist>
-        <listitem>
-	  <para>Deletes all fasl files and other object files in the
-	  <literal>ccl</literal>directory tree</para>
-	</listitem>
-        <listitem>
-	  <para>Runs an external process which does a
-	  <literal>make</literal> in the currentplatform's kernel
-	  build directory to create a new kernel</para>
-	</listitem>
-        <listitem>
-	  <para>Does <literal>(compile-ccl t)</literal> in the running
-	  lisp, to produce aset of fasl files from the &ldquo;higher
-	  level&rdquo; lisp sources.</para>
-	</listitem>
-        <listitem>
-	  <para>Does <literal>(xload-level-0 :force)</literal> in the
-	  running lisp, to compile thelisp sources in the
-	  &ldquo;ccl:level-0;&rdquo; directory into fasl files and
-	  then createa bootstrapping image from those fasl
-	  files.</para>
-	</listitem>
-        <listitem>
-	  <para>Runs another external process, which causes the newly
-	  compiled lispkernel to load the new bootstrapping image.
-	  The bootsrtrapping image then loadsthe &ldquo;higher
-	  level&rdquo; fasl files and a new copy of the platform's
-	  full heap imageis then saved.</para>
-	</listitem>
-      </itemizedlist>
-      <para>If all goes well, it'll all happen without user
-      intervention and with some simple progress messages.  If
-      anything goes wrong during execution of either of the external
-      processes, the process output is displayed as part of a lisp
-      error message.</para>
-      <para><literal>rebuild-ccl</literal> is essentially just a short
-      cut for running all the individual steps involved in rebuilding
-      the system.  You can also execute these steps individually, as
-      described below.</para>
-    </sect1>
-
-    <sect1 id="Building-the-kernel">
-      <title>Building the kernel</title>
-      <para>The Lisp kernel is the executable which you run to use
-      Lisp.  It doesn't actually contain the entire Lisp
-      implementation; rather, it loads a heap image which contains the
-      specifics - the "library", as it might be called if this was a C
-      program.  The kernel also provides runtime support to the heap
-      image, such as garbage collection, memory allocation, exception
-      handling, and the OS interface.</para>
-
-      <para>The Lisp kernel file has different names on different
-      platforms. See FIXTHIS . On all platforms the lisp kernel sources reside
-      in <literal>ccl/lisp-kernel</literal>.</para>
-
-      <para>This section gives directions on how to rebuild the Lisp
-      kernel from its source code.  Most OpenMCL users will rarely
-      have to do this.  You probably will only need to do it if you are
-      attempting to port OpenMCL to a new architecture or extend or enhance
-      its kernel in some way.  As mentioned above, this step happens
-      automatically when you do
-      <programlisting>
-? (rebuild-ccl :full t)
-      </programlisting>
-      </para>
-
-
-      <sect2 id="Kernel-build-prerequisites">
-        <title>Kernel build prerequisites</title>
-	<para>The OpenMCL kernel can be bult with the following widely
-	available tools:</para>
-        <itemizedlist>
-          <listitem><para>cc or gcc- the GNU C compiler</para></listitem>
-          <listitem><para>ld - the GNU linker</para></listitem>
-          <listitem><para>m4 or gm4- the GNU m4 macro processor</para></listitem>
-          <listitem><para>as - the GNU assembler (version 2.10.1 or later)</para></listitem>
-	  <listitem><para>make - either GNU make or, on FreeBSD, the default BSD make program</para></listitem>
-	</itemizedlist>
-	<para> In general, the more recent the versions of those
-	tools, the better; some versions of gcc 3.x on Linux have
-	difficulty compiling some of the kernel source code correctly
-	(so gcc 4.0 should be used, if possible.)  On OSX, the
-	versions of the tools distributed with XCode should work fine;
-	on Linux, the versions of the tools installed with the OS (or
-	available through its package management system) should work
-	fine if they're "recent enough".  On FreeBSD, the installed
-	version of the <literal>m4</literal> program doesn't support
-	some features that the kernel build process depends on; the
-	GNU version of the m4 macroprocessor (called
-	<literal>gm4</literal> on FreeBSD) should be installed
-
-	</para>
-      </sect2>
-      <sect2 id="kernel-build-command">
-	<title>Using "make" to build the lisp kernel</title>
-        <para>With those tools in place, do:
-        <programlisting>
-shell> cd ccl/lisp-kernel/<replaceable>PLATFORM</replaceable>
-shell> make
-	</programlisting>
-	</para>
-        <para>That'll assemble several assembly language source files,
-        compile several C source files, and link
-        ../../<replaceable>the kernel</replaceable>.
-	</para>
-      </sect2>
-    </sect1>
-    <sect1 id="Building-the-heap-image">
-      <title>Building the heap image</title>
-      <para>The initial heap image is loaded by the Lisp kernel, and
-      provides most all of the language implementation The heap image
-      captures the entire state of a running Lisp (except for external
-      resources, such as open files and TCP sockets).  After it is
-      loaded, the contents of the new Lisp process's memory are
-      exactly the same as those of the old Lisp process when the image
-      was created.</para>
-      <para>The heap image is how we get around the fact that we can't
-      run Lisp code until we have a working Lisp implementation, and
-      we can't make our Lisp implementation work until we can run Lisp
-      code.  Since the heap image already contains a fully-working
-      implementation, all we need to do is load it into memory and
-      start using it.</para>
-      <para>If you're building a new version of OpenMCL, you need to
-      build a new heap image.</para>
-      <para>(You might also wish to build a heap image if you have a
-      large program which it is very complicated or time-consuming to
-      load, so that you will be able to load it once, save an image,
-      and thenceforth never have to load it again. At any time, a heap
-      image capturing the entire memory state of a running Lisp can be
-      created by calling the function
-      <literal>ccl:save-application</literal>.)</para>
-
-      <sect2 id="Development-cycle">
-	<title>Development cycle</title>
-        <para>Creating a new OpenMCL full heap image consists of the
-        following steps:</para>
-        <orderedlist>
-          <listitem><para>Using your existing OpenMCL, create a
-          bootstrapping image</para></listitem>
-          <listitem><para>Using your existing OpenMCL, recompile your
-          updated OpenMCL sources</para></listitem>
-          <listitem><para>Invoke OpenMCL with the bootstrapping image
-          you just created (rather than with the existing full heap
-          image).</para></listitem>
-	</orderedlist>
-	<para>When you invoke OpenMCL with the bootstrapping image, it
-	will start up, load al of the OpenMCL fasl files, and save out
-	a new full heap image.  Voila.  You've created a new heap
-	image.</para>
-        <para>A few points worth noting:</para>
-	<itemizedlist>
-          <listitem>
-	    <para>There's a circular dependency between the full heap
-	    image and thebootstrapping image, in that each is used to
-	    build the other.</para>
-	  </listitem>
-          <listitem>
-	    <para>There are some minor implementation
-	    differences, but the environment in effect after the
-	    bootstrapping image has loaded its fasl files is essentially
-	    equivalent to the environment provided by the full heap
-	    image; the latter loads a lot faster and is easier to
-	    distribute, of course.</para>
-	  </listitem>
-          <listitem>
-	    <para>If the full heap image doesn't work (because
-	    of an OScompatibilty problem or other bug), it's very likely
-	    that thebootstrapping image will suffer the same
-	    problems.</para>
-	  </listitem>
-	</itemizedlist>
-        <para>Given a bootstrapping image and a set of up-to-date fasl
-        files, the development cycle usually involves editing lisp
-        sources (or updating those sources via cvs update),
-        recompiling modified files, and using the bootstrapping image
-        to produce a new heap image.</para>
-      </sect2>
-
-      <sect2 id="Generating-a-bootstrapping-image">
-        <title>Generating a bootstrapping image</title>
-        <para>The bootstrapping image isn't provided in OpenMCL
-        distributions. It can be built from the source code provided
-        in distributions (using a lisp image and kernel provided in
-        those distributions) using the procedure described
-        below.</para>
-
-        <para>The bootstrapping image is built by invoking a special
-        utility inside a running OpenMCL heap image to load files
-        contained in the <literal>ccl/level-0</literal> directory. The
-        bootstrapping image loads several dozen fasl files.  After
-        it's done so, it saves a heap image via
-        <literal>save-application</literal>. This process is called
-        "cross-dumping".</para>
-
-        <para>Given a source distribution, a lisp kernel, and aheap
-        image, one can produce a bootstapping image by first invoking
-        OpenMCL from the shell:</para>
-        <programlisting>
-shell&gt; openmcl
-Welcome to OpenMCL .... !
-?
-	</programlisting>
-	<para>then calling <literal>ccl:xload-level-0</literal> at the
-	lisp prompt</para>
-	<programlisting>
-? (ccl:xload-level-0)
-	</programlisting>
-        <para>This will compile the lisp sources in the ccl/level-0
-        directory if they're newer than the corresponding fasl files
-        and will then load the resulting fasl files into a simulated
-        lisp heap contained inside data structures inside the running
-        lisp. That simulated heap image is then written to
-        disk.</para>
-        <para><literal>xload-level-0</literal> should be called
-        whenever your existing boot image is out-of-date with respect
-        to the source files in <literal>ccl:level-0;</literal>
-        :</para>
-        <programlisting>
-? (ccl:xload-level-0 :force)
-</programlisting>
-        <para>will force recompilation of the level-0 sources.</para>
-      </sect2>
-
-      <sect2 id="Generating-fasl-files">
-        <title>Generating fasl files</title>
-	<para> Calling:</para>
-        <programlisting>
-? (ccl:compile-ccl)
-	</programlisting>
-	<para>at the lisp prompt will compile any fasl files that are
-	out-of-date with respect to the corresponding lisp sources;
-	<literal>(ccl:compile-ccl t)</literal> will force
-	recompilation. <literal>ccl:compile-ccl</literal> will reload
-	newly-compiled versions of some files;
-	<literal>ccl:xcompile-ccl</literal> is analogous, but skips
-	this reloading step.</para>
-        <para>Unless there are bootstrapping considerations involved,
-        it usually doesn't matter whether these files reloaded after
-        they're recompiled.</para>
-        <para>Calling <literal>compile-ccl</literal> or
-        <literal>xcompile-ccl</literal> in an environment where fasl
-        files don't yet exist may produce warnings to that effect
-        whenever files are <literal>require</literal>d during
-        compilation; those warnings can be safely ignored. Depending
-        on the maturity of the OpenMCL release, calling
-        <literal>compile-ccl</literal> or
-        <literal>xcompile-ccl</literal> may also produce several
-        warnings about undefined functions, etc. They should be
-        cleaned up at some point.</para>
-      </sect2>
-
-      <sect2 id="Building-a-full-image-from-a-bootstrapping-image">
-	<title>Building a full image from a bootstrapping image</title>
-	<para>To build a full image from a bootstrapping image, just
-	invoke the kernel with the bootstrapping image is an
-	argument</para>
-        <programlisting>
-$ cd ccl                        # wherever your ccl directory is
-$ ./KERNEL BOOT_IMAGE
-	</programlisting>
-        <para>Where <replaceable>KERNEL</replaceable> and
-        <replaceable>BOOT_IMAGE</replaceable> are the names of
-        the kernel and boot image appropriate to the platform you are
-        running on.  See FIXTHIS</para>
-        <para>That should load a few dozen fasl files (printing a
-        message as each file is loaded.) If all of these files
-        successfully load, the lisp will print a prompt. You should be
-        able to do essentially everything in that environment that you
-        can in the environment provided by a "real" heap image. If
-        you're confident that things loaded OK, you can save that
-        image.</para>
-        <programlisting>
-? (ccl:save-application "<replaceable>image_name</replaceable>") ; Overwiting the existing heap image
-	</programlisting>
-	<para>Where <replaceable>image_name</replaceable> is the name
-        of the full heap image for your platform. See FIXTHIS.</para>
-        <para>If things go wrong in the early stages of the loading
-        sequence, errors are often difficult to debug; until a fair
-        amount of code (CLOS, the CL condition system, streams, the
-        reader, the read-eval-print loop) is loaded, it's generally
-        not possible for the lisp to report an error.  Errors that
-        occur during these early stages ("the cold load") sometimes
-        cause the lisp kernel debugger (see ) to be invoked; it's
-        primitive, but can sometimes help one to get oriented.</para>
-      </sect2>
-    </sect1>
-  </chapter>
-
-  <chapter id="Questions-and-Answers">
-
-    <title>Questions and Answers</title>
-
-    <sect1 id="How-can-I-do-nonblocking--aka--unbuffered--and--raw---IO-">
-      <title>How can I do nonblocking (aka "unbuffered" and "raw") IO?</title>
-      <para>There's some code for manipulating TTY modes in
-      "ccl:library;pty.lisp".</para>
-      <programlisting>
-? (require "PTY")
-
-? (ccl::disable-tty-local-modes 0 #$ICANON)
-T
-      </programlisting>
-      <para>will turn off "input canonicalization" on file descriptor
-      0, which is at least part of what you need to do here.  This
-      disables the #$ICANON mode, which tells the OS not to do any
-      line-buffering or line-editing.  Of course, this only has any
-      effect in situations where the OS ever does that, which means
-      when stdin is a TTY or PTY.</para>
-      <para>If the #$ICANON mode is disabled, you can do things like:</para>
-      <programlisting>
-? (progn (read-char) (read-char))
-a
-#\a
-      </programlisting>
-      <para>(where the first READ-CHAR consumes the newline, which
-      isn't really necessary to make the reader happy anymore.)  So,
-      you can do:</para>
-      <programlisting>
-? (read-char)
-#\Space
-</programlisting>
-      <para>(where there's a space after the close-paren) without
-      having to type a newline.</para>
-    </sect1>
-
-    <sect1 id="I-m-using-the-graphics-demos--Why-doesn-t-the-menubar-change-">
-      <title>I'm using the graphics demos. Why doesn't the menubar
-      change?</title>
-      <para>When you interact with text-only OpenMCL, you're either
-      in Terminal or in Emacs, running OpenMCL as a subprocess.  When
-      you load Cocoa or the graphical environment, the subprocess does
-      some tricky things that turn it into a full-fledged Application,
-      as far as the OS is concerned.</para>
-      <para>So, it gets its own icon in the dock, and its own menubar,
-      and so on.  It can be confusing, because standard input and
-      output will still be connected to Terminal or Emacs, so you can
-      still type commands to OpenMCL from there.  To see the menubar
-      you loaded, or the windows you opened, just click on the OpenMCL
-      icon in the dock.</para>
-    </sect1>
-
-    <sect1 id="I-m-using-Slime-and-Cocoa--Why-doesn-t--standard-output--seem-to-work-">
-      <title>I'm using Slime and Cocoa. Why doesn't *standard-output*
-      seem to work? </title>
-      <para>This comes up if you're using the Slime interface
-      to run OpenMCL under Emacs, and you are doing Cocoa programming
-      which involves printing to *standard-output*.  It seems as
-      though the output goes nowhere; no error is reported, but it
-      doesn't appear in the *slime-repl* buffer.</para>
-
-      <para>For the most part, this is only relevant when you are
-      trying to insert debug code into your event handlers.  The SLIME
-      listener runs in a thread where the standard stream varaiables
-      (like <literal>*STANDARD-OUTPUT* and</literal> and
-      <literal>*TERMINAL-IO*</literal> are bound to the stream used to
-      communicate with Emacs; the Cocoa event thread has its own
-      bindings of these standard stream variables, and output to these
-      streams goes to the *inferior-lisp* buffer instead.  Look for it
-      there.</para>
-    </sect1>
-  </chapter>
-
-  <chapter id="Programming-with-Threads">
-    <title>Programming with Threads</title>
-
-    <sect1 id="Threads-overview">
-      <title>Threads Overview</title>
-
-      <para>OpenMCL provides facilities which enable multiple threads
-      of execution (<emphasis>threads</emphasis>, sometimes called
-      <emphasis>lightweight processes</emphasis> or just
-      <emphasis>processes</emphasis>, though the latter term shouldn't
-      be confused with the OS's notion of a process) within a lisp
-      session. This document describes those facilities and issues
-      related to multitheaded programming in OpenMCL.</para>
-
-      <para>Wherever possible, I'll try to use the term "thread" to
-      denote a lisp thread, even though many of the functions in the
-      API have the word "process" in their name. A
-      <emphasis>lisp-process</emphasis> is a lisp object (of type
-      CCL:PROCESS) which is used to control and communicate with an
-      underlying <emphasis>native thread</emphasis>. Sometimes, the
-      distinction between these two (quite different) objects can be
-      blurred; other times, it's important to maintain.</para>
-      <para>Lisp threads share the same address space, but maintain
-      their own execution context (stacks and registers) and their own
-      dynamic binding context.</para>
-      
-      <para>Traditionally, OpenMCL's threads have been
-      <emphasis>cooperatively scheduled</emphasis>: through a
-      combination of compiler and runtime suppport, the currently
-      executing lisp thread arranged to be interrrupted at certain
-      discrete points in its execution (typically on entry to a
-      function and at the beginning of any looping construct). This
-      interrupt occurred several dozen times per second; in response,
-      a handler function might observe that the current thread had
-      used up its time slice and another function (<emphasis>the lisp
-      scheduler</emphasis>) would be called to find some other thread
-      that was in a runnable state, suspend execution of the current
-      thread, and resume execution of the newly executed thread.  The
-      process of switching contexts between the outgoing and incoming
-      threads happened in some mixture of Lisp and assembly language
-      code; as far as the OS was concerned, there was one native
-      thread running in the Lisp image and its stack pointer and other
-      registers just happened to change from time to time.</para>
-      <para>Under OpenMCL's cooperative scheduling model, it was
-      possible (via the use of the CCL:WITHOUT-INTERRUPTS construct)
-      to defer handling of the periodic interrupt that invoked the
-      lisp scheduler; it was not uncommon to use WITHOUT-INTERRUPTS to
-      gain safe, exclusive access to global data structures. In some
-      code (including much of OpenMCL itself) this idiom was very
-      common: it was (justifiably) believed to be an efficient way of
-      inhibiting the execution of other threads for a short period of
-      time.</para>
-
-      <para>The timer interrupt that drove the cooperative scheduler
-      was only able to (pseudo-)preempt lisp code: if any thread
-      called a blocking OS I/O function, no other thread could be
-      scheduled until that thread resumed execution of lisp code. Lisp
-      library functions were generally attuned to this constraint, and
-      did a complicated mixture of polling and "timed blocking" in an
-      attempt to work around it. Needless to say, this code is
-      complicated and less efficient than it might be; it meant that
-      the lisp was a little busier than it should have been when it
-      was "doing nothing" (waiting for I/O to be possible.)</para>
-
-      <para>For a variety of reasons - better utilization of CPU
-      resources on single and multiprocessor systems and better
-      integration with the OS in general - threads in OpenMCL 0.14 and
-      later are <emphasis>preemptively scheduled. </emphasis>In this
-      model, lisp threads are native threads and all scheduling
-      decisions involving them are made by the OS kernel. (Those
-      decisions might involve scheduling multiple lisp threads
-      simultaneously on multiple processors on SMP systems.) This
-      change has a number of subtle effects:</para>
-
-      <itemizedlist>
-        <listitem>
-	  <para>it is possible for two (or more) lisp threads to be
-	  executingsimultaneously, possibly trying to access and/or
-	  modify the same datastructures. Such access really should
-	  have been coordinated throughthe use of synchronization
-	  objects regardless of the scheduling modelin effect;
-	  preemptively scheduled threads increase the chance ofthings
-	  going wrong at the wrong time and do not offer
-	  lightweightalternatives to the use of those synchronization
-	  objects.</para>
-	</listitem>
-        <listitem>
-	  <para>even on a single-processor system, a context switch
-	  can happenon any instruction boundary. Since (in general)
-	  other threads mightallocate memory, this means that a GC can
-	  effectively take place atany instruction boundary. That's
-	  mostly an issue for the compilerand runtime system to be
-	  aware of, but it means that certain practices(such as trying
-	  to pass the address of a lisp object to foreign code)that
-	  were always discouraged are now discouraged
-	  ... vehemently.</para>
-	</listitem>
-        <listitem>
-	  <para>there is no simple and efficient way to "inhibit the
-	  scheduler"or otherwise gain exclusive access to the entire
-	  CPU.</para>
-	</listitem>
-        <listitem>
-	  <para>There are a variety of simple and efficient ways
-	  tosynchronize access to particular data
-	  structures.</para>
-	</listitem>
-      </itemizedlist>
-      <para>As a broad generalization: code that's been aggressively
-      tuned to the constraints of the cooperative scheduler may need
-      to be redesigned to work well with the preemptive scheduler (and
-      code written to run under OpenMCL's interface to the native
-      scheduler may be less portable to other CL implementations, many
-      of which offer a cooperative scheduler and an API similar to
-      OpenMCL (&lt; 0.14) 's.) At the same time, there's a large
-      overlap in functionality in the two scheduling models, and it'll
-      hopefully be possible to write interesting and useful MP code
-      that's largely independent of the underlying scheduling
-      details.</para>
-      <para>The keyword :OPENMCL-NATIVE-THREADS is on *FEATURES* in
-      0.14 and later and can be used for conditionalization where
-      required.</para>
-    </sect1>
-
-    <sect1 id="Intentionally--Missing-Functionality">
-      <title>(Intentionally) Missing Functionality</title>
-      <para>Much of the functionality described above is similar to
-      that provided by OpenMCL's cooperative scheduler, some other
-      parts of which make no sense in a native threads
-      implementation.</para>
-      <itemizedlist>
-        <listitem>
-	  <para>PROCESS-RUN-REASONS and PROCESS-ARREST-REASONS were
-	  SETFable process attributes; each was just a list of
-	  arbitrary tokens. A thread was eligible for scheduling
-	  (roughly equivalent to being "enabled") if its arrest-reasons
-	  list was empty and its run-reasons list was not. I don't
-	  think that it's appropriate to encourage a programming style
-	  in which otherwise runnable threads are enabled and disabled
-	  on a regular basis (it's preferable for threads to wait for
-	  some sort of synchronization event to occur if they can't
-	  occupy their time productively.)</para>
-	</listitem>
-        <listitem>
-	  <para>There were a number of primitives for maintaining
-	  process queues;that's now the OS's job.</para>
-	</listitem>
-        <listitem>
-	  <para>Cooperative threads were based on coroutining
-	  primitivesassociated with objects of type
-	  STACK-GROUP. STACK-GROUPs no longerexist.</para>
-	</listitem>
-      </itemizedlist>
-    </sect1>
-
-    <sect1 id="Implementation-Decisions-and-Open-Questions">
-      <title>Implementation Decisions and Open Questions</title>
-      <para> As of August 2003:</para>
-      <itemizedlist>
-        <listitem>
-	  <para>It's not clear that exposing
-	  PROCESS-SUSPEND/PROCESS-RESUME is a good idea: it's not clear
-	  that they offer ways to win, and it's clear that they offer
-	  ways to lose.</para>
-	</listitem>
-        <listitem>
-	  <para>It has traditionally been possible to reset and enable
-	  a process that's "exhausted" . (As used here, the
-	  term"exhausted" means that the process's initial function
-	  hasrun and returned and the underlying native thread has
-	  beendeallocated.) One of the principle uses of PROCESS-RESET
-	  is to "recycle" threads; enabling an exhausted process
-	  involves creating a new native thread (and stacks and
-	  synchronization objects and ...),and this is the sort of
-	  overhead that such a recycling scheme is seeking to avoid. It
-	  might be worth trying to tighten things up and declare that
-	  it's an error to apply PROCESS-ENABLE to an exhausted thread
-	  (and to make PROCESS-ENABLE detect this error.)</para>
-	</listitem>
-        <listitem>
-	  <para>When native threads that aren't created by OpenMCL
-	  first call into lisp, a "foreign process" is created, and
-	  that process is given its own set of initial bindings and set
-	  up to look mostly like a process that had been created by
-	  MAKE-PROCESS. The life cycle of a foreign process is
-	  certainly different from that of a lisp-created one: it
-	  doesn't make sense to reset/preset/enable a foreign process,
-	  and attempts to perform these operations should be
-	  detectedand treated as errors.</para>
-	</listitem>
-      </itemizedlist>
-    </sect1>
-
-    <sect1 id="Porting-Code-from-the-Old-Thread-Model">
-      <title>Porting Code from the Old Thread Model</title>
-      <para>Older versions of OpenMCL used what are often called
-      "user-mode threads", a less versatile threading model which does
-      not require specific support from the operating system.  This
-      section discusses how to port code which was written for that
-      mode.</para>
-      <para>It's hard to give step-by-step instructions; there are certainly
-      a few things that one should look at carefully:</para>
-      <itemizedlist>
-        <listitem>
-	  <para>It's wise to be suspicious of most uses
-	  of WITHOUT-INTERRUPTS; there may be exceptions, but
-	  WITHOUT-INTERRUPTS is often used as shorthand for
-	  WITH-APPROPRIATE-LOCKING. Determining what type of locking
-	  is appropriate and writing the code to implement it is
-	  likely to be straightforward and simple most of the
-	  time.</para>
-	</listitem>
-        <listitem>
-	  <para>I've only seen one case where a process's "run reasons"
-	  were used to communicate information as well as tocontrol
-	  execution; I don't think that this is a common idiom, but may
-	  be mistaken about that.
-	  </para>
-	</listitem>
-        <listitem>
-	  <para>It's certainly possible that programs written
-	  for cooperatively scheduled lisps that have run reliably for
-	  a long timehave done so by accident: resource-contention
-	  issues tend to be timing-sensitive, and decoupling thread
-	  scheduling from lisp program execution affects timing. I know
-	  that there is or was code in both OpenMCL and commercial MCL
-	  that was written under the explicit assumption that certain
-	  sequences of open-coded operations were uninterruptable; it's
-	  certainly possible that the same assumptions have been made
-	  (explicitly or otherwise) by application developers.</para>
-	</listitem>
-      </itemizedlist>
-    </sect1>
-
-    <sect1 id="Background-Terminal-Input">
-      <title>Background Terminal Input</title>
-
-      <sect2 id="backgrount-ti-overview">
-        <title>Overview</title>
-	<para>
-	  Unless and until OpenMCL provides alternatives (via window
-	  streams, telnet streams, or some other mechanism) all lisp
-	  processes share a common *TERMINAL-IO* stream (and therefore
-	  share *DEBUG-IO*, *QUERY-IO*, and other standard and
-	  internal interactive streams.)</para>
-	  <para>It's anticipated that most lisp processes other than
-	  the "Initial" process run mostly in the background. If a
-	  background process writes to the output side of
-	  *TERMINAL-IO*, that may be a little messy and a little
-	  confusing to the user, but it shouldn't really be
-	  catastrophic. All I/O to OpenMCL's buffered streams goes
-	  thru a locking mechanism that prevents the worst kinds of
-	  resource-contention problems.</para>
-	  <para>Although the problems associated with terminal output
-	  from multiple processes may be mostly cosmetic, the question
-	  of which process receives input from the terminal is likely
-	  to be a great deal more important. The stream locking
-	  mechanisms can make a confusing situation even worse:
-	  competing processes may "steal" terminal input from each
-	  other unless locks are held longer than they otherwise need
-	  to be, and locks can be held longer than they need to be (as
-	  when a process is merely waiting for input to become
-	  available on an underlying file descriptor).</para>
-	  <para>Even if background processes rarely need to
-	  intentionally read input from the terminal, they may still
-	  need to do so in response to errors or other unanticipated
-	  situations. There are tradeoffs involved in any solution to
-	  this problem. The protocol described below allows background
-	  processes which follow it to reliably prompt for and receive
-	  terminal input. Background processes which attempt to
-	  receive terminal input without following this protocol will
-	  likely hang indefinitely while attempting to do so. That's
-	  certainly a harsh tradeoff, but since attempts to read
-	  terminal input without following this protocol only worked
-	  some of the time anyway, it doesn't seem to be an
-	  unreasonable one.</para>
-	  <para>In the solution described here (and introduced in
-	  OpenMCL 0.9), the internal stream used to provide terminal
-	  input is always locked by some process (the "owning"
-	  process.) The initial process (the process that typically
-	  runs the read-eval-print loop) owns that stream when it's
-	  first created. By using the macro WITH-TERMINAL-INPUT,
-	  background processes can temporarily obtain ownership of the
-	  terminal and relinquish ownership to the previous owner when
-	  they're done with it.</para>
-	  <para>In OpenMCL, BREAK, ERROR, CERROR, Y-OR-N-P,
-	  YES-OR-NO-P, and CCL:GET-STRING- FROM-USER are all defined
-	  in terms of WITH-TERMINAL-INPUT, as are the :TTY
-	  user-interfaces to STEP and INSPECT.</para>
-      </sect2>
-
-      <sect2 id="background-terminal-example">
-        <title>An example</title>
-        <programlisting>
-? Welcome to OpenMCL Version (Beta: linux) 0.9!
-?
-
-? (process-run-function "sleeper" #'(lambda () (sleep 5) (break "broken")))
-#&lt;PROCESS sleeper(1) [Enabled] #x3063B33E&gt;
-
-?
-;;
-;; Process sleeper(1) needs access to terminal input.
-;;
-</programlisting>
-        <para>This example was run under ILISP; ILISP often gets confused if one
-	tries to enter input and "point" doesn't follow a prompt.
-	Entering a "simple" expression at this point gets it back in
-	synch; that's otherwise not relevant to this example.</para>
-	<programlisting>
-()
-NIL
-? (:y 1)
-;;
-;; process sleeper(1) now controls terminal input
-;;
-> Break in process sleeper(1): broken
-> While executing: #&lt;Anonymous Function #x3063B276&gt;
-> Type :GO to continue, :POP to abort.
-> If continued: Return from BREAK.
-Type :? for other options.
-1 &gt; :b
-(30C38E30) : 0 "Anonymous Function #x3063B276" 52
-(30C38E40) : 1 "Anonymous Function #x304984A6" 376
-(30C38E90) : 2 "RUN-PROCESS-INITIAL-FORM" 340
-(30C38EE0) : 3 "%RUN-STACK-GROUP-FUNCTION" 768
-1 &gt; :pop
-;;
-;; control of terminal input restored to process Initial(0)
-;;
-?
-</programlisting>
-      </sect2>
-
-      <sect2 id="A-more-elaborate-example-">
-        <title>A more elaborate example.</title>
-	<para>If a background process ("A") needs access to the terminal
-	input stream and that stream is owned by another background process
-	("B"), process "A" announces that fact, then waits until
-	the initial process regains control.</para>
-	<programlisting>
-? Welcome to OpenMCL Version (Beta: linux) 0.9!
-?
-
-? (process-run-function "sleep-60" #'(lambda () (sleep 60) (break "Huh?")))
-#&lt;PROCESS sleep-60(1) [Enabled] #x3063BF26&gt;
-
-? (process-run-function "sleep-5" #'(lambda () (sleep 5) (break "quicker")))
-#&lt;PROCESS sleep-5(2) [Enabled] #x3063D0A6&gt;
-
-? ;;
-;; Process sleep-5(2) needs access to terminal input.
-;;
-()
-NIL
-
-? (:y 2)
-;;
-;; process sleep-5(2) now controls terminal input
-;;
-> Break in process sleep-5(2): quicker
-> While executing: #x3063CFDE>
-> Type :GO to continue, :POP to abort.
-> If continued: Return from BREAK.
-Type :? for other options.
-1 > ;; Process sleep-60(1) will need terminal access when
-;; the initial process regains control of it.
-;;
-()
-NIL
-1 > :pop
-;;
-;; Process sleep-60(1) needs access to terminal input.
-;;
-;;
-;; control of terminal input restored to process Initial(0)
-;;
-
-? (:y 1)
-;;
-;; process sleep-60(1) now controls terminal input
-;;
-> Break in process sleep-60(1): Huh?
-> While executing: #x3063BE5E>
-> Type :GO to continue, :POP to abort.
-> If continued: Return from BREAK.
-Type :? for other options.
-1 > :pop
-;;
-;; control of terminal input restored to process Initial(0)
-;;
-
-?
-</programlisting>
-      </sect2>
-
-      <sect2 id="Summary">
-	<title>Summary</title>
-	<para>This scheme is certainly not bulletproof: imaginative
-	use of PROCESS-INTERRUPT and similar functions might be able
-	to defeat it and deadlock the lisp, and any scenario where
-	several background processes are clamoring for access to the
-	shared terminal input stream at the same time is likely to be
-	confusing and chaotic. (An alternate scheme, where the input
-	focus was magically granted to whatever thread the user was
-	thinking about, was considered and rejected due to technical
-	limitations.)</para>
-	<para>The longer-term fix would probably involve using network or
-	window-system streams to give each process unique instances of
-	*TERMINAL-IO*.</para>
-        <para>Existing code that attempts to read from *TERMINAL-IO*
-        from a background process will need to be changed to use
-        WITH-TERMINAL-INPUT.  Since that code was probably not working
-        reliably in previous versions of OpenMCL, this requirement
-        doesn't seem to be too onerous.</para>
-        <para>Note that WITH-TERMINAL-INPUT both requests ownership of
-        the terminal input stream and promises to restore that
-        ownership to the initial process when it's done with it. An ad
-        hoc use of READ or READ-CHAR doesn't make this promise; this
-        is the rationale for the restriction on the :Y command.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="The-Threads-which-OpenMCL-Uses-for-Its-Own-Purposes">
-      <title>The Threads which OpenMCL Uses for Its Own Purposes</title>
-      <para>
-In the "tty world", OpenMCL starts out with 2 lisp-level threads:</para>
-      <programlisting>
-? :proc
-1 : -> listener     [Active]
-0 :    Initial      [Active]
-</programlisting>
-      <para>If you look at a running OpenMCL with a debugging tool,
-      such as GDB, or Apple's Thread Viewer.app, you'll see an
-      additional kernel-level thread on Darwin; this is used by the
-      Mach exception-handling mechanism.</para>
-      <para>The initial thread, conveniently named "initial", is the
-      one that was created by the operating system when it launched
-      OpenMCL.  It maps the heap image into memory, does some
-      Lisp-level initialization, and, when the Cocoa IDE isn't being
-      used, creates the thread "listener", which runs the top-level
-      loop that reads input, evaluates it, and prints the
-      result.</para>
-      <para>After the listener thread is created, the initial thread
-      does "housekeeping": it sits in a loop, sleeping most of the
-      time and waking up occasionally to do "periodic tasks".  These
-      tasks include forcing output on specified interactive streams,
-      checking for and handling control-C interrupts, etc.  Currently,
-      those tasks also include polling for the exit status of external
-      processes and handling some kinds of I/O to and from those
-      processes.</para>
-      <para>In this environment, the initial thread does these
-      "housekeeping" activities as necessary, until
-      <literal>ccl:quit</literal> is called;
-      <literal>quit</literal>ting interrupts the initial thread, which
-      then ends all other threads in as orderly a fashion as possible
-      and calls the C function <literal>#_exit</literal>.</para>
-      <para>The short-term plan is to handle each external-process in
-      a dedicated thread; the worst-case behavior of the current
-      scheme can involve busy-waiting and excessive CPU utilization
-      while waiting for an external process to terminate in some
-      cases.</para>
-      <para>The Cocoa features use more threads.  Adding a Cocoa
-      listener creates two threads:</para>
-      <programlisting>
-? :proc
-3 : -> Listener     [Active]
-2 :    housekeeping  [Active]
-1 :    listener     [Active]
-0 :    Initial      [Active]
-      </programlisting>
-      <para>The Cocoa event loop has to run in the initial thread;
-      when the event loop starts up, it creates a new thread to do the
-      "housekeeping" tasks which the initial thread would do in the
-      terminal-only mode.  The initial thread then becomes the one to
-      receive all Cocoa events from the window server; it's the only
-      thread which can.</para>
-      <para>It also creates one "Listener" (capital-L) thread for each
-      listener window, with a lifetime that lasts as long as the
-      thread does.  So, if you open a second listener, you'll see five
-      threads all together:</para>
-      <programlisting>
-? :proc
-4 : -> Listener-2   [Active]
-3 :    Listener     [Active]
-2 :    housekeeping  [Active]
-1 :    listener     [Active]
-0 :    Initial      [Active]
-</programlisting>
-      <para>Unix signals, such as SIGINT (control-C), invoke a handler
-      installed by the Lisp kernel.  Although the OS doesn't make any
-      specific guarantee about which thread will receive the signal,
-      in practice, it seems to be the initial thread.  The handler
-      just sets a flag and returns; the housekeeping thread (which may
-      be the initial thread, if Cocoa's not being used) will check for
-      the flag and take whatever action is appropriate to the
-      signal.</para>
-      <para>In the case of SIGINT, the action is to enter a break
-      loop, by calling on the thread being interrupted.  When there's
-      more than one Lisp listener active, it's not always clear what
-      thread that should be, since it really depends on the user's
-      intentions, which there's no way to divine programmatically.  To
-      make its best guess, the handler first checks whether the value
-      of <literal>ccl:*interactive-abort-process*</literal> is a
-      thread, and, if so, uses it.  If that fails, it chooses the
-      thread which currently "owns" the default terminal input stream;
-      see .</para>
-      <para>In the bleeding-edge version of the Cocoa support which is
-      based on Hemlock, an Emacs-like editor, each editor window has a
-      dedicated thread associated with it.  When a keypress event
-      comes in which affects that specific window the initial thread
-      sends it to the window's dedicated thread.  The dedicated thread
-      is responsible for trying to interpret keypresses as Hemlock
-      commands, applying those commands to the active buffer; it
-      repeats this in a loop, until the window closes.  The initial
-      thread handles all other events, such as mouse clicks and
-      drags.</para>
-      <para>This thread-per-window scheme makes many things simpler,
-      including the process of entering a "recursive command loop" in
-      commands like "Incremental Search Forward", etc.  (It might be
-      possible to handle all Hemlock commands in the Cocoa event
-      thread, but these "recursive command loops" would have to
-      maintain a lot of context/state information; threads are a
-      straightforward way of maintaining that information.)</para>
-      <para>Currently (August 2004), when a dedicated thread needs to
-      alter the contents of the buffer or the selection, it does so by
-      invoking methods in the initial thread, for synchronization
-      purposes, but this is probably overkill and will likely be
-      replaced by a more efficient scheme in the future.</para>
-      <para>The per-window thread could probably take more
-      responsibility for drawing and handling the screen than it
-      currently does; -something- needs to be done to buffer screen
-      updates a bit better in some cases: you don't need to see
-      everything that happens during something like indentation; you
-      do need to see the results...</para>
-      <para>When Hemlock is being used, listener windows are editor
-      windows, so in addition to each "Listener" thread, you should
-      also see a thread which handles Hemlock command
-      processing.</para>
-      <para>The Cocoa runtime may make additional threads in certain
-      special situations; these threads usually don't run lisp code,
-      and rarely if ever run much of it.</para>
-    </sect1>
-
-    <sect1 id="Threads-Dictionary">
-      <title>Threads Dictionary</title>
-      <refentry id="f_all-processes">
-	<indexterm zone="f_all-processes">
-	  <primary>all-processes</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>ALL-PROCESSES</refname>
-	  <refpurpose>Obtain a fresh list of all known Lisp
-	  threads.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>all-processes</function> => result
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>a list of all lisp processes (threads)
-		known to OpenMCL.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns a list of all lisp processes (threads) known
-	  to OpenMCL as of
-	  the precise instant it&#39;s called. It&#39;s safe to traverse
-	  this list and to modify the cons cells that comprise that list
-	  (it&#39;s freshly consed.) Since other threads can create and kill
-	  threads at any time, there&#39;s generally no way to get an
-	  &#34;accurate&#34; list of all threads, and (generally) no
-	  sense in which such a list can be accurate.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="v_current-process"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_make-process">
-	<indexterm zone="f_make-process">
-	  <primary>make-process</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>MAKE-PROCESS</refname>
-	  <refpurpose>Creates and returns a new process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>make-process</function>
-	    name &key;
-	    persistent priority class stack-size vstack-size
-	    tstack-size initial-bindings use-standard-initial-bindings
-	    => process
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-	      
-	      <listitem>
-		<para>a string, used to identify the process.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>persistent</term>
-	      
-	      <listitem>
-		<para>if true, requests that information about the process
-		be retained by SAVE-APPLICATION so that an equivalent
-		process can be restarted when a saved image is run.  The
-		default is nil.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>priority</term>
-	      
-	      <listitem>
-		<para>ignored.  It
-		shouldn't be ignored of course, but there are
-		complications on some platforms.  The default is 0.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>class</term>
-	      
-	      <listitem>
-		<para>the class of process object to create;
-		should be a subclass of CCL:PROCESS.  The default is
-		CCL:PROCESS.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>stack-size</term>
-	      
-	      <listitem>
-		<para>the size, in bytes, of the newly-created process's
-		control stack; used for foreign function calls and to save
-		function return address context.  The default is
-		CCL:*DEFAULT-CONTROL-STACK-SIZE*.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>vstack-size</term>
-	      
-	      <listitem>
-		<para>the size, in bytes, of the newly-created process's
-		value stack; used for lisp function arguments, local
-		variables, and other stack-allocated lisp objects.
-		The default is CCL:*DEFAULT-VALUE-STACK-SIZE*.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>tstack-size</term>
-	      
-	      <listitem>
-		<para>the size, in bytes, of the newly-created process's
-		temp stack; used for the allocation of dynamic-extent
-		objects.  The default is CCL:*DEFAULT-TEMP-STACK-SIZE*.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>use-standard-initial-bindings</term>
-	      
-	      <listitem>
-		<para>when true, the global "standard initial
-		bindings" are put into effect in the new thread before. See
-		DEF-STANDARD-INITIAL-BINDING.  "standard" initial bindings
-		are put into effect before any bindings specified by
-		:initial-bindings are.  The default is t.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>initial-bindings</term>
-	      
-	      <listitem>
-		<para>an alist of (<varname>symbol</varname> .
-		<varname>valueform</varname>) pairs, which can be
-		used to initialize special variable bindings in the new
-		thread. Each <varname>valueform</varname> is used to
-		compute the value of a new binding of
-		<varname>symbol</varname> in the execution environment of
-		the newly-created thread.  The default is nil.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>process</term>
-	      
-	      <listitem>
-		<para>the newly-created process.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates and returns a new lisp process (thread) with the
-	  specified attributes. <varname>process</varname> will not begin
-	  execution immediately; it will need to be
-	  <emphasis>preset</emphasis> (given
-	  an initial function to run, as by
-	  <xref linkend="f_process-preset"/>) and
-	  <emphasis>enabled</emphasis>
-	  (allowed to execute, as by <xref linkend="f_process-enable"/>)
-	  before it&#39;s able to actually do anything.</para>
-
-	  <para>If <varname>valueform</varname> is a function, it is
-	  called, with no arguments, in the execution environment of the
-	  newly-created thread; the primary value it returns is used for
-	  the binding of the corresponding <varname>symbol</varname>.</para>
-
-	  <para>Otherwise, <varname>valueform</varname> is evaluated in the
-	  execution
-	  environment of the newly-created thread, and the resulting value
-	  is used.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-preset"/></member>
-	    <member><xref linkend="f_process-enable"/></member>
-	    <member><xref linkend="f_process-run-function"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-suspend">
-	<indexterm zone="f_process-suspend">
-	  <primary>process-suspend</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-SUSPEND</refname>
-	  <refpurpose>Suspends a specified process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-	
-	<refsynopsisdiv>
-	  <synopsis><function>process-suspend</function> process
-	  => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>T if <varname>process</varname> had been runnable
-		and is now suspended; NIL otherwise.  That is, T if
-		<varname>process</varname>'s
-		<xref linkend="f_process-suspend-count"/>
-		transitioned from 0 to 1.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Suspends <varname>process</varname>, preventing it from
-	  running, and stopping it if it was already running. This is a fairly
-	  expensive operation, because it involves a few
-	  calls to the OS.  It also risks creating deadlock if used
-	  improperly, for instance, if the process being suspended owns a
-	  lock or other resource which another process will wait for.</para>
-
-	  <para>
-	  Each
-	  call to <function>process-suspend</function> must be reversed by
-	  a matching call to <xref linkend="f_process-resume"/>
-	  before <varname>process</varname> is able to run.  What
-	  <function>process-suspend</function> actually does is increment
-	  the <xref linkend="f_process-suspend-count"/> of
-	  <varname>process</varname>.
-	  </para>
-
-	  <para>A process can suspend itself; it it&#39;s successful in doing
-	  so, then it can obviously only be resumed by some other
-	  process.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-resume"/></member>
-	    <member><xref linkend="f_process-suspend-count"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-	  <para><function>process-suspend</function> was previously called
-	  <function>process-disable</function>.
-	  <xref linkend="f_process-enable"/>
-	  now names a function for which there is no
-	  obvious inverse, so <function>process-disable</function>
-	  is no longer
-	  defined.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-resume">
-	<indexterm zone="f_process-resume">
-	  <primary>process-resume</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-RESUME</refname>
-	  <refpurpose>Resumes a specified process which had previously
-	  been suspended by process-suspend.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-resume</function> process
-	  => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>T if <varname>process</varname> had been suspended
-		and is now runnable; NIL otherwise.  That is, T if
-		<varname>process</varname>'s
-		<xref linkend="f_process-suspend-count"/>
-		transitioned from  to 0.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Undoes the effect of a previous call to
-	  <xref linkend="f_process-suspend"/>; if
-	  all such calls are undone, makes the process runnable. Has no
-	  effect if the process is not suspended.  What
-	  <function>process-resume</function> actually does is decrement
-	  the <xref linkend="f_process-suspend-count"/> of
-	  <varname>process</varname>, to a minimum of 0.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-suspend"/></member>
-	    <member><xref linkend="f_process-suspend-count"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>
-	    This was previously called PROCESS-ENABLE;
-	    <xref linkend="f_process-enable"/> now does something slightly
-	    different.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-suspend-count">
-	<indexterm zone="f_process-suspend-count">
-	  <primary>process-suspend-count</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-SUSPEND-COUNT</refname>
-	  <refpurpose>Returns the number of currently-pending suspensions
-	  applicable to a given process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>process-suspend-count</function>
-	    process => result
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>The number of "outstanding"
-		<xref linkend="f_process-suspend"/> calls on
-		<varname>process</varname>, or NIL if
-		<varname>process</varname> has expired.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>An "outstanding" <xref linkend="f_process-suspend"/> call
-	  is one which has not yet been reversed by a call to
-	  <xref linkend="f_process-resume"/>.  A process expires when
-	  its initial function returns, although it may later be
-	  reset.</para>
-
-	  <para>A process is <emphasis>runnable</emphasis> when it has a
-	  <function>process-suspend-count</function> of 0, has been
-	  preset as by <xref linkend="f_process-preset"/>, and has been
-	  enabled as by <xref linkend="f_process-enable"/>.  Newly-created
-	  processes have a <function>process-suspend-count</function> of
-	  0.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-suspend"/></member>
-	    <member><xref linkend="f_process-resume"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-preset">
-	<indexterm zone="f_process-preset">
-	  <primary>process-preset</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-PRESET</refname>
-	  <refpurpose>Sets the initial function and arguments of a specified
-	  process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-preset</function>
-	  process function &rest; args
-	  => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>function</term>
-	      <listitem>
-		<para>a function, designated by itself or by a symbol
-		which names it.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>args</term>
-	      <listitem>
-		<para>a list of values, appropriate as arguments to
-		<varname>function</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>undefined.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Typically used to initialize a newly-created or newly-reset
-	  process, setting things up so that when <varname>process</varname>
-	  becomes enabled, it will begin execution by
-	  applying <varname>function</varname> to <varname>args</varname>.
-	  <function>process-preset</function> does not enable
-	  <varname>process</varname>,
-	  although a process must be <function>process-preset</function>
-	  before it can be enabled.  Processes are normally enabled by
-	  <xref linkend="f_process-enable"/>.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-process"/></member>
-	    <member><xref linkend="f_process-enable"/></member>
-	    <member><xref linkend="f_process-run-function"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-enable">
-	<indexterm zone="f_process-enable">
-	  <primary>process-enable</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-ENABLE</refname>
-	  <refpurpose>Begins executing the initial function of a specified
-	  process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-enable</function>
-	  process &optional; timeout
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>timeout</term>
-	      <listitem>
-		<para>a time interval in seconds.  May be any
-		non-negative real number the <function>floor</function> of
-		which fits in 32 bits.  The default is 1.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>undefined.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to begin the execution of <varname>process</varname>.
-	  An error is signaled if <varname>process</varname> has never
-	  been <xref linkend="f_process-preset"/>.  Otherwise,
-	  <varname>process</varname> invokes its initial function.
-	  </para>
-	  
-	  <para><function>process-enable</function> attempts to
-	  synchronize with <varname>process</varname>, which is presumed
-	  to be reset or in the act of resetting itself.  If this attempt
-	  is not successful within the time interval specified by
-	  <varname>timeout</varname>, a continuable error is signaled,
-	  which offers the opportunity to continue waiting.
-	  </para>
-
-	  <para>A process cannot meaningfully attempt to enable itself.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-process"/></member>
-	    <member><xref linkend="f_process-preset"/></member>
-	    <member><xref linkend="f_process-run-function"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>It would be nice to have more discussion of what it means
-	  to synchronize with the process.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-run-function">
-	<indexterm zone="f_process-run-function">
-	  <primary>process-run-function</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-RUN-FUNCTION</refname>
-	  <refpurpose>Creates a process, presets it, and enables it.
-	  </refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-run-function</function>
-	  process-specifier function &rest; args => process</synopsis>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process-specifier</term>
-	      <listitem>
-		<para>
-		  <varname>name</varname> | 
-		  (&key; <varname>name</varname>
-		  <varname>persistent</varname>
-		  <varname>priority</varname>
-		  <varname>class</varname>
-		  <varname>stack-size</varname>
-		  <varname>vstack-size</varname>
-		  <varname>tstack-size</varname>)
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-	      <listitem>
-		<para>a string, used to identify the process.
-		Passed to <function>make-process</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>function</term>
-	      <listitem>
-		<para>a function, designated by itself or by a symbol
-		which names it.  Passed to
-		<function>preset-process</function>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>persistent</term>
-	      
-	      <listitem>
-		<para>a boolean, passed to <function>make-process</function>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>priority</term>
-	      
-	      <listitem>
-		<para>ignored.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>class</term>
-	      
-	      <listitem>
-		<para>a subclass of CCL:PROCESS.  Passed to
-		<function>make-process</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>stack-size</term>
-	      
-	      <listitem>
-		<para>a size, in bytes.  Passed to
-		<function>make-process</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>vstack-size</term>
-	      
-	      <listitem>
-		<para>a size, in bytes.  Passed to
-		<function>make-process</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>tstack-size</term>
-	      
-	      <listitem>
-		<para>a size, in bytes.  Passed to
-		<function>make-process</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>the newly-created process.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates a lisp process (thread) via
-	  <xref linkend="f_make-process"/>,
-	  presets it via <xref linkend="f_process-preset"/>, and
-	  enables it via <xref linkend="f_process-enable"/>.  This means
-	  that <varname>process</varname> will immediately begin to
-	  execute.
-	  <function>process-run-function</function> is
-	  the simplest way to create and run a process.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-process"/></member>
-	    <member><xref linkend="f_process-preset"/></member>
-	    <member><xref linkend="f_process-enable"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-interrupt">
-	<indexterm zone="f_process-interrupt">
-	  <primary>process-interrupt</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-INTERRUPT</refname>
-	  <refpurpose>Arranges for the target process to invoke a
-	  specified function at some point in the near future, and then
-	  return to what it was doing.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-interrupt</function>
-	  process function &rest; args => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>function</term>
-	      <listitem>
-		<para>a function.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>args</term>
-	      <listitem>
-		<para>a list of values, appropriate as arguments to
-		<varname>function</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the result of applying <varname>function</varname>
-		to <varname>args</varname> if <varname>proceess</varname>
-		is the <function>current-process</function>, otherwise
-		NIL.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Arranges for <varname>process</varname>
-	  to apply <varname>function</varname> to <varname>args</varname> at
-	  some point in the near future (interrupting whatever
-	  <varname>process</varname>
-	  was doing.) If <varname>function</varname> returns normally,
-	  <varname>process</varname> resumes
-	  execution at the point at which it was interrupted.</para>
-
-	  <para><varname>process</varname> must be in an enabled state in
-	  order to respond
-	  to a <function>process-interrupt</function> request.  It's
-	  perfectly legal for a process to call
-	  <function>process-interrupt</function> on itself.</para>
-
-	  <para><function>process-interrupt</function>
-	  uses asynchronous POSIX signals to interrupt threads. If the
-	  thread being interrupted is executing lisp code, it can
-	  respond to the interrupt almost immediately (as soon as it
-	  has finished pseudo-atomic operations like consing and
-	  stack-frame initialization.)</para>
-
-	  <para>If the interrupted thread is
-	  blocking in a system call, that system call is aborted by
-	  the signal and the interrupt is handled on return.
-	  </para>
-
-	  <para>It is
-	  still difficult to reliably interrupt arbitrary foreign code
-	  (that may be stateful or otherwise non-reentrant); the
-	  interrupt request is handled when such foreign code returns
-	  to or enters lisp.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="m_without-interrupts"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>It would probably be better for <varname>result</varname>
-	  to always be NIL, since the present behaviour is inconsistent.
-	  </para>
-
-	  <para>
-	    <function>Process-interrupt</function> works by sending signals
-	    between threads, via the C function
-	    <function>#_pthread_signal</function>.  It could be argued
-	    that it should be done in one of several possible other ways
-	    under
-	    Darwin, to make it practical to asynchronously interrupt
-	    things which make heavy use of the Mach nanokernel.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="v_current-process">
-	<indexterm zone="v_current-process">
-	  <primary>*current-process*</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*CURRENT-PROCESS*</refname>
-	  <refpurpose>Bound in each process, to that process
-	  itself.</refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Value Type</title>
-
-	  <para>A lisp process (thread).</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Initial Value</title>
-	  
-	  <para>Bound separately in each process, to that process itself.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Used when lisp code needs to find out what process it is
-	  executing in.  Shouldn't be set by user code.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_all-processes"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-reset">
-	<indexterm zone="f_process-reset">
-	  <primary>process-reset</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-RESET</refname>
-	  <refpurpose>Causes a specified process to cleanly exit from
-	  any ongoing computation.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-reset</function>
-	  process &optional; kill-option => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>kill-option</term>
-	      <listitem>
-		<para>a generalized boolean.  The default is T.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>undefined.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Causes <varname>process</varname> to cleanly exit
-	  from any ongoing computation.  If <varname>kill-option</varname>
-	  is true, <varname>process</varname> then exits.  Otherwise, it
-	  enters a state where it can be
-	  <xref linkend="f_process-preset"/>. This
-	  is implemented by signaling a condition of type PROCESS-RESET;
-	  user-defined condition handlers should generally refrain from
-	  attempting to handle conditions of this type.</para>
-
-	  <para>A process can meaningfully reset itself.</para>
-
-	  <para>There is in general no way to know precisely when
-	  <varname>process</varname>
-	  has completed the act of resetting or killing itself; a process
-	  which has either entered the limbo of the reset state or exited
-	  has few ways of communicating either fact.
-	  <xref linkend="f_process-enable"/>
-	  can reliably determine when a process has entered
-	  the "limbo of the reset state", but can't predict how long the
-	  clean exit from ongoing computation might take: that depends on
-	  the behavior of <function>unwind-protect</function> cleanup
-	  forms, and of the OS scheduler.</para>
-
-	  <para>Resetting a process other than
-	  <xref linkend="v_current-process"/> involves the
-	  use of <xref linkend="f_process-interrupt"/>.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-kill"/></member>
-	    <member><xref linkend="f_process-abort"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-kill">
-	<indexterm zone="f_process-kill">
-	  <primary>process-kill</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-KILL</refname>
-	  <refpurpose>Causes a specified process to cleanly exit from any
-	  ongoing computation, and then exit.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-kill</function> process
-	  => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>undefined.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Entirely equivalent to calling
-	  (PROCESS-RESET PROCESS T).  Causes <varname>process</varname>
-	  to cleanly exit from any ongoing computation, and then exit.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	  
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-reset"/></member>
-	    <member><xref linkend="f_process-abort"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-abort">
-	<indexterm zone="f_process-abort">
-	  <primary>process-abort</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-ABORT</refname>
-	  <refpurpose>Causes a specified process to process an abort
-	  condition, as if it had invoked
-	  <function>abort</function>.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-abort</function> process
-	  &optional; condition
-	  => NIL</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>condition</term>
-	      <listitem>
-		<para>a lisp condition.  The default is NIL.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Entirely equivalent to calling
-	  (<xref linkend="f_process-interrupt"/> <varname>process</varname>
-	  (<function>lambda</function> ()
-	  (<function>abort</function> <varname>condition</varname>))).
-	  Causes <varname>process</varname> to transfer control to the
-	  applicable handler or restart for <function>abort</function>.</para>
-
-	  <para>If <varname>condition</varname> is non-NIL,
-	  <function>process-abort</function> does not consider any
-	  handlers which are explicitly bound to conditions other than
-	  <varname>condition</varname>.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	  
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-reset"/></member>
-	    <member><xref linkend="f_process-kill"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="v_ticks-per-second">
-	<indexterm zone="v_ticks-per-second">
-	  <primary>*ticks-per-second*</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*TICKS-PER-SECOND*</refname>
-	  <refpurpose>Bound to the clock resolution of the OS
-	  scheduler.</refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-
-	  <refsect1>
-	    <title>Value Type</title>
-
-	    <para>A positive integer.</para>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Initial Value</title>
-	    
-	    <para>The clock resoluton of the OS scheduler.  Currently,
-	    both LinuxPPC and DarwinPPC yeild an initial value of 100.
-	    </para>
-	  </refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>This value is ordinarily of marginal interest at best,
-	  but, for backward compatibility, some functions accept timeout
-	  values expressed in "ticks".  This value gives the number of
-	  ticks per second.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-wait-with-timeout"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-whostate">
-	<indexterm zone="f_process-whostate">
-	  <primary>process-whostate</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-WHOSTATE</refname>
-	  <refpurpose>Returns a string which describes the status of
-	  a specified process.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-whostate</function> process
-	  => whostate</synopsis>
-	  <variablelist>
-	    <varlistentry>
-	      <term>process</term>
-	      <listitem>
-		<para>a lisp process (thread).</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>whostate</term>
-	      <listitem>
-		<para>a string which describes the "state" of
-		<varname>process</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>This information is primarily for the benefit of
-	  debugging tools.  <varname>whostate</varname> is a terse report
-	  on what <varname>process</varname> is doing, or not doing,
-	  and why.</para>
-
-	  <para>If the process is currently waiting in a call to
-	  <xref linkend="f_process-wait"/> or
-	  <xref linkend="f_process-wait-with-timeout"/>, its
-	  <function>process-whostate</function> will be the value
-	  which was passed to that function as <varname>whostate</varname>.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-wait"/></member>
-	    <member><xref linkend="f_process-wait-with-timeout"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>This should arguably be SETFable, but doesn't seem to
-	  ever have been.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-allow-schedule">
-	<indexterm zone="f_process-allow-schedule">
-	  <primary>process-allow-schedule</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-ALLOW-SCHEDULE</refname>
-	  <refpurpose>Used for cooperative multitasking; probably never
-	  necessary.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-allow-schedule</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Advises the OS scheduler that the current thread has nothing
-	  useful to do and that it should try to find some other thread to
-	  schedule in its place. There's almost always a better
-	  alternative, such as waiting for some specific event to
-	  occur.  For example, you could use a lock or semaphore.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>This is a holdover from the days of cooperative
-	  multitasking.  All modern general-purpose operating systems use
-	  preemptive multitasking.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-wait">
-	<indexterm zone="f_process-wait">
-	  <primary>process-wait</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-WAIT</refname>
-	  <refpurpose>Causes the current lisp process (thread) to wait for
-	  a given
-	  predicate to return true.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-wait</function>
-	  whostate function &rest; args => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>whostate</term>
-
-	      <listitem>
-		<para>a string, which will be the value of
-		<xref linkend="f_process-whostate"/>
-		while the process is waiting.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>function</term>
-	      <listitem>
-		<para>a function, designated by itself or by a symbol
-		which names it.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>args</term>
-	      <listitem>
-		<para>a list of values, appropriate as arguments to
-		<varname>function</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>NIL.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Causes the current lisp process (thread) to repeatedly
-	  apply <varname>function</varname> to
-	  <varname>args</varname> until the call returns a true result, then
-	  returns NIL. After
-	  each failed call, yields the CPU as if by
-	  <xref linkend="f_process-allow-schedule"/>.</para>
-	  
-	  <para>
-	  As with <xref linkend="f_process-allow-schedule"/>, it's almost
-	  always more efficient to wait for some
-	  specific event to occur; this isn't exactly busy-waiting, but
-	  the OS scheduler can do a better job of scheduling if it's given
-	  the relevant information.  For example, you could use a lock
-	  or semaphore.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-whostate"/></member>
-	    <member><xref linkend="f_process-wait-with-timeout"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-wait-with-timeout">
-	<indexterm zone="f_process-wait-with-timeout">
-	  <primary>process-wait-with-timeout</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-WAIT-WITH-TIMEOUT</refname>
-	  <refpurpose>Causes the current thread to wait for a given
-	  predicate to return true, or for a timeout to expire.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-wait-with-timeout</function>
-	  whostate ticks function args => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>whostate</term>
-	      <listitem>
-		<para>a string, which will be the value of
-		<xref linkend="f_process-whostate"/>
-		while the process is waiting.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>ticks</term>
-	      <listitem>
-		<para>either a positive integer expressing a duration
-		in "ticks" (see <xref linkend="v_ticks-per-second"/>),
-		or NIL.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>function</term>
-	      <listitem>
-		<para>a function, designated by itself or by a symbol
-		which names it.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>args</term>
-	      <listitem>
-		<para>a list of values, appropriate as arguments to
-		<varname>function</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>T if <function>process-wait-with-timeout</function>
-		returned because its <varname>function</varname> returned
-		true, or NIL if it returned because the duration
-		<varname>ticks</varname> has been exceeded.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If <varname>ticks</varname> is NIL, behaves exactly like
-	  <xref linkend="f_process-wait"/>, except for returning T.
-	  Otherwise, <varname>function</varname> will be tested repeatedly,
-	  in the same
-	  kind of test/yield loop as in <xref linkend="f_process-wait"/>>
-	  until either <varname>function</varname> returns true,
-	  or the duration <varname>ticks</varname> has been exceeded.
-	  </para>
-
-	  <para> Having already read the descriptions of
-	  <xref linkend="f_process-allow-schedule"/> and
-	  <xref linkend="f_process-wait"/>, the
-	  astute reader has no doubt anticipated the observation that
-	  better alternatives should be used whenever possible.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="v_ticks-per-second"/></member>
-	    <member><xref linkend="f_process-whostate"/></member>
-	    <member><xref linkend="f_process-wait"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_without-interrupts">
-	<indexterm zone="m_without-interrupts">
-	  <primary>without-interrupts</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITHOUT-INTERRUPTS</refname>
-	  <refpurpose>Evaluates its body in an environment in which
-	  process-interrupt requests are deferred.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>without-interrupts</function>
-	  &body; body => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>body</term>
-	      <listitem>
-		<para>an implicit progn.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the primary value returned by
-		<varname>body</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Executes <varname>body</varname>
-	  in an environment in which <xref linkend="f_process-interrupt"/>
-	  requests are
-	  deferred. As noted in the description of
-	  <xref linkend="f_process-interrupt"/>, this has nothing to do
-	  with the
-	  scheduling of other threads; it may be necessary to inhibit
-	  <xref linkend="f_process-interrupt"/> handling when
-	  (for instance) modifying some data
-	  structure (for which the current thread holds an appropriate lock)
-	  in some manner that&#39;s not reentrant.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_process-interrupt"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_make-lock">
-	<indexterm zone="f_make-lock">
-	  <primary>make-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>MAKE-LOCK</refname>
-	  <refpurpose>Creates and returns a lock object, which can
-	  be used for synchronization between threads.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>make-lock</function> &optional;
-	  name => lock</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-	      <listitem>
-		<para>any lisp object; saved as part of
-		<varname>lock</varname>.  Typically a string or symbol
-		which may appear in the <xref linkend="f_process-whostate"/>s
-		of threads which are waiting for <varname>lock</varname>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>lock</term>
-	      <listitem>
-		<para>a newly-allocated object of type CCL:LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates and returns a lock object, which can
-	  be used to synchronize access to some shared resource.
-	  <varname>lock</varname> is
-	  initially in a &#34;free&#34; state; a lock can also be
-	  &#34;owned&#34; by a
-	  thread.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="m_with-lock-grabbed"/></member>
-	    <member><xref linkend="f_grab-lock"/></member>
-	    <member><xref linkend="f_release-lock"/></member>
-	    <member><xref linkend="f_try-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_with-lock-grabbed">
-	<indexterm zone="m_with-lock-grabbed">
-	  <primary>with-lock-grabbed</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-LOCK-GRABBED</refname>
-	  <refpurpose>Waits until a given lock can be obtained, then
-	  evaluates its body with the lock held.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-lock-grabbed</function>
-	  (lock) &body; body</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>lock</term>
-	      <listitem>
-		<para>an object of type CCL:LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>body</term>
-	      <listitem>
-		<para>an implicit progn.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the primary value returned by
-		<varname>body</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Waits until <varname>lock</varname> is either free or
-	  owned by the calling
-	  thread, then excutes <varname>body</varname> with the
-	  lock owned by the calling thread. If <varname>lock</varname>
-	  was free when <function>with-lock-grabbed</function> was called,
-	  it is restored to a free state after <varname>body</varname>
-	  is executed.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_grab-lock"/></member>
-	    <member><xref linkend="f_release-lock"/></member>
-	    <member><xref linkend="f_try-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_grab-lock">
-	<indexterm zone="f_grab-lock">
-	  <primary>grab-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>GRAB-LOCK</refname>
-	  <refpurpose>Waits until a given lock can be obtained, then
-	  obtains it.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>grab-lock</function> lock</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>lock</term>
-	      <listitem>
-		<para>an object of type CCL:LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Blocks until <varname>lock</varname> is owned by the
-	  calling thread.</para>
-
-	  <para>The macro <xref linkend="m_with-lock-grabbed"/>
-	  <emphasis>could</emphasis> be defined in
-	  terms of <function>grab-lock</function> and
-	  <xref linkend="f_release-lock"/>, but it is actually
-	  implemented at a slightly lower level.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="m_with-lock-grabbed"/></member>
-	    <member><xref linkend="f_release-lock"/></member>
-	    <member><xref linkend="f_try-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_release-lock">
-	<indexterm zone="f_release-lock">
-	  <primary>release-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>RELEASE-LOCK</refname>
-	  <refpurpose>Relinquishes ownership of a given lock.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>release-lock</function> lock</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>lock</term>
-	      <listitem>
-		<para>an object of type CCL:LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Signals an error of type CCL:LOCK-NOT-OWNER if
-	  <varname>lock</varname>
-	  is not already owned by the calling thread; otherwise, undoes the
-	  effect of one previous 
-	  <xref linkend="f_grab-lock"/>.  If this means that
-	  <function>release-lock</function> has now been called on
-	  <varname>lock</varname> the same number of times as
-	  <xref linkend="f_grab-lock"/> has, <varname>lock</varname>
-	  becomes free.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="m_with-lock-grabbed"/></member>
-	    <member><xref linkend="f_grab-lock"/></member>
-	    <member><xref linkend="f_try-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_try-lock">
-	<indexterm zone="f_try-lock">
-	  <primary>try-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>TRY-LOCK</refname>
-	  <refpurpose>Obtains the given lock, but only if it is not
-	  necessary to wait for it.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>try-lock</function> lock => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>lock</term>
-	      <listitem>
-		<para>an object of type CCL:LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>T if <varname>lock</varname> has been obtained,
-		or NIL if it has not.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tests whether <varname>lock</varname>
-	  can be obtained without blocking - that is, either
-	  <varname>lock</varname> is already free, or it is already owned
-	  by <xref linkend="v_current-process"/>.  If it can,
-	  causes it to
-	  be owned by the calling lisp process (thread) and returns T.
-	  Otherwise, the lock
-	  is already owned by another thread and cannot be obtained without
-	  blocking; NIL is returned in this case.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="m_with-lock-grabbed"/></member>
-	    <member><xref linkend="f_grab-lock"/></member>
-	    <member><xref linkend="f_release-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_make-read-write-lock">
-	<indexterm zone="f_make-read-write-lock">
-	  <primary>make-read-write-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>MAKE-READ-WRITE-LOCK</refname>
-	  <refpurpose>Creates and returns a read-write lock, which can
-	  be used for synchronization between threads.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>make-read-write-lock</function>
-	  => read-write-lock</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>read-write-lock</term>
-	      <listitem>
-		<para>a newly-allocated object of type
-		CCL:READ-WRITE-LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates and returns an object of type CCL::READ-WRITE-LOCK.
-	  A read-write lock may, at any given time, belong to any number
-	  of lisp processes (threads) which act as "readers"; or, it may
-	  belong to at most one process which acts as a "writer".  A
-	  read-write lock may never be held by a reader at the same time as
-	  a writer.  Intially, <varname>read-write-lock</varname> has
-	  no readers and no writers.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="m_with-read-lock"/></member>
-	    <member><xref linkend="m_with-write-lock"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>There probably should be some way to
-	  atomically &#34;promote&#34; a reader, making it a writer without
-	  releasing the lock, which could otherwise cause delay.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_with-read-lock">
-	<indexterm zone="m_with-read-lock">
-	  <primary>with-read-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-READ-LOCK</refname>
-	  <refpurpose>Waits until a given lock is available for
-	  read-only access, then evaluates its body with the lock
-	  held.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-read-lock</function>
-	  (read-write-lock) &body; body => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>read-write-lock</term>
-	      <listitem>
-		<para>an object of type
-		CCL:READ-WRITE-LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>body</term>
-	      <listitem>
-		<para>an implicit progn.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the primary value returned by
-		<varname>body</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Waits until <varname>read-write-lock</varname> has no
-	  writer,
-	  ensures that <xref linkend="v_current-process"/> is a
-	  reader of it, then executes <varname>body</varname>.
-	  </para>
-
-	  <para>After executing <varname>body</varname>, if
-	  <xref linkend="v_current-process"/> was not a reader of
-	  <varname>read-write-lock</varname> before
-	  <function>with-read-lock</function> was called, the lock is
-	  released.  If it was already a reader, it remains one.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="m_with-write-lock"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_with-write-lock">
-	<indexterm zone="m_with-write-lock">
-	  <primary>with-write-lock</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-WRITE-LOCK</refname>
-	  <refpurpose>Waits until the given lock is available for write
-	  access, then executes its body with the lock held.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-write-lock</function>
-	  (read-write-lock) &body; body</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>read-write-lock</term>
-	      <listitem>
-		<para>an object of type
-		CCL:READ-WRITE-LOCK.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>body</term>
-	      <listitem>
-		<para>an implicit progn.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the primary value returned by
-		<varname>body</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Waits until <varname>read-write-lock</varname> has no
-	  readers and no writer other than <xref linkend="v_current-process"/>,
-	  then ensures that <xref linkend="v_current-process"/> is the
-	  writer of it.  With the lock held, executes <varname>body</varname>.
-	  </para>
-
-	  <para>After executing <varname>body</varname>, if
-	  <xref linkend="v_current-process"/> was not the writer of
-	  <varname>read-write-lock</varname> before
-	  <function>with-write-lock</function> was called, the lock is
-	  released.  If it was already the writer, it remains the
-	  writer.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="m_with-read-lock"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_make-semaphore">
-	<indexterm zone="f_make-semaphore">
-	  <primary>make-semaphore</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>MAKE-SEMAPHORE</refname>
-	  <refpurpose>Creates and returns a semaphore, which can be used
-	  for synchronization between threads.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>make-semaphore</function>
-	  => semaphore</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>semaphore</term>
-	      <listitem>
-		<para>a newly-allocated object of type CCL:SEMAPHORE.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates and returns an object of type CCL:SEMAPHORE.
-	  A semaphore has an associated "count" which may be incremented
-	  and decremented atomically; incrementing it represents sending
-	  a signal, and decrementing it represents handling that signal.
-	  <varname>semaphore</varname> has an initial count of 0.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_signal-semaphore"/></member>
-	    <member><xref linkend="f_wait-on-semaphore"/></member>
-	    <member><xref linkend="f_timed-wait-on-semaphore"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_signal-semaphore">
-	<indexterm zone="f_signal-semaphore">
-	  <primary>signal-semaphore</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>SIGNAL-SEMAPHORE</refname>
-	  <refpurpose>Atomically increments the count of a given
-	  semaphore.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>signal-semaphore</function>
-	  semaphore => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>semaphore</term>
-	      <listitem>
-		<para>an object of type CCL:SEMAPHORE.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>an integer representing an error identifier
-		which was returned by the underlying OS call.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Atomically increments <varname>semaphore</varname>'s
-	  "count" by 1; this
-	  may enable a waiting thread to resume execution.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_wait-on-semaphore"/></member>
-	    <member><xref linkend="f_timed-wait-on-semaphore"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para><varname>result</varname> should probably be interpreted
-	  and acted on by <function>signal-semaphore</function>, because
-	  it is not likely to be meaningful to a lisp program, and the
-	  most common cause of failure is a type error.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_wait-on-semaphore">
-	<indexterm zone="f_wait-on-semaphore">
-	  <primary>wait-on-semaphore</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WAIT-ON-SEMAPHORE</refname>
-	  <refpurpose>Waits until the given semaphore has a positive
-	  count which can be atomically decremented.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>wait-on-semaphore</function>
-	  semaphore => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>semaphore</term>
-	      <listitem>
-		<para>an object of type CCL:SEMAPHORE.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>an integer representing an error identifier
-		which was returned by the underlying OS call.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Waits until <varname>semaphore</varname>
-	  has a positive count that can be
-	  atomically decremented; this will succeed exactly once for each
-	  corresponding call to SIGNAL-SEMAPHORE.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_signal-semaphore"/></member>
-	    <member><xref linkend="f_timed-wait-on-semaphore"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para><varname>result</varname> should probably be interpreted
-	  and acted on by <function>wait-on-semaphore</function>, because
-	  it is not likely to be meaningful to a lisp program, and the
-	  most common cause of failure is a type error.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_timed-wait-on-semaphore">
-	<indexterm zone="f_timed-wait-on-semaphore">
-	  <primary>timed-wait-on-semaphore</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>TIMED-WAIT-ON-SEMAPHORE</refname>
-	  <refpurpose>Waits until the given semaphore has a postive
-	  count which can be atomically decremented, or until a timeout
-	  expires.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>timed-wait-on-semaphore</function>
-	  semaphore timeout => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>semaphore</term>
-	      <listitem>
-		<para>An object of type CCL:SEMAPHORE.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>timeout</term>
-	      <listitem>
-		<para>a time interval in seconds.  May be any
-		non-negative real number the <function>floor</function> of
-		which fits in 32 bits.  The default is 1.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>T if <function>timed-wait-on-semaphore</function>
-		returned because it was able to decrement the count of
-		<varname>semaphore</varname>; NIL if it returned because
-		the duration <varname>timeout</varname> has been
-		exceeded.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Waits until <varname>semaphore</varname>
-	  has a positive count that can be
-	  atomically decremented, or until the duration
-	  <varname>timeout</varname> has
-	  elapsed.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_wait-on-semaphore"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-input-wait">
-	<indexterm zone="f_process-input-wait">
-	  <primary>process-input-wait</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-INPUT-WAIT</refname>
-	  <refpurpose>Waits until input is available on a given
-	  file-descriptor.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-input-wait</function>
-	  fd &optional; timeout</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>fd</term>
-	      <listitem>
-		<para>a file descriptor, which is a non-negative integer
-		used by the OS to refer to an open file, socket, or similar
-		I/O connection.  See <xref linkend="f_stream-device"/>.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>timeout</term>
-	      <listitem>
-		<para>either NIL, or a time interval in seconds.  May be any
-		non-negative real number the <function>floor</function> of
-		which fits in 32 bits.  The default is NIL.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Wait until input is available on <varname>fd</varname>.
-	  This uses the <function>select()</function> system call, and is
-	  generally a fairly
-	  efficient way of blocking while waiting for input. More
-	  accurately, <function>process-input-wait</function>
-	  waits until it&#39;s possible to read
-	  from fd without blocking, or until <varname>timeout</varname>, if
-	  it is not NIL, has been exceeded.</para>
-
-	  <para>
-	  Note that it&#39;s possible to read without blocking if
-	  the file is at its end - although, of course, the read will
-	  return zero bytes.</para>
-	</refsect1>
-	
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>
-	  <function>process-input-wait</function> has a timeout parameter,
-	  and
-	  <xref linkend="f_process-output-wait"/> does not.  This
-	  inconsistency should probably be corrected.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_process-output-wait">
-	<indexterm zone="f_process-output-wait">
-	  <primary>process-output-wait</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PROCESS-OUTPUT-WAIT</refname>
-	  <refpurpose>Waits until output is possible on a given file
-	  descriptor.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>process-output-wait</function> fd</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>fd</term>
-	      <listitem>
-		<para>a file descriptor, which is a non-negative integer
-		used by the OS to refer to an open file, socket, or similar
-		I/O connection.  See <xref linkend="f_stream-device"/>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Wait until output is possible on <varname>fd</varname>.
-	  This uses the <function>select()</function> system call, and is
-	  generally a fairly
-	  efficient way of blocking while waiting to output.</para>
-
-	  <para>If <function>process-output-wait</function> is called on
-	  a network socket which has not yet established a connection, it
-	  will wait until the connection is established.  This is an
-	  important use, often overlooked.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	  </simplelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>
-	  <xref linkend="f_process-input-wait"/> has a timeout parameter,
-	  and
-	  <function>process-output-wait</function> does not.  This
-	  inconsistency should probably be corrected.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_with-terminal-input">
-	<indexterm zone="m_with-terminal-input">
-	  <primary>with-terminal-input</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-TERMINAL-INPUT</refname>
-	  <refpurpose>Executes its body in an environment with exclusive
-	  read access to the terminal.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-terminal-input</function>
-	  &body; body => result</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>body</term>
-	      <listitem>
-		<para>an implicit progn.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>result</term>
-	      <listitem>
-		<para>the primary value returned by
-		<varname>body</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Requests exclusive read access to the standard terminal
-	  stream, <varname>*terminal-io*</varname>.  Executes
-	  <varname>body</varname> in an environment with that access.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref
-	              linkend="v_request-terminal-input-via-break"/></member>
-	    <member><xref linkend="cmd_y"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="v_request-terminal-input-via-break">
-	<indexterm zone="v_request-terminal-input-via-break">
-	  <primary>request-terminal-input-via-break</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*REQUEST-TERMINAL-INPUT-VIA-BREAK*</refname>
-	  <refpurpose>Controls how attempts to obtain ownership of
-	  terminal input are made.</refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Value Type</title>
-
-	  <para>A boolean.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Initial Value</title>
-	  
-	  <para>NIL.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Controls how attempts to obtain ownership of terminal input
-	  are made. When NIL, a message is printed on *TERMINAL-IO*;
-	  it's expected that the user will later yield
-	  control of the terminal via the :Y toplevel command. When T, a
-	  BREAK condition is signaled in the owning process; continuing from
-	  the break loop will yield the terminal to the requesting process
-	  (unless the :Y command was already used to do so in the break
-	  loop.)</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	    <member><xref linkend="cmd_y"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="cmd_y">
-	<indexterm zone="cmd_y">
-	  <primary>:y</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>:Y</refname>
-	  <refpurpose>Yields control of terminal input to a specified
-	  lisp process (thread).</refpurpose>
-	  <refclass>Toplevel Command</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>(<function>:y</function> p)</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>p</term>
-	      <listitem>
-		<para>a lisp process (thread), designated either by
-		an integer which matches its
-		<function>process-serial-number</function>,
-		or by a string which is <function>equal</function> to
-		its <function>process-name</function>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>:Y is a toplevel command, not a function.  As such, it
-	  can only be used interactively, and only from the initial
-	  process.</para>
-
-	  <para>The command yields control of terminal input to the
-	  process <varname>p</varname>, which must have used
-	  <xref linkend="m_with-terminal-input"/> to request access to the
-	  terminal input stream.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-	 
-	  <simplelist type="inline">
-	    <member><xref linkend="m_with-terminal-input"/></member>
-	    <member><xref
-	              linkend="v_request-terminal-input-via-break"/></member>
-	    <member><xref linkend="f_make-lock"/></member>
-	    <member><xref linkend="f_make-read-write-lock"/></member>
-	    <member><xref linkend="f_make-semaphore"/></member>
-	    <member><xref linkend="f_process-input-wait"/></member>
-	    <member><xref linkend="f_process-output-wait"/></member>
-	  </simplelist>
-	</refsect1>
-      </refentry>
-
-    </sect1>
-  </chapter>
-
-  <chapter id="Programming-with-Sockets">
-    <title>Programming with Sockets</title>
-
-    <sect1 id="Sockets-Overview">
-      <title>Overview</title>
-
-      <para>OpenMCL supports the socket abstraction for
-      interprocess communication. A socket represents a connection to
-      another process, typically (but not necessarily) a TCP/IP
-      network connection to a client or server running on some other
-      machine on the network.</para>
-      <para>All symbols mentioned in this chapter are exported from
-      the CCL package. As of version 0.13, these symbols are
-      additionally exported from the OPENMCL-SOCKET package.</para>
-      <para>OpenMCL supports three types of sockets: TCP sockets, UDP
-      sockets, and Unix-domain sockets.  This should be enough for all
-      but the most esoteric network situations.  All sockets are
-      created by <xref linkend="f_make-socket"/>.  The type of socket
-      depends on the arguments to it, as follows:</para>
-
-      <variablelist>
-	<varlistentry>
-	  <term>tcp-stream</term>
-
-	  <listitem>
-	    <para>A buffered bi-directional stream over a TCP/IP connection.
-	    tcp-stream is a subclass of stream, and you can read and write to it
-	    using all the usual stream functions. Created by (make-socket
-	    :addess-family :internet :type :stream :connect :active ...) or by
-	    (accept-connection ...).</para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>file-socket-stream</term>
-
-	  <listitem>
-	    <para>A buffered bi-directional stream over a &#34;UNIX domain&#34;
-	    connection. file-socket-stream is a subclass of stream, and you can
-	    read and write to it using all the usual stream functions. Created
-	    by (make-socket :address-family :file :type :stream :connect :active
-	    ...) or by (accept-connection ...),</para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>listener-socket</term>
-
-	  <listitem>
-	    <para>A passive socket used to listen for incoming TCP/IP
-	    connections on a particular port. A listener-socket is not a stream.
-	    It doesn&#39;t support I/O. It can only be used to create new
-	    tcp-streams by accept-connection. Created by (make-socket :type
-	    :stream :connect :passive ...)</para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>file-listener-socket</term>
-
-	  <listitem>
-	    <para>A passive socket used to listen for incoming UNIX domain
-	    connections named by a file in the local filesystem. A
-	    listener-socket is not a stream. It doesn&#39;t support I/O. It can
-	    only be used to create new file-socket-streams by accept-connection.
-	    Created by (make-socket :address-family :file :type :stream :connect
-	    :passive ...)</para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>udp-socket</term>
-
-	  <listitem>
-	    <para>A socket representing a packet-based UDP/IP connection. A
-	    udp-socket supports I/O but it is not a stream. Instead, you must
-	    use the special functions send-to and receive-from to read and write
-	    to it. Created by (make-socket :type :datagram ...)</para>
-	  </listitem>
-	</varlistentry>
-      </variablelist>
-    </sect1>
-
-    <sect1 id="Sockets-Dictionary">
-      <title>Sockets Dictionary</title>
-      <refentry id="f_make-socket">
-	<indexterm zone="f_make-socket">
-	  <primary>make-socket</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>MAKE-SOCKET</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>make-socket</function>
-	  &key; address-family type connect eol format
-	  remote-host remote-port local-host local-port local-filename
-	  remote-filename keepalive reuse-address nodelay broadcast linger
-	  backlog</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>address-family</term>
-
-	      <listitem>
-		<para>The address/protocol family of this socket. Currently
-		only :internet (the default), meaning IP, and :file,
-		referring to UNIX domain addresses, are supported.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>type</term>
-
-	      <listitem>
-		<para>One of :stream (the default) to request a
-		connection-oriented socket, or :datagram to request a
-		connectionless socket. The default is :stream.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>connect</term>
-
-	      <listitem>
-		<para>This argument is only relevant to sockets of type
-		:stream. One of :active (the default) to request a :passive
-		to request a file or TCP listener socket.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>eol</term>
-
-	      <listitem>
-		<para>This argument is currently ignored (it is accepted for
-		compatibility with Franz Allegro).</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>format</term>
-
-	      <listitem>
-		<para>One of :text (the default), :binary, or :bivalent.
-		This argument is ignored for :stream sockets for now, as
-		:stream sockets are currently always bivalent (i.e. they
-		support both character and byte I/O). For :datagram sockets,
-		the format determines the type of buffer created by
-		receive-from.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>remote-host</term>
-
-	      <listitem>
-		<para>Required for TCP streams, it specifies the host to
-		connect to (in any format acceptable to lookup-hostname).
-		Ignored for listener sockets. For UDP sockets, it can be
-		used to specify a default host for subsequent calls to
-		send-to or receive-from.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>remote-port</term>
-
-	      <listitem>
-		<para>Required for TCP streams, it specifies the port to
-		connect to (in any format acceptable to lookup-port).
-		Ignored for listener sockets. For UDP sockets, it can be
-		used to specify a default port for subsequent calls to for
-		subsequent calls to send-to or receive-from.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>remote-filename</term>
-
-	      <listitem>
-		<para>Required for file-socket streams, it specifies the
-		name of a file in the local filesystem (e.g., NOT mounted
-		via NFS, AFP, SMB, ...) which names and controls access to a
-		UNIX-domain socket.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>local-host</term>
-
-	      <listitem>
-		<para>Allows you to specify a local host address for a
-		listener or UDP socket, for the rare case where you want to
-		restrict connections to those coming to a specific local
-		address for security reasons.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>local-port</term>
-
-	      <listitem>
-		<para>Specify a local port for a socket. Most useful for
-		listener sockets, where it is the port on which the socket
-		will listen for connections.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>local-filename</term>
-
-	      <listitem>
-		<para>Required for file-listener-sockets. Specifies the name
-		of a file in the local filesystem which is used to name a
-		UNIX-domain socket. The actual filesystem file should not
-		previously exist when the file-listener-socket is created;
-		its parent directory should exist and be writable by the
-		caller. The file used to name the socket will be deleted
-		when the file-listener-socket is closed.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>keepalive</term>
-
-	      <listitem>
-		<para>If true, enables the periodic transmission of
-		&#34;keepalive&#34; messages.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>reuse-address</term>
-
-	      <listitem>
-		<para>If true, allows the reuse of local ports in listener
-		sockets, overriding some TCP/IP protocol specifications. You
-		will need this if you are debugging a server..</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>nodelay</term>
-
-	      <listitem>
-		<para>If true, disables Nagle&#39;s algorithm, which tries
-		to minimize TCP packet fragmentation by introducing
-		transmission delays in the absence of replies. Try setting
-		this if you are using a protocol which involves sending a
-		steady stream of data with no replies and are seeing
-		significant degradations in throughput.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>broadcast</term>
-
-	      <listitem>
-		<para>If true, requests permission to broadcast datagrams on
-		a UDP socket.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>linger</term>
-
-	      <listitem>
-		<para>If specified and non-nil, should be the number of
-		seconds the OS is allowed to wait for data to be pushed
-		through when a close is done. Only relevant for TCP sockets.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>backlog</term>
-
-	      <listitem>
-		<para>For a listener socket, specifies the number of
-		connections which can be pending but not accepted. The
-		default is 5, which is also the maximum on some operating
-		systems.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Creates and returns a new socket</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_accept-connection">
-	<indexterm zone="f_accept-connection">
-	  <primary>accept-connection</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>ACCEPT-CONNECTION</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>accept-connection</function>
-	  (socket listener-socket) &key; wait</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The listener-socket to listen on.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>wait</term>
-
-	      <listitem>
-		<para>If true (the default), and there are no connections
-		waiting to be accepted, waits until one arrives. If false,
-		returns NIL immediately.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Extracts the first connection on the queue of pending
-	  connections, accepts it (i.e. completes the connection startup
-	  protocol) and returns a new tcp-stream or file-socket-stream
-	  representing the newly established connection. The tcp stream
-	  inherits any properties of the listener socket that are relevant
-	  (e.g. :keepalive, :nodelay, etc.) The original listener socket
-	  continues to be open listening for more connections, so you can
-	  call accept-connection on it again.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_dotted-to-ipaddr">
-	<indexterm zone="f_dotted-to-ipaddr">
-	  <primary>dotted-to-ipaddr</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>DOTTED-TO-IPADDR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>dotted-to-ipaddr</function>
-	  dotted &key; errorp</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>dotted</term>
-
-	      <listitem>
-		<para>A string representing an IP address in the
-		&#34;nn.nn.nn.nn&#34; format</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>errorp</term>
-
-	      <listitem>
-		<para>If true (the default) an error is signaled if dotted
-		is invalid. If false, NIL is returned.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Converts a dotted-string representation of a host address to
-	  a 32-bit unsigned IP address.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_ipaddr-to-dotted">
-	<indexterm zone="f_ipaddr-to-dotted">
-	  <primary>ipaddr-to-dotted</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>IPADDR-TO-DOTTED</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>ipaddr-to-dotted</function>
-	  ipaddr &key; values</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>ipaddr</term>
-
-	      <listitem>
-		<para>A 32-bit integer representing an internet host address</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>values</term>
-
-	      <listitem>
-		<para>If false (the default), returns a string in the form
-		&#34;nn.nn.nn.nn&#34;. If true, returns four values
-		representing the four octets of the address as unsigned
-		8-bit integers.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Converts a 32-bit unsigned IP address into octets.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_ipaddr-to-hostname">
-	<indexterm zone="f_ipaddr-to-hostname">
-	  <primary>ipaddr-to-hostname</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>IPADDR-TO-HOSTNAME</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>ipaddr-to-hostname</function>
-	  ipaddr &key; ignore-cache</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>ipaddr</term>
-
-	      <listitem>
-		<para>a 32-bit integer representing an internet host address</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>ignore-cache</term>
-
-	      <listitem>
-		<para>This argument is ignored (it is accepted for
-		compatibility with Franz Allegro)</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Converts a 32-bit unsigned IP address into a host name
-	  string</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_lookup-hostname">
-	<indexterm zone="f_lookup-hostname">
-	  <primary>lookup-hostname</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>LOOKUP-HOSTNAME</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>lookup-hostname</function>
-	  host</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>host</term>
-
-	      <listitem>
-		<para>Specifies the host. It can be either a host name
-		string such as &#34;clozure.com&#34;, or a dotted address
-		string such as &#34;192.168.0.1&#34;, or a 32-bit unsigned
-		IP address such as 3232235521.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Converts a host spec in any of the acceptable formats into a
-	  32-bit unsigned IP address</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_lookup-port">
-	<indexterm zone="f_lookup-port">
-	  <primary>lookup-port</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>LOOKUP-PORT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>lookup-port</function>
-	  port protocol</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>port</term>
-
-	      <listitem>
-		<para>Specifies the port. It can be either a string, such as
-		&#34;http&#34; or a symbol, such as :http, or an unsigned
-		port number. Note that a string is case-sensitive. A symbol
-		is lowercased before lookup.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>protocol</term>
-
-	      <listitem>
-		<para>Must be one of &#34;tcp&#34; or &#34;udp&#34;.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Finds the port number for the specified port and protocol</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_receive-from">
-	<indexterm zone="f_receive-from">
-	  <primary>receive-from</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>RECEIVE-FROM</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>receive-from</function>
-	  (socket udp-socket) size &key; buffer
-	  extract offset</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket to read from</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>size</term>
-
-	      <listitem>
-		<para>Maximum number of bytes to read. If the packet is
-		larger than this, any extra bytes are discarded.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>buffer</term>
-
-	      <listitem>
-		<para>If specified, must be either a string or a byte vector
-		which will be used to read in the data. If not specified, a
-		new buffer will be created (of type determined by
-		socket-format).</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>extract</term>
-
-	      <listitem>
-		<para>If true, the subsequence of the buffer corresponding
-		only to the data read in is extracted and returned as the
-		first value. If false (the default) the original buffer is
-		returned even if it is only partially filled.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>offset</term>
-
-	      <listitem>
-		<para>Specifies the start offset into the buffer at which
-		data is to be stored. The default is 0.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Reads a UDP packet from a socket. If no packets are
-	  available, waits for a packet to arrive. Returns four values:</para>
-
-	  <orderedlist continuation="restarts" inheritnum="ignore">
-	    <listitem>
-	      <para>The buffer with the data</para>
-	    </listitem>
-
-	    <listitem>
-	      <para>The number of bytes read</para>
-	    </listitem>
-
-	    <listitem>
-	      <para>The 32-bit unsigned IP address of the sender of the data</para>
-	    </listitem>
-
-	    <listitem>
-	      <para>The port number of the sender of the data</para>
-	    </listitem>
-	  </orderedlist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_send-to">
-	<indexterm zone="f_send-to">
-	  <primary>send-to</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SEND-TO</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>send-to</function>
-	  (socket udp-socket) buffer size &key; remote-host
-	  remote-port offset</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket to write to</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>buffer</term>
-
-	      <listitem>
-		<para>A vector containing the data to send. It must be
-		either a string or a byte vector (either one is acceptable
-		regardless of the stream format).</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>size</term>
-
-	      <listitem>
-		<para>Number of bytes to send</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>remote-host</term>
-
-	      <listitem>
-		<para>The host to send the packet to, in any format
-		acceptable to lookup-hostname. The default is the remote
-		host specified in the call to make-socket.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>remote-port</term>
-
-	      <listitem>
-		<para>The port to send the packet to, in any format
-		acceptable to lookup-port. The default is the remote port
-		specified in the call to make-socket.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>offset</term>
-
-	      <listitem>
-		<para>The offset in the buffer where the packet data starts</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Send a UDP packet over a socket.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_shutdown">
-	<indexterm zone="f_shutdown">
-	  <primary>shutdown</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SHUTDOWN</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>shutdown</function>
-	  socket &key; direction</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket to shut down (typically a tcp-stream)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>direction</term>
-
-	      <listitem>
-		<para>One of :input to disallow further input, or :output to
-		disallow further output.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Shuts down part of a bidirectional connection. This is
-	  useful if e.g. you need to read responses after sending an
-	  end-of-file signal.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-os-fd">
-	<indexterm zone="f_socket-os-fd">
-	  <primary>socket-os-fd</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-OS-FD</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-os-fd</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the native OS&#39;s representation of the socket, or
-	  NIL if the socket is closed. On Unix, this is the Unix &#39;file
-	  descriptor&#39;, a small non-negative integer. Note that it is
-	  rather dangerous to mess around with tcp-stream fd&#39;s, as there
-	  is all sorts of buffering and asynchronous I/O going on above the
-	  OS level. listener-socket and udp-socket fd&#39;s are safer to
-	  mess with directly as there is less magic going on.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_remote-host">
-	<indexterm zone="f_remote-host">
-	  <primary>remote-host</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>REMOTE-HOST</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>remote-host</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the 32-bit unsigned IP address of the remote host,
-	  or NIL if the socket is not connected.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_remote-port">
-	<indexterm zone="f_remote-port">
-	  <primary>remote-port</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>REMOTE-PORT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>remote-port</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the remote port number, or NIL if the socket is not
-	  connected.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_local-host">
-	<indexterm zone="f_local-host">
-	  <primary>local-host</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>LOCAL-HOST</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>local-host</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns 32-bit unsigned IP address of the local host.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_local-port">
-	<indexterm zone="f_local-port">
-	  <primary>local-port</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>LOCAL-PORT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>local-port</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the local port number</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-address-family">
-	<indexterm zone="f_socket-address-family">
-	  <primary>socket-address-family</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-ADDRESS-FAMILY</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-address-family</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns :internet or :file, as appropriate.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-connect">
-	<indexterm zone="f_socket-connect">
-	  <primary>socket-connect</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-CONNECT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-connect</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns :active for tcp-stream, :passive for
-	  listener-socket, and NIL for udp-socket</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-format">
-	<indexterm zone="f_socket-format">
-	  <primary>socket-format</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-FORMAT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-format</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the socket format as specified by the :format
-	  argument to make-socket.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-type">
-	<indexterm zone="f_socket-type">
-	  <primary>socket-type</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-TYPE</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-type</function>
-	  socket</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>returns :stream for tcp-stream and listener-socket, and
-	  :datagram for udp-socket.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="c_socket-error">
-	<indexterm zone="c_socket-error">
-	  <primary>socket-error</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-ERROR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Class</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>The class of OS errors signaled by socket functions</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Superclasses</title>
-
-	  <para>simple-error</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-error-code">
-	<indexterm zone="f_socket-error-code">
-	  <primary>socket-error-code</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-ERROR-CODE</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-error-code</function>
-	  socket-error</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket-error</term>
-
-	      <listitem>
-		<para>the condition</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>The OS error code of the error</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-error-identifier">
-	<indexterm zone="f_socket-error-identifier">
-	  <primary>socket-error-identifier</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-ERROR-IDENTIFIER</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-error-identifier</function>
-	  socket-error</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket-error</term>
-
-	      <listitem>
-		<para>the condition</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>A symbol representing the error code in a more
-	  OS-independent way.</para>
-
-	  <para>One of: :address-in-use :connection-aborted :no-buffer-space
-	  :connection-timed-out :connection-refused :host-unreachable
-	  :host-down :network-down :address-not-available :network-reset
-	  :connection-reset :shutdown :access-denied or :unknown.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_socket-error-situation">
-	<indexterm zone="f_socket-error-situation">
-	  <primary>socket-error-situation</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>SOCKET-ERROR-SITUATION</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>socket-error-situation</function>
-	  socket-error</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket-error</term>
-
-	      <listitem>
-		<para>the condition</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>A string describing the context where the error happened. On
-	  Linux, this is the name of the system call which returned the
-	  error.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="o_close">
-	<indexterm zone="o_close">
-	  <primary>close</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>CLOSE</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Method</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>close</function>
-	  (socket socket) &key; abort</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>socket</term>
-
-	      <listitem>
-		<para>The socket to close</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>abort</term>
-
-	      <listitem>
-		<para>If false (the default), closes the socket in an
-		orderly fashion, finishing up any buffered pending I/O,
-		before closing the connection. If true, aborts/ignores
-		pending I/O. (For listener and udp sockets, this argument is
-		effectively ignored since there is never any buffered I/O to
-		clean up).</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>The close generic function can be applied to sockets. It
-	  releases the operating system resources associated with the
-	  socket.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_with-open-socket">
-	<indexterm zone="m_with-open-socket">
-	  <primary>with-open-socket</primary>
-	</indexterm>
-	<refnamediv>
-	  <refname>WITH-OPEN-SOCKET</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-open-socket</function>
-	  (var . make-socket-args) &body; body</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>var</term>
-
-	      <listitem>
-		<para>variable to bind</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>make-socket-args</term>
-
-	      <listitem>
-		<para>arguments suitable for passing to make-socket</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>body</term>
-
-	      <listitem>
-		<para>body to execute</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>executes body with var bound to the result of applying
-	  make-socket to make-socket-args. The socket gets closed on exit.</para>
-	</refsect1>
-      </refentry>
-    </sect1>
-  </chapter>
-
-  <chapter id="Running-Other-Programs-as-Subprocesses">
-    <title>Running Other Programs as Subprocesses</title>
-
-    <sect1 id="Subprocess-Overview">
-      <title>Overview</title>
-      <para>OpenMCL provides primitives to run external Unix programs,
-      to select and connect Lisp streams to their input and output
-      sources, to (optionally) wait for their completion and to check
-      their execution and exit status.</para>
-      <para>All of the global symbols described below are exported
-      from the CCL package.</para>
-      <para>This implementation is modeled on - and uses some code
-      from - similar facilities in CMUCL.</para>
-    </sect1>
-
-    <sect1 id="Subprocess-Examples">
-      <title>Examples</title>
-      <programlisting>
-;;; Capture the output of the "uname" program in a lisp string-stream
-;;; and return the generated string (which will contain a trailing
-;;; newline.)
-? (with-output-to-string (stream)
-    (run-program "uname" '("-r") :output stream))
-;;; Write a string to *STANDARD-OUTPUT*, the hard way.
-? (run-program "cat" () :input (make-string-input-stream "hello") :output t)
-;;; Find out that "ls" doesn't expand wildcards.
-? (run-program "ls" '("*.lisp") :output t)
-;;; Let the shell expand wildcards.
-? (run-program "sh" '("-c" "ls *.lisp") :output t)
-</programlisting>
-      <para>These last examples will only produce output if OpenMCL's
-      current directory contains .lisp files, of course.</para>
-    </sect1>
-
-    <sect1 id="Limitations-and-known-bugs">
-      <title>Limitations and known bugs</title>
-      <itemizedlist>
-        <listitem><para>OpenMCL and the external processs may get
-        confused about whoowns which streams when input, output, or
-        error are specified as T and wait is specified as
-        NIL.</para></listitem>
-        <listitem><para>External processes that need to talk to a
-        terminal device may not work properly; the environment (SLIME,
-        ILISP) under which OpenMCL is run can affect
-        this.</para></listitem>
-      
-      </itemizedlist>
-    </sect1>
-
-    <sect1 id="External-Program-Dictionary">
-      <title>External-Program Dictionary</title>
-	<refentry id="f_run-program">
-	  <indexterm zone="f_run-program">
-	    <primary>run-program</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>RUN-PROGRAM</refname>
-	    <refpurpose>Invokes an external program as an OS subprocess
-	    of lisp.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>run-program</function>
-	    program args &key; (wait t) pty input
-	    if-input-does-not-exist output (if-output-exists :error) (error
-	    :output) (if-error-exists :error) status-hook</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>program</term>
-
-		<listitem>
-		  <para>A string or pathname which denotes an executable file.
-		  The PATH environment variable is used to find programs whose
-		  name doesn't contain a directory component.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>args</term>
-
-		<listitem>
-		  <para>A list of simple-strings</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>wait</term>
-
-		<listitem>
-		  <para>Indicates whether or not run-program should wait for
-		  the EXTERNAL-PROCESS to complete or should return
-		  immediately.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>pty</term>
-
-		<listitem>
-		  <para>This option is accepted but currently ignored;
-		  it's intended to make it easier to run external programs
-		  that need to interact with a terminal device.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>input</term>
-
-		<listitem>
-		  <para>Selects the input source used by the EXTERNAL-PROCESS.
-		  May be any of the following:</para>
-
-		  <itemizedlist>
-		    <listitem>
-		      <para>NIL Specifies that a null input stream (e.g.,
-		      /dev/null) should be used.</para>
-		    </listitem>
-
-		    <listitem>
-		      <para>T Specifies that the EXTERNAL-PROCESS should use
-		      the input source with which OpenMCL was invoked.</para>
-		    </listitem>
-
-		    <listitem>
-		      <para>A string or pathname. Specifies that the
-		      EXTERNAL-PROCESS should receive its input from the named
-		      existing file.</para>
-		    </listitem>
-
-		    <listitem>
-		      <para>:STREAM Creates a Lisp stream opened for character
-		      output. Any data written to this stream (accessible as
-		      the EXTERNAL-PROCESS-INPUT-STREAM of the
-		      EXTERNAL-PROCESS object) appears as input to the
-		      external process.</para>
-		    </listitem>
-
-		    <listitem>
-		      <para>A stream. Specifies that the lisp stream should
-		      provide input to the EXTERNAL-PROCESS.</para>
-		    </listitem>
-		  </itemizedlist>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>if-input-does-not-exist</term>
-
-		<listitem>
-		  <para>If the input argument specifies the name of an
-		  existing file, this argument is used as the
-		  if-does-not-exist argument to OPEN when that file is opened.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>output</term>
-
-		<listitem>
-		  <para>Specifies where standard output from the external
-		  process should be sent. Analogous to input above.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>if-output-exists</term>
-
-		<listitem>
-		  <para>If output is specified as a string or pathname, this
-		  argument is used as the if-exists argument to OPEN when that
-		  file is opened.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>error</term>
-
-		<listitem>
-		  <para>Specifies where error output from the external process
-		  should be sent. In addition to the values allowed for
-		  output, the keyword :OUTPUT can be used to indicate that
-		  error output should be sent where standard output goes.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>if-error-exists</term>
-
-		<listitem>
-		  <para>Analogous to if-output-exists.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>status-hook</term>
-
-		<listitem>
-		  <para>A user-defined function of one argument (the
-		  EXTERNAL-PROCESS structure.) This function is called
-		  whenever OpenMCL detects a change in the staus of the
-		  EXTERNAL-PROCESS.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Runs the specified program in an external (Unix) process,
-	    returning an object of type EXTERNAL-PROCESS if successful.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_signal-external-process">
-	  <indexterm zone="f_signal-external-process">
-	    <primary>signal-external-process</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>SIGNAL-EXTERNAL-PROCESS</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>signal-external-process</function>
-	    proc signal-number</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>signal</term>
-
-		<listitem>
-		  <para>A small integer.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Sends the specified "signal" to the specified
-	    external process. (Typically, it would only be useful tocall
-	    this function if the EXTERNAL-PROCESS was created with :WAIT
-	    NIL. ) Returns T if successful; signals an error otherwise.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_external-process-id">
-	  <indexterm zone="f_external-process-id">
-	    <primary>external-process-id</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>EXTERNAL-PROCESS-ID</refname>
-	    <refpurpose>Returns the "process ID" of an OS subprocess,
-	    a positive integer which identifies it.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>external-process-id</function>
-	    proc</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Returns the <emphasis>process id</emphasis> assigned to
-	    the external process by the operating system. This is typically
-	    a positive, 16-bit number.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_external-process-input-stream">
-	  <indexterm zone="f_external-process-input-stream">
-	    <primary>external-process-input-stream</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>EXTERNAL-PROCESS-INPUT-STREAM</refname>
-	    <refpurpose>Returns the lisp stream which is used to write
-	    input to a given OS subprocess, if it has one.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>external-process-input-stream</function>
-	    proc</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Returns the stream created when the input argument to
-	    run-program is specified as :STREAM.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_external-process-output-stream">
-	  <indexterm zone="f_external-process-output-stream">
-	    <primary>external-process-output-stream</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>EXTERNAL-PROCESS-OUTPUT-STREAM</refname>
-	    <refpurpose>Returns the lisp stream which is used to read
-	    output from an OS subprocess, if there is one.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>external-process-output-stream</function>
-	    proc</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Returns the stream created when the output argument to
-	    run-program is specified as :STREAM.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_external-process-error-stream">
-	  <indexterm zone="f_external-process-error-stream">
-	    <primary>external-process-error-stream</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>EXTERNAL-PROCESS-ERROR-STREAM</refname>
-	    <refpurpose>Returns the stream which is used to read
-	    "error" output from a given OS subprocess, if it has
-	    one.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>external-process-error-stream</function>
-	    proc</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Returns the stream created when the error argument to
-	    run-program is specified as :STREAM.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="f_external-process-status">
-	  <indexterm zone="f_external-process-status">
-	    <primary>external-process-status</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>EXTERNAL-PROCESS-STATUS</refname>
-	    <refpurpose>Returns information about whether an OS
-	    subprocess is running; or, if not, why not; and what its
-	    result code was if it completed.</refpurpose>
-	    <refclass>Function</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>external-process-status</function>
-	    proc</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>proc</term>
-
-		<listitem>
-		  <para>An EXTERNAL-PROCESS, as returned by RUN-PROGRAM.</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Returns, as multiple values, a keyword denoting the status
-	    of the external process (one of :running, :stopped, :signaled, or
-	    :exited), and the exit code or terminating signal if the first
-	    value is other than :running.</para>
-	  </refsect1>
-	</refentry>
-    </sect1>
-  </chapter>
-
-  <chapter id="Creating-Your-Own-Stream-Classes-with-Gray-Streams">
-    <title>Creating Your Own Stream Classes with Gray Streams</title>
-
-    <sect1 id="Streams-Overview">
-      <title>Overview</title>
-      <para>This chapter is still being written and revised, because
-      it is woefully incomplete.  The dictionary section currently
-      only lists a couple functions.  Caveat lector.</para>
-      <para>Gray streams are an extension to Common Lisp.  They were
-      proposed for standardization by David Gray (the astute reader
-      now understands their name) quite some years ago, but not
-      accepted, because they had not been tried sufficiently to find
-      conceptual problems with them.</para>
-      <para>They have since been implemented by quite a few modern
-      Lisp implementations.  However, they do indeed have some
-      inadequacies, and each implementation has addressed these in
-      different ways.  The situation today is that it's difficult to
-      even find out how to get started using Gray streams.  This is
-      why standards are important.</para>
-      <para>Here's a list of some classes which you might wish for
-      your new stream class to inherit from:</para>
- 
-      <simplelist>
-	<member>fundamental-stream</member>
-	<member>fundamental-input-stream</member>
-	<member>fundamental-output-stream</member>
-	<member>fundamental-character-stream</member>
-	<member>fundamental-binary-stream</member>
-	<member>fundamental-character-input-stream</member>
-	<member>fundamental-character-output-stream</member>
-	<member>fundamental-binary-input-stream</member>
-	<member>fundamental-binary-output-stream</member>
-	<member>ccl::buffered-stream-mixin</member>
-	<member>ccl::buffered-input-stream-mixin</member>
-	<member>ccl::buffered-output-stream-mixin</member>
-	<member>ccl::buffered-io-stream-mixin</member>
-	<member>ccl::buffered-character-input-stream-mixin</member>
-	<member>ccl::buffered-character-output-stream-mixin</member>
-	<member>ccl::buffered-character-io-stream-mixin</member>
-	<member>ccl::buffered-binary-input-stream-mixin</member>
-	<member>ccl::buffered-binary-output-stream-mixin</member>
-	<member>ccl::buffered-binary-io-stream-mixin</member>
-	<member>file-stream</member>
-	<member>file-input-stream</member>
-	<member>file-output-stream</member>
-	<member>file-io-stream</member>
-	<member>file-character-input-stream</member>
-	<member>file-character-output-stream</member>
-	<member>file-charcter-io-stream</member>
-	<member>file-binary-input-stream</member>
-	<member>file-binary-output-stream</member>
-	<member>file-binary-io-stream</member>
-	<member>ccl::fd-stream</member>
-	<member>ccl::fd-input-stream</member>
-	<member>ccl::fd-output-stream</member>
-	<member>ccl::fd-io-stream</member>
-	<member>ccl::fd-character-input-stream</member>
-	<member>ccl::fd-character-output-stream</member>
-	<member>ccl::fd-character-io-stream</member>
-	<member>ccl::fd-binary-input-stream</member>
-	<member>ccl::fd-binary-output-stream</member>
-	<member>ccl::fd-binary-io-stream</member>
-      </simplelist>
-
-      <para>All of these are defined in ccl/level-1/l1-streams.lisp,
-      except for the ccl:file-* ones, which are in
-      ccl/level-1/l1-sysio.lisp.</para>
-      <para>According to the original Gray streams proposal, you
-      should inherit from the most specific of the fundamental-*
-      classes which applies.  Using OpenMCL, though, if you want
-      buffering for better performance, which, unless you know of some
-      reason you wouldn't, you do, you should instead inherit from the
-      appropriate ccl::buffered-* class The buffering you get this way
-      is exactly the same as the buffering which is used on ordinary,
-      non-Gray streams, and force-output will work properly on
-      it.</para>
-      <para>Notice that -mixin suffix in the names of all the
-      ccl::buffered-* classes?  The suffix means that this class is
-      not "complete" by itself; you still need to inherit from a
-      fundamental-* stream, even if you also inherit from a *-mixin
-      stream.  You might consider making your own class like this.
-      ....  Except that they do inherit from the fundamental-*
-      streams, that's weird.</para>
-      <para>If you want to be able to create an instance of your class
-      with the :class argument to (open) and (with-open-file), you
-      should make it inherit from one of the file-* classes.  If you
-      do this, it's not necessary to inherit from any of the other
-      classes (though it won't hurt anything), since the file-*
-      classes already do.</para>
-      <para>When you inherit from the file-* classes, you can use
-      (call-next-method) in any of your methods to get the standard
-      behaviour.  This is especially useful if you want to create a
-      class which performs some simple filtering operation, such as
-      changing everything to uppercase or to a different character
-      encoding.  If you do this, you will definitely need to
-      specialize ccl::select-stream-class.  Your method on
-      ccl::stream-select-class should accept an instance of the class,
-      but pay no attention to its contents, and return a symbol naming
-      the class to actually be instantiated.</para>
-      <para>If you need to make your functionality generic across all
-      the different types of stream, probably the best way to
-      implement it is to make it a mixin, define classes with all the
-      variants of input, output, io, character, and binary, which
-      inherit both from your mixin and from the appropriate other
-      class, then define a method on ccl::select-stream-class which
-      chooses from among those classes.</para>
-      <para>Note that some of these classes are internal to the CLL
-      package.  If you try to inherit from those ones without the
-      ccl:: prefix, you'll get an error which may confuse you, calling
-      them "forward-referenced classes".  That just means you used the
-      wrong symbol, so add the prefix.</para>
-      <para>Here's a list of some generic functions which you might
-      wish to specialize for your new stream class, and which ought to
-      be documented at some point.</para>
-      <simplelist>
-	<member>stream-direction stream =></member>
-	<member>stream-device stream direction =></member>
-	<member>stream-length stream &optional; new =></member>
-	<member>stream-position stream &optional; new =></member>
-	<member>streamp stream => boolean</member>
-	<member>stream-write-char output-stream char =></member>
-	<member>stream-write-entire-string output-stream string =></member>
-	<member>stream-read-char input-stream =></member>
-	<member>stream-unread-char input-stream char =></member>
-	<member>stream-force-output output-stream => nil</member>
-	<member>stream-maybe-force-output output-stream => nil</member>
-	<member>stream-finish-output output-stream => nil</member>
-	<member>stream-clear-output output-stream => nil</member>
-	<member>close stream &key; abort => boolean</member>
-	<member>stream-fresh-line stream => t</member>
-	<member>stream-line-length stream => length</member>
-	<member>interactive-stream-p stream => boolean</member>
-	<member>stream-clear-input input-stream => nil</member>
-	<member>stream-listen input-stream => boolean</member>
-	<member>stream-filename stream => string</member>
-	<member>ccl::select-stream-class instance in-p out-p char-p =>
-	        class</member>
-      </simplelist>
-      <para>The following functions are standard parts of Common Lisp, but
-behave in special ways with regard to Gray streams.</para>
-      <simplelist>
-	<member>open-stream-p stream => generalized-boolean</member>
-	<member>input-stream-p stream => generalized-boolean</member>
-	<member>output-stream-p stream => generalized-boolean</member>
-	<member>stream-element-type stream =></member>
-	<member>stream-error-stream =></member>
-	<member>open</member>
-	<member>close</member>
-	<member>with-open-file</member>
-      </simplelist>
-
-      <para>Specifically, (open) and (with-open-file) accept a new
-      keyword argument, :class, which may be a symbol naming a class;
-      the class itself; or an instance of it.  The class so given must
-      be a subtype of 'stream, and an instance of it with no
-      particular contents will be passed to ccl::select-stream-class
-      to determine what class to actually instantiate.</para>
-      <para>The following are standard, and do not behave specially
-      with regard to Gray streams, but probably should.</para>
-       <simplelist>
-	<member>stream-external-format</member>
-      </simplelist>
-    </sect1>
-
-    <sect1 id="Extending-READ-SEQUENCE-and-WRITE-SEQUENCE">
-      <title>Extending READ-SEQUENCE and WRITE-SEQUENCE</title>
-
-      <sect2 id="extending-read-write-overview">
-        <title>Overview</title>
-	<para>The "Gray Streams" API is based on an informal proposal that was
-	made before ANSI CL adopted the READ-SEQUENCE and WRITE-SEQUENCE
-	functions; as such, there is no "standard" way for the author of a Gray
-	stream class to improve the performance of these functions by exploiting
-	knowledge of the stream's internals (e.g., the buffering mechanism it
-	uses.)</para>
-        <para>In the absence of any such knowledge, READ-SEQUENCE and
-        WRITE-SEQUENCE are effectively just convenient shorthand for a
-        loop which calls READ-CHAR/READ-BYTE/WRITE-CHAR/WRITE-BYTE as
-        appropriate. The mechanism described below allows subclasses
-        of FUNDAMENTAL-STREAM to define more specialized (and
-        presumably more efficient) behavior.</para>
-      </sect2>
-
-      <sect2 id="Notes">
-	<title>Notes</title>
-        <para>READ-SEQUENCE and WRITE-SEQUENCE do a certain amount of
-        sanity-checking and normalization of their arguments before
-        dispatching to one of the methods above. If an individual
-        method can't do anything particularly clever, CALL-NEXT-METHOD
-        can be used to handle the general case.</para>
-      </sect2>
-
-      <sect2 id="Example">
-        <title>Example</title>
-        <programlisting>
-(defclass my-string-input-stream (fundamental-character-input-stream)
-  ((string :initarg :string :accessor my-string-input-stream-string)
-   (index :initform 0 :accessor my-string-input-stream-index)
-   (length)))
-
-(defmethod stream-read-vector ((stream my-string-input-stream) vector start end)
-  (if (not (typep vector 'simple-base-string))
-      (call-next-method)
-      (with-slots (string index length)
-        (do* ((outpos start (1+ outpos)))
-             ((or (= outpos end)
-                  (= index length))
-              outpos))
-          (setf (schar vector outpos)
-                (schar string index))
-          (incf index)))))
-</programlisting>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Multibyte-I-O">
-      <title>Multibyte I/O</title>
-      <para>All heap-allocated objects in OpenMCL that cannot contain
-      pointers to lisp objects are represented as
-      <emphasis>ivectors</emphasis>. OpenMCL provides low-level
-      functions, and , to efficiently transfer data between buffered
-      streams and ivectors. There's some overlap in functionality
-      between the functions described here and the ANSI CL
-      READ-SEQUENCE and WRITE-SEQUENCE functions.</para>
-      <para>As used here, the term "octet" means roughly the same
-      thing as the term "8-bit byte". The functions described below
-      transfer a specified sequence of octets between a buffered
-      stream and an ivector, and don't really concern themselves with
-      higher-level issues (like whether that octet sequence is within
-      bounds or how it relates to the logical contents of the
-      ivector.) For these reasons, these functions are generally less
-      safe and more flexible than their ANSI counterparts.</para>
-    </sect1>
-
-    <sect1 id="Gray-Streams-Dictionary">
-      <title>Gray Streams Dictionary</title>
-      <refentry id="f_stream-read-list">
-	<indexterm zone="f_stream-read-list">
-	  <primary>stream-read-list</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL:STREAM-READ-LIST</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-read-list</function>
-	  stream list count</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>a stream, presumably a fundamental-input-stream.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>list</term>
-
-	      <listitem>
-		<para>a list. When a STREAM-READ-LIST method is called by
-		READ-SEQUENCE, this argument is guaranteed to be a proper
-		list.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>count</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-READ-LIST method
-		is called by READ-SEQUENCE, this argument is guaranteed not
-		to be greater than the length of the list.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Should try to read up to count elements from stream into the
-	  list list, returning the number of elements actually read (which
-	  may be less than count in case of a premature end-of-file.)</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-write-list">
-	<indexterm zone="f_stream-write-list">
-	  <primary>stream-write-list</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL:STREAM-WRITE-LIST</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-write-list</function>
-	  stream list count</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>a stream, presumably a fundamental-ouput-stream.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>list</term>
-
-	      <listitem>
-		<para>a list. When a STREAM-WRITE-LIST method is called by
-		WRITE-SEQUENCE, this argument is guaranteed to be a proper
-		list.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>count</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-WRITE-LIST
-		method is called by WRITE-SEQUENCE, this argument is
-		guaranteed not to be greater than the length of the list.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>should try to write the first count elements of list to
-	  stream. The return value of this method is ignored.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-read-vector">
-	<indexterm zone="f_stream-read-vector">
-	  <primary>stream-read-vector</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL:STREAM-READ-VECTOR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-read-vector</function>
-	  stream vector start end</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>a stream, presumably a fundamental-input-stream</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>vector</term>
-
-	      <listitem>
-		<para>a vector. When a STREAM-READ-VECTOR method is called
-		by READ-SEQUENCE, this argument is guaranteed to be a simple
-		one-dimensional array.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>start</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-READ-VECTOR
-		method is called by READ-SEQUENCE, this argument is
-		guaranteed to be no greater than end and not greater than
-		the length of vector.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>end</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-READ-VECTOR
-		method is called by READ-SEQUENCE, this argument is
-		guaranteed to be no less than end and not greater than the
-		length of vector.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>should try to read successive elements from stream into
-	  vector, starting at element start (inclusive) and continuing
-	  through element end (exclusive.) Should return the index of the
-	  vector element beyond the last one stored into, which may be less
-	  than end in case of premature end-of-file.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-write-vector">
-	<indexterm zone="f_stream-write-vector">
-	  <primary>stream-write-vector</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL:STREAM-WRITE-VECTOR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-write-vector</function>
-	  stream vector start end</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>a stream, presumably a fundamental-output-stream</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>vector</term>
-
-	      <listitem>
-		<para>a vector. When a STREAM-WRITE-VECTOR method is called
-		by WRITE-SEQUENCE, this argument is guaranteed to be a
-		simple one-dimensional array.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>start</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-WRITE-VECTOR
-		method is called by WRITE-SEQUENCE, this argument is
-		guaranteed to be no greater than end and not greater than
-		the length of vector.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>end</term>
-
-	      <listitem>
-		<para>a non-negative integer. When a STREAM-WRITE-VECTOR
-		method is called by WRITE-SEQUENCE, this argument is
-		guaranteed to be no less than end and not greater than the
-		length of vector.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>should try to write successive elements of vector to stream,
-	  starting at element start (inclusive) and continuing through
-	  element end (exclusive.)</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-device">
-	<indexterm zone="f_stream-device">
-	  <primary>stream-device</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::STREAM-DEVICE</refname>
-	  <refpurpose>Returns the OS file descriptor associated with a
-	  given lisp stream.</refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>ccl::stream-device</function>
-	  s direction</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Method Signatures</title>
-
-	  <synopsis><function>ccl::stream-device</function>
-	  (s stream) direction => fd</synopsis>
-	</refsect1>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>s</term>
-	      <listitem>
-		<para>a stream.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>direction</term>
-	      <listitem>
-		<para>either :INPUT or :OUTPUT.</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>fd</term>
-	      <listitem>
-		<para>a file descriptor, which is a non-negative integer
-		used by the OS to refer to an open file, socket, or similar
-		I/O connection.  NIL if there is no file descriptor associated
-		with <varname>s</varname> in the direction given by
-		<varname>direction</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the file descriptor associated with
-	  <varname>s</varname> in the direction given by
-	  <varname>direction</varname>.  It is necessary to specify
-	  <varname>direction</varname> because the input and output
-	  file descriptors may be different; the most common case is when
-	  one of them has been redirected by the Unix shell.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-read-ivector">
-	<indexterm zone="f_stream-read-ivector">
-	  <primary>stream-read-ivector</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>STREAM-READ-IVECTOR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-read-ivector</function>
-	  stream ivector start-octet max-octets</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Reads up to max-octets octets from stream into ivector,
-	  storing them at start-octet. Returns the number of octets actually
-	  read.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Arguments</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>An input stream. The method defined on
-		BUFFERED-INPUT-STREAMs requires that the size in octets of
-		an instance of the stream's element type is 1.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>ivector</term>
-
-	      <listitem>
-		<para>Any ivector.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>start-octet</term>
-
-	      <listitem>
-		<para>A non-negative integer.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>max-octets</term>
-
-	      <listitem>
-		<para>A non-negative integer. The return value may be less
-		than the value of this parameter if EOF was encountered.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_stream-write-ivector">
-	<indexterm zone="f_stream-write-ivector">
-	  <primary>stream-write-ivector</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>STREAM-WRITE-IVECTOR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Generic Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>stream-write-ivector stream</function>
-	  ivector start-octet max-octets</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Writes max-octets octets to stream from ivector, starting at
-	  start-octet. Returns max-octets.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Arguments</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>stream</term>
-
-	      <listitem>
-		<para>An input stream. The method defined on
-		BUFFERED-OUTPUT-STREAMs requires that the size in octets of
-		an instance of the stream's element type is 1.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>ivector</term>
-
-	      <listitem>
-		<para>Any ivector</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>start-octet</term>
-
-	      <listitem>
-		<para>A non-negative integer.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>max-octet</term>
-
-	      <listitem>
-		<para>A non-negative integer.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Examples</title>
-
-<programlisting format="linespecific">;;; Write the contents of a (SIMPLE-ARRAY(UNSIGNED-BYTE 16) 3) 
-;;; to a character file stream. Read back the characters.
-(let* ((a (make-array 3 
-                     :element-type '(unsigned-byte 16)
-                     :initial-contents '(26725 27756 28449))))
-  (with-open-file (s "junk"
-                   :element-type 'character
-                   :direction :io
-                   :if-does-not-exist :create
-                   :if-exists :supersede)
-    ;; Write six octets (three elements).
-    (stream-write-ivector s a 0 6)
-    ;; Rewind, then read a line
-    (file-position s 0)
-    (read-line s)))
-
-;;; Write a vector of DOUBLE-FLOATs. Note that (to maintain
-;;; alignment) there are 4 octets of padding before the 0th 
-;;; element of a (VECTOR DOUBLE-FLOAT).
-;;; (Note that (= (- arch::misc-dfloat-offset 
-;;;                  arch::misc-data-offset) 4))
-(defun write-double-float-vector
-  (stream vector &#38;key (start 0) (end (length vector)))
-  (check-type vector (vector double-float))
-  (let* ((start-octet (+ (* start 8) 
-                         (- arch::misc-dfloat-offset
-                         arch::misc-data-offset)))
-         (num-octets (* 8 (- end start))))
-    (stream-write-ivector stream vector start-octet num-octets)))</programlisting>
-	</refsect1>
-      </refentry>
-    </sect1>
-  </chapter>
-
-  <chapter id="Writing-Portable-Extensions-to-the-Object-System-using-the-MetaObject-Protocol">
-    <title>Writing Portable Extensions to the Object System  using the MetaObject Protocol</title>
-
-    <sect1 id="MOP-Overview">
-      <title>Overview</title>
-      <para>OpenMCL supports a fairly large subset of the
-      semi-standard MetaObject Protocol (MOP) for CLOS, as defined in
-      chapters 5 and 6 of "The Art Of The Metaobject Protocol",
-      (Kiczales et al, MIT Press 1991, ISBN 0-262-61074-4); this
-      specification is also available online at
-      http://www.alu.org/mop/index.html.</para>
-    </sect1>
-
-    <sect1 id="MOP-Implementation-status">
-      <title>Implementation status</title>
-      <para>The keyword :openmcl-partial-mop is on *FEATURES* to
-      indicate the presence of this functionality.</para>
-
-      <para>All of the symbols defined in the MOP specification
-      (whether implemented or not) are exported from the "CCL" package
-      and from an "OPENMCL-MOP" package.</para>
-      <para><informaltable><tgroup cols="2" colsep="1"
-      rowsep="1"><colspec align="center" colname="col0" /><colspec
-      align="center" colname="col1" /><thead><row><entry
-      align="center" valign="top"><para>construct</para></entry><entry
-      align="center"
-      valign="top"><para>status</para></entry></row></thead><tbody><row><entry
-      align="center"
-      valign="top"><para>accessor-method-slot-definition</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>add-dependent</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>add-direct-method</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>add-direct-subclass</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>add-method</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-default-initargs</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-direct-default-initargs</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-direct-slots</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-direct-subclasses</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-direct-superclasses</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-finalized-p</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-prototype</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>class-slots</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-applicable-methods</para></entry><entry
-      align="center"
-      valign="top"><para>-</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-applicable-methods-using-classes</para></entry><entry
-      align="center"
-      valign="top"><para>-</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-class-precedence-list</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-direct-initargs</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-discriminating-function</para></entry><entry
-      align="center"
-      valign="top"><para>-</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-effective-method</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-effective-slot-definition</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>compute-slots</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>direct-slot-definition-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>effective-slot-definition-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>ensure-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>ensure-class-using-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>ensure-generic-function-using-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>eql-specializer-object</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>extract-lambda-list</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>extract-specializer-names</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>finalize-inheritance</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>find-method-combination</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>funcallable-standard-instance-access</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-argument-precedence-order</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-declarations</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-lambda-list</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-method-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-method-combination</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-methods</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>generic-function-name</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>intern-eql-specializer</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>make-method-lambda</para></entry><entry
-      align="center"
-      valign="top"><para>-</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>map-dependents</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>method-function</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>method-generic-function</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>method-lambda-list</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>method-qualifiers</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>method-specializers</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>reader-method-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>remove-dependent</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>remove-direct-method</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>remove-direct-subclass</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>remove-method</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>set-funcallable-instance-function</para></entry><entry
-      align="center"
-      valign="top"><para>-</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-boundp-using-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-allocation</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-initargs</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-initform</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-initfunction</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-location</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-name</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-readers</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-type</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-definition-writers</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-makunbound-using-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>slot-value-using-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>specializer-direct-generic-functions</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>specializer-direct-methods</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>standard-instance-access</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>update-dependent</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>validate-superclass</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row><row><entry
-      align="center"
-      valign="top"><para>writer-method-class</para></entry><entry
-      align="center"
-      valign="top"><para>+</para></entry></row></tbody></tgroup></informaltable></para>
-      
-      <para>Note that those generic functions whose status is "-" in
-      the table above deal with the internals of generic function
-      dispatch and method invocation (the "Generic Function Invocation
-      Protocol".) Method functions are implemented a bit differently
-      in OpenMCL from what the MOP expects, and it's not yet clear if
-      or how this subprotocol can be well-supported.</para>
-      <para>Those constructs that are marked as "+" in the table above
-      are nominally implemented as the MOP document specifies
-      (deviations from the specification should be considered bugs;
-      please report them as such.) Note that some CLOS implementations
-      in widespread use (e.g., PCL) implement some things
-      (ENSURE-CLASS-USING-CLASS comes to mind) a bit differently from
-      what the MOP specifies.</para>
-    </sect1>
-
-    <sect1 id="Concurrency-issues">
-      <title>Concurrency issues</title>
-      <para>The entire CLOS class and generic function hierarchy is
-      effectively a (large, complicated) shared data structure; it's
-      not generally practical for a thread to request exclusive access
-      to all of CLOS, and the effects of volitional modification of
-      the CLOS hierarchy (via clas redefinition, CHANGE-CLASS, etc) in
-      a multithreaded environment aren't always tractable.</para>
-      <para>Native threads exacerbate this problem (in that they
-      increase the opportunities for concurrent modification and
-      access.) The implementation should try to ensure that a thread's
-      view of any subset of the CLOS hierarchy is consistent (to the
-      extent that that's possible) and should try to ensure that
-      incidental modifications of the hierarchy (cache updates, etc.)
-      happen atomically; it's not generally possible for the
-      implementation to guarantee that a thread's view of things is
-      correct and current.</para>
-      <para>If you are loading code and defining classes in the most
-      usual way, which is to say, via the compiler, using only a
-      single thread, these issues are probably not going to affect you
-      much.</para>
-      <para>If, however, you are making finicky changes to the class
-      hierarchy while you're running multiple threads which manipulate
-      objects related to each other, more care is required.  Before
-      doing such a thing, you should know what you're doing and
-      already be aware of what precautions to take, without being
-      told.  That said, if you do it, you should seriously consider
-      what your application's critical data is, and use locks for
-      critical code sections.</para>
-    </sect1>
-  </chapter>
-
-  <chapter id="The-Foreign-Function-Interface">
-    <title>The Foreign-Function Interface</title>
-
-    <sect1 id="Specifying-And-Using-Foreign-Types">
-      <title>Specifying And Using Foreign Types</title>
-
-      <sect2 id="Overview-foreign-types">
-	<title>Overview</title>
-        <para>OpenMCL provides a fairly rich language for defining and
-        specifying foreign data types (this language is derived from
-        CMUCL's "alien type" system.)</para>
-        <para>In practice, most foreign type definitions are
-        introduced into OpenMCL via its interface database (see ),
-        though it's also possible to define foreign types
-        interactively and/or programmatically.</para>
-        <para>OpenMCL's foreign type system is "evolving" (a polite
-        word for not-quite-complete): there are some inconsistencies
-        involving package usage, for instance. Symbols used in foreign
-        type specifiers <emphasis>should</emphasis> be keywords, but
-        this convention isn't always enforced.</para>
-        <para>Foreign type, record, and field names are
-        case-sensitive; OpenMCL uses some escaping conventions (see )
-        to allow keywords to be used to denote these names.</para>
-      </sect2>
-
-      <sect2 id="Syntax-of-Foreign-Type-Specifiers">
-        <title>Syntax of Foreign Type Specifiers</title>
-        <itemizedlist>
-          <listitem>
-	    <para>Some foreign types are builtin: keywords denote
-	    primitive,builtin types such as the IEEE-double-float type
-	    (denoted:DOUBLE-FLOAT), in much the same way as certain
-	    symbols(CONS, FIXNUM,etc.) define primitive CL
-	    types.</para>
-	  </listitem>
-          <listitem>
-	    <para>Constructors such as :SIGNED and :UNSIGNED can be
-	    used to denotesigned and unsigned integer subtypes
-	    (analogous to the CL typespecifiers SIGNED-BYTE and
-	    UNSIGNED-BYTE.) :SIGNED is shorthand for(:SIGNED 32) and
-	    :UNSIGNED is shorthand for (:UNSIGNED 32).</para>
-	  </listitem>
-          <listitem>
-	    <para>Aliases for other (perhaps more complicated) types
-	    can bedefined via CCL:DEF-FOREIGN-TYPE (sort of like
-	    CL:DEFTYPE or the Ctypedef facility). The type :CHAR is
-	    defined as an alias for (:SIGNED8) on some platforms, as
-	    (:UNSIGNED 8) on others.</para>
-	  </listitem>
-          <listitem>
-	    <para>The construct (:STRUCT <emphasis>name</emphasis>)
-	    can be used torefer to a named structure type; (:UNION
-	    <emphasis>name</emphasis>)can be used to refer to a named
-	    union type. It isn't necessary toenumerate a structure or
-	    union type's fields in order to refer tothe type.</para>
-	  </listitem>
-          <listitem>
-	    <para>If <emphasis>X</emphasis> is a valid foreign type
-	    reference,then (:* <emphasis>X</emphasis>) denotes the
-	    foreign type "pointerto<emphasis> X</emphasis>". By
-	    convention, (:* T) denotes ananonymous pointer type,
-	    vaguely equivalent to "void*" in C.</para>
-	  </listitem>
-          <listitem>
-	    <para>If a fieldlist is a list of lists, each of whose CAR
-	    is a foreign field name (keyword) and whose CADR is a
-	    foreign type specifier, then (:STRUCT
-	    <emphasis>name</emphasis> ,@fieldlist) is adefinition of
-	    the structure type <emphasis>name</emphasis>,
-	    and (:UNION<emphasis> name</emphasis> ,@fieldlist) is a
-	    definition of theunion type
-	    <emphasis>name</emphasis>. Note that it's necessary
-	    todefine a structure or union type in order to include
-	    that type in a structure, union, or array, but only
-	    necessary to "refer to" a strucure or union type in order
-	    to define a type alias or a pointer type.</para>
-	  </listitem>
-	  <listitem>
-	    <para>If <emphasis>X</emphasis> is a defined foreign type
-	    , then (:array <emphasis>X</emphasis> &amp;rest dims)
-	    denotes the foreigntype "array of
-	    <emphasis>X</emphasis>". Although multiplearray dimensions
-	    are allowed by the :array constructor,
-	    only single-dimensioned arrays are (at all) well-supported
-	    in OpenMCL.</para>
-	  </listitem>
-        </itemizedlist>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Foreign-Function-Calls">
-      <title>Foreign Function Calls</title>
-
-      <sect2 id="Overview-foreign-calls">
-	<title>Overview</title>
-        <para>OpenMCL provides a number of constructs for calling
-        foreign functions from Lisp code (all of them based on the
-        function CCL:%FF-CALL).  In many cases, OpenMCL's interface
-        translator (see ) provides information about the foreign
-        function's entrypoint name and argument and return types; this
-        enables the use of the #_ reader macro (described below),
-        which may be more concise and/or more readable than other
-        constructs.</para>
-        <para>OpenMCL also provides a mechanism for defining
-        <emphasis>callbacks</emphasis>: lisp functions which can be
-        called from foreign code.</para>
-        <para>There's no supported way to directly pass lisp data to
-        foreign functions: scalar lisp data must be coerced to an
-        equivalent foreign representatation, and lisp arrays (notably
-        strings) must be copied to non-GCed memory.</para>
-
-        <sect3 id="Type-Designators-for-Arguments-and-Return-Values">
-	  <title>Type Designators for Arguments and Return Values</title>
-          <para>The types of foreign argument and return values in foreign
-	  function calls and callbacks can be specified by any of the following
-keywords:</para>
-	  <variablelist>
-	    <varlistentry>
-	      <term>:UNSIGNED-BYTE</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (UNSIGNED-BYTE 8)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:SIGNED-BYTE</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (SIGNED-BYTE 8)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:UNSIGNED-HALFWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (UNSIGNED-BYTE 16)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:SIGNED-HALFWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (SIGNED-BYTE 16)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:UNSIGNED-FULLWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (UNSIGNED-BYTE 32)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:SIGNED-FULLWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (SIGNED-BYTE 32)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:UNSIGNED-DOUBLEWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (UNSIGNED-BYTE 64)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:SIGNED-DOUBLEWORD</term>
-
-	      <listitem>
-		<para>The argument/return value is of type (SIGNED-BYTE 64)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:SINGLE-FLOAT</term>
-
-	      <listitem>
-		<para>The argument/return value is of type SINGLE-FLOAT</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:DOUBLE-FLOAT</term>
-
-	      <listitem>
-		<para>The argument/return value is of type DOUBLE-FLOAT</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:ADDRESS</term>
-
-	      <listitem>
-		<para>The argument/return values
-		is <link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link>.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>:VOID</term>
-
-	      <listitem>
-		<para>or NIL Not valid as an argument type specifier; specifies
-		that there is no meaningful return value</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-
-          <para>On some platforms, a small positive integer
-          <emphasis>N</emphasis> can also be used as an argument
-          specifier; it indicates that the corresponding argument is a
-          pointer to an <emphasis>N</emphasis>-word structure or union
-          which should be passed by value to the foreign
-          function.  Exactly which foreign structures are passed
-	  by value and how is very dependent on the Application
-	  Binary Interface (ABI) of the platform; unless you're
-	  very familar with ABI detatils (some of which are quite
-	  baroque), it's often easier to let higher-level constructs
-	  deal with these details.</para>
-        </sect3>
-
-        <sect3 id="External-Entrypoints-and-Named-External-Entrypoints">
-	  <title>External Entrypoints and Named External Entrypoints</title>
-          <para>PowerPC machine instructions are always aligned on
-          32-bit boundaries, so the two least significant bits of the
-          first instruction ("entrypoint") of a foreign function are
-          always 0. OpenMCL often represents an entrypoint address as
-          a fixnum that's binary-equivalent to the entrypoint address:
-          if<emphasis> E</emphasis> is an entrypoint address expressed
-          as a signed 32-bit integer, then (ash <emphasis>E</emphasis>
-          -2) is an equivalent fixnum representation of that
-          address. An entrypoint address can also be encapsulated in a
-          MACPTR (see FIXTHIS), but that's somewhat less efficient.</para>
-          <para>Although it's possible to use fixnums or macptrs to
-          represent entrypoint addresses, it's somewhat cumbersome to
-          do so. OpenMCL can cache the addresses of named external
-          functions in structure-like objects of type
-          CCL:EXTERNAL-ENTRY-POINT (sometimes abbreviated as EEP).
-          Through the use of LOAD-TIME-VALUE, compiled lisp functions
-          are able to reference EEPs as constants; the use of an
-          indirection allows OpenMCL runtime system to ensure that the
-          EEP's address is current and correct.</para>
-        </sect3>
-      </sect2>
-
-      <sect2 id="Return-Conventions-for-C-Structures">
-	<title>Return Conventions for C Structures</title>
-        <para> On some platforms, C functions that are defined to
-        return structures do so by reference: they actually
-        accept a first parameter of type "pointer to returned
-        struct/union" - which must be allocated by the caller - and
-        don't return a meaningful value.</para>
-	<para><emphasis>Exactly</emphasis> how a C function that's
-	defined to return a foreign structure does so is dependent on
-	the ABI (and on the size ad composition of the structure/union
-	in many cases.)</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Referencing-and-Using-Foreign-Memory-Addresses">
-      <title>Referencing and Using Foreign Memory Addresses</title>
-
-      <sect2 id="Overview-memory-addresses">
-        <title>Overview</title>
-
-        <sect3 id="Basics">
-	  <title>Basics</title>
-          <para>For a variety of technical reasons, it isn't generally
-          possible to directly reference arbitrary absolute addresses
-          (such as those returned by the C library function malloc(),
-          for instance) in OpenMCL. In OpenMCL (and in MCL), such
-          addresses need to be <emphasis>encapsulated</emphasis> in
-          objects of type CCL:MACPTR; one can think of a MACPTR as
-          being a specialized type of structure whose sole purpose is
-          to provide a way of referring to an underlying "raw"
-          address.</para>
-          <para>It's sometimes convenient to blur the distinction
-          between a MACPTR and the address it represents; it's
-          sometimes necessary to maintain that distiction. It's
-          important to remember that a MACPTR is (generally) a
-          first-class Lisp object in the same sense that a CONS cell
-          is: it'll get GCed when it's no longer possible to reference
-          it. The "lifetime" of a MACPTR doesn't generally have
-          anything to do with the lifetime of the block of memory its
-          address points to.</para>
-          <para>It might be tempting to ask "How does one obtain the
-          address encapsulated by a MACPTR ?". The answer to that
-          question is that one doesn't do that (and there's no way to
-          do that): addresses aren't first-class objects, and there's
-          no way to refer to one.</para>
-          <para>Two MACPTRs that encapsulate the same address are EQL
-          to each other.</para>
-          <para>There are a small number of ways to directly create a
-          MACPTR (and there's a fair amount of syntactic sugar built
-          on top of of those primitives.) These primitives will be
-          discussed in greater detail below, but they include:</para>
-
-	  <itemizedlist>
-            <listitem>
-	    <para>Creating a MACPTR with a specified address, usually
-	    via thefunction CCL:%INT-TO-PTR.</para>
-	    </listitem>
-            <listitem>
-	      <para>Referencing the return valueof a foreign function
-	      call (see )that's specified to return an address.</para>
-	    </listitem>
-            <listitem>
-	      <para>Referencing a memory location that's specified to
-	      contain an address.</para>
-	    </listitem>
-	  </itemizedlist>
-
-          <para>All of these primitive MACPTR-creating operations are
-          usually open-coded by the compiler; it has a fairly good
-          notion of what low-level operations "produce" MACPTRs and
-          which operations "consume" the addresses that the
-          encapsulate, and will usually optimize out the introduction
-          of intermediate MACPTRs in a simple expression.</para>
-          <para>One consequence of the use of MACPTR objects to
-          encapsulate foreign addresses is that (naively)
-          <emphasis>every reference to a foreign address causes a
-          MACPTR to be allocated.</emphasis></para>
-          <para>Consider a code fragment like the following:</para>
-          <programlisting>
-(defun get-next-event ()
-  "get the next event from a hypothetical window system"
-  (loop
-    (let* ((event (#_get_next_window_system_event))) ; via an FF-CALL
-          (unless (null-event-p event)
-            (handle-event event)))))
-</programlisting>
-          <para>As this is written, each call to the (hypothetical)
-          foreign function #_get_next_window_system_event will return
-          a new MACPTR object.  Ignoring for the sake of argument the
-          question of whether this code fragment exhibits a good way
-          to poll for external events (it doesn't), it's not hard to
-          imagine that this loop could execute several millon times
-          per second (producing several million MACPTRs per second.)
-          Clearly, the "naive" approach is impractical in many
-          cases.</para>
-        </sect3>
-
-        <sect3 id="Stack-allocation-of---and-destructive-operations-on---MACPTRs-">
-          <title>Stack allocation of - and destructive operations on - MACPTRs.</title>
-	  <para>If certain conditions held in the environment in which
-	  GET-NEXT-EVENT ran - namely, if it was guaranteed that
-	  neither NULL-EVENT-P nor HANDLE-EVENT cached or otherwise
-	  retained their arguments (the "event" pointer) - there'd be
-	  a few alternatives to the naive approach. One of those
-	  approaches would be to use the primitive function
-	  %SETF-MACPTR (described in greater detail below) to
-	  destructively modify a MACPTR (to change the value of the
-	  address it encapsulates.) The GET-NEXT-EVENT example could
-	  be re-written as:</para>
-          <programlisting>
-(defun get-next-event ()
-  (let* ((event (%int-to-ptr 0))) ; create a MACPTR with address 0
-    (loop
-      (%setf-macptr event (#_get_next_window_system_event)) ; re-use it
-      (unless (null-event-p event)
-        (handle-event event)))))
-</programlisting>
-          <para>That version's a bit more realistic: it allocates a
-          single MACPTR outside if the loop, then changes its address
-          to point to the current address of the hypothetical event
-          structure on each loop iteration. If there are a million
-          loop iterations per call to GET-NEXT-EVENT, we're allocating
-          a million times fewer MACPTRs per call; that sounds like a
-          Good Thing.</para>
-          <para>An Even Better Thing would be to advise the compiler
-          that the initial value (the null MACPTR) bound to the
-          variable event has dynamic extent (that value won't be
-          referenced once control leaves the extent of the binding of
-          that variable.) Common Lisp allows us to make such an
-          assertion via a DYNAMIC-EXTENT declaration; OpenMCL's
-          compiler can recognize the "primitive MACPTR-creating
-          operation" involved and can replace it with an equivalent
-          operation that stack-allocates the MACPTR object. If we're
-          not worried about the cost of allocating that MACPTR on
-          every iteration (the cost is small and there's no hidden GC
-          cost), we could move the binding back inside the
-          loop:</para>
-          <programlisting>
-(defun get-next-event ()
-  (loop
-    (let* ((event (%null-ptr))) ; (%NULL-PTR) is shorthand for (%INT-TO-PTR 0)
-      (declare (dynamic-extent event))
-      (%setf-macptr event (#_get_next_window_system_event))
-      (unless (null-event-p event)
-        (handle-event event)))))
-</programlisting>
-          <para>The idiom of binding one or more variables to
-          stack-allocated MACPTRs, then destructively modifying those
-          MACPTRs before executing a body of code is common enough
-          that OpenMCL provides a macro (WITH-MACPTRS) that handles
-          all of the gory details. The following version of
-          GET-NEXT-EVENT is semantically equivalent to the previous
-          version, but hopefully a bit more concise:</para>
-          <programlisting>
-(defun get-next-event ()
-  (loop
-    (with-macptrs ((event (#_get_next_window_system_event)))
-      (unless (null-event-p event)
-        (handle-event event)))))
-</programlisting>
-        </sect3>
-
-        <sect3 id="Stack-allocated-memory--and-stack-allocated-pointers-to-it--">
-          <title>Stack-allocated memory (and stack-allocated pointers to it.)</title>
-	  <para>Fairly often, the blocks of foreign memory (obtained
-	  by malloc or something similar) have well-defined lifetimes
-	  (they can safely be freed at some point when it's known that
-	  they're no longer needed and it's known that they're no
-	  longer referenced.) A common idiom might be:</para>
-          <programlisting>
-(with-macptrs (p (#_allocate_foreign_memory size))
-  (unwind-protect
-    (use-foreign-memory p)
-    (#_deallocate_foreign_memory p)))
-</programlisting>
-          <para>That's not unreasonable code, but it's fairly
-          expensive for a number of reasons: foreign functions calls
-          are themselves fairly expensive (as is UNWIND-PROTECT), and
-          most library routines for allocating and deallocating
-          foreign memory (things like malloc and free) can be fairly
-          expensive in their own right.</para>
-          <para>In the idiomatic code above, both the MACPTR P and the
-          block of memory that's being allocated and freed have
-          dynamic extent and are therefore good candidates for stack
-          allocation. OpenMCL provides the %STACK-BLOCK macro, which
-          executes a body of code with one or more variables bound to
-          stack-allocated MACPTRs which encapsulate the addresses of
-          stack-allocated blocks of foreign memory. Using
-          %STACK-BLOCK, the idiomatic code is:</para>
-          <programlisting>
-(%stack-block ((p size))
-  (use-foreign-memory p))
-</programlisting>
-          <para>which is a bit more efficient and a bit more concise
-          than the version presented earlier.</para>
-          <para>%STACK-BLOCK is used as the basis for slightly
-          higher-level things like RLET. (See FIXTHIS for more information
-          about RLET.)</para>
-        </sect3>
-
-        <sect3 id="Caveats-">
-	  <title>Caveats.</title>
-          <para>Reading from, writing to, allocating, and freeing
-          foreign memory are all potentially dangerous operations;
-          this is no less true when these operations are performed in
-          OpenMCL than when they're done in C or some other
-          lower-level language. In addition, destructive operations on
-          Lisp objects be dangerous, as can stack allocation if it's
-          abused (if DYNAMIC-EXTENT declarations are violated.)
-          Correct use of the constructs and primitives described here
-          is reliable and safe; slightly incorrect use of these
-          constructs and primitives can crash OpenMCL.</para>
-        </sect3>
-      </sect2>
-
-      <sect2 id="Foreign-Memory-Addresses-Dictionary">
-	<title>Foreign-Memory-Addresses Dictionary</title>
-        <para>Unless otherwise noted, all of the symbols mentioned
-        below are exported from the CCL package.</para>
-
-        <sect3 id="Scalar-memory-reference">
-          <title>Scalar memory reference</title>
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%get-signed-byte ptr &#38;optional (offset 0)</para>
-
-		<para>%get-unsigned-byte ptr &#38;optional (offset 0)</para>
-
-		<para>%get-signed-word ptr &#38;optional (offset 0)</para>
-
-		<para>%get-unsigned-word ptr &#38;optional (offset 0)</para>
-
-		<para>%get-signed-long ptr &#38;optional (offset 0)</para>
-
-		<para>%get-unsigned-long ptr &#38;optional (offset 0)</para>
-
-		<para>%%get-signed-longlong ptr &#38;optional (offset 0)</para>
-
-		<para>%%get-unsigned-longlong ptr &#38;optional (offset 0)</para>
-
-		<para>%get-ptr ptr &#38;optional (offset 0)</para>
-
-		<para>%get-single-float ptr &#38;optional (offset 0)</para>
-
-		<para>%get-double-float ptr &#38;optional (offset 0)</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>References and returns the signed or unsigned 8-bit byte,
-		signed or unsigned 16-bit word, signed or unsigned 32-bit long
-		word, signed or unsigned 64-bit long long word, 32-bit address,
-		32-bit single-float, or 64-bit double-float at the effective byte
-		address formed by adding offset to the address encapsulated by
-		ptr.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>offset</term>
-
-		    <listitem>
-		      <para>A fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-
-          <para>All of the memory reference primitives described above can be</para>
-          <para>used with SETF.</para>
-        </sect3>
-
-        <sect3 id="iget-bit--Function-">
-	  <title>%get-bit [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%get-bit ptr bit-offset</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>References and returns the bit-offsetth bit at the address
-		encapsulated by ptr. (Bit 0 at a given address is the most
-		significant bit of the byte at that address.) Can be used with
-		SETF.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>bit-offset</term>
-
-		    <listitem>
-		      <para>A fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-        </sect3>
-
-        <sect3 id="iget-bitfield--Function-">
-          <title>%get-bitfield [Function]</title>
- 	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%get-bitfield ptr bit-offset width</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>References and returns an unsigned integer composed from the
-		width bits found bit-offsetbits from the address encapsulated by
-		ptr. (The least significant bit of the result is the value of
-		(%get-bit ptr (1- (+ bit-offset width))). Can be used with SETF.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>ptr</term>
-
-	      <listitem>
-		<para>A MACPTR</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>bit-offset</term>
-
-		    <listitem>
-		      <para>A fixnum</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>width</term>
-
-		    <listitem>
-		      <para>A positive fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-        </sect3>
-
-	<sect3>
-	  <title>%int-to-ptr [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%int-to-ptr int</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Creates and returns a MACPTR whose address matches int.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>int</term>
-
-		    <listitem>
-		      <para>An (unsigned-byte 32)</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%inc-ptr [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%inc-ptr ptr &#38;optional (delta 1)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Creates and returns a MACPTR whose address is the address of
-		ptr plus delta. The idiom (%inc-ptr ptr 0) is sometimes used to
-		copy a MACPTR, e.g., to create a new MACPTR encapsulating the same
-		address as ptr.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>delta</term>
-
-		    <listitem>
-		      <para>A fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%ptr-to-int [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%ptr-to-int ptr</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Returns the address encapsulated by ptr, as an
-		(unsigned-byte 32).</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%null-ptr [Macro]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%null-ptr</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Equivalent to (%ptr-to-int 0).</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%null-ptr-p [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%null-ptr-p ptr</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Returns T If ptr is a MACPTR encapsulating the address 0,
-		NIL if ptr encapsulates some other address.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%setf-macptr [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%setf-macptr dest-ptr src-ptr</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Causes dest-ptr to encapsulate the same address that src-ptr
-		does, then returns dest-ptr.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>dest-ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>src-ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%incf-ptr [Macro]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%incf-ptr ptr &#38;optional (delta 1)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Destructively modifies ptr, by adding delta to the address
-		it encapsulates. Returns ptr.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>delta</term>
-
-		    <listitem>
-		      <para>A fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>with-macptrs [Macro]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>with-macptrs (var expr)* &#38;body body</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Executes body in an environment in which each var is bound
-		to a stack-allocated macptr which encapsulates the foreign address
-		yielded by the corresponding expr. Returns whatever value(s) body
-		returns.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>var</term>
-
-		    <listitem>
-		      <para>A symbol (variable name)</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>expr</term>
-
-		    <listitem>
-		      <para>A MACPTR-valued expression</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%stack-block [Macro]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%stack-block (var expr)* &#38;body body</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Executes body in an environment in which each var is bound
-		to a stack-allocated macptr which encapsulates the address of a
-		stack-allocated region of size expr bytes. Returns whatever
-		value(s) body returns.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>var</term>
-
-		    <listitem>
-		      <para>A symbol (variable name)</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>expr</term>
-
-		    <listitem>
-		      <para>An expression which should evaluate to a non-negative
-		      fixnum</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	  <sect3>
-	    <title>make-cstring [Function]</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>Syntax</term>
-
-		<listitem>
-		  <para>make-cstring string</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>Description</term>
-
-		<listitem>
-		  <para>Allocates a block of memory (via malloc) of length (1+
-		  (length string)). Copies the string to this block and appends a
-		  trailing NUL byte; returns a MACPTR to the block.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>Arguments</term>
-
-		<listitem>
-		  <para>&#x00A0;</para>
-
-		  <variablelist>
-		    <varlistentry>
-		      <term>string</term>
-
-		      <listitem>
-			<para>A lisp string</para>
-		      </listitem>
-		    </varlistentry>
-		  </variablelist>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </sect3>
-
-	<sect3>
-	  <title>with-cstrs [Macro]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>with-cstrs (var string)* &#38;body body</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Executes body in an environment in which each var is bound
-		to a stack-allocated macptr which encapsulates the %address of a
-		stack-allocated region of into which each string (and a trailing
-		NUL byte) has been copied. Returns whatever value(s) body returns.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para>&#x00A0;</para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>var</term>
-
-		    <listitem>
-		      <para>A symbol (variable name)</para>
-		    </listitem>
-		  </varlistentry>
-
-		  <varlistentry>
-		    <term>string</term>
-
-		    <listitem>
-		      <para>An expression which should evaluate to a lisp string</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%get-cstring [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%get-cstring ptr</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Interprets ptr as a pointer to a (NUL -terminated) C string;
-		returns an equivalent lisp string.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para></para>
-
-		<variablelist>
-		  <varlistentry>
-		    <term>ptr</term>
-
-		    <listitem>
-		      <para>A MACPTR</para>
-		    </listitem>
-		  </varlistentry>
-		</variablelist>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-
-	<sect3>
-	  <title>%str-from-ptr [Function]</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>Syntax</term>
-
-	      <listitem>
-		<para>%str-from-ptr ptr length</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Description</term>
-
-	      <listitem>
-		<para>Returns a lisp string of length <varname>length</varname>,
-		whose contents are initialized from the bytes at<varname> ptr.</varname>
-		</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>Arguments</term>
-
-	      <listitem>
-		<para><variablelist><varlistentry><term>ptr</term><listitem><para>A
-		MACPTR</para></listitem></varlistentry><varlistentry><term>length</term><listitem><para>a
-		non-negative fixnum</para></listitem></varlistentry></variablelist></para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</sect3>
-      </sect2>
-    </sect1>
-
-    <sect1 id="The-Interface-Database">
-      <title>The Interface Database</title>
-
-      <sect2 id="interface-database-Overview">
-	<title>Overview</title>
-        <para>OpenMCL uses a set of database files which contain
-        foreign type, record, constant, and function definitions
-        derived from the operating system's header files, be that
-        Linux or Darwin.  An archive containing these database files
-        (and the shell scripts which were used in their creation) is
-        available; see the Distributions page for information about
-        obtaining current interface database files.</para>
-        <para>Not surprisingly, different platforms use different database files.</para>
-        <para>OpenMCL defines reader macros that consult these databases:</para>
-	<itemizedlist>
-          <listitem>
-	    <para>#$foo looks up the value of the constant definition of foo</para>
-	  </listitem>
-	  <listitem>
-	    <para>#_foo looks up the foreign function definition for foo</para>
-	  </listitem>
-        
-        </itemizedlist>
-        <para>In both cases, the symbol foo is interned in the "OS"
-        package. The #$ reader macro has the side-effect of defining
-        foo as a constant (as if via DEFCONSTANT); the #_ reader macro
-        has the side effect of defining foo as a macro which will
-        expand into an (EXTERNAL-CALL form.)</para>
-        <para>It's important to remember that the side-effect happens
-        when the form containing the reader macro is
-        read. Macroexpansion functions that expand into forms which
-        contain instances of those reader macros don't do what one
-        might think that they do, unless the macros are expanded in
-        the same lisp session as the reader macro was read in.</para>
-        <para>In addition, references to foreign type,
-        structure/union, and field names (when used in the RREF/PREF
-        and RLET macros) will cause these database files to be
-        consulted.</para>
-        <para>Since the OpenMCL sources contain instances of these
-        reader macros (and references to foreign record types and
-        fields), compiling OpenMCL from those sources depends on the
-        ability to find and use (see <xref
-        linkend="Building-the-heap-image"/>).</para>
-      </sect2>
-
-      <sect2 id="Other-issues">
-        <title>Other issues:</title>
-        <itemizedlist>
-          <listitem>
-	    <para>OpenMCL now preserves the case of external symbols
-	    in itsdatabase files. See for information about case in
-	    foreign symbol names.</para>
-	  </listitem>
-	  <listitem>
-	    <para>The Linux databases are derived from a somewhat
-	    arbitrary set of Linux header files. Linux is enough of a
-	    moving target that it may be difficult to define a standard,
-	    reference set of interfaces from which to derive a standard,
-	    reference set of database files.This seems to be less of
-	    an issue with Darwin and FreeBSD.</para>
-	  </listitem>
-	</itemizedlist>
-        <para>For information about building the database files,
-	see <xref linkend="The-Interface-Translator"/>.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Using-Interface-Directories">
-      <title>Using Interface Directories</title>
-
-      <sect2 id="Interface-Directory-Overview">
-	<title>Overview</title>
-        <para>As distributed, the "ccl:headers;" (for LinuxPPC)
-        directory is organized like:</para>
-        <programlisting>
-headers/
-headers/gl/
-headers/gl/C/
-headers/gl/C/populate.sh
-headers/gl/constants.cdb
-headers/gl/functions.cdb
-headers/gl/records.cdb
-headers/gl/objc-classes.cdb
-headers/gl/objc-methods.cdb
-headers/gl/types.cdb
-headers/gnome/
-headers/gnome/C/
-headers/gnome/C/populate.sh
-headers/gnome/constants.cdb
-headers/gnome/functions.cb
-headers/gnome/records.cdb
-headers/gnome/objc-classes.cdb
-headers/gnome/objc-methods.cdb
-headers/gnome/types.cdb
-headers/gtk/
-headers/gtk/C/
-headers/gtk/C/populate.sh
-headers/gtk/constants.cdb
-headers/gtk/functions.cdb
-headers/gtk/records.cdb
-headers/gtk/objc-classes.cdb
-headers/gtk/objc-methods.cdb
-headers/gtk/types.cdb
-headers/libc/
-headers/libc/C/
-headers/libc/C/populate.sh
-headers/libc/constants.cdb
-headers/libc/functions.cdb
-headers/libc/records.cdb
-headers/libc/objc-classes.cdb
-headers/libc/objc-methods.cdb
-headers/libc/types.cdb
-</programlisting>
-        <para>e.g, as a set of parallel subdirectories, each with a
-        lowercase name and each of which contains a set of 6 database
-        files and a "C" subdirectory which contains a shell script
-        used in the database creation process.</para>
-        <para>As one might assume, the database files in each of these
-        subdirectories contain foreign type, constant, and function
-        definitions - as well as ObjC class and method info -that
-        correspond (roughly) to the information contained in the
-        header files associated with a "-dev" package in a Linux
-        distribution.  "libc" corresponds pretty closely to the
-        interfaces associated with "glibc/libc6" header files, "gl"
-        corresponds to an "openGL+GLUT" developmnent package, "gtk"
-        and "gnome" contain interface information from the GTK+1.2 and
-        GNOME libraries, respectively.</para>
-        <para>For Darwin, the "ccl:darwin-headers" directory contains
-        a "libc" subdirectory, whose contents roughly correspond to
-        those of "/usr/include" under Darwin, as well as
-        subdirectories corresponding to the MacOSX Carbon and Cocoa
-        frameworks.</para>
-        <para>To see the precise set of .h files used to generate the
-        database files in a given interface directory, consult the
-        corresponding "populate.sh" shell script (in the interface
-        directory's "C" subdirectory.)</para>
-        <para>The intent is that this initial set can be augmented to
-        meet local needs, and that this can be done in a fairly
-        incremental fashion: one needn't have unrelated header files
-        installed in order to generate interface databases for a
-        package of interest.</para>
-        <para>Hopefully, this scheme will also make it easier to
-        distribute patches and bug fixes.</para>
-        <para>OpenMCL maintains a list of directories; when looking
-        for a foreign type, constant, function, or record definition,
-        it'll consult the database files in each directory on that
-        list. Initially, the list contains an entry for the "libc"
-        interface directory. OpenMCL needs to be explicitly told to
-        look in other interface directories should it need to do
-        so.</para>
-      </sect2>
-
-      <sect2 id="Creating-new-interface-directories">
-	<title>Creating new interface directories</title>
-        <para>This example refers to "ccl:headers;", which is
-        appropriate for LinuxPPC. The procedure's analogous under
-        Darwin, where the "ccl:darwin-headers;" directory would be
-        used instead.</para>
-        <para>To create a new interface directory, "foo", and a set of
-        database files in that directory:</para>
-	<orderedlist continuation="restarts" inheritnum="ignore">
-	  <listitem>
-	    <para>Create a subdirectory of &#34;ccl:headers;&#34; named
-	    &#34;foo&#34;.</para>
-	  </listitem>
-
-	  <listitem>
-	    <para>Create a subdirectory of &#34;ccl:headers;foo;&#34; named
-	    &#34;C&#34;.</para>
-	  </listitem>
-
-	  <listitem>
-	    <para>Create a file in &#34;ccl:headers;foo;C;&#34; named
-	    &#34;populate.sh&#34;.</para>
-
-	    <para>One way of accomplishing the above steps is:</para>
-
-	    <programlisting format="linespecific">? (close (open &#34;ccl:headers;foo;C;populate.sh&#34; :direction :output :
-               if-does-not-exist :create :if-exists :overwrite))</programlisting>
-	  </listitem>
-
-	  <listitem>
-	    <para>Edit the file created above, using the &#34;populate.sh&#34;
-	    files in the distribution as guidelines.</para>
-
-	    <para>The file might wind up looking something like:</para>
-
-	    <programlisting format="linespecific">#/bin/sh
-h-to-ffi.sh `foo-config -cflags` /usr/include/foo/foo.h</programlisting>
-	  </listitem>
-	</orderedlist>
-
-        <para>Refer to <xref linkend="The-Interface-Translator"/> for
-        information about running the interface translator and .ffi
-        parser.</para>
-        <para>Assuming that all went well, there should now be .cdb
-        files in "ccl:headers;foo;". You can then do
-        <programlisting>
-? (use-interface-dir :foo)
-	</programlisting> 
-	whenever you need to
-        access the foreign type information in those database
-        files.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Using-Shared-Libraries">
-      <title>Using Shared Libraries</title>
-
-      <sect2 id="Shared-Library-Overview">
-	<title>Overview</title>
-
-        <para>OpenMCL provides facilities to open and close shared
-        libraries.</para>
-        <para>"Opening" a shared library, which is done with <xref
-        linkend="f_open-shared-library"/>, maps the library's code and
-        data into OpenMCL's address space and makes its exported
-        symbols accessible to OpenMCL.</para>
-        <para>"Closing" a shared library, which is done with <xref
-        linkend="f_close-shared-library"/>, unmaps the library's code
-        and and removes the library's symbols from the global
-        namespace.</para>
-        <para>A small number of shared libraries (including libc,
-        libm, libdl under Linux, and the "system" library under
-        Darwin) are opened by the lisp kernel and can't be
-        closed.</para>
-        <para>OpenMCL uses data structures of type
-        EXTERNAL-ENTRY-POINT to map a foreign function name (string)
-        to that foreign function's <emphasis>current</emphasis>
-        address. (A function's address may vary from session to
-        session as different versions of shared libraries may load at
-        different addresses; it may vary within a session for similar
-        reasons.)</para>
-        <para>An EXTERNAL-ENTRY-POINT whose address is known is said
-        to be <emphasis>resolved</emphasis>. When an external entry
-        point is resolved, the shared library which defines that entry
-        point is noted; when a shared library is closed, the entry
-        points that it defines are made unresolved.  An
-        EXTERNAL-ENTRY-POINT must be in the resolved state in order to
-        be FF-CALLed; calling an unresolved entry point causes a "last
-        chance" attempt to resolve it. Attempting to resolve an
-        entrypoint that was defined in a closed library will cause an
-        attempt to reopen that library.</para>
-        <para>OpenMCL keeps track of all libraries that have been
-        opened in a lisp session. When a saved application is first
-        started, an attempt is made to reopen all libraries that were
-        open when the image was saved, and an attempt is made to
-        resolve all entrypoints that had been referenced when the
-        image was saved. Either of these attempts can fail "quietly",
-        leaving some entry points in an unresolved state.</para>
-        <para>Linux shared libraries can be referred to either by a
-        string which describes their full pathname or by their
-        <emphasis>soname</emphasis>, a shorter string that can be
-        defined when the library is created. The dynamic linker
-        mechanisms used in Linux make it possible (through a series of
-        filesystem links and other means) to refer to a library via
-        several names; the library's soname is often the most
-        appropriate identifier.</para>
-        <para>sonames are often less version-specific than other names
-        for libraries; a program that refers to a library by the name
-        "libc.so.6" is more portable than one which refers to
-        "libc-2.1.3.so" or to "libc-2.2.3.so", even though the latter
-        two names might each be platform-specific aliases of the
-        first.</para>
-        <para>All of the global symbols described below are exported
-        from the CCL package.</para>
-      </sect2>
-
-      <sect2 id="Limitations-and-known-bugs--1-">
-        <title>Limitations and known bugs</title>
-	<itemizedlist>
-          <listitem>
-	    <para>Don't get me started.</para>
-	  </listitem>
-          <listitem>
-	    <para>The underlying functionality has a poor notion of
-	    dependency;it's not always possible to open libraries that
-	    depend on unopened libraries, but it's possible to close
-	    libraries on which other libraries depend. It
-	    <emphasis>may</emphasis> be possible to generate
-	    more explicit dependency information by parsing the output
-	    of the Linux ldd and ldconfig programs.</para>
-	  </listitem>
-        
-	</itemizedlist>
-      </sect2>
-
-      <sect2 id="Darwin-Notes">
-        <title>>Darwin Notes</title>
-	<para>Darwin shared libraries come in two (basic) flavors:</para>
-	<itemizedlist>
-          <listitem>
-	    <para>"dylibs" (which often have the extension".dylib")
-	    are primarily intended to be linked against atcompile/link
-	    time. They can be loaded dynamically,<emphasis>but can't
-	    be unloaded</emphasis>. Accordingly,OPEN-SHARED-LIBRARY
-	    can be used to open a .dylib-style library;calling
-	    CLOSE-SHARED-LIBRARY on the result of such a callproduces
-	    a warning, and has no other effect.It appears that (due to
-	    an OS bug) attempts to open .dylibshared-libraries that
-	    are already open can cause memory corruptionunless the
-	    full pathname of the .dylib file is specified on thefirst
-	    and all subsequent calls.</para>
-	  </listitem>
-          <listitem>
-	    <para>"bundles" are intended to serve as application
-	    extensions; they can be opened multiple times (creating
-	    multiple instances of the library!) and closed
-	    properly.</para>
-          </listitem>
-	</itemizedlist>
-        <para>Thanks to Michael Klingbeil for getting both kinds of
-        Darwin shared libraries working in OpenMCL.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="The-Interface-Translator">
-      <title>The Interface Translator</title>
-
-      <sect2 id="Inteface-translator-overview">
-	<title>Overview</title>
-	<para>OpenMCL uses an interface translation system based on the FFIGEN
-	system, which is described at
-	http://www.ccs.neu.edu/home/lth/ffigen/.
-	The interface translator makes
-	the constant, type, structure, and function definitions in a set of
-	C-language header files available to lisp code.</para>
-        <para>The basic idea of the FFIGEN scheme is to use the C
-        compiler's frontend and parser to translate .h files into
-        semantically equivalent .ffi files, which represent the
-        definitions from the headers using a syntax based on
-        S-expressions.  Lisp code can then concentrate on the .ffi
-        representation, without having to concern itself with the
-        semantics of header file inclusion or the arcana of C
-        parsing.</para>
-        <para>The original FFIGEN system used a modified version of
-        the LCC C compiler to produce .ffi files. Since many LinuxPPC
-        header files contain GCC-specific constructs, OpenMCL's
-        translation system uses a modified version of GCC (called,
-        somewhat confusingly, ffigen.)</para>
-        <para>A version of ffigen based on GCC-4.0 was developed
-        during the spring and summer of 2005.  Sources (diffs relative
-        to the GCC-4.0 release) are available here, and binaries are
-        available for DarwinPPC and for LinuxPPC.  These versions
-        should be insensitive to to the version of GCC (and its
-        preprocessor) installed on the system.</para>
-        <para>An older version was developed in 2001-2002; it depended
-        on the installed version of GCC being 2.95.  It may still be
-        of interest for people unable to run the GCC-4.0-based version
-        for whatever reason.</para>
-        <para>A LinuxPPC binary of this older version is available at
-        ftp://clozure.com/pub/ffigen-0.1.tar.gz, and LinuxPPC source
-        differences are at
-        ftp://clozure.com/pub/ffigen-src.tar.gz.</para>
-        <para>For Darwin, the binary of the older FFIGEN is available
-        at ftp://clozure.com/pub/ffigen-darwin.tar.gz, and the source
-        differences are at
-        ftp://clozure.com/pub/ffigen-darwin-src.tar.gz.</para>
-        <para>A shell script (distributed with the source and binary
-        packages) called h-to-ffi.sh reads a specified .h file (and
-        optional preprocessor arguments) and writes a (hopefully)
-        equivalent .ffi file to standard output, calling the installed
-        C preprocessor and the ffigen program with appropriate
-        arguments.</para>
-        <para>For each interface directory (see FIXTHIS)
-        <emphasis>subdir</emphasis> distributed with OpenMCL, a shell
-        script (distributed with OpenMCL as
-        "ccl:headers;<emphasis>subdir</emphasis>;C;populate.sh"
-        ("ccl:darwin-headers;<emphasis>subdir</emphasis>;C;populate.sh"
-        for Darwin)) calls h-to-ffi.sh on a large number of the header
-        files in /usr/include (or some other <emphasis>system header
-        path</emphasis>) and creates a parallel directory tree in
-        "ccl:headers;<emphasis>subdir</emphasis>;C;<emphasis>system</emphasis>;<emphasis>header</emphasis>;<emphasis>path</emphasis>;"
-        (or
-        "ccl:darwin-headers;<emphasis>subdir</emphasis>;C;<emphasis>system</emphasis>;<emphasis>header</emphasis>;<emphasis>path</emphasis>;"),
-        populating that directory with .ffi files.</para>
-        <para>A lisp function defined in "ccl:library;parse-ffi.lisp"
-        reads the .ffi files in a specified interface directory
-        <emphasis>subdir</emphasis> and generates new versions of the
-        databases (files with the extension .cdb).</para>
-        <para>The CDB databases are used by the #$ and #_ reader
-        macros and are used in the expansion of RREF, RLET, and
-        related macros.</para>
-      </sect2>
-
-      <sect2 id="Details--rebuilding-the-CDB-databases--step-by-step">
-        <title>Details: rebuilding the CDB databases, step by step</title>
-	<orderedlist>
-	  <listitem>
-	    <para>Ensure that the FFIGEN program is installed. See
-	    the"README" file in the source or binary archive for
-	    specificinstallation instructions.This example assumes
-	    LinuxPPC; for 32-bit DarwinPPC,
-	    substitute"ccl:darwin-headers;" for "ccl:headers;".  For
-	    64-bit DarwinPPC,substitute
-	    "ccl:darwin-headers64;".</para>
-	  </listitem>
-          <listitem>
-	    <para>Edit the
-	    "ccl:headers;<emphasis>subdir</emphasis>;C;populate.sh"shell
-	    script. When you're confident that the files
-	    andpreprocessor options match your environment, cd to
-	    the"ccl:headers;<emphasis>subdir</emphasis>;C;" directory
-	    andinvoke ./populate.sh. Repeat this step until you're
-	    able tocleanly translate all files refrenced in the shell
-	    script.</para>
-	  </listitem>
-	  <listitem>
-	    <para>Run OpenMCL:
-            <programlisting>
-? (require "PARSE-FFI")
-PARSE-FFI
-
-? (parse-standard-ffi-files :SUBDIR)
-;;; lots of output ... after a while, shiny new .cdb files should
-;;; appear in "ccl:headers;subdir;"
-;;; (or "ccl:darwin-headers;subdir;" under Darwin)
-</programlisting></para>
-	  </listitem>
-	</orderedlist>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Case-sensitivity-of-foreign-names-in-OpenMCL">
-      <title>Case-sensitivity of foreign names in OpenMCL</title>
-
-      <sect2 id="Case-sensitivity-overview">
-	<title>Overview</title>
-	<para>As of release 0.11, OpenMCL addresses the fact that
-	foreign type, constant, record, field, and function nams are
-	case-sensitive and provides mechanisms to refer to these names
-	via lisp symbols.</para>
-        <para>Previous versions of OpenMCL have tried to ignore that
-        fact, under the belief that case conflicts were rare and that
-        many users (and implementors) would prefer not to deal with
-        case-related issues. The fact that some information in the
-        interface databases was incomplete or inaccessable because of
-        this policy made it clearer that the policy was untenable. I
-        can't claim that the approach described here is aesthetically
-        pleasing, but I can honestly say that it's less unpleasant
-        than other approaches that I'd thought of. I'd be interested
-        to hear alternate proposals.</para>
-        <para>The issues described here have to do with how lisp
-        symbols are used to denote foreign functions, constants,
-        types, records, and fields. It doesn't affect how other lisp
-        objects are sometimes used to denote foreign objects. For
-        instance, the first argument to the EXTERNAL-CALL macros is
-        now and has always been a case-sensitive string.</para>
-      </sect2>
-
-      <sect2 id="Foreign-constant-and-function-names">
-	<title>Foreign constant and function names</title>
-        <para>The primary way of referring to foreign constant and
-        function names in OpenMCL is via the #$ and #_ reader
-        macros. These reader macro functions each read a symbol into
-        the "OS" package, look up its constant or function definition
-        in the interface database, and assign the value of the
-        constant to the symbol or install a macroexpansion function on
-        the symbol.</para>
-        <para>In order to observe case-sensitivity, the reader-macros
-        now read the symbol with (READTABLE-CASE :PRESERVE) in
-        effect.</para>
-        <para>This means that it's necessary to type the foreign
-        constant or function name in correct case, but it isn't
-        necessary to use any special escaping constructs when writing
-        the variable name. For instance:</para>
-        <programlisting>
-(#_read fd buf n) ; refers to foreign symbol "read"
-(#_READ fd buf n) ; refers to foreign symbol "READ", which may
-; not exist ...
-#$o_rdonly ; Probably doesn't exist
-#$O_RDONLY ; Exists on most platforms
-</programlisting>
-      </sect2>
-
-      <sect2 id="Foreign-type--record--and-field-names">
-	<title>Foreign type, record, and field names</title>
-	<para>Constructs like RLET expect a foreign type or record
-	name to be denoted by a symbol (typically a keyword); RREF
-	(and PREF) expect an "accessor" form, typically a keyword
-	formed by concatenating a foreign type or record name with a
-	sequence of one or more foreign field names, separated by
-	dots. These names are interned by the reader as other lisp
-	symbols are, with an arbitrary value of READTABLE-CASE in
-	effect (typically :UPCASE.) It seems like it would be very
-	tedious to force users to manually escape (via vertical bar or
-	backslash syntax) all lowercase characters in symbols used to
-	specify foreign type, record, and field names (especially
-	given that many traditional POSIX structure, type, and field
-	names are entirely lowercase.)</para>
-        <para>The approach taken by OpenMCL is to allow the symbols
-        (keywords) used to denote foreign type, record, and field
-        names to contain angle brackets (<literal>&lt;</literal> and
-        <literal>&gt;</literal>). Such symbols are translated to
-	foreign names via the following set of conventions:</para>
-	<itemizedlist>
-          <listitem>
-	    <para>All instances of &lt; and &gt; in the symbol's pname
-	    are balanced and don't nest.</para>
-	  </listitem>
-          <listitem>
-	    <para>Any alphabetic characters in the symbol's pname
-	    thataren't enclosed in angle brackets are treated as
-	    lower-case,regardless of the value of READTABLE-CASE and
-	    regardless of the case in which they were written.</para>
-	  </listitem>
-          <listitem>
-	    <para>Alphabetic characters that appear within angle
-	    brackets aremapped to upper-case, again regardless of how
-	    they were written orinterned.</para>
-	  </listitem>
-        </itemizedlist>
-	<para>There may be many ways of "escaping" (with angle
-	brackets) sequences of upper-case and non-lower-case
-	characters in a symbol used to denote a foreign name. When
-	translating in the other direction, OpenMCL always escapes the
-	longest sequence that starts with an upper-case character and
-	doesn't contain a lower-case character.</para>
-        <para>It's often preferable to use this canonical form of a
-        foreign type name.</para>
-        <para>The accessor forms used by PREF/RREF should be viewed as
-        a series of foreign type/record and field names; upper-case
-        sequences in the component names should be escaped with angle
-        brackets, but those sequences shouldn't span components. (More
-        simply, the separating dots shouldn't be enclosed, even if
-        both surrounding characters need to be.)</para>
-        <para>Older POSIX code tends to use lower-case exclusively for
-        type, record, and field names; there are only a few cases in
-        the OpenMCL sources where mixed-case names need to be
-        escaped.</para>
-	
-      </sect2>
-
-      <sect2 id="Examples--1-">
-        <title>Examples</title>
-        <programlisting>
-;;; Allocate a record of type "window".
-(rlet ((w :window)) ...)
-;;; Allocate a record of type "Window", which is probably a
-;;;  different type
-(rlet ((w :&lt;w&gt;indow)) ...)
-;;; This is equivalent to the last example
-(rlet ((w :&lt;w&gt;INDOW)))
-</programlisting>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Tutorial--Using-Basic-Calls-and-Types">
-      <title>Tutorial: Using Basic Calls and Types</title>
-      <para>This tutorial is meant to cover the basics of OpenMCL for
-      calling external C functions and passing data back and forth.
-      These basics will provide the foundation for more advanced
-      techniques which will allow access to the various external
-      libraries and toolkits.</para>
-      <para>The first step is to start with a simple C dynamic library
-      in order to actually observe what is actually passing between
-      OpenMCL and C.  So, some C code is in order:</para>
-      <para>Create the file typetest.c, and put the following code
-      into it:</para>
-      <programlisting>
-
-#include &lt;stdio.&gt;
-
-void
-void_void_test(void)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-}
-
-signed char
-sc_sc_test(signed char data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %d\n", (signed int)data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-
-unsigned char
-uc_uc_test(unsigned char data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %d\n", (signed int)data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-      </programlisting>
-      <para>This defines three functions.  If you're familiar with C,
-      notice that there's no <literal>main()</literal>, because we're
-      just building a library, not an executable.</para>
-      <para>The function <literal>void_void_test()</literal> doesn't
-      take any parameters, and doesn't return anything, but it prints
-      two lines to let us know it was called.
-      <literal>sc_sc_test()</literal> takes a signed char as a
-      parameter, prints it, and returns it.
-      <literal>uc_uc_test()</literal> does the same thing, but with an
-      unsigned char.  Their purpose is just to prove to us that we
-      really can call C functions, pass them values, and get values
-      back from them.</para>
-      <para>This code is compiled into a dynamic library on OS X
-      10.3.4 with the command:</para>
-      <programlisting>
-
-gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
-    -install_name ./libtypetest.dylib
-      </programlisting>
-      <tip><para>Users of 64-bit platforms may need to pass options such
-      as "-m64" to gcc, may need to give the output library a different
-      extension (such as ".so"), and may need to user slightly different
-      values for other options in order to create an equivalent test
-      library.</para></tip>
-
-      <para>The -dynamiclib tells gcc that we will be compiling this
-      into a dynamic library and not an executable binary program.
-      The output filename is "libtypetest.dylib".  Notice that we
-      chose a name which follows the normal OS X convention, being in
-      the form "libXXXXX.dylib", so that other programs can link to
-      the library.  OpenMCL doesn't need it to be this way, but it is
-      a good idea to adhere to existing conventions.</para>
-      <para>The -install_name flag is primarily used when building OS
-      X "bundles".  In this case, we are not using it, so we put a
-      placeholder into it, "./libtypetest.dylib".  If we wanted to use
-      typetest in a bundle, the -install_name argument would be a
-      relative path from some "current" directory.</para>
-      <para>After creating this library, the first step is to tell
-      OpenMCL to open the dynamic library.  This is done by calling
-      .</para>
-      <programlisting>
-
-Welcome to OpenMCL Version (Beta: Darwin) 0.14.2-040506!
-
-? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
-#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E&gt;
-</programlisting>
-      <para>You should use an absolute path here; using a relative
-      one, such as just "libtypetest.dylib", would appear to work, but
-      there are subtle problems which occur after reloading it.  See
-      the Darwin notes on for details.  It would be a bad idea anyway,
-      because software should never rely on its starting directory
-      being anything in particular.</para>
-      <para>This command returns a reference to the opened shared library, and
-OpenMCL also adds one to the global variable
-<literal>ccl::*shared-libraries*</literal>:</para>
-      <programlisting>
-
-? ccl::*shared-libraries*
-(#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
- #&lt;SHLIB /usr/lib/libSystem.B.dylib #x606179E>)
-      </programlisting>
-      <para>Before we call anything, let's check that the individual
-      functions can actually be found by the system.  We don't have to
-      do this, but it helps to know how to find out whether this is
-      the problem, when something goes wrong.  We use <xref
-      linkend="m_external-call"/>:</para>
-      <programlisting>
-
-? (external "_void_void_test")
-#&lt;EXTERNAL-ENTRY-POINT "_void_void_test" (#x000CFDF8) /Users/andewl/openmcl/libtypetest.dylib #x638EDF6>
-
-? (external "_sc_sc_test")
-#&lt;EXTERNAL-ENTRY-POINT "_sc_sc_test" (#x000CFE50) /Users/andewl/openmcl/libtypetest.dylib #x638EB3E>
-
-? (external "_uc_uc_test")
-#&lt;EXTERNAL-ENTRY-POINT "_uc_uc_test" (#x000CFED4) /Users/andewl/openmcl/libtypetest.dylib #x638E626>
-      </programlisting>
-      <para>Notice that the actual function names have been "mangled"
-      by the C linker.  The first function was named "void_void_test"
-      in typetest.c, but in libtypetest.dylib, it has an underscore (a
-      "_" symbol) before it: "_void_void_test".  So, this is the name
-      which you have to use.  The mangling - the way the name is
-      changed - may be different for other operating systems or other
-      versions, so you need to "just know" how it's done...</para>
-      <para>Also, pay particular attention to the fact that a
-      hexadecimal value appears in the EXTERNAL-ENTRY-POINT.
-      (#x000CFDF8, for example - but what it is doesn't matter.)
-      These hex numbers mean that the function can be dereferenced.
-      Functions which aren't found will not have a hex number.  For
-      example:</para>
-      <programlisting>
-
-? (external "functiondoesnotexist")
-#&lt;EXTERNAL-ENTRY-POINT "functiondoesnotexist" {unresolved}  #x638E3F6>
-</programlisting>
-      <para>The "unresolved" tells us that OpenMCL wasn't able to find this
-      function, which means you would get an error, "Can't resolve foreign
-      symbol," if you tried to call it.</para>
-      <para>These external function references also are stored in a
-      hash table which is accessible through a global variable,
-      <literal>ccl::*eeps*</literal>.</para>
-      <para>At this point, we are ready to try our first external
-      function call:</para>
-      <programlisting>
-
-? (external-call "_void_void_test" :void)
-Entered void_void_test:
-Exited  void_void_test:
-NIL
-      </programlisting>
-      <para>We used , which is is the normal mechanism for accessing
-      externally linked code.  The "_void_void_test" is the mangled
-      name of the external function.  The :void refers to the return
-      type of the function.</para>
-      <para>The next step is to try passing a value to C, and getting one
-back:</para>
-      <programlisting>
-
-? (external-call "_sc_sc_test" :signed-byte -128 :signed-byte)
-Entered sc_sc_test:
-Data In: -128
-Exited  sc_sc_test:
--128
-</programlisting>
-      <para>The first :signed-byte gives the type of the first
-      argument, and then -128 gives the value to pass for it.  The
-      second :signed-byte gives the return type.  The return type is
-      always given by the last argument to .</para>
-      <para>Everything looks good.  Now, let's try a number outside
-      the range which fits in one byte:</para>
-      <programlisting>
-
-? (external-call "_sc_sc_test" :signed-byte -567 :signed-byte)
-Entered sc_sc_test:
-Data In: -55
-Exited  sc_sc_test:
--55
-</programlisting>
-      <para>Hmmmm.  A little odd.  Let's look at the unsigned stuff to
-      see how it reacts:</para>
-      <programlisting>
-
-? (external-call "_uc_uc_test" :unsigned-byte 255 :unsigned-byte)
-Entered uc_uc_test:
-Data In: 255
-Exited  uc_uc_test:
-255
-</programlisting>
-      <para>That looks okay.  Now, let's go outside the valid range again:</para>
-      <programlisting>
-
-? (external-call "_uc_uc_test" :unsigned-byte 567 :unsigned-byte)
-Entered uc_uc_test:
-Data In: 55
-Exited  uc_uc_test:
-55
-
-? (external-call "_uc_uc_test" :unsigned-byte -567 :unsigned-byte)
-Entered uc_uc_test:
-Data In: 201
-Exited  uc_uc_test:
-201
-      </programlisting>
-      <para>Since a signed byte can only hold values from -128 through 127, and
-      an unsigned one can only hold values from 0 through 255, any number
-      outside that range gets "clipped": only the low eight bits of it
-      are used.</para>
-      <para>What is important to remember is that <emphasis>external
-      function calls have
-      very few safety checks.</emphasis>
-      Data outside the valid range for its type will silently do
-      very strange things; pointers outside the valid range can very well
-      crash the system.</para>
-      <para>That's it for our first example library.  If you're still
-      following along, let's add some more C code to look at the rest
-      of the primitive types.  Then we'll need to recompile the
-      dynamic library, load it again, and then we can see what
-      happens.</para>
-      <para>Add the following code to typetest.c:</para>
-      <programlisting>
-
-int
-si_si_test(int data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %d\n", data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-
-long
-sl_sl_test(long data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %ld\n", data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-
-long long
-sll_sll_test(long long data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %lld\n", data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-
-float
-f_f_test(float data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %e\n", data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-
-double
-d_d_test(double data)
-{
-    printf("Entered %s:\n", __FUNCTION__);
-    printf("Data In: %e\n", data);
-    printf("Exited  %s:\n", __FUNCTION__);
-    fflush(stdout);
-    return data;
-}
-</programlisting>
-      <para>The command line to compile the dynamic library is the same as before:</para>
-      <programlisting>
-
-gcc -dynamiclib -Wall -o libtypetest.dylib typetest.c \
-    -install_name ./libtypetest.dylib
-</programlisting>
-      <para>Now, restart OpenMCL.  This step is required because
-      OpenMCL cannot close and reload a dynamic library on OS
-      X.</para>
-      <para>Have you restarted?  Okay, try out the new code:</para>
-      <programlisting>
-
-Welcome to OpenMCL Version (Beta: Darwin) 0.14.2-040506!
-
-? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
-#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
-
-? (external-call "_si_si_test" :signed-fullword -178965 :signed-fullword)
-Entered si_si_test:
-Data In: -178965
-Exited  si_si_test:
--178965
-
-? ;; long is the same size as int on 32-bit machines.
-(external-call "_sl_sl_test" :signed-fullword -178965 :signed-fullword)
-Entered sl_sl_test:
-Data In: -178965
-Exited  sl_sl_test:
--178965
-
-? (external-call "_sll_sll_test"
-                 :signed-doubleword -973891578912 :signed-doubleword)
-Entered sll_sll_test:
-Data In: -973891578912
-Exited  sll_sll_test:
--973891578912
-</programlisting>
-      <para>Okay, everything seems to be acting as expected.  However,
-      just to remind you that most of this stuff has no safety net,
-      here's what happens if somebody mistakes
-      <literal>sl_sl_test()</literal> for
-      <literal>sll_sll_test()</literal>, thinking that a long is
-      actually a doubleword:</para>
-      <programlisting>
-
-? (external-call "_sl_sl_test"
-                 :signed-doubleword -973891578912 :signed-doubleword)
-Entered sl_sl_test:
-Data In: -227
-Exited  sl_sl_test:
--974957576192
-      </programlisting>
-      <para>Ouch.  The C function changes the value with no warning
-      that something is wrong.  Even worse, it manages to pass the
-      original value back to OpenMCL, which hides the fact that
-      something is wrong.</para>
-      <para>Finally, let's take a look at doing this with
-      floating-point numbers.</para>
-      <programlisting>
-
-Welcome to OpenMCL Version (Beta: Darwin) 0.14.2-040506!
-
-? (open-shared-library "/Users/andewl/openmcl/libtypetest.dylib")
-#&lt;SHLIB /Users/andewl/openmcl/libtypetest.dylib #x638EF3E>
-
-? (external-call "_f_f_test" :single-float -1.256791e+11 :single-float)
-Entered f_f_test:
-Data In: -1.256791e+11
-Exited  f_f_test:
--1.256791E+11
-
-? (external-call "_d_d_test" :double-float -1.256791d+290 :double-float)
-Entered d_d_test:
-Data In: -1.256791e+290
-Exited  d_d_test:
--1.256791D+290
-      </programlisting>
-      <para>Notice that the number ends with "...e+11" for the single-float,
-and "...d+290" for the
-double-float.  Lisp has both of these float types itself, and the
-d instead of the e is how you specify which to create.  If
-you tried to pass :double-float 1.0e2 to external-call, Lisp would
-be nice enough to notice and give you a type error.  Don't get the
-:double-float wrong, though, because then there's no protection.</para>
-      <para>Congratulations!  You now know how to call external C functions from
-within OpenMCL, and pass numbers back and forth.  Now that the basic
-mechanics of calling and passing work, the next step is to examine how
-to pass more complex data structures around.</para>
-
-      <sect2 id="Acknowledgement">
-        <title>Acknowledgement</title>
-	<para>This chapter was generously contributed by Andrew
-	P. Lentvorski Jr.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap">
-      <title>Tutorial: Allocating Foreign Data on the Lisp Heap </title>
-      <para>Not every foreign function is so marvelously easy to use
-      as the ones we saw in the last section.  Some of them require
-      you to allocate a C struct, fill it in with your own
-      information, and pass it a pointer to the struct.  Some of them
-      require you to allocate an empty struct so they can fill it in,
-      and then you can read the information out of it.</para>
-      <para>Also, some of them have their own structs and return a
-      pointer to that same struct every time you call them, but those
-      are easier to deal with, so they won't be covered in this
-      section.</para>
-      <para>You might know that Lisp (and, indeed, most programming
-      languages) has two separate regions of memory.  There's the
-      stack, which is where variable bindings are kept.  Memory on the
-      stack is allocated every time any function is called, and
-      deallocated when it returns, so it's useful for anything that
-      doesn't need to last longer than one function call, when there's
-      only one thread.  If that's all you need, you can do it with
-      .</para>
-      <para>Then, there's the heap, which holds everything else, and
-      is our subject here.  There are two advantages and one big
-      disadvantage to putting things on the heap rather than the
-      stack.  First, data allocated on the heap can be passed outside
-      of the scope in which it was created.  This is useful for data
-      which may need to be passed between multiple C calls or multiple
-      threads. Also, some data may be too large to copy multiple times
-      or may be too large to allocate on the stack.</para>
-      <para>The second advantage is security.  If incoming data is
-      being placed directly onto the stack, the input data can cause
-      stack overflows and underflows.  This is not something which
-      Lisp users generally worry about since garbage collection
-      generally handles memory management.  However, "stack smashing"
-      is one of the classic exploits in C which malicious hackers can
-      use to gain control of a machine.  Not checking external data is
-      always a bad idea; however, allocating it into the heap at least
-      offers more protection than direct stack allocation.</para>
-      <para>The big disadvantage to allocating data on the heap is
-      that it must be explicitly deallocated - you need to "free" it
-      when you're done with it.  Ordinarily, in Lisp, you wouldn't
-      allocate memory yourself, and the garbage collector would know
-      about it, so you wouldn't have to think about it again.  When
-      you're doing it manually, it's very different.  Memory
-      management becomes a manual process, just like in C and
-      C++.</para>
-      <para>What that means is that, if you allocate something and
-      then lose track of the pointer to it, there's no way to ever
-      free that memory.  That's what's called a memory leak, and if
-      your program leaks enough memory it will eventually use up all
-      of it!  So, you need to be careful to not lose your
-      pointers.</para>
-      <para>That disadvantage, though, is also an advantage for using
-      foreign functions.  Since the garbage collector doesn't know
-      about this memory, it will never move it around.  External C
-      code needs this, because it doesn't know how to follow it to
-      where it moved, the way that Lisp code does.  If you allocate
-      data manually, you can pass it to foreign code and know that no
-      matter what that code needs to do with it, it will be able to,
-      until you deallocated it.  Of course, you'd better be sure it's
-      done before you do.  Otherwise, your program will be unstable
-      and might crash sometime in the future, and you'll have trouble
-      figuring out what caused the trouble, because there won't be
-      anything pointing back and saying "you deallocated this too
-      soon."</para>
-      <para>And, so, on to the code...</para>
-      <para>As in the last tutorial, our first step
-      is to create a local dynamic library in order to help show
-      what is actually going on between OpenMCL and C.  So, create the file
-      ptrtest.c, with the following code:</para>
-      <programlisting>
-#include &lt;stdio.h&gt;
-
-void reverse_int_array(int * data, unsigned int dataobjs)
-{
-  int i, t;
-
-  for(i=0; i&lt;dataobjs/2; i++)
-    {
-      t = *(data+i);
-      *(data+i) = *(data+dataobjs-1-i);
-      *(data+dataobjs-1-i) = t;
-    }
-}
-
-void reverse_int_ptr_array(int **ptrs, unsigned int ptrobjs)
-{
-  int *t;
-  int i;
-
-  for(i=0; i&lt;ptrobjs/2; i++)
-    {
-      t = *(ptrs+i);
-      *(ptrs+i) = *(ptrs+ptrobjs-1-i);
-      *(ptrs+ptrobjs-1-i) = t;
-    }
-}
-
-void
-reverse_int_ptr_ptrtest(int **ptrs)
-{
-  reverse_int_ptr_array(ptrs, 2);
-
-  reverse_int_array(*(ptrs+0), 4);
-  reverse_int_array(*(ptrs+1), 4);
-}
-      </programlisting>
-      <para>This defines three functions.
-      <literal>reverse_int_array</literal> takes a pointer to an array
-      of <literal>int</literal>s, and a count telling how many items
-      are in the array, and loops through it putting the elements in
-      reverse.  <literal>reverse_int_ptr_array</literal> does the same
-      thing, but with an array of pointers to <literal>int</literal>s.
-      It only reverses the order the pointers are in; each pointer
-      still points to the same thing.
-      <literal>reverse_int_ptr_ptrtest</literal> takes an array of
-      pointers to arrays of <literal>int</literal>s.  (With me?)  It
-      doesn't need to be told their sizes; it just assumes that the
-      array of pointers has two items, and that both of those are
-      arrays which have four items.  It reverses the array of
-      pointers, then it reverses each of the two arrays of
-      <literal>int</literal>s.</para>
-      <para>Now, compile ptrtest.c into a dynamic library using the
-      command:</para>
-      <programlisting>
-gcc -dynamiclib -Wall -o libptrtest.dylib ptrtest.c -install_name ./libptrtest.dylib
-      </programlisting>
-      <para>If that command doesn't make sense to you, feel free to go back
-and read about it at .</para>
-      <para>Now, start OpenMCL and enter:</para>
-      <programlisting>
-? ;; make-heap-ivector courtesy of Gary Byers
-(defun make-heap-ivector (element-count element-type)
-  (let* ((subtag (ccl::element-type-subtype element-type)))
-    (unless (= (logand subtag target::fulltagmask)
-               target::fulltag-immheader)
-      (error "~s is not an ivector subtype." element-type))
-    (let* ((size-in-bytes (ccl::subtag-bytes subtag element-count)))
-      (ccl::%make-heap-ivector subtag size-in-bytes element-count))))
-MAKE-HEAP-IVECTOR
-
-? ;; dispose-heap-ivector created for symmetry
-(defmacro dispose-heap-ivector (a mp)
-  `(progn
-     (ccl::%dispose-heap-ivector ,a)
-     ;; Demolish the arguments for safety
-     (setf ,a nil)
-     (setf ,mp nil)))
-DISPOSE-HEAP-IVECTOR
-</programlisting>
-      <para>If you don't understand how those functions do what they do.
-      That's okay; it gets into very fine detail which really doesn't
-      matter, because you don't need to change them.</para>
-      <para>The function <literal>make-heap-ivector</literal> is the
-      primary tool for allocating objects in heap memory.  It
-      allocates a fixed-size OpenMCL object in heap memory.  It
-      returns both an array reference, which can be used directly from
-      OpenMCL, and a <literal>macptr</literal>, which can be used to
-      access the underlying memory directly.  For example:</para>
-      <programlisting>
-? ;; Create an array of 3 4-byte-long integers
-(multiple-value-bind (la lap)
-    (make-heap-ivector 3 '(unsigned-byte 32))
-  (setq a la)
-  (setq ap lap))
-;Compiler warnings :
-;   Undeclared free variable A, in an anonymous lambda form.
-;   Undeclared free variable AP, in an anonymous lambda form.
-#&lt;A Mac Pointer #x10217C>
-
-? a
-#(1396 2578 97862649)
-
-? ap
-#&lt;A Mac Pointer #x10217C>
-</programlisting>
-      <para>It's important to realize that the contents of the
-      <literal>ivector</literal> we've just created haven't been
-      initialized, so their values are unpredictable, and you should
-      be sure not to read from them before you set them, to avoid
-      confusing results.</para>
-      <para>At this point, <literal>a</literal> references an object
-      which works just like a normal array.  You can refer to any item
-      of it with the standard <literal>aref</literal> function, and
-      set them by combining that with <literal>setf</literal>.  As
-      noted above, the <literal>ivector</literal>'s contents haven't
-      been initialized, so that's the next order of business:</para>
-      <programlisting>
-? a
-#(1396 2578 97862649)
-
-? (aref a 2)
-97862649
-
-? (setf (aref a 0) 3)
-3
-
-? (setf (aref a 1) 4)
-4
-
-? (setf (aref a 2) 5)
-5
-
-? a
-#(3 4 5)
-</programlisting>
-      <para>In addition, the <literal>macptr</literal> allows direct
-      access to the same memory:</para>
-      <programlisting>
-? (setq *byte-length-of-long* 4)
-4
-
-? (%get-signed-long ap (* 2 *byte-length-of-long*))
-5
-
-? (%get-signed-long ap (* 0 *byte-length-of-long*))
-3
-
-? (setf (%get-signed-long ap (* 0 *byte-length-of-long*)) 6)
-6
-
-? (setf (%get-signed-long ap (* 2 *byte-length-of-long*)) 7)
-7
-
-? ;; Show that a actually got changed through ap
-a
-#(6 4 7)
-      </programlisting>
-      <para>So far, there is nothing about this object that could not
-      be done much better with standard Lisp.  However, the
-      <literal>macptr</literal> can be used to pass this chunk of
-      memory off to a C function.  Let's use the C code to reverse the
-      elements in the array:</para>
-      <programlisting>
-? ;; Insert the full path to your copy of libptrtest.dylib
-(open-shared-library "/Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib")
-#&lt;SHLIB /Users/andrewl/openmcl/openmcl/gtk/libptrtest.dylib #x639D1E6>
-
-? a
-#(6 4 7)
-
-? ap
-#&lt;A Mac Pointer #x10217C>
-
-? (external-call "_reverse_int_array" :address ap :unsigned-int (length a) :address)
-#&lt;A Mac Pointer #x10217C>
-
-? a
-#(7 4 6)
-
-? ap
-#&lt;A Mac Pointer #x10217C>
-</programlisting>
-      <para>The array gets passed correctly to the C function,
-      <literal>reverse_int_array</literal>.  The C function reverses
-      the contents of the array in-place; that is, it doesn't make a
-      new array, just keeps the same one and reverses what's in it.
-      Finally, the C function passes control back to OpenMCL.  Since
-      the allocated array memory has been directly modifed, OpenMCL
-      reflects those changes directly in the array as well.</para>
-      <para>There is one final bit of housekeeping to deal with.
-      Before moving on, the memory needs to be deallocated:</para>
-      <programlisting>
-? ;; dispose-heap-ivector created for symmetry
-;; Macro repeated here for pedagogy
-(defmacro dispose-heap-ivector (a mp)
-  `(progn
-     (ccl::%dispose-heap-ivector ,a)
-     ;; Demolish the arguments for safety
-     (setf ,a nil)
-     (setf ,mp nil)))
-DISPOSE-HEAP-IVECTOR
-
-? (dispose-heap-ivector a ap)
-NIL
-
-? a
-NIL
-
-? ap
-NIL
-</programlisting>
-      <para>The <literal>dispose-heap-ivector</literal> macro actually
-      deallocates the ivector, releasing its memory into the heap for
-      something else to use.  In addition, it makes sure that the
-      variables which it was called with are set to nil, because
-      otherwise they would still be referencing the memory of the
-      ivector - which is no longer allocated, so that would be a bug.
-      Making sure there are no other variables set to it is up to
-      you.</para>
-      <para>When do you call <literal>dispose-heap-ivector</literal>?
-      Anytime after you know the ivector will never be used again, but
-      no sooner.  If you have a lot of ivectors, say, in a hash table,
-      you need to make sure that when whatever you were doing with the
-      hash table is done, those ivectors all get freed.  Unless
-      there's still something somewhere else which refers to them, of
-      course!  Exactly what strategy to take depends on the situation,
-      so just try to keep things simple unless you know better.</para>
-      <para>The simplest situation is when you have things set up so
-      that a Lisp object "encapsulates" a pointer to foreign data,
-      taking care of all the details of using it.  In this case, you
-      don't want those two things to have different lifetimes: You
-      want to make sure your Lisp object exists as long as the foreign
-      data does, and no longer; and you want to make sure the foreign
-      data doesn't get deallocated while your Lisp object still refers
-      to it.</para>
-      <para>If you're willing to accept a few limitations, you can
-      make this easy.  First, you can't let foreign code keep a
-      permanent pointer to the memory; it has to always finish what
-      it's doing, then return, and not refer to that memory again.
-      Second, you can't let any Lisp code that isn't part of your
-      encapsulating "wrapper" refer to the pointer directly.  Third,
-      nothing, either foreign code or Lisp code, should explicitly
-      deallocate the memory.</para>
-      <para>If you can make sure all of these are true, you can at
-      least ensure that the foreign pointer is deallocated when the
-      encapsulating object is about to become garbage, by using
-      OpenMCL's nonstandard "termination" mechanism, which is
-      essentially the same as what Java and other languages call
-      "finialization".</para>
-      <para>Termination is a way of asking the garbage collector to
-      let you know when it's about to destroy an object which isn't
-      used anymore.  Before destroying the object, it calls a function
-      which you write, called a terminator.</para>
-      <para>So, you can use termination to find out when a particular
-      <literal>macptr</literal> is about to become garbage.  That's
-      not quite as helpful as it might seem: It's not exactly the same
-      thing as knowing that the block of memory it points to is
-      unreferenced.  For example, there could be another
-      <literal>macptr</literal> somewhere to the same block; or, if
-      it's a struct, there could be a <literal>macptr</literal> to one
-      of its fields.  Most problematically, if the address of that
-      memory has been passed to foreign code, it's sometimes hard to
-      know whether that code has kept the pointer.  Most foreign
-      functions don't, but it's not hard to think of
-      exceptions.</para>
-      <para>You can use code such as this to make all this happen:</para>
-      <programlisting>
-(defclass wrapper (whatever)
-  ((element-type :initarg :element-type)
-   (element-count :initarg :element-count)
-   (ivector)
-   (macptr)))
-
-(defmethod initialize-instance ((wrapper wrapper) &amp;rest initargs)
-  (declare (ignore initargs))
-  (call-next-method)
-  (ccl:terminate-when-unreachable wrapper)
-  (with-slots (ivector macptr element-type element-count) wrapper
-    (multiple-value-bind (new-ivector new-macptr)
-        (make-heap-ivector element-count element-type)
-      (setq ivector new-ivector
-            macptr new-macptr))))
-
-(defmethod ccl:terminate ((wrapper wrapper))
-  (with-slots (ivector macptr) wrapper
-    (when ivector
-      (dispose-heap-ivector ivector macptr)
-      (setq ivector nil
-            macptr nil))))
-      </programlisting>
-      <para>The <literal>ccl:terminate</literal> method will be called
-      on some arbitrary thread sometime (hopefully soon) after the GC
-      has decided that there are no strong references to an object
-      which has been the argument of a
-      <literal>ccl:terminate-when-unreachable</literal> call.</para>
-      <para>If it makes sense to say that the foreign object should
-      live as long as there's Lisp code that references it (through
-      the encapsulating obect) and no longer, this is one way of doing
-      that.</para>
-      <para>Now we've covered passing basic types back and forth with
-      C, and we've done the same with pointers.  You may think this is
-      all...  but we've only done pointers to basic types.  Join us
-      next time for pointers... to pointers.</para>
-
-      <sect2 id="Acknowledgement--1-">
-	<title>Acknowledgement</title>
-	<para>Much of this chapter was generously contributed by
-	Andrew P. Lentvorski Jr.</para>
-      </sect2>
-    </sect1>
-
-    <sect1>
-      <title>The Foreign-Function-Interface Dictionary</title>
-        
-      <refentry id="m_def-foreign-type">
-	<indexterm zone="m_def-foreign-type">
-	  <primary>def-foreign-type</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>DEF-FOREIGN-TYPE</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>def-foreign-type</function> name foreign-type-spec
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-	      
-	      <listitem>
-		<para>NIL or a keyword; the keyword may contain
-		<link linkend="Case-sensitivity-of-foreign-names-in-OpenMCL" >escaping constructs</link>.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>foreign-type-spec</term>
-	      
-	      <listitem>
-		<para>A foreign type specifier, whose syntax is (loosely)
-		defined above.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If name is non-NIL, defines name to be an alias for the
-	  foreign type specified by foreign-type-spec. If foreign-type-spec
-	  is a named structure or union type, additionally defines that
-	  structure or union type.</para>
-	  
-	  <para>If name is NIL, foreign-type-spec must be a named foreign
-	  struct or union definition, in which case the foreign structure
-	  or
-	  union definition is put in effect.</para>
-	  
-	  <para>Note that there are two separate namespaces for foreign
-	  type names, one for the names of ordinary types and one for
-	  the names of structs and unions.  Which one
-	  <varname>name</varname> refers to depends on
-	  <varname>foreign-type-spec</varname> in the obvious manner.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_make-record">
-	<indexterm zone="m_make-record">
-	  <primary>make-record</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>MAKE-RECORD</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>make-record</function> typespec
-	    &rest; initforms => result
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>typespec</term>
-
-	      <listitem>
-		<para>A foreign type specifier, or a keyword which is used
-		as the name of a foreign struct or union.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>initforms</term>
-
-	      <listitem>
-		<para>If the type denoted by <varname>typespec</varname>
-		is scalar, a single value appropriate for that type;
-		otherwise, a list of alternating field names and
-		values appropriate for the types of those fields.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>result</term>
-
-	      <listitem>
-		<para>
-		  A <type>macptr</type> which encapsulates the address of a
-		  newly-allocated record on the foreign heap.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Expands into code which allocates and initalizes
-	    an instance of the type 
-	    denoted by <varname>typespec</varname>, on the foreign
-	    heap.  The record is allocated using the C function
-	    <function>malloc</function>, and the user of
-	    <function>make-record</function> must explicitly call
-	    the C function <function>free</function> to deallocate the
-	    record, when it is no longer needed.
-	  </para>
-
-	  <para>
-	    If <varname>initforms</varname> is provided, its value
-	    or values are used in the initialization.  When the type
-	    is a scalar, <varname>initforms</varname> is either a single
-	    value which can be coerced to that type, or no value, in which
-	    case binary 0 is used.  When the type is a <type>struct</type>,
-	    <varname>initforms</varname> is a list, giving field names
-	    and the values for each.  Each field is treated in the same way
-	    as a scalar is: If a value for it is given, it must be
-	    coerceable to the field's type; if not, binary 0 is used.
-	  </para>
-
-	  <para>
-	    When the type is an array, <varname>initforms</varname> may
-	    not be provided, because <function>make-record</function>
-	    cannot initialize its values.  <function>make-record</function>
-	    is also unable to initialize fields of a <type>struct</type>
-	    which are themselves
-	    <type>struct</type>s.  The user of
-	    <function>make-record</function> should set these values
-	    by another means.
-	  </para>
-
-	  <para>
-	    A possibly-significant limitation is that it must be possible to
-	    find the foreign type at the time the macro is expanded;
-	    <function>make-record</function> signals an error if this is
-	    not the case.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>
-	    It is inconvenient that <function>make-record</function> is a
-	    macro, because this means that <varname>typespec</varname>
-	    cannot be a variable; it must be an immediate value.
-	  </para>
-	    
-	  <para>
-	    If it weren't for this requirement,
-	    <function>make-record</function> could be a function.  However,
-	    that would mean that any stand-alone application using it would
-	    have to include a copy of the interface database
-	    (see <xref linkend="The-Interface-Database"/>), which is undesireable
-	    because it's large.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_rlet">
-	<indexterm zone="m_rlet">
-	  <primary>rlet</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>RLET</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>rlet</function> (var typespec &rest; initforms)*
-	    &body; body
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>var</term>
-
-	      <listitem>
-		<para>A symbol (a lisp variable)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>typespec</term>
-
-	      <listitem>
-		<para>A foreign type specifier or foreign record name.</para>
-	      </listitem>
-	    </varlistentry>
-
- <varlistentry>
-	      <term>initforms</term>
-
-	      <listitem>
-		<para>As described above, for
-		<xref linkend="m_make-record"/></para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Executes <varname>body</varname>
-	  in an environment in which each var is bound
-	  to <link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link> encapsulating the
-	  address of a stack-allocated foreign memory block, allocated and
-	  initialized from typespec and initforms as per
-	  <xref linkend="m_make-record"/>.
-	  Returns whatever value(s) <varname>body</varname>
-	  returns.</para>
-	  
-	  <para>Record fields that aren&#39;t explicitly initialized have
-	  unspecified contents.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_rletz">
-	<indexterm zone="m_rletz">
-	  <primary>rletz</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>RLETZ</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>rletz</function> (var typespec &rest; initforms)*
-	    &body; body
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>var</term>
-
-	      <listitem>
-		<para>A symbol (a lisp variable)</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>typespec</term>
-
-	      <listitem>
-		<para>A foreign type specifier or foreign record name.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>initforms</term>
-
-	      <listitem>
-		<para>As described above, for ccl:make-record</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Executes body in an environment in which each var is
-	  bound to <link
-	  linkend="Referencing-and-Using-Foreign-Memory-Addresses">a
-	  MACPTR</link> encapuslating the address of a stack-allocated
-	  foreign memory block, allocated and initialized from
-	  typespec and initforms as ccl:make-record.</para>
-	  
-	  <para>Returns whatever value(s) body returns.</para>
-
-	  <para>Unlike rlet, record fields that aren&#39;t explicitly
-	  initialized are set to binary 0.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_pref">
-	<indexterm zone="m_pref">
-	  <primary>pref</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>PREF</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>pref</function> ptr accessor-form
-	  </synopsis>
-
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>ptr</term>
-
-	      <listitem>
-		<para><link linkend="Referencing-and-Using-Foreign-Memory-Addresses">a MACPTR</link>.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>accessor-form</term>
-
-	      <listitem>
-		<para>a keyword which names a foreign type or record, as
-		described in <xref linkend="Foreign-type--record--and-field-names"/>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>References an instance of a foreign type (or a component of
-	  a foreign type) accessible via ptr.</para>
-	  
-	  <para>Expands into code which references the indicated scalar type
-	  or component, or returns a pointer to a composite type.</para>
-	  
-	  <para>PREF can be used with SETF.</para>
-	  
-	  <para>RREF is a deprecated alternative to PREF. It accepts a
-	  :STORAGE keyword and rather loudly ignores it.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_open-shared-library">
-	<indexterm zone="f_open-shared-library">
-	  <primary>open-shared-library</primary>
-	</indexterm>
-	
-	<refnamediv>
-	  <refname>OPEN-SHARED-LIBRARY</refname>
-	  <refpurpose>Asks the operating system to load a shared library
-	  for OpenMCL to use.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-	
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>open-shared-library</function> name => library
-	  </synopsis>
-	</refsynopsisdiv>
-	
-	<refsect1>
-	  <title>Values</title>
-	  
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>	
-	      <listitem>
-		<para>A SIMPLE-STRING which is presumed to be the so-name of
-		or a filesystem path to the library.</para>
-	      </listitem>
-	    </varlistentry>
-	    
-	    <varlistentry>
-	      <term>library</term>
-	      <listitem>
-		<para>An object of type SHLIB which describes the
-		library denoted by <varname>name</varname>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-	
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If the library denoted by <varname>name</varname> can
-	  be loaded by the
-	  operating system, returns an object of type SHLIB that describes
-	  the library; if the library is already open, increments a
-	  reference count. If the library can&#39;t be loaded, signals a
-	  SIMPLE-ERROR which contains an often-cryptic message from the
-	  operating system.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Examples</title>
-
-	  <programlisting format="linespecific">;;; Try to do something simple.
-? (open-shared-library &#34;libgtk.so&#34;)
-&#62; Error: Error opening shared library &#34;libgtk.so&#34;: /usr/lib/libgtk.so: undefined symbol: gdk_threads_mutex
-&#62; While executing: OPEN-SHARED-LIBRARY
-
-;;; Grovel around, curse, and try to find out where &#34;gdk_threads_mutex&#34;
-;;; might be defined. Then try again:
-
-? (open-shared-library &#34;libgdk.so&#34;)
-#&#60;SHLIB libgdk.so #x3046DBB6&#62;
-
-? (open-shared-library &#34;libgtk.so&#34;)
-#&#60;SHLIB libgtk.so #x3046DC86&#62;
-
-;;; Reference an external symbol defined in one of those libraries.
-
-? (external &#34;gtk_main&#34;)
-#&#60;EXTERNAL-ENTRY-POINT &#34;gtk_main&#34; (#x012C3004) libgtk.so #x3046FE46&#62;
-
-;;; Close those libraries.
-
-? (close-shared-library &#34;libgtk.so&#34;)
-T
-
-? (close-shared-library &#34;libgdk.so&#34;)
-T
-
-;;; Reference the external symbol again.
-
-? (external &#34;gtk_main&#34;)
-#&#60;EXTERNAL-ENTRY-POINT &#34;gtk_main&#34; {unresolved} libgtk.so #x3046FE46&#62;</programlisting>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>It would be helpful to describe what an soname is and give
-	  examples of one.</para>
-
-	  <para>Does the SHLIB still get returned if the library is
-	  already open?</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_close-shared-library">
-	<indexterm zone="f_close-shared-library">
-	  <primary>close-shared-library</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CLOSE-SHARED-LIBRARY</refname>
-	  <refpurpose>Stops using a shared library, informing the operating
-	  system that it can be unloaded if appropriate.</refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>close-shared-library</function> library &key;
-	  completely</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>library</term>
-
-	      <listitem>
-		<para>either an object of type SHLIB, or a string which
-		designates one by its so-name.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>completely</term>
-
-	      <listitem>
-		<para>a boolean.  The default is T.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If <varname>completely</varname> is T, sets the
-	  reference count of <varname>library</varname> to 0.  Otherwise,
-	  decrements it by 1.  In either case, if the reference count
-	  becomes 0, <function>close-shared-library</function>
-	  frees all memory resources consumed <varname>library</varname>
-	  and
-	  causes any EXTERNAL-ENTRY-POINTs known to be defined by it to
-	  become unresolved.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_external">
-	<indexterm zone="m_external">
-	  <primary>external</primary>
-	</indexterm>
-	
-	<refnamediv>
-	  <refname>EXTERNAL</refname>
-	  <refpurpose>Resolves a reference to an external symbol which
-	  is defined in a shared library.</refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>external</function> name => entry
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-	      <listitem>
-		<para>
-		  a simple-string which names an external symbol.
-		  Case-sensitive.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>entry</term>
-	      <listitem>
-		<para>
-		  an object of type EXTERNAL-ENTRY-POINT which maintains
-		  the address of the foreign symbol named by
-		  <varname>name</varname>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If there is already an EXTERNAL-ENTRY-POINT for
-	  the symbol named by <varname>name</varname>, finds it and
-	  returns it.  If not, creates one and returns it.</para>
-
-	  <para>Tries to resolve the entry point to a memory address,
-	  and identify the containing library.</para>
-
-	  <para>Be aware that under Darwin, external functions which
-	  are callable from C have underscores prepended to their names,
-	  as in "_fopen".</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_Pff-call">
-	<indexterm zone="f_Pff-call">
-	  <primary>%ff-call</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>%FF-CALL</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>%ff-call</function> entrypoint
-	    {arg-type-keyword arg}* &optional; result-type-keyword
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>entrypoint</term>
-	      
-	      <listitem>
-		<para>A fixnum or MACPTR</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg-type-keyword</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg</term>
-
-	      <listitem>
-		<para>A lisp value of type indicated by the corresponding
-		arg-type-keyword</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>result-type-keyword</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Calls the foreign function at address entrypoint passing the
-	  values of each arg as a foreign argument of type indicated by the
-	  corresponding arg-type-keyword. Returns the foreign function
-	  result (coerced to a Lisp object of type indicated by
-	  result-type-keyword), or NIL if result-type-keyword is :VOID or
-	  NIL</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_ff-call">
-	<indexterm zone="m_ff-call">
-	  <primary>ff-call</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>FF-CALL</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>ff-call</function> entrypoint
-	    {arg-type-specifier arg}* &optional; result-type-specifier
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>entrypoint</term>
-
-	      <listitem>
-		<para>A fixnum or MACPTR</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg-type-specifer</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
-		type specifier</link>.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg</term>
-
-	      <listitem>
-		<para>A lisp value of type indicated by the corresponding
-		arg-type-specifier</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>result-type-specifier</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
-		type specifier</link>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Calls the foreign function at address entrypoint passing the
-	  values of each arg as a foreign argument of type indicated by the
-	  corresponding arg-type-specifier. Returns the foreign function
-	  result (coerced to a Lisp object of type indicated by
-	  result-type-specifier), or NIL if result-type-specifer is :VOID or
-	  NIL</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_Preference-external-entry-point">
-	<indexterm zone="f_Preference-external-entry-point">
-	  <primary>%reference-external-entry-point</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>%REFERENCE-EXTERNAL-ENTRY-POINT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>%reference-external-entry-point</function> eep
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>eep</term>
-
-	      <listitem>
-		<para>An EXTERNAL-ENTRY-POINT, as obtained by the EXTERNAL
-		macro.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to resolve the address of the EXTERNAL-ENTRY-POINT
-	  eep; returns a fixnum representation of that address if
-	  successful, else signals an error.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_external-call">
-	<indexterm zone="m_external-call">
-	  <primary>external-call</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>EXTERNAL-CALL</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>external-call</function> name
-	    {arg-type-specifier arg}* &optional; result-type-specifier
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>A lisp string. See external, above.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg-type-specifer</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
-		type specifier</link>.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg</term>
-
-	      <listitem>
-		<para>A lisp value of type indicated by the corresponding
-		arg-type-specifier</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>result-type-specifier</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords, described
-		above, or an equivalent <link linkend="Specifying-And-Using-Foreign-Types">foreign
-		type specifier</link>.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Calls the foreign function at the address obtained by
-	  resolving the external-entry-point associated with name, passing
-	  the values of each arg as a foreign argument of type indicated by
-	  the corresponding arg-type-specifier. Returns the foreign function
-	  result (coerced to a Lisp object of type indicated by
-	  result-type-specifier), or NIL if result-type-specifer is :VOID or
-	  NIL</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_foreign-symbol-entry">
-	<indexterm zone="f_foreign-symbol-entry">
-	  <primary>foreign-symbol-entry</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>FOREIGN-SYMBOL-ENTRY</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>foreign-symbol-entry</function> name
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>A lisp string.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to resolve the address of the foreign symbol name. If
-	  successful, returns a fixnum representation of that address, else
-	  returns NIL.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_foreign-symbol-address">
-	<indexterm zone="f_foreign-symbol-address">
-	  <primary>foreign-symbol-address</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>FOREIGN-SYMBOL-ADDRESS</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>foreign-symbol-address</function> name
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>A lisp string.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to resolve the address of the foreign symbol
-	  name. If successful, returns that address encapsulated in
-	  <link
-	  linkend="Referencing-and-Using-Foreign-Memory-Addresses">a
-	  MACPTR</link>, else returns NIL.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_defcallback">
-	<indexterm zone="m_defcallback">
-	  <primary>defcallback</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>DEFCALLBACK</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>defcallback</function> name
-	    ({arg-type-specifier var}* &optional; result-type-specifier)
-	    &body; body
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>A symbol which can be made into a special variable</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>arg-type-specifer</term>
-
-	      <listitem>
-		<para>One of the foreign argument-type keywords,
-		described above, or an equivalent <link
-		linkend="Specifying-And-Using-Foreign-Types">foreign
-		type specifier</link>.  In addition, if the keyword
-		:WITHOUT-INTERRUPTS is specified, the callback will be
-		executed with lisp interrupts disabled if the
-		corresponding var is non-NIL. If :WITHOUT-INTERRUPTS
-		is specified more than once, the rightmost instance
-		wins.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>var</term>
-
-	      <listitem>
-		<para>A symbol (lisp variable), which will be bound to a
-		value of the specified type.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>body</term>
-
-	      <listitem>
-		<para>A sequence of lisp forms, which should return a value
-		which can be coerced to the specified result-type.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Proclaims <varname>name</varname>
-	  to be a special variable; sets its value to a
-	  MACPTR which, when called by foreign code, calls a lisp function
-	  which expects foreign arguments of the specified types and which
-	  returns a foreign value of the specified result type. Any argument
-	  variables which correspond to foreign arguments of type :ADDRESS
-	  are bound to stack-allocated MACPTRs.</para>
-	  
-	  <para>If <varname>name</varname>
-	  is already a callback function pointer, its value is
-	  not changed; instead, it&#39;s arranged
-	  that an
-	  updated version of the lisp callback function will be called.
-	  This feature allows for callback functions to be redefined
-	  incrementally, just like Lisp functions are.</para>
-
-	  <para><function>defcallback</function>
-	  returns the callback pointer, e.g., the
-	  value of <varname>name</varname>.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="rm_sharpsign-underscore">
-	<indexterm zone="rm_sharpsign-underscore">
-	  <primary>#_</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>#_</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Reader Macro</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Reads a symbol from the current input stream, with *PACKAGE*
-	  bound to the &#34;OS&#34; package and with readtable-case preserved.</para>
-	  
-	  <para>Does a lookup on that symbol in <link
-	  linkend="The-Interface-Database">the OpenMCL interface
-	  database</link>, signalling an error if no foreign function
-	  information can be found for the symbol in any active <link
-	  linkend="Using-Interface-Directories">interface
-	  directory</link>.</para>
-
-	  <para>Notes the foreign function information, including the foreign
-	  function&#39;s return type, the number and type of the foreign
-	  function&#39;s required arguments, and an indication of whether or
-	  not the function accepts additional arguments (via e.g., the
-	  &#34;varargs&#34; mechanism in C).</para>
-
-	  <para>Defines a macroexpansion function on the symbol, which expand
-	  macro calls involving the symbol into EXTERNAL-CALL forms where
-	  foreign argument type specifiers for required arguments and the
-	  return value specifer are provided from the information ind the
-	  database.</para>
-
-	  <para>Returns the symbol.</para>
-
-	  <para>The effect of these steps is that it&#39;s possible to call
-	  foreign functions that take fixed numbers of arguments by simply
-	  providing argument values, as in:</para>
-
-	  <programlisting format="linespecific">(#_isatty fd)
-(#_read fd buf n)</programlisting>
-
-	  <para>and to call foreign functions that take variable numbers of
-	  arguments by specifying the types of non-required args, as in:</para>
-
-	  <programlisting format="linespecific">(with-cstrs ((format-string &#34;the answer is: %d&#34;))
-  (#_printf format-string :int answer))</programlisting>
-	</refsect1>
-      </refentry>
-
-      <refentry id="rm_sharpsign-questionmark">
-	<indexterm zone="rm_sharpsign-questionmark">
-	  <primary>#?</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>#?</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Reader Macro</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>In OpenMCL 0.14.2 and later, the #? reader macro can be used to
-	  access foreign variables; this functionality depends on the presence of
-	  &#34;vars.cdb&#34; files in the interface database. The current behavior
-	  of the #? reader macro is to:</para>
-
-	  <para>Read a symbol from the current input stream, with *PACKAGE*
-	  bound to the &#34;OS&#34; package and with readtable-case preserved.</para>
-	  
-	  <para>Use that symbol&#39;s pname to access the OpenMCL interface
-	  database, signalling an error if no appropriate foreign variable
-	  information can be found with that name in any active interface
-	  directory.</para>
-
-	  <para>Use type information recorded in the database to construct a
-	  form which can be used to access the foreign variable, and return
-	  that form.</para>
-
-	  <para>Please note that the set of foreign variables declared in header files
-	  may or may not match the set of foreign variables exported from
-	  libraries (we&#39;re generally talking about C and Unix here ...). When
-	  they do match, the form constructed by the #? reader macro manages the
-	  details of resolving and tracking changes to the foreign variable&#39;s
-	  address.</para>
-
-	  <para>Future extensions (via prefix arguments to the reader macro) may
-	  offer additional behavior; it might be convenient (for instance) to be
-	  able to access the address of a foreign variable without dereferencing
-	  that address.</para>
-
-	  <para>Foreign variables in C code tend to be platform- and
-	  packge-specific (the canonical example - &#34;errno&#34; - is typically
-	  not a variable when threads are involved. )</para>
-
-	  <para>In LinuxPPC, </para>
-
-	  <programlisting>? #?stderr</programlisting>
-
-	  <para>returns a pointer to the stdio error stream (&#34;stderr&#34; is a
-	  macro under OSX/Darwin).</para>
-
-	  <para>On both LinuxPPC and DarwinPPC, </para>
-
-	  <programlisting>? #?sys_errlist</programlisting>
-
-	  <para>returns a pointer to a C array of C error message strings.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_use-interface-dir">
-	<indexterm zone="f_use-interface-dir">
-	  <primary>use-interface-dir</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>USE-INTERFACE-DIR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>use-interface-dir</function> dir-id
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>dir-id</term>
-
-	      <listitem>
-		<para>A keyword whose pname, mapped to lower case, names a
-		subdirectory of &#34;ccl:headers;&#34; (or
-		"ccl:darwin-headers;")</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tells OpenMCL to add the interface directory denoted by
-	  dir-id to the list of interface directories which it consults for
-	  foreign type and function information. Arranges that that
-	  directory is searched before any others.</para>
-
-	  <para>Note that <function>use-interface-dir</function>
-	  merely adds an entry
-	  to a search list.
-	  If the named directory doesn&#39;t exist in the file system
-	  or doesn&#39;t
-	  contain a set of database files, a runtime error may occur
-	  when OpenMCL
-	  tries to open some database file in that directory, and it
-	  will try to
-	  open such a database file whenever it needs to find any
-	  foreign type or
-	  function information. <xref linkend="f_unuse-interface-dir"/>
-	  may come in
-	  handy in that case.</para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Examples</title>
-
-	  <para>One typically wants interface information to be
-	  available at compile-time (or, in many cases, at read-time).
-	  A typical idiom would be:</para>
-
-	  <programlisting format="linespecific">(eval-when (:compile-toplevel :execute)
-  (use-interface-dir :GTK))</programlisting>
-
-	  <para>Using the :GTK interface directory makes available
-	  information on
-	  foreign types, functions, and constants.  It's generally
-	  necessary to
-	  load foreign libraries before actually calling the
-	  foreign code, which for GTK can be done like this:</para>
-
-	  <programlisting>(load-gtk-libraries)</programlisting>
-
-	  <para>It should now be possible to do things like:</para>
-
-	  <programlisting>(#_gtk_widget_destroy w)</programlisting>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_unuse-interface-dir">
-	<indexterm zone="f_unuse-interface-dir">
-	  <primary>unuse-interface-dir</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>UNUSE-INTERFACE-DIR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>unuse-interface-dir</function> dir-id
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>dir-id</term>
-
-	      <listitem>
-		<para>A keyword whose pname, mapped to lower case, names a
-		subdirectory of &#34;ccl:headers;&#34; (or
-		"ccl:darwin-headers;")</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tells OpenMCL to remove the interface directory denoted by
-	  dir-id from the list of interface directories which are
-	  consulted for
-	  foreign type and function information. Returns T if the directory
-	  was on the search list, NIL otherwise.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_terminate-when-unreachable">
-	<indexterm zone="f_terminate-when-unreachable">
-	  <primary>terminate-when-unreachable</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>TERMINATE-WHEN-UNREACHABLE</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>terminate-when-unreachable</function> object
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>object</term>
-
-	      <listitem>
-		<para>A CLOS object of a class for which there exists
-		a method of the generic function
-		<function>ccl:terminate</function>.
-		</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    The "termination" mechanism is a way to have the garbage
-	    collector run a function right before an object is about to
-	    become garbage.  It is very similar to the "finalization"
-	    mechanism which Java has.  It is not standard Common Lisp,
-	    although other Lisp implementations have similar features.
-	    It is useful when there is some sort of special cleanup,
-	    deallocation, or releasing of resources which needs to happen
-	    when a certain object is no longer being used.
-	  </para>
-
-	  <para>
-	    When the garbage collector discovers that an object is no
-	    longer referred to anywhere in the program, it deallocates
-	    that object, freeing its memory.  However, if
-	    <function>ccl:terminate-when-unreachable</function> has been
-	    called on the object at any time, the garbage collector first
-	    invokes the generic function <function>ccl:terminate</function>,
-	    passing it the object as a parameter.
-	  </para>
-
-	  <para>
-	    Therefore, to make termination do something useful, you need to
-	    define a method on <function>ccl:terminate</function>.
-	  </para>
-
-	  <para>
-	    Because calling
-	    <function>ccl:terminate-when-unreachable</function> only
-	    affects a single object, rather than all objects of its
-	    class, you
-	    may wish to put a call to it in the
-	    <function>initialize-instance</function> method of a
-	    class.  Of course, this is only appropriate if you do in fact
-	    want to use termination for all objects of a given class.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Example</title>
-
-      <programlisting format="linespecific">
-(defclass resource-wrapper ()
-  ((resource :accessor resource)))
-
-(defmethod initialize-instance :after ((x resource-wrapper) &amp;rest initargs)
-  (ccl:terminate-when-unreachable x))
-
-(defmethod ccl:terminate ((x resource-wrapper))
-  (when (resource x)
-    (deallocate (resource x))))</programlisting>
-	</refsect1>
-
-	<refsect1>
-	  <title>See Also</title>
-
-	  <simplelist type="inline">
-	    <member><xref linkend="Tutorial--Allocating-Foreign-Data-on-the-Lisp-Heap"/></member>
-	  </simplelist>
-	</refsect1>
-
-      </refentry>
-
-    </sect1>
-  </chapter>
-
-  <chapter id="The-Objective-C-Bridge">
-    <title>The Objective-C Bridge</title>
-
-    <para>OS X APIs use a language called "Objective C", which is
-    built on C.  The Objective-C bridge makes it possible to work with
-    ObjC objects and classes from Lisp, and to define classes in Lisp
-    which can be used by ObjC.</para>
-    <para>The ultimate purpose of the ObjC and Cocoa bridges is to
-    make Cocoa as easy as possible to use from OpenMCL, in order to
-    support the development of GUI applications and IDEs.  The
-    eventual goal, which is much closer than it used to be, is
-    complete integration of Cocoa into CLOS (whatever that
-    means).</para>
-    <para>The current release provides Lisp-like syntax and naming
-    conventions for the basic ObjC operations, with automatic type
-    processing and messages checked for validity at compile-time.  It
-    also provides some convenience facilities for working with
-    Cocoa.</para>
-
-    <sect1 id="Using-Objective-C-Classes">
-      <title>Using Objective-C Classes</title>
-
-      <para>The class of most "standard" CLOS classes is the class
-      named STANDARD-CLASS. In the Objective-C object model, each
-      class is an instance of a (usually unique) metaclass, which is
-      itself an instance of a "base" metaclass (often the metaclass of
-      the class named "NSObject".) So, the Objective-C class named
-      "NSWindow" and the ObjC class "NSArray" are (sole) instances of
-      their distinct metaclasses whose names are also "NSWindow" and
-      "NSArray", respectively. (In the Objective-C world, it's much
-      more common and useful to specialize class behavior such as
-      instance allocation.)</para>
-      <para>When foreign libraries containing Objective-C classes are first
-loaded, the classes they contain are identified. The foreign class
-name, such as "NSWindow", is mapped to an external symbol in the
-"NS" package via the bridge's translation rules, such as NS:NS-WINDOW.
-A similar transformation happens to the
-metaclass name, with a "+" prepended, yielding something like
-NS:+NS-WINDOW.</para>
-      <para>These classes are integrated into CLOS such that the
-metaclass is an instance of the class OBJC:OBJC-METACLASS and
-the class
-is an instance of the metaclass. SLOT-DESCRIPTION metaobjects are
-created for each instance variable, and the class and metaclass go
-through something very similar to the "standard" CLOS class
-initialization protocol (with a difference being that these classes
-have already been allocated.)</para>
-      <para>Performing all this initialization, which is done when you
-(require "COCOA"), currently takes several
-seconds; it could conceivably be sped up some, but it's never likely
-to be fast.</para>
-      <para>When the process is complete, CLOS is aware of several hundred
-new ObjC classes and their metaclasses. OpenMCL's runtime system can
-reliably recognize MACPTRs to ObjC classes as being CLASS objects, and
-can (fairly reliably but heuristically) recognize instances of those
-classes (though there are complicating factors here; see below.)
-SLOT-VALUE can be used to access (and, with care, set) instance
-variables in ObjC instances. To see this, do:</para>
-      <programlisting>
-? (require "COCOA")
-</programlisting>
-      <para>and, after waiting a bit longer for a Cocoa listener window to
-appear, activate that Cocoa listener and do:</para>
-      <programlisting>? (describe (ccl::send ccl::*NSApp* 'key-window))
-</programlisting>
-      <para>This sends a message asking for the key window, which is the window
-that has the input focus (often the frontmost), and then describes
-it. As we can see, NS:NS-WINDOWs have lots of interesting slots.</para>
-    </sect1>
-
-    <sect1 id="Instantiating-Objective-C-Objects">
-      <title>Instantiating Objective-C Objects</title>
-      <para>Making an instance of an ObjC class (whether the class in
-      question is predefined or defined by the application) involves
-      calling MAKE-INSTANCE with the class and a set of initargs as
-      arguments.  As with STANDARD-CLASS, making an instance involves
-      initializing (with INITIALIZE-INSTANCE) an object allocated with
-      ALLOCATE-INSTANCE.</para>
-      <para>For example, you can create an ns:ns-number like this:</para>
-      <programlisting>
-? (make-instance 'ns:ns-number :init-with-int 42)
-#&lt;NS-CF-NUMBER 42 (#x85962210)>
-</programlisting>
-      <para>It's worth looking at how this would be done if you were
-      writing in Objective C:</para>
-      <programlisting>
-[[NSNumber alloc] initWithInt: 42]
-      </programlisting>
-      <para>Allocating an instance of an ObjC class involves sending the
-class an "alloc" message, and then using those initargs that
-<emphasis>don't</emphasis> correspond to slot initags as the
-"init" message to be sent to the newly-allocated instance.  So, the
-example above could have been done more verbosely as:</para>
-      <programlisting>
-? (defvar *n* (ccl::send (find-class 'ns:ns-number) 'alloc))
-*N*
-
-? (setq *n* (ccl::send *n* :init-with-int 42))
-#&lt;NS-CF-NUMBER 42 (#x16D340)>
-</programlisting>
-      <para>That setq is important; this is a case where init
-decides to replace the object and return the new one, instead
-of modifying the existing one.
-In fact, if you leave out the setq and
-then try to view the value of *N*, OpenMCL will freeze.  There's
-little reason to ever do it this way; this is just to show
-what's going on.</para>
-      <para>You've seen that an ObjC initialization method doesn't have to
-return the same object it was passed.  In fact, it doesn't have
-to return any object at all; in this case, the initialization fails
-and make-instance returns nil.</para>
-      <para>In some special cases, such as loading an ns:ns-window-controller
-from a .nib file, it may be necessary for you to pass the
-instance itself as one of the parameters to the initialization
-method.  It goes like this:</para>
-      <programlisting>
-? (defvar *controller*
-          (make-instance 'ns:ns-window-controller))
-*CONTROLLER*
-
-? (setq *controller*
-        (ccl::send *controller*
-                   :init-with-window-nib-name #@"DataWindow"
-                   :owner *controller*))
-#&lt;NS-WINDOW-CONTROLLER &lt;NSWindowController: 0x1fb520> (#x1FB520)>
-</programlisting>
-      <para>This example calls (make-instance) with no initargs.  When you
-do this, the object is only allocated, and not initialized.  It
-then sends the "init" message to do the initialization by hand.</para>
-    </sect1>
-
-    <sect1 id="Calling-Objective-C-Methods">
-      <title>Calling Objective-C Methods</title>
-      <para>In Objective-C, methods are called "messages", and there's
-      a special syntax to send a message to an object:</para>
-      <programlisting>
-[w alphaValue]
-[w setAlphaValue: 0.5]
-[v mouse: p inRect: r]
-      </programlisting>
-      <para>The first line sends the method "alphaValue" to the object
-      <literal>w</literal>, with no parameters.  The second line sends
-      the method "setAlphaValue", with the parameter 0.5.  The third
-      line sends the method "mouse:inRect:" - yes, all one long word -
-      with the parameters <literal>p</literal> and
-      <literal>r</literal>.</para>
-      <para>In Lisp, these same three lines are:</para>
-      <programlisting>
-(send w 'alpha-value)
-(send w :set-alpha-value 0.5)
-(send v :mouse p :in-rect r)
-</programlisting>
-      <para>Notice that when a method has no parameters, its name is an ordinary
-symbol (it doesn't matter what package the symbol is in, as
-only its name is checked).  When a method has parameters,
-each part of its name is a keyword, and the keywords alternate
-with the values.</para>
-      <para>These two lines break those rules, and both  will
-result in error messages:</para>
-      <programlisting>
-(send w :alpha-value)
-(send w 'set-alpha-value 0.5)
-</programlisting>
-      <para>Instead of (send), you can also invoke (send-super), with the
-same interface.  It has roughly the same purpose as CLOS's
-(call-next-method); when you use (send-super), the message is
-handled by the superclass.  This can be used to get at the
-original implementation of a method when it is shadowed by a
-method in your subclass.</para>
-
-      <sect2 id="Type-Coercion-for-ObjC-Method-Calls">
-	<title>Type Coercion for ObjC Method Calls</title>
-        <para>OpenMCL's FFI handles many common conversions between
-        Lisp and foreign data, such as unboxing floating-point args
-        and boxing floating-point results.  The bridge adds a few more
-        automatic conversions:</para>
-        <para>NIL is equivalent to (%NULL-PTR) for any message
-        argument that requires a pointer.</para>
-        <para>T/NIL are equivalent to #$YES/#$NO for any boolean argument.</para>
-        <para>A #$YES/#$NO returned by any method that returns BOOL
-        will be automatically converted to T/NIL.</para>
-      </sect2>
-
-      <sect2 id="Methods-which-Return-Structures">
-	<title>Methods which Return Structures</title>
-        <para>Some Cocoa methods return small structures, such as
-        those used to represent points, rects, sizes and ranges. When
-        writing in Objective C, the compiler hides the implementation
-        details.  Unfortunately, in Lisp we must be slightly more
-        aware of them.</para>
-        <para>Methods which return structures are called in a special
-        way; the caller allocates space for the result, and passes a
-        pointer to it as an extra argument to the method.  This is
-        called a Structure Return, or STRET.  Don't look at me; I
-        don't name these things.</para>
-        <para>Here's a simple use of this in Objective C.  The first line
-	sends the "bounds" message to v1, which returns a rectangle.
-	The second line sends the "setBounds" message to v2, passing
-	that same rectangle as a parameter.</para>
-        <programlisting>
-NSRect r = [v1 bounds];
-[v2 setBounds r];
-	</programlisting>
-        <para>In Lisp, we must explicitly allocate the memory, which
-        is done most easily and safely with <xref linkend="m_rlet"/>.
-        We do it like this:</para>
-        <programlisting>
-(rlet ((r :&lt;NSR>ect))
-  (send/stret r v1 'bounds)
-  (send v2 :set-bounds r))
-</programlisting>
-        <para>The rlet allocates the storage (but doesn't initialize
-        it), and makes sure that it will be deallocated when we're
-        done.  It binds the variable r to refer to it.  The call to
-        <literal>send/stret</literal> is just like an ordinary call to
-        <literal>send</literal>, except that r is passed as an extra,
-        first parameter.  The third line, which calls
-        <literal>send</literal>, does not need to do anything special,
-        because there's nothing complicated about passing a structure
-        as a parameter.</para>
-	<para>In order to make STRETs easier to use, the bridge
-	provides two conveniences.</para>
-        <para>First, you can use the macros <literal>slet</literal>
-        and <literal>slet*</literal> to allocate and initialize local
-        variables to foreign structures in one step.  The example
-        above could have been written more tersely as:</para>
-        <programlisting>
-(slet ((r (send v1 'bounds)))
-  (send v2 :set-bounds r))
-	</programlisting>
-        <para>Second, when one call to <literal>send</literal> is made
-inside another, the inner one has an implicit
-<literal>slet</literal> around it.  So, one could in fact
-just write:</para>
-        <programlisting>
-(send v1 :set-bounds (send v2 'bounds))
-</programlisting>
-        <para>There are also several psuedo-functions provided for convenience
-by the ObjC compiler, to make objects of specific types. The
-following are currently supported by the bridge: NS-MAKE-POINT,
-NS-MAKE-RANGE, NS-MAKE-RECT, and NS-MAKE-SIZE.</para>
-        <para>These pseudo-functions can be used within an SLET initform:</para>
-        <programlisting>
-(slet ((p (ns-make-point 100.0 200.0)))
-  (send w :set-frame-origin p))
-</programlisting>
-        <para>Or within a call to <literal>send</literal>:</para>
-        <programlisting>
-(send w :set-origin (ns-make-point 100.0 200.0))
-</programlisting>
-        <para>However, since these aren't real functions, a call like the
-following won't work:</para>
-        <programlisting>
-(setq p (ns-make-point 100.0 200.0))
-</programlisting>
-        <para>To extract fields from these objects, there are also some
-convenience macros: NS-MAX-RANGE, NS-MIN-X,
-NS-MIN-Y, NS-MAX-X, NS-MAX-Y, NS-MID-X, NS-MID-Y,
-NS-HEIGHT, and NS-WIDTH.</para>
-        <para>Note that there is also a <literal>send-super/stret</literal>
-for use within methods.  Like <literal>send-super</literal>,
-it ignores any shadowing methods in a subclass, and calls the
-version of a method which belongs to its superclass.</para>
-      </sect2>
-
-      <sect2 id="Variable-Arity-Messages">
-	<title>Variable-Arity Messages</title>
-        <para>
-There are a few messages in Cocoa which take variable numbers
-of arguments. Perhaps the most common examples involve
-formatted strings:</para>
-        <programlisting>
-[NSClass stringWithFormat: "%f %f" x y]
-</programlisting>
-        <para>In Lisp, this would be written:</para>
-        <programlisting>
-(send (find-class 'ns:ns-string)
-      :string-with-format #@"%f %f"
-      (:double-float x :double-float y))
-</programlisting>
-        <para>Note that it's necessary to specify the foreign types of the
-variables (in this example, :double-float), because the
-compiler has no general way of knowing these types.  (You
-might think that it could parse the format string, but this
-would only work for format strings which are not determined
-at runtime.)</para>
-        <para>Because the ObjC runtime system does not provide any information
-on which messages are variable arity, they must be explicitly
-declared. The standard variable arity messages in Cocoa are
-predeclared by the bridge.  If you need to declare a new
-variable arity message, use
-(DEFINE-VARIABLE-ARITY-MESSAGE "myVariableArityMessage:").</para>
-      </sect2>
-
-      <sect2 id="Optimization">
-	<title>Optimization</title>
-        <para>The bridge works fairly hard to optimize message sends,
-        when it has enough information to do so.  There are two cases
-        when it does.  In either, a message send should be nearly as
-        efficient as when writing in Objective C.</para>
-        <para>The first case is when both the message and the
-        receiver's class are known at compile-time. In general, the
-        only way the receiver's class is known is if you declare it,
-        which you can do with either a DECLARE or a THE form.  For
-        example:</para>
-        <programlisting>
-(send (the ns:ns-window w) 'center)
-	</programlisting>
-        <para>Note that there is no way in ObjC to name the class of a
-        class.  Thus the bridge provides a declaration, @METACLASS.
-        The type of an instance of "NSColor" is ns:ns-color.  The type
-        of the <emphasis>class</emphasis> "NSColor" is (@metaclass
-        ns:ns-color):</para>
-        <programlisting>
-(let ((c (find-class 'ns:ns-color)))
-  (declare ((ccl::@metaclass ns:ns-color) c))
-  (send c 'white-color))
-</programlisting>
-        <para>The other case that alllows optimization is when only
-        the message is known at compile-time, but its type signature
-        is unique. Of the more-than-6000 messages currently provided
-        by Cocoa, only about 50 of them have nonunique type
-        signatures.</para>
-        <para>An example of a message with a type signature that is
-        not unique is SET.  It returns VOID for NSColor, but ID for
-        NSSet.  In order to optimize sends of messages with nonunique
-        type signatures, the class of the receiver must be declared at
-        compile-time.</para>
-        <para>If the type signature is nonunique or the message is
-        unknown at compile-time, then a slower runtime call must be
-        used.</para>
-        <para>When the receiver's class is unknown, the bridge's
-        ability to optimize relies on a type-signature table which it
-        maintains.  When first loaded, the bridge initializes this
-        table by scanning every method of every ObjC class.  When new
-        methods are defined later, the table must be updated.  This
-        happens automatically when you define methods in Lisp.  After
-        any other major change, such as loading an external framework,
-        you should rebuild the table:</para>
-        <programlisting>
-? (update-type-signatures)
-</programlisting>
-        <para>Because <literal>send</literal> and its relatives
-        <literal>send-super</literal>, <literal>send/stret</literal>,
-        and <literal>send-super/stret</literal> are macros, they
-        cannot be <literal>funcall</literal>ed,
-        <literal>apply</literal>ed, or passed as arguments to
-        functions.</para>
-        <para>To work around this, there are function equivalents to
-        them: <literal>%send</literal>,
-        <literal>%send-super</literal>,
-        <literal>%send/stret</literal>, and
-        <literal>%send-super/stret</literal>.  However, these
-        functions should be used only when the macros will not do,
-        because they are unable to optimize.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Defining-Objective-C-Classes">
-      <title>Defining Objective-C Classes</title>
-      <para>You can define your own foreign classes, which can then be
-      passed to foreign functions; the methods which you implement in
-      Lisp will be made available to the foreign code as
-      callbacks.</para>
-      <para>You can also define subclasses of existing classes,
-      implementing your subclass in Lisp even though the parent class
-      was in Objective C.  One such subclass is CCL::NS-LISP-STRING.
-      It is also particularly useful to make subclasses of
-      NS-WINDOW-CONTROLLER.</para>
-      <para>We can use the MOP to define new Objective-C classes, but
-      we have to do something a little funny: the :METACLASS that we'd
-      want to use in a DEFCLASS option generally doesn't exist until
-      we've created the class (recall that ObjC classes have, for the
-      sake of argument, unique and private metaclasses.) We can sort
-      of sleaze our way around this by specifying a known ObjC
-      metaclass object name as the value of the DEFCLASS :METACLASS
-      object; the metaclass of the root class NS:NS-OBJECT,
-      NS:+NS-OBJECT, makes a good choice. To make a subclass of
-      NS:NS-WINDOW (that, for simplicity's sake, doesn't define any
-      new slots), we could do:</para>
-      <programlisting>
-(defclass example-window (ns:ns-window)
-  ()
-  (:metaclass ns:+ns-object))
-</programlisting>
-      <para>That'll create a new ObjC class named EXAMPLE-WINDOW whose
-      metaclass is the class named +EXAMPLE-WINDOW. The class will be
-      an object of type OBJC:OBJC-CLASS, and the metaclass will be of
-      type OBJC:OBJC-METACLASS.  EXAMPLE-WINDOW will be a subclass of
-      NS-WINDOW.</para>
-
-      <sect2 id="Defining-classes-with-foreign-slots">
-	<title>Defining classes with foreign slots</title>
-        <para>If a slot specification in an Objective-C class
-        definition contains the keyword :FOREIGN-TYPE, the slot will
-        be a "foreign slot" (i.e. an ObjC instance variable). Be aware
-        that it is an error to redefine an ObjC class so that its
-        foreign slots change in any way, and OpenMCL doesn't do
-        anything consistent when you try to.</para>
-        <para>The value of the :FOREIGN-TYPE initarg should be a
-        foreign type specifier. For example, if we wanted (for some
-        reason) to define a subclass of NS:NS-WINDOW that kept track
-        of the number of key events it had received (and needed an
-        instance variable to keep that information in), we could
-        say:</para>
-        <programlisting>
-(defclass key-event-counting-window (ns:ns-window)
-  ((key-event-count :foreign-type :int
-                    :initform 0
-                    :accessor window-key-event-count))
-  (:metaclass ns:+ns-object))
-</programlisting>
-        <para>Foreign slots are always SLOT-BOUNDP, and the initform
-        above is redundant: foreign slots are initialized to binary
-        0.</para>
-      </sect2>
-
-      <sect2 id="Defining-classes-with-Lisp-slots">
-	<title>Defining classes with Lisp slots</title>
-        <para>A slot specification in an ObjC class definition that
-        doesn't contain the :FOREIGN-TYPE initarg defines a
-        pretty-much normal lisp slot that'll happen to be associated
-        with "an instance of a foreign class". For instance:</para>
-        <programlisting>
-(defclass hemlock-buffer-string (ns:ns-string)
-  ((hemlock-buffer :type hi::hemlock-buffer
-                   :initform hi::%make-hemlock-buffer
-                   :accessor string-hemlock-buffer))
-  (:metaclass ns:+ns-object))
-	</programlisting>
-        <para>As one might expect, this has memory-management
-        implications: we have to maintain an association between a
-        MACPTR and a set of lisp objects (its slots) as long as the
-        ObjC instance exists, and we have to ensure that the ObjC
-        instance exists (does not have its -dealloc method called)
-        while lisp is trying to think of it as a first-class object
-        that can't be "deallocated" while it's still possible to
-        reference it. Associating one or more lisp objects with a
-        foreign instance is something that's often very useful; if you
-        were to do this "by hand", you'd have to face many of the same
-        memory-management issues.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Defining-Objective-C-Methods">
-      <title>Defining Objective-C Methods</title>
-      <para>In ObjC, unlike in CLOS, every method belongs to some
-      particular class.  This is probably not a strange concept to
-      you, because C++ and Java do the same thing.  When you use Lisp
-      to define ObjC methods, it is only possible to define methods
-      belonging to ObjC classes which have been defined in
-      Lisp.</para>
-      <para>The macro <literal>define-objc-method</literal> is used
-      for this.  As described in , the names of ObjC methods are
-      broken into pieces, each piece followed by a parameter.  The
-      types of all parameters must be explicitly declared.</para>
-      <para>Right now, I'm not sure how to formally describe the usage
-of define-objc-method, so I'm going to do it with some short
-examples.  Let us define a class to use in them:</para>
-      <programlisting>
-(defclass data-window-controller (ns:ns-window-controller)
-  ((window :foreign-type :id :accessor window)
-   (data :initform nil :accessor data))
-  (:metaclass ns:+ns-object))
-</programlisting>
-      <para>There's nothing special about this class.  It inherits
-      from ns:ns-window-controller.  It has two slots:
-      <literal>window</literal> is a foreign slot, stored in the ObjC
-      world; and <literal>data</literal> is an ordinary slot, stored
-      in the Lisp world.</para>
-      <para>Here is an example of how to define a method which takes
-      no arguments.  It happens to be an initialization method, but
-      that's not important:</para>
-      <programlisting>
- (define-objc-method ((:id get-window)
-                     data-window-controller)
-  (window self))
-      </programlisting>
-      <para>The return type of this method is the foreign type :id,
-      which is used for all ObjC objects.  The name of the method is
-      <literal>get-window</literal>.  The body of the method is the
-      single line (window self).  The variable <literal>self</literal>
-      is bound, within the body, to the instance which is receiving
-      the message.  The call to <literal>window</literal> uses the
-      CLOS accessor to get the value of the window field.</para>
-      <para>Here's an example which takes a parameter.  Notice that
-      the name of the method without a parameter was an ordinary
-      symbol, but with a parameter, it's a keyword:</para>
-      <programlisting>
-(define-objc-method ((:id :init-with-multiplier (:int multiplier))
-                     data-window-controller)
-  (setf (data self) (make-array 100))
-  (dotimes (i 100)
-    (setf (aref (data self) i)
-          (* i multiplier)))
-  self)
-      </programlisting>
-      <para>To Objective-C code which uses the class, the name of this
-      method is "initWithMultiplier:".  The name of the parameter is
-      <literal>multiplier</literal>, and its type is :int.  The body
-      of the method does some meaningless things.  Then it returns
-      <literal>self</literal>, because this is an initialization
-      method.</para>
-      <para>Here's an example with more than one parameter:</para>
-      <programlisting>
-(define-objc-method ((:id :init-with-multiplier (:int multiplier)
-                          :and-addend (:int addend))
-                     data-window-controller)
-  (setf (data self) (make-array size))
-  (dotimes (i 100)
-    (setf (aref (data self) i)
-          (+ (* i multiplier)
-             addend)))
-  self)
-      </programlisting>
-      <para>To Objective-C, the name of this method is
-      "initWithMultiplier:andAddend:".  Both parameters are of type
-      :int; the first is named <literal>multiplier</literal>, and the
-      second is <literal>addend</literal>.  Again, the method returns
-      <literal>self</literal>.</para>
-      <para>Here is a method which does not return any value, a
-      so-called "void method".  Where our other methods said :id, this
-      one says :void for the return type:</para>
-      <programlisting>
-(define-objc-method ((:void :take-action (:id sender))
-                     data-window-controller)
-  (declare (ignore sender))
-  (dotimes (i 100)
-    (setf (aref (data self) i)
-          (- (aref (data self) i)))))
-</programlisting>
-      <para>This method would be called "takeAction:" in ObjC.  The
-      convention for methods that are going to be used as Cocoa
-      actions is that they take one parameter, which is the object
-      responsible for triggering the action.  However, this method
-      doesn't actually need to use that parameter, so it explicitly
-      ignores it to avoid a compiler warning.  As promised, the method
-      doesn't return any value.</para>
-      <para>There is also an alternate syntax, illustrated here.  The
-      following two method definitions are equivalent:</para>
-      <programlisting>
-(define-objc-method ("applicationShouldTerminate:"
-                     "LispApplicationDelegate")
-                    (:id sender :&lt;BOOL>)
-  (declare (ignore sender))
-  nil)
-
-(define-objc-method ((:&lt;BOOL>
-                      :application-should-terminate sender)
-                     lisp-application-delegate)
-  (declare (ignore sender))
-  nil)
-</programlisting>
-      <sect2 id="Method-Redefinition-Constraints">
-	<title>Method Redefinition Constraints</title>
-        <para>Objective C was not designed, as Lisp was, with runtime
-        redefinition in mind.  So, there are a few constraints about
-        how and when you can replace the definition of an Objective C
-        method.  Currently, if you break these rules, nothing will
-        collapse, but the behaviour will be confusing; so
-        don't.</para>
-        <para>Objective C methods can be redefined at runtime, but
-        their signatures shouldn't change.  That is, the types of the
-        arguments and the return type have to stay the same.  The
-        reason for this is that changing the signature changes the
-        selector which is used to call the method.</para>
-        <para>When a method has already been defined in one class, and
-        you define it in a subclass, shadowing the original method,
-        they must both have the same type signature.  There is no such
-        constraint, though, if the two classes aren't related and the
-        methods just happen to have the same name.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="How-Objective-C-Names-are-Mapped-to-Lisp-Symbols">
-      <title>How Objective-C Names are Mapped to Lisp Symbols</title>
-      <para>There is a standard set of naming conventions for Cocoa
-      classes, messages, etc.  As long as they are followed, the
-      bridge is fairly good at automaticallly translating between ObjC
-      and Lisp names.</para>
-      <para>For example, "NSOpenGLView" becomes ns:ns-opengl-view;
-      "NSURLHandleClient" becomes ns:ns-url-handle-client; and
-      "nextEventMatchingMask:untilDate:inMode:dequeue:" becomes
-      (:next-event-matching-mask :until-date :in-mode :dequeue).  What
-      a mouthful.</para>
-      <para>To see how a given ObjC or Lisp name will be translated by
-      the bridge, you can use the following functions:</para>
-	<simplelist type="vert">
-	  <member>(ccl::objc-to-lisp-classname string)</member>
-	  <member>(ccl::lisp-to-objc-classname symbol)</member>
-	  <member>(ccl::objc-to-lisp-message string)</member>
-	  <member>(ccl::lisp-to-objc-message string)</member>
-	  <member>(ccl::objc-to-lisp-init string)</member>
-	  <member>(ccl::lisp-to-objc-init keyword-list)</member>
-	</simplelist>
-
-      <para>Of course, there will always be exceptions to any naming
-      convention.  Please tell us on the mailing lists if you come
-      across any name translation problems that seem to be bugs.
-      Otherwise, the bridge provides two ways of dealing with
-      exceptions:</para>
-      <para>First, you can pass a string as the class name of
-      MAKE-OBJC-INSTANCE and as the message to SEND.  These strings
-      will be directly interpreted as ObjC names, with no
-      translation. This is useful for a one-time exception.  For
-      example:</para>
-      <programlisting>
-(ccl::make-objc-instance "WiErDclass")
-(ccl::send o "WiErDmEsSaGe:WithARG:" x y)
-      </programlisting>
-      <para>Alternatively, you can define a special translation rule
-      for your exception.  This is useful for an exceptional name that
-      you need to use througout your code.  Some examples:</para>
-      <programlisting>
-(ccl::define-classname-translation "WiErDclass" wierd-class)
-(ccl::define-message-translation "WiErDmEsSaGe:WithARG:" (:weird-message :with-arg))
-(ccl::define-init-translation "WiErDiNiT:WITHOPTION:" (:weird-init :option))
-</programlisting>
-      <para>The normal rule in ObjC names is that each word begins with a
-capital letter (except possibly the first).  Using this rule
-literally, "NSWindow" would be translated as N-S-WINDOW, which
-seems wrong.  "NS" is a special word in ObjC that should not be
-broken at each capital letter. Likewise "URL", "PDF", "OpenGL",
-etc. Most common special words used in Cocoa are already defined
-in the bridge, but you can define new ones as follows:</para>
-      <programlisting>
-(ccl::define-special-objc-word "QuickDraw")
-</programlisting>
-      <para>Note that message keywords in a SEND such as (SEND V
-      :MOUSE P :IN-RECT R) may look like the keyword arguments in a
-      Lisp function call, but they really aren't. All keywords must be
-      present and the order is significant. Neither (:IN-RECT :MOUSE)
-      nor (:MOUSE) translate to "mouse:inRect:"</para>
-      <para>Also, as a special exception, an "init" prefix is optional
-      in the initializer keywords, so (MAKE-OBJC-INSTANCE 'NS-NUMBER
-      :INIT-WITH-FLOAT 2.7) can also be expressed as
-      (MAKE-OBJC-INSTANCE 'NS-NUMBER :WITH-FLOAT 2.7)</para>
-    </sect1>
-  </chapter>
-
-  <chapter id="Platform-specific-notes">
-    <title>Platform-specific notes</title>
-      
-
-    <sect1 id="Platform-specific-overview">
-      <title>Overview</title>
-      <para> The documentation and whatever experience you may have in
-      using OpenMCL under Linux should also apply to using it under
-      Darwin/MacOS X and FreeBSD. There are some differences between
-      the platforms, and these differences are sometimes exposed in
-      the implementation.</para>
-
-
-      <sect2 id="File-system-case">
-	<title>File-system case</title>
-
-	<para>Darwin and MacOS X use HFS+ file systems by default;
-	HFS+ file systems are usually case-insensitive. Most of
-	OpenMCL's filesystem and pathname code assumes that the
-	underlying filesystem is case-sensitive; this assumption
-	extends to functions like EQUAL, which assumes that #p"FOO"
-	and #p"foo" denote different, un-EQUAL filenames. Since
-	Darwin/MacOS X can also use UFS and NFS filesystems, the
-	opposite assumption would be no more correct than the one
-	that's currently made.</para>
-        <para>Whatever the best solution to this problem turns out to be, there are
-some practical considerations. Doing:</para>
-        <programlisting>
-? (save-application "DPPCCL")
-	</programlisting>
-        <para>on 32-bit DarwinPPC has the unfortunate side-effect of
-        trying to overwrite the Darwin OpenMCL kernel, "dppccl", on a
-        case-insensitive filesystem.</para>
-        <para>To work around this, the Darwin OpenMCL kernel expects
-        the default heap image file name to be the kernel's own
-        filename with the string ".image" appended, so the idiom would
-        be:</para>
-        <programlisting>
-? (save-application "dppccl.image")
-	</programlisting>
-      </sect2>
-
-      <sect2 id="Line-Termination-Characters">
-	<title>Line Termination Characters</title>
-        <para>MacOSX effectively supports two distinct line-termination
-	conventions. Programs in its Darwin substrate follow the Unix
-	convention of recognizing #\LineFeed as a line terminator; traditional
-	MacOS programs use #\Return for this purpose.  Many modern
-	GUI programs try to support several different line-termination
-	conventions (on the theory that the user shouldn't be too concerned
-	about what conventions are used an that it probably doesn't matter.
-	Sometimes this is true, other times ... not so much.
-	</para>
-        <para>OpenMCL follows the Unix convention on both Darwin and
-        LinuxPPC, but offers some support for reading and writing
-        files that use other conventions (including traditional MacOS
-        conventions) as well.</para> 
-	<para>This support (and anything like it) is by nature
-	heuristic: it can successfully hide the distinction between
-	newline conventions much of the time, but could mistakenly
-	change the meaning of otherwise correct programs (typically
-	when files contain both #\Return and #\Linefeed characters or
-	when files contain mixtures of text and binary data.) Because
-	of this concern, the default settings of some of the variables
-	that control newline translation and interpretation are
-	somewhat conservative.</para>
-	<para>Although the issue of multiple newline conventions
-	primarily affects MacOSX users, the functionality described
-	here is available under LinuxPPC as well (and may occasionally
-	be useful there.)</para> <para>None of this addresses issues
-	related to the third newline convention ("CRLF") in widespread
-	use (since that convention isn't native to any platform on
-	which OpenMCL currently runs). If OpenMCL is ever ported to
-	such a platform, that issue might be revisited.</para>
-	<para>Note that some MacOS programs (including some versions
-	of commercial MCL) may use HFS file type information to
-	recognize TEXT and other file types and so may fail to
-	recognize files created with OpenMCL or other Darwin
-	applications (regardless of line termination issues.)</para>
-	<para>Unless otherwise noted, the symbols mentioned in this
-	documentation are exported from the CCL package.</para>
-      </sect2>
-
-      <sect2 id="Single-precision-trig---transcendental-functions">
-	<title>Single-precision trig &amp; transcendental functions</title>
-        <para>
-	Despite what Darwin's man pages say, early versions of its math library
-	(up to and including at least OSX 10.2 (Jaguar) don't implement
-	single-precision variants of the transcendental and trig functions
-	(#_sinf, #_atanf, etc.) OpenMCL worked around this by coercing
-	single-precision args to double-precision, calling the
-	double-precision version of the math library function, and coercing
-	the result back to a SINGLE-FLOAT. These steps can introduce rounding
-	errors (and potentially overflow conditions) that might not be present
-	or as severe if true 32-bit variants were available.</para>
-      </sect2>
-
-      <sect2 id="Shared-libraries">
-	<title>Shared libraries</title>
-        <para>Darwin/MacOS X distinguishes between "shared libraries"
-        and "bundles" or "extensions"; Linux and FreeBSD don't. In
-        Darwin, "shared libraries" have the file type "dylib" : the
-        expectation is that this class of file is linked against when
-        executable files are created and loaded by the OS when the
-        executable is launched. The latter class -
-        "bundles/extensions" - are expected to be loaded into and
-        unloaded from a running application, via a mechanism like the
-        one used by OpenMCL's OPEN-SHARED-LIBRARY function.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Unix-Posix-Darwin-Features">
-      <title>Unix/Posix/Darwin Features</title>
-      <para>OpenMCL has several convenience functions which allow you
-      to make Posix (portable Unix) calls without having to use the
-      foreign-function interface.  Each of these corresponds directly
-      to a single Posix function call, as it might be made in C.
-      There is no attempt to make these calls correspond to Lisp
-      idioms, such as <literal>setf</literal>.  This means that their
-      behaviour is simple and predictable.</para>
-      <para>For working with environment variables, there are
-      CCL::GETENV and CCL::SETENV.</para>
-      <para>For working with user and group IDs, there are
-      CCL::GETUID, CCL::SETUID, and CCL::SETGID.  To find the home
-      directory of an arbitrary user, as set in the user database
-      (/etc/passwd), there is CCL::GET-USER-HOME-DIR.</para>
-      <para>For process IDs, there is CCL::GETPID.</para>
-      <para>For the <literal>system()</literal> function, there is
-      CCL::OS-COMMAND.  Ordinarily, it is better - both more efficient
-      and more predictable - to use the features described in <xref
-      linkend="Running-Other-Programs-as-Subprocesses"/>.  However,
-      sometimes you may want to specifically ask the shell to invoke a
-      command for you.</para>
-    </sect1>
-
-    <sect1 id="Cocoa-Programming-in-OpenMCL">
-      <title>Cocoa Programming in OpenMCL</title>
-      <para>Cocoa is one of Apple's APIs for GUI programming; for most
-      purposes, development is considerably faster with Cocoa than
-      with the alternatives.  You should have a little familiarity
-      with it, to better understand this section.</para>
-      <para>A small sample Cocoa program can be invoked by evaluating
-      (REQUIRE 'TINY) and then (CCL::TINY-SETUP). This program
-      provides a simple example of using several of the bridge's
-      capabilities.</para>
-      <para>The Tiny demo creates Cocoa objects dynamically, at
-      runtime, which is always an option.  However, for large
-      applications, it is usually more convenient to create your
-      objects with Apple Interface Builder, and store them in .nib
-      files to be loaded when needed.  Both approaches can be freely
-      mixed in a single program.</para>
-
-      <sect2 id="The-Command-Line-and-the-Window-System">
-	<title>The Command Line and the Window System</title>
-        <para>OpenMCL is ordinarily a command-line application (it
-        doesn't have a connection to the OSX Window server, doesn't
-        have its own menubar or dock icon, etc.) By opening some
-        libraries and jumping through some hoops, it's able to sort of
-        transform itself into a full-fledged GUI application (while
-        retaining its original TTY-based listener.) The general idea
-        is that this hybrid environment can be used to test and
-        protoype UI ideas and the resulting application can eventually
-        be fully transformed into a bundled, double-clickable
-        application. This is to some degree possible, but there needs
-        to be a bit more infrastructure in place before many people
-        would find it easy.</para>
-        <para>Cocoa applications use the NSLog function to write
-        informational/warning/error messages to the application's
-        standard output stream. When launched by the Finder, a GUI
-        application's standard output is diverted to a logging
-        facility that can be monitored with the Console application
-        (found in /Applications/Utilities/Console.app).  In the hybrid
-        environment, the application's standard output stream is
-        usually the initial listener's standard output stream. With
-        two different buffered stream mechanisms trying to write to
-        the same underlying Unix file descriptor, it's not uncommon to
-        see NSLog output mixed with lisp output on the initial
-        listener.</para>
-      </sect2>
-
-      <sect2 id="Writing--and-reading--Cocoa-code">
-	<title>Writing (and reading) Cocoa code</title> <para>The
-	syntax of the constructs used to define Cocoa classes and
-	methods has changed a bit (it was never documented outside of
-	the source code and never too well documented at all), largely
-	as the result of functionality offered by Randall Beer's
-	bridge; the &ldquo;standard name-mapping conventions&rdquo;
-	referenced below are described in his CocoaBridgeDoc.txt file,
-	as are the constructs used to invoke (&ldquo;send messages
-	to&rdquo;) Cocoa methods.</para>
-        <para>All of the symbols described below are currently internal to
-the CCL package.</para>
-	<simplelist type="vert" columns="1">
-	  <member><xref linkend="m_class"/></member>
-	  <member><xref linkend="m_selector"/></member>
-	  <member><xref linkend="m_define-objc-method"/></member>
-	  <member><xref linkend="m_define-objc-class-method"/></member>
-	</simplelist>
-      </sect2>
-
-      <sect2 id="The-Application-Kit-and-Multiple-Threads">
-	<title>The Application Kit and Multiple Threads</title>
-        <para>The Cocoa API is broken into several pieces.  The
-        Application Kit, affectionately called AppKit, is the one
-        which deals with window management, drawing, and handling
-        events.  AppKit really wants all these things to be done by a
-        "distinguished thread".  creation, and drawing to take place
-        on a distinguished thread.</para>
-        <para>Apple has published some guidelines which discuss these
-        issues in some detail; see the Apple Multithreading
-        Documentation, and in particular the guidelines on Using the
-        Application Kit from Multiple Threads.  The upshot is that
-        there can sometimes be unexpected behavior when objects are
-        created in threads other than the distinguished event thread;
-        eg, the event thread sometimes starts performing operations on
-        objects that haven't been fully initialized.</para> <para>It's
-        certainly more convenient to do certain types of exploratory
-        programming by typing things into a listener or evaluating a
-        &ldquo;defun&rdquo; in an Emacs buffer; it may sometimes be
-        necessary to be aware of this issue while doing so.</para>
-        <para>Each thread in the Cocoa runtime system is expected to
-        maintain a current &ldquo;autorelease pool&rdquo; (an instance
-        of the NSAutoreleasePool class); newly created objects are
-        often added to the current autorelease pool (via the
-        -autorelease method), and periodically the current autorelease
-        pool is sent a &ldquo;-release&rdquo; message, which causes it
-        to send &ldquo;-release&rdquo; messages to all of the objects
-        that've been added to it.</para>
-        <para>If the current thread doesn't have a current autorelease
-        pool, the attempt to autorelease any object will result in a
-        severe-looking warning being written via NSLog. The event
-        thread maintains an autorelease pool (it releases the current
-        pool after each event is processed and creates a new one for
-        the next event), so code that only runs in that thread should
-        never provoke any of these severe-looking NSLog
-        messages.</para> <para>To try to suppress these messages (and
-        still participate in the Cocoa memory management scheme), each
-        listener thread (the initial listener and any created via the
-        &ldquo;New Listener&rdquo; command in the IDE) is given a
-        default autorelease pool; there are REPL colon-commands for
-        manipulating the current listener's &ldquo;toplevel
-        auturelease pool&rdquo;.</para>
-        <para>In the current scheme, every time that Cocoa calls lisp
-        code, a lisp error handler is established which maps any lisp
-        conditions to ObjC exceptions and arranges that this exception
-        is raised when the callback to lisp returns. Whenever lisp
-        code invokes a Cocoa method, it does so with an ObjC exception
-        handler in place; this handler maps ObjC exceptions to lisp
-        conditions and signals those conditions.</para> <para>Any
-        unhandled lisp error or ObjC exception that occurs during the
-        execution of the distinguished event thread's event loop
-        causes a message to be NSLog'ed and the event loop to (try to)
-        continue execution. Any error that occurs in other threads is
-        handled at the point of the outermost Cocoa method
-        invocation. (Note that the error is not necessarily
-        &ldquo;handled&rdquo; in the dynamic context in which it
-        occurs.)</para>
-        <para>Both of these behaviors could possibly be improved; both of them
-seem to be substantial improvements over previous behaviors (where,
-for instance, a misspelled message name typically terminated the
-application.)</para>
-      </sect2>
-
-      <sect2 id="Acknowledgement--2-">
-	<title>Acknowledgement</title>
-        <para>The Cocoa bridge was originally developed, and
-        generously contributed by, Randal Beer.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Building-an-Application-Bundle">
-      <title>Building an Application Bundle</title>
-      <para>You may have noticed that (require "COCOA") takes a long
-      time to load.  It is possible to avoid this by saving a Lisp
-      heap image which has everything already loaded.  There is an
-      example file which allows you to do this,
-      "ccl/examples/cocoa-application.lisp", by producing a
-      double-clickable application which runs your program.  First,
-      load your own program.  Then, do:</para>
-      <programlisting>
-? (require "COCOA-APPLICATION")
-      </programlisting>
-      <para>When it finishes, you should be able to double-click the OpenMCL icon
-in the ccl directory, to quickly start your program.</para>
-      <para>The OS may have already decided that OpenMCL.app isn't a valid
-executable bundle, and therefore won't let you double-click it.
-If this happens to you, to force it to reconsider, just update the
-last-modified time of the bundle.  In Terminal:</para>
-      <programlisting>> touch OpenMCL.app
-</programlisting>
-      <para>There is one important caveat.</para>
-      <para>Because of the way that the ObjC bridge currently works, a saved
-image is dependent upon the <emphasis>exact</emphasis> versions of
-the Cocoa libraries which were present when it was saved.
-Specifically, the interface database is.  So, for example, an
-application produced under OS X 10.3.5 will not work under
-OS X 10.3.6.  This is inconvenient when you wish to distribute an
-application you have built this way.</para>
-      <para>Work in this direction is ongoing.  It is worth looking at the project
-"Bosco", by Mikel Evins, which is a template that can be used to build
-application bundles in a different way.  It is
-available here, as part
-of the "Clotho" project, and there is
-here.</para>
-      <para>When an image which had contained ObjC classes (which are also
-CLOS classes) is re-launched, those classes are "revived": all
-preexisting classes have their addresses updated destructively, so that
-existing subclass/superclass/metaclass relationships are maintained.
-It's not possible (and may never be) to preserve foreign
-instances across SAVE-APPLICATION. (It may be the case that NSArchiver
-and NSCoder and related classes offer some approximation of that.)</para>
-    </sect1>
-
-    <sect1 id="Recommended-Reading">
-      <title>Recommended Reading></title>
-      <variablelist>
-	<varlistentry>
-	   <term>
-	     <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink>
-	   </term>
-
-	   <listitem>
-	     <para>
-	       This is the top page for all of Apple's documentation on
-	       Cocoa.  If you are unfamiliar with Cocoa, it is a good
-	       place to start.
-	     </para>
-	   </listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term>
-	    <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink>
-	  </term>
-
-	  <listitem>
-	    <para>
-	      This is one of the two most important Cocoa references; it
-	      covers all of the basics, except for GUI programming.  This is
-	      a reference, not a tutorial.
-	    </para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>
-	    <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/index.html">Application Kit Reference for Objective-C</ulink>
-	  </term>
-
-	  <listitem>
-	    <para>
-	      This is the other; it covers GUI programming with Cocoa
-	      in considerable depth.  This is a reference, not a tutorial.
-	    </para>
-	  </listitem>
-	</varlistentry>
-
-	<varlistentry>
-	  <term>
-	    <ulink url="http://developer.apple.com/documentation/index.html">Apple Developer Documentation</ulink>
-	  </term>
-
-	  <listitem>
-	    <para>
-	      This is the site which the above two documents are found on;
-	      go here to find the documentation on any other Apple API.
-	      Also go here if you need general guidance about OS X, Carbon,
-	      Cocoa, Core Foundation, or Objective C.
-	    </para>
-	  </listitem>
-	</varlistentry>
-      </variablelist>
-
-    </sect1>
-
-    <sect1 id="Operating-System-Dictionary">
-      <title>Operating-System Dictionary</title>
-
-      <refentry id="f_getenv">
-	<indexterm zone="f_getenv">
-	  <primary>getenv</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::GETENV</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>getenv</function> name => value</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>a string which is the name of an existing
-		environment variable;
-		case-sensitive</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>value</term>
-
-	      <listitem>
-		<para>if there is an environment variable named
-		<varname>name</varname>, its value, as a string; if there
-		is not, NIL</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Looks up the value of the environment variable named by
-	    <varname>name</varname>, in the OS environment.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_setenv">
-	<indexterm zone="f_setenv">
-	  <primary>setenv</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::SETENV</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>setenv</function> name value => errno</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>name</term>
-
-	      <listitem>
-		<para>a string which is the name of a new or existing
-		environment variable;
-		case-sensitive</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>value</term>
-
-	      <listitem>
-		<para>a string, to be the new value of the
-		environment variable
-		named by <varname>name</varname></para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>errno</term>
-
-	      <listitem>
-		<para>zero if the function call completes successfully;
-		otherwise, a platform-dependent integer which describes
-		the problem</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Sets the value of the environment variable named by
-	    <varname>name</varname>, in the OS environment.  If there is
-	    no such environment
-	    variable, creates it.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_current-directory-name">
-	<indexterm zone="f_current-directory-name">
-	  <primary>current-directory-name</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::CURRENT-DIRECTORY-NAME</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>current-directory-name</function>
-	  => path</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>path</term>
-
-	      <listitem>
-		<para>a string, an absolute pathname in Posix format - with
-		directory components separated by slashes</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Looks up the current working directory of the OpenMCL process;
-	    unless it has been changed, this is the directory OpenMCL was
-	    started in.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_getuid">
-	<indexterm zone="f_getuid">
-	  <primary>getuid</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::GETUID</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>getuid</function> => uid</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>uid</term>
-
-	      <listitem>
-		<para>a non-negative integer, identifying a specific user
-		account as defined in the OS user database</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Returns the ("real") user ID of the current user.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_setuid">
-	<indexterm zone="f_setuid">
-	  <primary>setuid</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::SETUID</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>setuid</function> uid => errno</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>uid</term>
-
-	      <listitem>
-		<para>a non-negative integer, identifying a specific user
-		account as defined in the OS user database</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>errno</term>
-
-	      <listitem>
-		<para>zero if the function call completes successfully;
-		otherwise, a platform-dependent integer which describes
-		the problem</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Attempts to change the current user ID (both "real" and
-	    "effective"); fails unless
-	    the OpenMCL process has super-user privileges or the ID
-	    given is that of the current user.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_setgid">
-	<indexterm zone="f_setgid">
-	  <primary>setgid</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::SETGID</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>setgid</function> gid => errno</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>gid</term>
-
-	      <listitem>
-		<para>a non-negative integer, identifying a specific
-		group as defined in the OS user database</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>errno</term>
-
-	      <listitem>
-		<para>zero if the function call completes successfully;
-		otherwise, a platform-dependent integer which describes
-		the problem</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Attempts to change the current group ID (both "real" and
-	    "effective"); fails unless
-	    the OpenMCL process has super-user privileges or the ID
-	    given is that of a group to which the current user belongs.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_getpid">
-	<indexterm zone="f_getpid">
-	  <primary>getpid</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::GETPID</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>getpid</function> => pid</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>pid</term>
-
-	      <listitem>
-		<para>a non-negative integer, identifying an OS process</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Returns the ID of the OpenMCL OS process.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_get-user-home-dir">
-	<indexterm zone="f_get-user-home-dir">
-	  <primary>get-user-home-dir</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::GET-USER-HOME-DIR</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>get-user-home-dir</function> 
-	  uid => path</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>uid</term>
-
-	      <listitem>
-		<para>a non-negative integer, identifying a specific user
-		account as defined in the OS user database</para>
-	      </listitem>
-	    </varlistentry>
-	    <varlistentry>
-	      <term>path</term>
-
-	      <listitem>
-		<para>a string, an absolute pathname in Posix format - with
-		directory components separated by slashes; or NIL</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Looks up and returns the defined home directory of the user
-	    identified by <varname>uid</varname>.  This value comes from the
-	    OS user database, not from the <varname>$HOME</varname>
-	    environment variable.  Returns NIL if there is no user with
-	    the ID <varname>uid</varname>.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_os-command">
-	<indexterm zone="f_os-command">
-	  <primary>os-command</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CCL::OS-COMMAND</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>os-command</function> command-line
-	  => exit-code</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>command-line</term>
-
-	      <listitem><para>a string, obeying all the whitespace and
-	      escaping
-	      conventions required by the user's default system shell</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	  <variablelist>
-	    <varlistentry>
-	      <term>exit-code</term>
-
-	      <listitem><para>a non-negative integer, returned as the exit
-	      code of a subprocess; zero indicates success</para></listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>
-	    Invokes the Posix function <function>system()</function>, which
-	    invokes the user's default system shell (such as
-	    sh or tcsh) as a new process, and has that shell execute
-	    <varname>command-line</varname>.
-	  </para>
-	  
-	  <para>
-	    If the shell was able to find the command specified in
-	    <varname>command-line</varname>, then <varname>exit-code</varname>
-	    is the exit code of that command.  If not, it is the exit
-	    code of the shell itself.
-	  </para>
-	</refsect1>
-
-	<refsect1>
-	  <title>Notes</title>
-
-	  <para>
-	    By convention, an exit code of 0 indicates success.  There are
-	    also other conventions; unfortunately, they are OS-specific, and
-	    the portable macros to decode their meaning are implemented
-	    by the system headers as C preprocessor macros.  This means
-	    that there is no good, automated way to make them available
-	    to Lisp.
-	  </para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="m_class">
-	<indexterm zone="m_class">
-	  <primary>@class</primary>
-	</indexterm>
-	
-	<refnamediv>
-	  <refname>CCL::@CLASS</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>@class</function> class-name</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>class-name</term>
-
-	      <listitem>
-		<para>a string which denotes an existing class name, or a
-		symbol which can be mapped to such a string via the standard
-		name-mapping conventions for class names</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Used to refer to a known ObjC class by name. (Via the use
-	  LOAD-TIME-VALUE, the results of a class-name -&#62; class lookup
-	  are cached.)</para>
-
-	  <para>
-	    <function>@class</function> is obsolete as of late 2004, because
-	    find-class now works on ObjC classes.  It is described here
-	    only because some old code still uses it.
-	  </para>
-	</refsect1>
-	</refentry>
-
-	<refentry id="m_selector">
-	  <indexterm zone="m_selector">
-	    <primary>@selector</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>CCL::@SELECTOR</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Macro</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>@selector</function> string</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>string</term>
-
-		<listitem>
-		  <para>a string constant, used to canonically refer to an
-		  ObjC method selector</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Used to refer to an ObjC method selector (method name). Uses
-	    LOAD-TIME-VALUE to cache the result of a string -&#62; selector
-	    lookup.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="m_define-objc-method">
-	  <indexterm zone="m_define-objc-method">
-	    <primary>define-objc-method</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>CCL::DEFINE-OBJC-METHOD</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Macro</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>define-objc-method</function>
-	    (selector class-name) &body; body</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <variablelist>
-	      <varlistentry>
-		<term>selector</term>
-
-		<listitem>
-		  <para>either a string which represents the name of the
-		  selector or a list which describ+es the method's return
-		  type, selector components, and argument types (see below.)
-		  If the first form is used, then the first form in the body
-		  must be a list which describes the selector's argument
-		  types and return value type, as per DEFCALLBACK.</para>
-		</listitem>
-	      </varlistentry>
-
-	      <varlistentry>
-		<term>class-name</term>
-
-		<listitem>
-		  <para>either a string which names an existing ObjC class
-		  name or a list symbol which can map to such a string via the
-		  standard name-mapping conventions for class names. (Note
-		  that the "canonical" lisp class name is such a
-		  symbol)</para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Defines an ObjC-callable method which implements the
-	    specified message selector for instances of the existing ObjC
-	    class class-name.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="m_define-objc-class-method">
-	  <indexterm zone="m_define-objc-class-method">
-	    <primary>define-objc-class-method</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>CCL::DEFINE-OBJC-CLASS-METHOD</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Macro</refclass>
-	  </refnamediv>
-
-	  <refsynopsisdiv>
-	    <synopsis><function>define-objc-class-method</function>
-	    (selector class-name) &body; body</synopsis>
-	  </refsynopsisdiv>
-
-	  <refsect1>
-	    <title>Arguments and Values</title>
-
-	    <para>As per DEFINE-OBJC-METHOD</para>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Like DEFINE-OBJC-METHOD, only used to define methods on the
-	    <emphasis>class</emphasis> named by class-name and on its
-	    subclasses.</para>
-
-	    <para>For both DEFINE-OBJC-METHOD and DEFINE-OBJC-CLASS-METHOD, the
-	    "selector" argument can be a list whose first element is a
-	    foreign type specifier for the method's return value type and whose
-	    subsequent elements are either:</para>
-
-	    <itemizedlist>
-	      <listitem>
-		<para>a non-keyword symbol, which can be mapped to a selector string
-		for a parameterless method according to the standard name-mapping
-		conventions for method selectors.</para>
-	      </listitem>
-	      
-	      <listitem>
-		<para>a list of alternating keywords and variable/type specifiers,
-		where the set of keywords can be mapped to a selector string for a
-		parameteriezed method according to the standard name-mapping
-		conventions for method selectors and each variable/type-specifier is
-		either a variable name (denoting a value of type :ID) or a list whose
-		CAR is a variable name and whose CADR is the corresponding
-		argument's foreign type specifier.</para>
-	      </listitem>
-	    </itemizedlist>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="v_alternate-line-terminator">
-	  <indexterm zone="v_alternate-line-terminator">
-	    <primary>*alternate-line-terminator*</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>CCL:*ALTERNATE-LINE-TERMINATOR*</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Variable</refclass>
-	  </refnamediv>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>This variable is currently only used by the standard reader macro
-	    function for #\; (single-line comments); that function reads successive
-	    characters until EOF, a #\NewLine is read, or a character EQL to the
-	    value of *alternate-line-terminator* is read. In OpenMCL for Darwin, the
-	    value of this variable is initially #\Return ; in OpenMCL for LinuxPPC,
-	    it&#39;s initially NIL.</para>
-	    
-	    <para>Their default treatment by the #\; reader macro is the primary way
-	    in which #\Return and #\Linefeed differ syntactally; by extending the
-	    #\; reader macro to (conditionally) treat #\Return as a
-	    comment-terminator, that distinction is eliminated. This seems to make
-	    LOAD and COMPILE-FILE insensitive to line-termination issues in many
-	    cases. It could fail in the (hopefully rare) case where a LF-terminated
-	    (Unix) text file contains embedded #\Return characters, and this
-	    mechanism isn&#39;t adequate to handle cases where newlines are embedded
-	    in string constants or other tokens (and presumably should be translated
-	    from an external convention to the external one) : it doesn&#39;t change
-	    what READ-CHAR or READ-LINE &#34;see&#34;, and that may be necessary to
-	    handle some more complicated cases.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="k_external-format">
-	  <indexterm zone="k_external-format">
-	    <primary>:external-format</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>:EXTERNAL-FORMAT</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Keyword Argument</refclass>
-	  </refnamediv>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>Per ANSI CL, OpenMCL supports the :EXTERNAL-FORMAT keyword
-	    argument to the functions OPEN, LOAD, and COMPILE-FILE. This argument is
-	    intended to provide a standard way of providing implementation-dependent
-	    information about the format of files opened with an element-type of
-	    CHARACTER. This argument can meaningfully take on the values :DEFAULT
-	    (the default), :MACOS, :UNIX, or :INFERRED in OpenMCL.</para>
-	    
-	    <para>When defaulted to or specified as :DEFAULT, the format of the file
-	    stream is determined by the value of the variable
-	    CCL:*DEFAULT-EXTERNAL-FORMAT*. See below.</para>
-	    
-	    <para>When specified as :UNIX, all characters are read from and written
-	    to files verbatim.</para>
-	    
-	    <para>When specified as :MACOS, all #\Return characters read from the
-	    file are immediately translated to #\Linefeed (#\Newline); all #\Newline
-	    (#\Linefeed) characters are written externally as #\Return characters.</para>
-	    
-	    <para>When specified as :INFERRED and the file is open for input, the
-	    first bufferful of input data is examined; if a #\Return character
-	    appears in the buffer before the first #\Linefeed, the file stream&#39;s
-	    external-format is set to :MACOS; otherwise, it is set to :UNIX.</para>
-	    
-	    <para>All other values of :EXTERNAL-FORMAT - and any combinations that
-	    don&#39;t make sense, such as trying to infer the format of a
-	    newly-created output file stream - are treated as if :UNIX was
-	    specified. As mentioned above, the :EXTERNAL-FORMAT argument doesn&#39;t
-	    apply to binary file streams.</para>
-	    
-	    <para>The translation performed when :MACOS is specified or inferred has
-	    a somewhat greater chance of doing the right thing than the
-	    *alternate-line-terminator* mechanism does; it probably has a somewhat
-	    greater chance of doing the wrong thing, as well.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="v_default-external-format">
-	  <indexterm zone="v_default-external-format">
-	    <primary>*default-external-format*</primary>
-	  </indexterm>
-	  
-	  <refnamediv>
-	    <refname>CCL:*DEFAULT-EXTERNAL-FORMAT*</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Variable</refclass>
-	  </refnamediv>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>The value of this variable is used when :EXTERNAL-FORMAT is
-	    unspecified or specified as :DEFAULT. It can meaningfully be given any
-	    of the values :UNIX, :MACOS, or :INFERRED, each of which is interpreted
-	    as described above.</para>
-	    
-	    <para>Because there&#39;s some risk that unsolicited newline translation
-	    could have undesirable consequences, the initial value of this variable
-	    in OpenMCL is :UNIX.</para>
-	  </refsect1>
-	</refentry>
-
-	<refentry id="c_ns-lisp-string">
-	  <indexterm zone="c_ns-lisp-string">
-	    <primary>ns-lisp-string</primary>
-	  </indexterm>
-
-	  <refnamediv>
-	    <refname>CCL::NS-LISP-STRING</refname>
-	    <refpurpose></refpurpose>
-	    <refclass>Class</refclass>
-	  </refnamediv>
-
-	  <refsect1>
-	    <title>Superclasses</title>
-
-	    <para>NS:NS-STRING</para>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Initargs</title>
-	    
-	    <variablelist>
-	      <varlistentry>
-		<term>:string</term>
-		
-		<listitem>
-		  <para>
-		    a Lisp string which is to be the content of
-		    the newly-created ns-lisp-string.
-		  </para>
-		</listitem>
-	      </varlistentry>
-	    </variablelist>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Description</title>
-
-	    <para>
-	      This class
-	      implements the interface of an NSString, which means that it can
-	      be passed to any Cocoa or Core Foundation function which expects
-	      one.
-	    </para>
-
-	    <para>
-	      The string itself is stored on the Lisp heap, which
-	      means that its memory management is automatic.  However, the
-	      ns-lisp-string object itself is a foreign
-	      object (that is, it has an objc metaclass), and resides on the
-	      foreign heap.  Therefore, it is necessary to explicitly free
-	      it, by sending a dealloc message.
-	    </para>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Examples</title>
-
-	    <para>
-	      You can create an ns-lisp-string with
-	      <function>make-instance</function>, just like
-	      any normal Lisp class:
-	    </para>
-
-	    <programlisting format="linespecific"
->? (defvar *the-string*
-          (make-instance 'ccl::ns-lisp-string
-                         :string "Hello, Cocoa."))</programlisting>
-	    
-	    <para>
-	      When you are done with the string, you must explicitly
-	      deallocate it:
-	    </para>
-
-	    <programlisting format="linespecific">? (ccl::send *the-string* 'dealloc)</programlisting>
-
-	    <para>
-	      You may wish to use an <function>unwind-protect</function>
-	      form to ensure that this happens:
-	    </para>
-
-	    <programlisting format="linespecific"
->(let (*the-string*)
-  (unwind-protect (progn (setq *the-string*
-                               (make-instance 'ccl::ns-lisp-string
-                                              :string "Hello, Cocoa."))
-                         (format t "~&amp;The string is ~D characters long.~%"
-                                 (ccl::send *the-string* 'length)))
-    (when *the-string*
-      (ccl::send *the-string* 'dealloc))))</programlisting>
-	  </refsect1>
-
-	  <refsect1>
-	    <title>Notes</title>
-
-	    <para>
-	      Currently, ns-lisp-string is defined in
-	      the file ccl/examples/cocoa-backtrace.lisp, which is a
-	      rather awkward place.  It was probably not originally meant
-	      as a public utility at all.  It would be good if it were
-	      moved someplace else.  Use at your own risk.
-	    </para>
-	  </refsect1>
-	</refentry>
-    </sect1>
-  </chapter>
-
-  <chapter id="Understanding-and-Configuring-the-Garbage-Collector">
-    <title>Understanding and Configuring the Garbage Collector</title>
-
-    <sect1 id="Heap-space-allocation">
-      <title>Heap space allocation</title>
-      <para>Release 0.10 or later of OpenMCL uses a different memory
-      management scheme than previous versions did. Those earlier
-      versions would allocate a block of memory (of specified size) at
-      startup and would allocate lisp objects within that block. When
-      that block filled with live (non-GCed) objects, the lisp would
-      signal a "heap full" condition. The heap size imposed a limit on
-      the size of the largest object that could be allocated.</para>
-      <para>The new strategy involves reserving a very large (2GB on
-      DarwinPPC32, 1GB on LinuxPPC, "very large" on 64-bit
-      implementations) block at startup and consuming (and
-      relinquishing) its contents as the size of the live lisp heap
-      data grows and shrinks. After the initial heap image loads and
-      after each full GC, the lisp kernel will try to ensure that a
-      specified amount (the "lisp-heap-gc-threshold") of free memory
-      is available. The inital value of this kernel variable is 16MB
-      on 32-bit implementations and 32MB on 64-bit implementations ;
-      it can be manipulated from Lisp (see below.)</para>
-      <para>The large reserved memory block consumes very little in
-      the way of system resources; memory that's actually committed to
-      the lisp heap (live data and the "threshold" area where
-      allocation takes place) consumes finite resources (physical
-      memory and swap space). The lisp's consumption of those
-      resources is proportional to its actual memory usage, which is
-      generally a good thing.</para>
-      <para>This scheme is much more flexible than the old one, but it
-      may also increase the possibility that those resources can
-      become exhausted.  Neither the new scheme nor the old handles
-      that situation gracefully; under the old scheme, a program that
-      consumes lots of memory may have run into an artificial limit on
-      heap size before exhausting virtual memory.</para> 
-
-      <para>The -R or &ndash;heap-reserve command-line option can be
-      use to limit the size of the reserved block and therefore bound
-      heap expansion. Running</para>
-      <programlisting>
-> openmcl --heap-reserve 8M
-</programlisting>
-      <para>would provide an execution environment that's very similar to
-that provided by earlier OpenMCL versions.</para>
-    </sect1>
-
-    <sect1 id="The-Ephemeral-GC">
-      <title>The Ephemeral GC</title>
-      <para>For many programs, the following observations are true to
-      a very large degree:</para>
-
-      <orderedlist continuation="restarts" inheritnum="ignore">
-	<listitem>
-	  <para>Most heap-allocated objects have very short lifetimes ("are
-	  ephemeral"): they become inaccessible soon after they&#39;re created.</para>
-	</listitem>
-
-	<listitem>
-	  <para>Most non-ephemeral objects have very long lifetimes: it&#39;s
-	  rarely productive for the GC to consider reclaiming them, since
-	  it&#39;s rarely able to do so. (An object that&#39;s survived a large
-	  number of GCs is likely to survive the next one. That&#39;s not always
-	  true of course, but it&#39;s a reasonable heuristic.)</para>
-	</listitem>
-
-	<listitem>
-	  <para>It&#39;s relatively rare for an old object to be destructively
-	  modified (via SETF) so that it points to a new one, therefore most
-	  references to newly-created objects can be found in the stacks and
-	  registers of active threads. It&#39;s not generally necessary to scan
-	  the entire heap to find references to new objects (or to prove that
-	  such references don&#39;t exists), though it is necessary to keep
-	  track of the (hopefully exceptional) cases where old objects are
-	  modified to point at new ones.</para>
-	</listitem>
-      </orderedlist>
-      <orderedlist continuation="restarts" inheritnum="ignore">
-	<listitem>
-	  <para>Most heap-allocated objects have very short lifetimes ("are
-	  ephemeral"): they become inaccessible soon after they&#39;re created.</para>
-	</listitem>
-
-	<listitem>
-	  <para>Most non-ephemeral objects have very long lifetimes: it&#39;s
-	  rarely productive for the GC to consider reclaiming them, since
-	  it&#39;s rarely able to do so. (An object that&#39;s survived a large
-	  number of GCs is likely to survive the next one. That&#39;s not always
-	  true of course, but it&#39;s a reasonable heuristic.)</para>
-	</listitem>
-
-	<listitem>
-	  <para>It&#39;s relatively rare for an old object to be destructively
-	  modified (via SETF) so that it points to a new one, therefore most
-	  references to newly-created objects can be found in the stacks and
-	  registers of active threads. It&#39;s not generally necessary to scan
-	  the entire heap to find references to new objects (or to prove that
-	  such references don&#39;t exists), though it is necessary to keep
-	  track of the (hopefully exceptional) cases where old objects are
-	  modified to point at new ones.</para>
-	</listitem>
-      </orderedlist>
-
-      <para>"Ephemeral" (or "generational") garbage collectors try to
-      exploit these observations: by concentrating on frequently
-      reclaiming newly-created objects quickly, it's less often
-      necessary to do more expensive GCs of the entire heap in order
-      to reclaim unreferenced memory.  In some environments, the
-      pauses associated with such full GCs can be noticable and
-      disruptive, and minimizing the frequency (and sometimes the
-      duration) of these pauses is probably the EGC's primary goal
-      (though there may be other benefits, such as increased locality
-      of reference and better paging behavior.) The EGC generally
-      leads to slightly longer execution times (and slightly higher,
-      amortized GC time), but there are cases where it can improve
-      overall performance as well; the nature and degree of its impact
-      on performance is highly application-dependant.</para>
-      <para>Most EGC strategies (including the one employed by
-      OpenMCL) logically or physically divide memory into one or more
-      areas of relatively young objects ("generations") and one or
-      more areas of old objects.  Objects that have survived one or
-      more GCs as members of a young generation are promoted (or
-      "tenured") into an older generation, where they may or may not
-      survive long enough to be promoted to the next generation and
-      eventually may become "old" objects that can only be reclaimed
-      if a full GC proves that there are no live references to them.
-      This filtering process isn't perfect - a certain amount of
-      premature tenuring may take place - but it usually works very
-      well in practive.</para>
-      <para>It's important to note that a GC of the youngest
-      generation is typically very fast (perhaps a few milliseconds on
-      a modern CPU, depending on various factors), OpenMCL's EGC is
-      not concurrent and doesn't offer realtime guarantees.</para>
-      <para>OpenMCL's EGC maintains three ephemeral generations; all
-      newly created objects are created as members of the youngest
-      generation. Each generation has an associated
-      <emphasis>threshold</emphasis>, which indicates the number of
-      bytes in it and all younger generations that can be allocated
-      before a GC is triggered. These GCs will involve the target
-      generation and all younger ones (and may therefore cause some
-      premature tenuring); since the older generations have larger
-      thresholds, they're GCed less frequently and most short-lived
-      objects that make it into an older generation tend not to
-      survive there very long.</para>
-      <para>The EGC can be <emphasis>enabled</emphasis> or
-      <emphasis>disabled</emphasis> under program control; under some
-      circumstances, it may be enabled but
-      <emphasis>inactive</emphasis> (because a full GC is imminent.)
-      Since it may be hard to know or predict the consing behavior of
-      other threads, the distinction between the "active" and
-      "inactive" state isn't very meaningful, especially when native
-      threads are involved.</para>
-    </sect1>
-
-    <sect1 id="GC-Page-reclamation-policy">
-      <title>GC Page reclamation policy</title>
-      <para>After a full GC finishes, it'll try to ensure that at
-      least (LISP-HEAP-GC-THRESHOLD) of virtual memory are available;
-      objects will be allocated in this block of memory until it fills
-      up, the GC is triggered, and the process repeats itself.</para>
-      <para>Many programs reach near stasis in terms of the amount of
-      logical memory that's in use after full GC (or run for long
-      periods of time in a nearly static state), so the logical
-      address range used for consing after the Nth full GC is likely
-      to be nearly or entirely identical to the address range used by
-      the N+1th full GC.</para>
-      <para>By default (and traditionally in OpenMCL), the GC's policy
-      is to "release" the pages in this address range: to advise the
-      virtual memory system that the pages contain garbage and any
-      physical pages associated with them don't need to be swapped out
-      to disk before being reused and to (re-)map the logical address
-      range so that the pages will be zero-filled by the virtual
-      memory system when they're next accessed.  This policy is
-      intended to reduce the load on the VM system and keep OpenMCL's
-      working set to a minimum.</para>
-      <para>For some programs (especially those that cons at a very
-      high rate), the default policy may be less than ideal: releasing
-      pages that're going to be needed almost immediately - and
-      zero-fill-faulting them back in, lazily - incurs unnecessary
-      overhead. (There's a false economy associated with minimizing
-      the size of the working set if it's just going to shoot back up
-      again until the next GC.) A policy of "retaining" pages between
-      GCs might work better in such an environment.</para>
-      <para>Functions described below give the user some control over
-      this behavior. An adaptive, feedback-mediated approach might
-      yield a better solution.</para>
-    </sect1>
-
-    <sect1 id="iPure--areas-are-read-only--paged-from-image-file">
-      <title>"Pure" areas are read-only, paged from image file</title>
-      <para>SAVE-APPLICATION identifies code vectors and the pnames of
-      interned symbols and copies these objects to a "pure" area of
-      the image file it creates. (The "pure" area accounts for most of
-      what the ROOM function reports as "static" space.)</para>
-      <para>When the resulting image file is loaded, the pure area of
-      the file is now memory-mapped with read-only access. Code and
-      pure data are paged in from the image file as needed (and don't
-      compete for global virtual memory resources with other memory
-      areas.)</para>
-      <para>Code-vectors and interned symbol pnames are immutable : it
-      is an error to try to change the contents of such an
-      object. Previously, that error would have manifested itself in
-      some random way. In the new scheme, it'll manifest itself as an
-      "unhandled exception" error in the Lisp kernel. The kernel could
-      probably be made to detect a spurious, accidental write to
-      read-only space and signal a lisp error in that case, but it
-      doesn't yet do so.</para>
-      <para>The image file should be opened and/or mapped in some mode
-      which disallows writing to the memory-mapped regions of the file
-      from other processes. I'm not sure of how to do that; writing to
-      the file when it's mapped by OpenMCL can have unpredictable and
-      unpleasant results.  SAVE-APPLICATION will delete its output
-      file's directory entry and create a new file; one may need to
-      exercise care when using file system utilities (like tar, for
-      instance) that might overwrite an existing image file.</para>
-    </sect1>
-
-    <sect1 id="Weak-Hash-Tables">
-      <title>Weak Hash Tables</title>
-      <para>In general, a "weak reference" is a reference to an object
-      which will not prevent the object from being garbage-collected.
-      For example, suppose that you want to keep a list of all the
-      objects of a certain type.  If you don't take special steps, the
-      fact that you have a list of them will mean that the objects are
-      always "live", because you can always reference them through the
-      list.  Therefore, they will never be garbage-collected, and
-      their memory will never be reclaimed, even if they are
-      referenced nowhere else in the program.  You may want this
-      behaviour.  If you don't, you need weak references.</para>
-      <para>OpenMCL supports weak references with "weak hash tables".
-      Hash tables may be weak with respect to either their keys or
-      their values.  To make a hash table with weak keys, invoke
-      <literal>make-hash-table</literal> with the option :weak t, or,
-      equivalently, :weak :key.  To make one with weak values, use
-      :weak :value.  When the key is weak, the equality test must be
-      #'eq (because it wouldn't make sense otherwise).</para>
-      <para>When garbage-collection occurs, key-value pairs are
-      removed from the hash table if there are no other references to
-      the weak element of the pair (key or value).</para>
-      <para>In general, weak-key hash tables are useful when you want
-      to use the hash to store some extra information about the
-      objects you look up in it, while weak-value hash tables are
-      useful when you want to use the hash as an index for looking up
-      objects.</para>
-      <para>If you are experimenting with weak hash tables
-      interactively, remember that an object is not dead if it was
-      returned by one of the last three interactively-evaluated
-      expressions, because of the variables <literal>*</literal>,
-      <literal>**</literal>, and <literal>***</literal>.  The easy
-      workaround is to evaluate some meaningless expression before
-      invoking <literal>gc</literal>, to get the object out of the
-      repl variables.</para>
-    </sect1>
-
-    <sect1 id="Garbage-Collection-Dictionary">
-      <title>Garbage-Collection Dictionary</title>
-
-      <refentry id="f_lisp-heap-gc-threshold">
-	<indexterm zone="f_lisp-heap-gc-threshold">
-	  <primary>lisp-heap-gc-threshold</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>LISP-HEAP-GC-THRESHOLD</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>lisp-heap-gc-threshold</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns the value of the kernel variable that specifies the
-	  amount of free space to leave in the heap after full GC.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_set-lisp-heap-gc-threshold">
-	<indexterm zone="f_set-lisp-heap-gc-threshold">
-	  <primary>set-lisp-heap-gc-threshold</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>SET-LISP-HEAP-GC-THRESHOLD</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>lisp-heap-gc-threshold new-threshold</function>
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>new-value</term>
-
-	      <listitem>
-		<para>The requested new lisp-heap-gc-threshold.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Sets the value of the kernel variable that specifies the
-	  amount of free space to leave in the heap after full GC to
-	  new-value, which should be a non-negative fixnum. Returns the
-	  value of that kernel variable (which may be somewhat larger than
-	  what was specified).</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_use-lisp-heap-gc-threshold">
-	<indexterm zone="f_use-lisp-heap-gc-threshold">
-	  <primary>use-lisp-heap-gc-threshold</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>USE-LISP-HEAP-GC-THRESHOLD</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis>
-	    <function>use-lisp-heap-gc-threshold</function>
-	  </synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to grow or shrink lisp&#39;s heap space, so that the
-	  free space is (approximately) equal to the current heap threshold.
-	  Returns NIL</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_egc">
-	<indexterm zone="f_egc">
-	  <primary>egc</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>EGC</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>egc</function> arg</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>arg</term>
-
-	      <listitem>
-		<para>a generalized boolean</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Enables the EGC if arg is non-nil, disables the EGC
-	  otherwise. Returns the previous enabled status. Although this
-	  function is thread-safe (in the sense that calls to it are
-	  serialized), it doesn&#39;t make a whole lot of sense to be
-	  turning the EGC on and off from multiple threads ...</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_egc-enabled-p">
-	<indexterm zone="f_egc-enabled-p">
-	  <primary>egc-enabled-p</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>EGC-ENABLED-P</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>egc-enabled-p</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns T if the EGC was enabled at the time of the call,
-	  NIL otherwise.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_egc-active-p">
-	<indexterm zone="f_egc-active-p">
-	  <primary>egc-active-p</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>EGC-ACTIVE-P</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>egc-active-p</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns T if the EGC was active at the time of the call, NIL
-	  otherwise. Since this is generally a volatile piece of
-	  information, it&#39;s not clear whether this function serves a
-	  useful purpose when native threads are involved.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_egc-configuration">
-	<indexterm zone="f_egc-configuration">
-	  <primary>egc-configuration</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>EGC-CONFIGURATION</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>egc-configuration</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns, as multiple values, the sizes in kilobytes of the
-	  thresholds associated with the youngest ephemeral generation, the
-	  middle ephemeral generation, and the oldest ephemeral generation</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_configure-gcc">
-	<indexterm zone="f_configure-gcc">
-	  <primary>configure-gcc</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>CONFIGURE-GCC</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>configure-egc</function>
-	  generation-0-size generation-1-size
-	  generation-2-size</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>generation-0-size</term>
-
-	      <listitem>
-		<para>the requested threshold size of the youngest
-		generation, in kilobytes</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>generation-1-size</term>
-
-	      <listitem>
-		<para>the requested threshold size of the middle generation,
-		in kilobytes</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>generation-2-size</term>
-
-	      <listitem>
-		<para>the requested threshold size of the oldest generation,
-		in kilobytes</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>If the EGC is currently disabled, puts the indicated
-	  threshold sizes in effect and returns T, otherwise, returns NIL.
-	  (The provided threshold sizes are rounded up to a multiple of
-	  64Kbytes in OpenMCL 0.14 and to a multiple of 32KBytes in earlier
-	  versions.)</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_gc-retain-pages">
-	<indexterm zone="f_gc-retain-pages">
-	  <primary>gc-retain-pages</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>GC-RETAIN-PAGES</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>gc-retain-pages</function> arg</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>arg</term>
-
-	      <listitem>
-		<para>a generalized boolean</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Tries to influence the GC to retain/recycle the pages
-	  allocated between GCs if arg is true, and to release them
-	  otherwise. This is generally a tradeoff between paging and other
-	  VM considerations.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_gc-retaining-pages">
-	<indexterm zone="f_gc-retaining-pages">
-	  <primary>gc-retaining-pages</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>GC-RETAINING-PAGES</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>gc-retaining-pages</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns T if the GC tries to retain pages between full GCs
-	  and NIL if it&#39;s trying to release them to improve VM paging
-	  performance.</para>
-	</refsect1>
-      </refentry>
-    </sect1>
-  </chapter>
-
-  <chapter id="Implementation-Details-of-OpenMCL">
-    <title>Implementation Details of OpenMCL</title>
-    <para>This chapter describes many aspects of OpenMCL's
-    implementation as of (roughly) version 1.1.  Details vary a bit
-    between the three archutectures (PPC32, PPC64, and X86-64)
-    currently supported and those details change over time, so the
-    definitive reference is the source code (especially some files in
-    the ccl/compiler/ directory whose names contain the string "arch"
-    and some files in the ccl/lisp-kernel/ directory whose namee
-    contain the string "constants".)  Hopefully, this chapter will
-    make it easier for someone who's interested to read and understand
-    the contents of those files.</para>
-
-    <sect1 id="Threads-and-exceptions">
-      <title>Threads and exceptions</title>
-      <para>OpenMCL's threads are "native" (meaning that they're
-      scheduled and controlled by the operating system.)  Most of the
-      implications of this are discussed elsewhere; this section tries
-      to describe how threads look from the lisp kernel's perspective
-      (and especailly from the GC's point of view.)</para>
-      <para>OpenMCL's runtime system tries to use machine-level
-      exception mechanisms (conditional traps when available, illegal
-      instructions, memory access protection in some cases) to detect
-      and handle ...  exceptional situations.  These situations
-      include some TYPE-ERRORs and PROGRAM-ERRORS (notably
-      wrong-number-of-args errors), and also include cases like "not
-      being able to allocate memory without GCing or obtaining more
-      memory from the OS."  The general idea is that it's usually
-      faster to pay (very occasional) exception-processing overhead
-      and figure out what's going on in an exception handler than it
-      is to maintain enough state and context to handle an exceptional
-      case via a lighter-weight mechanism when that exceptional case
-      (by definition) rarely occurs.</para>
-      <para>Some emulated execution environments (the Rosetta PPC
-      emulator on x86 versions of OSX) don't provide accurate
-      exception information to exception handling functions. OpenMCL
-      can't run in such environments.</para>
-
-      <sect2 id="The-Thread-Context-Record">
-	<title>The Thread Context Record</title>
-
-	<para>When a lisp thread is first created (or when a thread
-        created by foreign code first calls back to lisp), a data
-        structure called a Thread Context Record (or TCR) is allocated
-        and initialized.  On modern versions of Linux and FreeBSD, the
-        allocation actually happens via a set of thread-local-storage
-        ABI extensions, so a thread's TCR is created when the thread
-        is created and dies when the thread dies.  (The World's Most
-        Advanced Operating System - as Apple's marketing literature
-        refers to Darwin - is not very advanced in this regard, and I
-        know of no reason to assume that advances will be made in this
-        area anytime soon.)</para>
-        <para>A TCR contains a few dozen fields (and is therefore a
-        few hundred bytes in size.)  The fields are mostly
-        thread-specific information about the thread's stacks'
-        locations and sizes, information about the underlying (POSIX)
-        thread, and information about the thread's dynamic binding
-        history and pending CATCH/UNWIND-PROTECTs.  Some of this
-        information could be kept in individual machine registers
-        while the thread is running (and the PPC - which has more
-        registers available - keeps a few things in registers that the
-        X86-64 has to access via the TCR), but it's important to
-        remember that the information is thread-specific and can't
-        (for instance) be kept in a fixed global memory
-        location.</para>
-        <para>When lisp code is running, the current thread's TCR is
-        kept in a register.  On PPC platforms, a general purpose
-        register is used; on x86-64, an (otherwise nearly useless)
-        segment register works well (prevents the expenditure of a
-        more generally useful general- purpose register for this
-        purpose.)</para>
-        <para>The address of a TCR is aligned in memory in such a way
-        that a FIXNUM can be used to represent it.  The lisp function
-        CCL::%CURRENT-TCR returns the calling thread's TCR as a
-        fixnum; actual value of the TCR's address is 4 or 8 times the
-        value of this fixnum.</para>
-        <para>When the lisp kernel initializes a new TCR, it's added
-        to a global list maintained by the kernel; when a thread
-        exits, its TCR is removed from this list.</para>
-        <para>When a thread calls foreign code, lisp stack pointers
-        are saved in its TCR, lisp registers (at least those whose
-        value should be preserved across the call) are saved on the
-        thread's value stack, and (on x86-64) RSP is switched to the
-        control stack.  A field in the TCR (tcr.valence) is then set
-        to indicate that the thread is running foreigm code, foreign
-        argument registers are loaded from a frame on the foreign
-        stack, and the foreign function is called. (That's a little
-        oversimplified and possibly inaccurate, but the important
-        things to note are that the thread "stops following lisp stack
-        and register usage conventions" and that it advertises the
-        fact that it's done so.  Similar transitions in a thread's
-        state ("valence") occur when it enters of exits an exception
-        handler (which is sort of an OS/hardware-mandated foreign
-        function call where the OS thoughtfully saves the thread's
-        register state for it beforehand.)</para>
-      </sect2>
-
-      <sect2 id="Exception-contexts-comma---and-exception-handling-in-general">
-	<title>Exception contexts, and exception-handling in general</title>
-        <para>Unix-like OSes tend to refer to exceptions as "signals";
-        the same general mechanism ("signal handling") is used to
-        process both asynchronous OS-level events (such as the result
-        of the keyboard driver noticing that ^C or ^Z has been
-        pressed) and synchronous hardware-level events (like trying to
-        execute and illegal instruction or access protected memory.)
-        It makes some sense to defer ("block") handling of
-        aysnchronous signals so that some critical code sequences
-        complete without interruption; since it's generally not
-        possible for a thread to proceed after a synchronous exception
-        unless and until its state is modified by an exception
-        handler, it makes no sense to talk about blocking synchronous
-        signals (though some OSes will let you do so and doing so can
-        have mysterious effects.)</para>
-        <para>On OSX/Darwin, the POSIX signal handling facilities
-        coexist with lower-level Mach-based exception handling
-        facilities.  Unfortunately, the way that this is implemented
-        interacts poorly with debugging tools: GDB will generally stop
-        whenever the target program encounters a Mach-level exception
-        and offers no way to proceed from that point (and let the
-        program's POSIX signal handler try to handle the exception);
-        Apple's CrashReporter program has had a similar issue and,
-        depending on how it's configured, may bombard the user with
-        alert dialogs which falsely claim that an application has
-        crashed (when in fact the application in question has
-        routinely handled a routine exception.)  On Darwin/OSX,
-        OpenMCL uses Mach thread-level exception handling facilities
-        which run before GDB or CrashReporter get a chance to confuse
-        themeselves; OpenMCL's Mach exception handling tries to force
-        the thread which received a synchronous exception to invoke a
-        signal handling function ("as if" signal handling worked more
-        usefully under Darwin.)  Mach exception handlers run in a
-        dedicated thread (which basically does nothing but wait for
-        exception messages from the lisp kernel, obtain and modify
-        information about the state of threads in which exceptions
-        have occurred, and reply to the exception messages with an
-        indication that the exception has been handled.  The reply
-        from a thread-level exception handler keeps the exception from
-        being reported to GDB or CrashReporter and avoids the problems
-        related to those programs.  Since OpenMCL's Mach exception
-        handler doesn't claim to handle debugging-related exceptions
-        (from breakpoints or single-step operations), it's possible to
-        use GDB to debug OpenMCL.</para>
-        <para>On platforms where signal handling and debugging don't get in each
-other's way, a signal handler is entered with all signals blocked.
-(This behavior is specified in the call to the sigaction() function
-which established the signal handler.)  The signal handler recieves
-three arguments from the OS kernel; the first is an intger which
-identifies the signal, the second is a pointer to an object of
-type "siginfo_t", which may or may not contain a few fields that
-would help to identify the cause of the exception, and the third
-argument is a pointer to a data structure (called a "ucontext"
-or something similar) which contains machine-dependent information
-about the state of the tread at the time that the exception/signal
-occurred.  While asynchronous signals are blocked, the signal handler
-stores the pointer to its third argument (the "signal context") in
-a field in the current thread's TCR, sets some bits in another TCR
-field to indicate that the thread is now waiting to handle an
-exception, unblocks asynchronous signals, and waits for a global
-exception lock which serializes exception processing.</para>
-        <para>On Darwin, the Mach exception thread creates a signal
-        context (and maybe a siginfo_t structure), stores the signal
-        context in the thread's TCR, sets the TCR field wich describes
-        the thread's state, and arranges that the thread resume
-        execution at its signal handling function (with a signal
-        handler, possibly NULL siginfo_t, and signal context as
-        arguments.  When the thread resumes, it waits for the global
-        exception lock.</para>
-        <para>On x86-64 platforms where signal handing can be used to
-        handle synchronous exceptions, there's an additional
-        complication: the OS kernel ordinarily allocates the signal
-        context and siginfo structures on the stack of the thread
-        which received the signal; in practice, that means "wherever
-        RSP is pointing."  OpenMCL's require that the thread's value
-        stack - where RSP is usually pointing while lisp code is
-        running - contain only "nodes" (properly tagged lisp objects),
-        and scribbling a signal context all over the value stack would
-        violate this requirement.  To maintain consistency, the
-        sigaltstack() mechanism is used to cause the signal to be
-        delivered on (and the signal context and siginfo to be
-        allocated on) a special stack area (the last few pages of the
-        thread's cntrol stack, in practice.  When the signal handler
-        runs, it (carefully) copies the signal context and siginfo to
-        the thread's control stack and makes RSP point into that stack
-        before invoking the "real" signal handler.  (The effect of
-        this hack is that the "real" signal handler always runs on the
-        thread's control stack.)</para>
-        <para>Once the exception handler has obtained the global
-        exception lock, it uses the values of the signal number,
-        siginfo_t, and signal context arguments to determine the
-        (logical) cause of the exception.  Some exceptions may be
-        caused by factors that should generate lisp errors or other
-        serious conditions (stack overflow); if this is the case, the
-        kernel code may release the global exception lock and call out
-        to lisp code.  (The lisp code in question may need to repeat
-        some of the exception decoding process; in particular, it
-        needs to be able to interpret register values in the signal
-        context that it receives as an argument.)</para>
-        <para>In some cases, the lisp kernel exception handler may not
-        be able to recover from the exception (this is currently true
-        of some types of memory-access fault and is also true of traps
-        or illegal instructions that occur during foreign code
-        execution.  In such cases, the kernel exception handler
-        reports the exception as "unhandled", and the kernel debugger
-        is invoked.</para>
-        <para>If the kernel exception handler identifies the
-        exception' cause as being a transient out-of-memory condition
-        (indicating that the current thread needs more memory to cons
-        in), it tries to make that memory available.  In some cases,
-        doing so involves invoking the GC.</para>
-      </sect2>
-
-      <sect2 id="Threads-comma---exceptions-comma---and-the-GC">
-	<title>Threads, exceptions, and the GC</title>
-        <para>OpenMCL's GC is not concurrent: when the GC is invoked
-        in response to an exception in a particular thread, all other
-        lisp threads must stop until the GC's work is done.  The
-        thread that triggered the GC iterates over the global TCR
-        list, sending each other thread a distinguished "suspend"
-        signal, then iterates over the list again, waiting for a
-        per-thread semaphore that indicates that the thread has
-        received the "suspend" signal and responded appropriatedly.
-        Once all other threads have acknowledged the request to
-        suspend themselves, the GC thread can run the GC proper (after
-        doing any necessary .)  Once the GC's completed its work, the
-        thread that invoked the GC iterates over the global TCR list,
-        raising a per-thread "resume" semaphore for each other
-        thread.</para>
-        <para>The signal handler for the asynchronous "suspend" signal
-        is entered with all asynchronous signals blocked.  It saves
-        its signal-context argument in a TCR slot, raises the tcr's
-        "suspend" semaphore, then waits on the TCR's "resume"
-        semaphore.</para>
-        <para>The GC thread has access to the signal contexts of all
-        TCRs (including its own) at the time when the thread received
-        an exception or acknowledged a request to suspend itself.
-        This information (and information about stack areas in the TCR
-        itself) allows the GC to identify the "stack locations and
-        register contents" that are elements of the GC's root
-        set.</para>
-      </sect2>
-
-      <sect2 id="PC-lusering">
-	<title>PC-lusering</title>
-        <para>It's not quite accurate to say that OpenMCL's compiler
-        and runtime follow precise stack and register usage
-        conventions at all times; there are a few exceptions:</para>
-
-	<itemizedlist>
-          <listitem>
-<para>On both PPC and x86-64 platforms, consing isn't fully atomic.It takes at least a few instructions to allocate an object in memory(and slap a header on it if necesssary); if a thread is interrupted inthe middle of that instruction sequence, the new object may or may nothave been created or fully initialized at the point in time that theinterrupt occurred.  (There are actually a few different states ofpartial initialization)</para>
-</listitem>
-          <listitem>
-<para>On the PPC, the common act of building a lisp control stack frameinvolves allocating a four-word frame and storing three register valuesinto that frame.  (The fourth word - the back pointer to the previousframe - is automatically set when the frame is allocated.)  The previouscontents of those three words are unknown (there might have been aforeign stack frame at the same address a few instructions earlier),so interrupting a thread that's in the process of initializing aPPC control stack frame isn't GC-safe.</para>
-</listitem>
-          <listitem>
-<para>There are similar problems with the initialization of temp stackframes on the PPC.  (Allocation and initialization doesn't happenatomically, and the newly allocated stack memory may have undefinedcontents.)</para>
-</listitem>
-          <listitem>
-<para>'s write barrier has to be implemented atomically (i.e.,both an intergenerational store and the update of a correspondingreference bit has to happen without interruption, or neither of theseevents can happen.)</para>
-</listitem>
-          <listitem>
-<para>There are a few more similar cases.</para>
-</listitem>
-        
-        </itemizedlist>
-
-        <para>Fortunately, the number of these non-atomic instruction sequences is
-small, and fortunately it's fairly easy for the interrupting thread
-to recognize when the interrupted thread is in the middle of such
-a sequence.  When this is detected, the interrupting thread modfies
-the state of the interrupted thread (modifying its PC and other
-registers) so that it is no longer in the middle of such a sequenece
-(it's either backed out of it or the remaining instructions are
-emulated.)</para>
-        <para>This works because (a) many of the troublesome instruction sequences
-are PPC-specific and it's relatively easy to partially disassemble the
-instructions surrounding the interrupted thread's PC on the PPC and
-(b) those instruction sequences are heavily stylized and intended to
-be easily recognized.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Register-usage-and-tagging">
-      <title>Register usage and tagging</title>
-
-      <sect2 id="Register-usage-and-tagging-overview">
-	<title>Overview</title>
-	<para>Regardless of other details of its implementation, a
-	garbage collector's job is to partition the set of all
-	heap-allocated lisp objects (CONSes, STRINGs, INSTANCEs, etc.)
-	into two subsets.  The first subset contains all objects that
-	are transitively referenced from a small set of "root" objects
-	(the contents of the stacks and registers of all active
-	threads at the time the GC occurs and the values of some
-	global variables.)  The second subset contains everything
-	else: those lisp objects that are not transitively reachable
-	from the roots are garbage, and the memory occupied by garbage
-	objects can be reclaimed (since the GC has just proven that
-	it's impossible to reference them.)</para>
-        <para>The set of live, reachable lisp objects basically form
-        the nodes of a (usually large) graph, with edges from each
-        node A to any other objects (nodes) that object A
-        references.</para>
-        <para>Some nodes in this graph can never have outgoing edges:
-        an array with a specialized numeric or character type usually
-        represents its elements in some (possibly more compact)
-        specialized way.  Some nodes may refer to lisp objects that
-        are never allocated in memory (FIXNUMs, CHARACTERs,
-        SINGLE-FLOATs on 64-bit platforms ..)  This latter class of
-        objects are sometimes called "immediates", but that's a little
-        confusing because the term "immediate" is sometimes used to
-        refer to things that can never be part of the big connectivity
-        graph (e.g., the "raw" bits that make up a floating-point
-        value, foreign address, or numeric value that needs to be used
-        - at least fleetingly - in compiled code.)</para>
-        <para>For the GC to be able to build the connectivity graph
-        reliably, it's necessary for it to be able to reliably tell
-        (a) whether or not a "potential root" - the contents of a
-        machine register or stack location - is in fact a node and (b)
-        for any node, whether it may have components that refer to
-        other nodes.</para>
-        <para>There's no reliable way to answer the first question on
-        stock hardware.  (If everything was a node, as might be the
-        case on specially microcoded "lisp machine" hardware, it
-        wouldn't even need to be asked.)  Since there's no way to just
-        look at a machine word (the contents of a machine register or
-        stack location) and tell whether or not it's a node or just
-        some random non-node value, we have to either adopt and
-        enforce strict conventions on register and stack usage or
-        tolerate ambiguity.</para>
-        <para>"Tolerating ambiguity" is an approach taken by some
-        ("conservative") GC schemes; by contrast, OpenMCL's GC is
-        "precise", which in this case means that it believes that the
-        contents of certain machine registers and stack locations are
-        always nodes and that other registers and stack locations are
-        never nodes and that these conventions are never violated by
-        the compiler or runtime system.  The fact that threads are
-        preemptively scheduled means that a GC could occur (because of
-        activity in some other thread) on any instruction boundary,
-        which in turn means that the compiler and runtime system must
-        follow precise at all times.</para>
-        <para>Once we've decided that a given machine word is a node,
-        a describes how the node's value and type are encoded in that
-        machine word.</para>
-        <para>Most of this - so far - has discussed thigs from the
-        GC's very low-level perspective.  From a much higher point of
-        view, lisp functions accept nodes as arguments, return nodes
-        as values, and (usually) perform some operations on those
-        arguments in order to produce those results.  (In many cases,
-        the operations in question involve raw non-node values.)
-        Higher-level parts of the lisp type system (functions like
-        TYPE-OF and CLASS-OF, etc.) depend on the .</para>
-      </sect2>
-
-      <sect2 id="pc-locatives-on-the-PPC">
-	<title>pc-locatives on the PPC</title>
-        <para>On the PPC, there's a third case (besides "node" and
-        "immediate" values).  As discussed below, a node that denotes
-        a memory-allocated lisp object is a biased (tagged) pointer
-        -to- that object; it's not generally possible to point -into-
-        some composite (multi-element) object (such a pointer would
-        not be a node, and the GC would have no way to update the
-        pointer if it were to move the underlying object.)</para>
-        <para>Such a pointer ("into" the interior of a heap-allocated
-        object) is often called a <emphasis>locative</emphasis>; the
-        cases where locatives are allowed in OpenMCL mostly involve
-        the behavior of function call and return instructions.  (To be
-        technicaly accurate, the other case also arises on x86-64, but
-        that case isn't as user-visible.)</para>
-        <para>On the PowerPC (both PPC32 and PPC64), all machine
-        instructions are 32 bits wide and all in1struction words are
-        allocated on 32-bit boundaries.  In PPC OpenMCL, a CODE-VECTOR
-        is a specialized type of vector-like object; its elements are
-        32-bit PPC machine instructions.  A CODE-VECTOR is an
-        attribute of FUNCTION object; a function call involves
-        accessing the function's code-vector and jumping to the
-        address of its first instruction.</para>
-        <para>As each instruction in the code vector sequentially
-        executes, the hardware program counter (PC) register advances
-        to the address of the next instruction (a locative into the
-        code vector); since PPC instructions are always 32 bits wide
-        and aligned on 32-bit boundaries, the low two bits of the PC
-        are always 0.  If the function executes a call (simple call
-        instrucions have the mnemonic "bl" on the PPC, which stands
-        for "branch and link"), the address of the next instruction
-        (also a word-aligned locative into a code-vector) is copied
-        into the special- purpose PPC "link register" (lr); a function
-        returns to its caller via a "branch to link register" (blr)
-        instruction.  Some cases of function call and return might
-        also use the PPC's "count register" (ctr), and if either the
-        lr or ctr needs to be stored in memory it needs to first be
-        copied to a general-purpose registers.</para>
-        <para>OpenMCL's GC understands that certain registers contain
-        these special "pc-locatives" (locatives that point into
-        CODE-VECTOR objects); it contains specal support for finding
-        the containing CODE-VECTOR object and for adjusting all of
-        these "pc-locatives" if the containing object is moved in
-        memory.  The first part of that - finding the containing
-        object - is possible and practical on the PPC because of
-        architectural artifcacts (fixed-width instructions and arcana
-        of instruction encoding.)  It's not possible on x86-64, but
-        fortunately not necessary either (though the second part -
-        adjusting the PC/RIP when the containing object moves) is both
-        necessary and simple.</para>
-      </sect2>
-
-      <sect2 id="Register-and-stack-usage-conventions">
-        <title>Register and stack usage conventions</title>
-
-        <sect3 id="Stack-conventions">
-	  <title>Stack conventions</title>
-          <para>On both PPC and X86 platforms, each lisp thread uses 3
-          stacks; the ways in which these stacks are used differs
-          between the PPC and X86.</para>
-          <para>Each thread has:</para>
-	  <itemizedlist>
-            <listitem>
-	      <para>A "control stack".On both platforms, this is "the
-	      stack" used by foreign code.On the PPC, it consists of a
-	      linked list of frameswhere the first word in each frame
-	      points to the first word in theprevious frame (and the
-	      outermost frame points to 0.)  Some frameson a PPC
-	      control stack are lisp frames; lisp frames are always 4
-	      wordsin size and contain (in addition to the back
-	      pointer to the previousframe) the calling function (a
-	      node), the return address (a "locative"into the calling
-	      function's code-vector), and the value to which
-	      thevalue-stack pointer (see below) should be restored on
-	      function exit.On the PPC, the GC has to look at
-	      control-stack frames, identifywhich of those frames are
-	      lisp frames, and treat the contents ofthe saved function
-	      slot as a node (and handle the return addresslocative
-	      specially.)On x86-64, the control stack is used for
-	      dynamic-extent allocationof immediate objects.  Since
-	      the control stack never contains nodeson x86-64, the GC
-	      ignores it on that platform.Alignment of the control
-	      stack follows the ABI conventions of theplatform (at
-	      least at any point in time where foreign code could
-	      run.)On PPC, the r1 register always points to the top of
-	      the current thread'scontrol stack; on x86-64, the RSP
-	      register points to the top of thecurrent thread's
-	      control stack when the thread is running foreigncode and
-	      the address of the top of the control stack is kept in
-	      thethread's TCR see when not running foreigncode.The
-	      control stack "grows down."</para>
-	    </listitem>
-            <listitem>
-	      <para>A "value stack".On both platforms, all values on
-	      the value stack are nodes (including"tagged return
-	      addresses" on x86-64.)  The value stack is always
-	      alignedto the native word size; objects are always
-	      pushed on the value stackusing atomic instructions
-	      ("stwu"/"stdu" on PPC, "push" on x86-64), sothe contents
-	      of the value stack between its bottom and top are
-	      alwaysunambiguously nodes; the compiler usually tries to
-	      pop or discardnodes from the value stack as soon as
-	      possible after their last use(as soon as they may have
-	      become garbage.)On x86-64, the RSP register addresses
-	      the top of the value stackwhen running lisp code; that
-	      address is saved in the TCR whenrunning foreign code.On
-	      the PPC, a dedicated regiter (VSP, currently r15) is
-	      used toaddress the top of the value stack when running
-	      lisp code, and theVSP value is saved in the TCR when
-	      running foreign code.The value stack grows down.</para>
-	    </listitem>
-	    <listitem>
-	      <para>A "temp stack".The temp stack consists of a linked
-	      list of frames, each of which pointsto the previous temp
-	      stack frame.  The number of native machine wordsin each
-	      temp stack frame is always even, so the temp stack is
-	      alignedon a two-word (64- or 128-bit) boundary.The temp
-	      stack is used for dynamic-extent objects on both
-	      platforms;on the PPC, it's used for essentially all such
-	      objects (regardlessof whether or not the objects contain
-	      nodes); on the x86-64, immediatedynamic-extent objects
-	      (strings, foreign pointers, etc.) are allocatedon the
-	      control stack and only node-containing dynamic-extent
-	      objectsare allocated on the temp stack.Data structures
-	      used to implement CATCH and UNWIND-PROTECT are stored
-	      onthe temp stack on both ppc and x86-64.Temp stack
-	      frames are always doublenode aligned and objects withina
-	      temp stack frame are aligned on doublenode boundaries.
-	      The firstword in each frame contains a back pointer to
-	      the previous frame; onthe PPC, the second word is used
-	      to indicate to the GC whethe theremaining objects are
-	      nodes (if the second word is 0) or immediate(otherwise.)
-	      On x86-64, where temp stack frames always contain
-	      nodes,the second word is always 0.The temp stack grows
-	      down.  It usually takes several instuctions toallocate
-	      and safely initialize a temp stack frame that's intended
-	      tocontain nodes, and the GC has to recognize the case
-	      where a threadis in the process of allocating and
-	      initializing a temp stack frameand take care not to
-	      interpret any uninitialized words in the frameas nodes.
-	      See .The PPC keeps the current top of the temp stack in
-	      a dedicated register(TSP, currently r12) when running
-	      lisp code and saves this register'svalue in the TCR when
-	      running foreign code.  The x86-64 keeps theaddress of
-	      the top of each thread's temp stack in the thread's
-	      TCR.</para>
-	    </listitem>
-          </itemizedlist>
-        </sect3>
-
-        <sect3 id="Register-conventions">
-	  <title>Register conventions</title>
-          <para>If there are a "reasonable" (for some value of
-          "reasonable") number or general-purpose registers and the
-          instruction set is "reasonably" orthogonal (most
-          instructions that operate on GPRs can operate on any GPR),
-          then it's possible to statically partition the GPRs into at
-          least two sets: "immediate registers" never contain nodes,
-          and "node registers" always contain nodes.  (On the PPC, a
-          few registers are members of a third set of "PC locatives",
-          and on both platforms some registers may have dedicated
-          roles as stack or heap pointers; the latter class is treated
-          as immediates by the GC proper but may be used to help
-          determine the bounds of stack and heap memory areas.)</para>
-	  <para>The ultimate definition of register partitioning is
-          hardwired into the GC in functions like "mark_xp()" and
-          "forward_xp()", which process the values of some of the
-          registers in an exception frame as nodes and may give some
-          sort of special treatment to other register values they
-          encounter there.)</para>
-          <para>On x86-64, the static register partitioning scheme involves:</para>
-	  <itemizedlist>
-            <listitem>
-	      <para>(only) two "immediate" registers.The RAX and RDX
-	      registers are used as the implicit operands andresults
-	      of some extended-precision multiply and divide
-	      instructionswhich generally involve non-node values;
-	      since their use in theseinstructions means that they
-	      can't be guaranteed to contain nodevalues at all times,
-	      it's natural to put these registers in the"immediate"
-	      set.  RAX is generally given the symbolic name
-	      "imm0",and RDX is given the symbolic name "imm1"; you
-	      may see these namesin disassembled code, usually in
-	      operations involving type checking,array indexing, and
-	      foreign memory and function access.</para>
-	    </listitem>
-            <listitem>
-	      <para>(only) two "dedicated" registers.RSP and RBP have
-	      dedicated functionality dictated by the hardwareand
-	      calling conventions.  (There are a few places where RBP
-	      istemporarily used as an extra immediate
-	      register.)</para>
-	    </listitem>
-            <listitem>
-	      <para>12 "node" registers.All other registers (RBX, RCX,
-	      RSI, RDI, and R8-R15) are asserted tocontain node values
-	      at (almost) all times; legacy "string" operationsthat
-	      implicitly use RSI and/or RDI are not used.  Shift and
-	      rotateintructions which shift/rotate by a variable
-	      number of bits arerequired by the architecture to use
-	      the low byte of RCX (the traditionalCL register) as the
-	      implicit shift count; when it's necessary to keepa
-	      non-node shift count in the low byte of RCX, the upper 7
-	      bytes ofthe register are zeroed (so that
-	      misinterpetation of the immediatevalue in RCX as a node
-	      will not have negative GC affects.  (The GCmight briefly
-	      treate it as a node, but since it's not pointing
-	      anywherenear the lisp heap it'll soon lose interest in
-	      it.)Legacy instructions that use RCX (or some portions
-	      of it) as a loopcounter can not be used (since such
-	      instructions might introducenon-node values into
-	      RCX.)</para>
-</listitem>
-	  </itemizedlist>
-          <para>On the PPC, the static register partitioning scheme involves:</para>
-
-	  <itemizedlist>
-            <listitem>
-	      <para>6 "immediate" registersRegisters r3-r8 are given
-	      the symbolic names imm0-imm5.  As a RISCarchitecture
-	      with simpler addressing modes, the PPC probably
-	      usesimmediate registers a bit more often than the CISC
-	      x86-64 does, butthey're generally used for the same sort
-	      of things (type checking,array indexing, FFI,
-	      etc.)</para>
-	    </listitem>
-	    <listitem>
-	      <para>9 dedicated registers
-	      <itemizedlist>
-		<listitem>
-		  <para>r0 (symbolic name rzero) always contains the
-		  value 0 when runninglisp code.  Its value is
-		  sometimes read as 0 when it's used as thebase
-		  register in a memory address; keeping the value 0
-		  there issometimes convenient and avoids
-		  asymmetry.</para>
-		</listitem>
-		<listitem>
-		  <para>r1 (symbolic name sp) is the control stack
-		  pointer, by PPC convention.</para>
-		</listitem>
-                <listitem>
-		  <para>r2 is used to hold the current thread's TCR on
-		  ppc64 systems; it'snot used on ppc32.</para>
-		</listitem>
-                <listitem>
-		  <para>r9 and r10 (symbolic names allocptr and
-		  allocbase) are used to do per-thread memory
-		  allocation</para>
-		</listitem>
-                <listitem>
-		  <para>r11 (symbolic name nargs) contains the number
-		  of function arguments on entry and the number of
-		  return values in multiple-value returning
-		  constructs.  It's not used more generally as either
-		  a node or immediate register because of the way that
-		  certain trap instruction encodings are
-		  interpreted.</para>
-		</listitem>
-                <listitem>
-		  <para>r12 (symbolic name tsp) holds the top of the current thread's temp stack.</para>
-		</listitem>
-		<listitem>
-		  <para>r13 is used to hold the TCR on PPC32 sytems; it's not used on PPC64.</para>
-		</listitem>
-		<listitem>
-		  <para>r14 (symbolic name loc-pc) is used to copy
-		  "pc-locative" values between main memory and
-		  special-purpose PPC registers (LR and CTR) used in
-		  function-call and return instructions.</para>
-		</listitem>
-                <listitem>
-		  <para>r15 (symbolic name vsp) addresses the top of
-		  the current thread's value stack.</para>
-		</listitem>
-		<listitem>
-		  <para>lr and ctr are PPC branch-unit registers used
-		  in function call and return instructions; they're
-		  always treated as "pc-locatives", which precludes
-		  the use of the ctr in some PPC looping
-		  constructs.</para>
-		</listitem>
-              
-	      </itemizedlist>
-	      </para>
-	    </listitem>
-            <listitem>
-	      <para>17 "node" registersr15-r31 are always treated as
-	      node registers</para>
-	    </listitem>
-	    
-          </itemizedlist>
-        </sect3>
-      </sect2>
-
-      <sect2 id="Tagging-scheme">
-	<title>Tagging scheme</title>
-        <para>OpenMCL always allocates lisp objects on double-node
-        (64-bit for 32-bit platforms, 128-bit for 64-bit platforms)
-        boundaries; this mean that the low 3 bits (32-bit lisp) or 4
-        bits (64-bit lisp) are always 0 and are therefore redundant
-        (we only really need to know the upper 29 or 60 bits in order
-        to identify the aligned object address.)  The extra bits in a
-        lisp node can be used to encode at least some information
-        about the node's type, and the other 29/60 bits represent
-        either an immediate value or a doublenode-aligned memory
-        address.  The low 3 or 4 bits of a node are called the node's
-        "tag bits", and the conventions used to encode type
-        information in those tag bits are called a "tagging
-        scheme."</para>
-        <para>It might be possible to use the same tagging scheme on
-        all platforms (at least on all platforms with the same word
-        size and/or the same number of available tag bits), but there
-        are often some strong reasons for not doing so.  These
-        arguments tend to be very machine-specific: sometimes, there
-        are fairly obvious machine-dependent tricks that can be
-        exploited to make common operations on some types of tagged
-        objects faster; other times, there are architectural
-        restrictions that make it impractical to use certain tags for
-        certain types.  (On PPC64, the "ld" (load doubleword) and
-        "std" (store doubleword) instructions - which load and store a
-        GPR operand at the effective address formed by adding the
-        value of another GPR operand and a 16-bit constant operand -
-        require that the low two bits of that constant operand be 0.
-        Since such instructions would typically be used to access the
-        fields of things like CONS cells and structures, it's
-        desirable that that the tags chosen for CONS cells and
-        structures allow the use of these intructions as opposed to
-        more expensive alternatives.)</para>
-        <para>One architecture-dependent tagging trick that works well
-        on all architectures is to use a tag of 0 for FIXNUMs: a
-        fixnum basically encodes its value shifted left a few bits and
-        keeps those low bits clear. FIXNUM addition, subtraction, and
-        binary logical operations can operate directly on the node
-        operands, addition and subtraction can exploit hardware-based
-        overflow detection, and (in the absence of overflow) the
-        hardware result of those operations is a node (fixnum).  Some
-        other slightly-less-common operations may require a few extra
-        instructions, but arithmetic operations on FIXNUMs should be
-        as cheap as possible and using a tag of zero for FIXNUMs helps
-        to ensure that it will be.</para> 
-	<para>If we have N available tag bits (N = 3 for 32-bit
-	OpenMCL and N = 4 for 64-bit OpenMCL), this way of
-	representing fixnums with the low M bits forced to 0 works as
-	long as M &lt;= N.  The smaller we make M, the larger the
-	values of MOST-POSITIVE-FIXNUM and MOST-NEGATIVE become; the
-	larger we make N, the more distinct non-FIXNUM tags become
-	available.  A reasonable compromise is to choose M = N-1; this
-	basically yields two distinct FIXNUM tags (one for even
-	fixnums, one for odd fixnums), gives 30-bit fixnums on 32-bit
-	platforms and 61-bit fixnums on 64-bit platforms, and leaves
-	us with 6 or 14 tags to encoded other types.</para>
-        <para>Once we get past the assignment of FIXNUM tags, things
-        quickly devolve into machine-dependencies.  We can fairly
-        easily see that we can't directly all other primitive lisp
-        object types with only 6 or 14 available tag values; the
-        details of how types are encoded vary between the ppc32,
-        ppc64, and x86-64 implementations, but there are some general
-        common principles:</para>
-
-	<itemizedlist>
-	  <listitem>
-	    <para>CONS cells always contain exactly 2 elements and are
-	    usually fairly common.It therefore makes sense to give
-	    CONS cells their own tag.  Unlike thefixnum case - where a
-	    tag value of 0 had positive implications - theredoesn't
-	    seem to be any advantage to using any particular value.
-	    (A longtime ago - in the case of 68K MCL - the CONS tag
-	    and the order of CAR and CDR in memory were chosen to allow
-	    smaller, cheaper addressing modes to be used to "cdr down a
-	    list."  That's not a factor on ppc or x86-64,but all
-	    versions of OpenMCL still store the CDR of a CONS cell
-	    first in memory.  It doesn't matter, but doing it the way
-	    that the host system did made boostrapping to a new target
-	    system a little easier.)
-	    </para>
-	  </listitem>
-	  <listitem>
-	    <para>Any way you look at it, NIL is a bit ... unusual.NIL
-	    is both a SYMBOL and a LIST (as well as being a canonical
-	    truth value and probably a few other things.)  Its role as
-	    a LIST is probably much more important to most programs
-	    than its role as a SYMBOL is:LISTP has to be true of NIL
-	    and primitives like CAR and CDR do LISTP implicitly when
-	    safe and want that operation to be fast.There are several
-	    possible approaches to this; OpenMCL uses two of them. On
-	    PPC32 and X86-64, NIL is basically a weird CONS cell that
-	    straddles two doublenodes; the tag of NIL is unique and
-	    congruent modulo 4 (modulo 8 on 64-bit) with the tag used
-	    for CONS cells.  LISTP is therefore true of any node whose
-	    low 2 (or 3) bits contain the appropriate tag value (it's
-	    not otherwise necessary to special-case NIL.)
-	    SYMBOL accessors (SYMBOL-NAME, SYMBOL-VALUE, SYMBOL-PLIST
-	    ..) -do- have to special-case NIL (and access the
-	    components of an internal proxy symbol.) On PPC64 (where
-	    architectural restrictions dictate the set of tags that can
-	    be used to access fixed components of an object),
-	    that approach wasn't practical.  NIL is just a
-	    distinguished SYMBOL,and it just happens to be the case
-	    that its pname slot and values lots are at the same offsets
-	    from a tagged pointer as a CONS cell's CDR and CAR would be.
-	    NIL's pname is set to NIL (SYMBOL-NAME checks for this and
-	    returns the string "NIL"), and LISTP (and therefore safe
-	    CAR and CDR) have to check for (OR NULL CONSP).At least in
-	    the case of CAR and CDR, the fact that the PPC has multiple
-	    condition-code fields keeps that extra test from
-	    being prohibitively expensive.</para>
-	  </listitem>
-	  <listitem>
-	    <para>Some objects are immediate.(but not FIXNUMs).This is
-	    true of CHARACTERs and, on 64-bit platforms,
-	    SINGLE-FLOATs.It's also true of some nodes used in the
-	    runtime system (specialvalues used to indicate unbound
-	    variables and slots, for instance.)On 64-bit platforms,
-	    SINGLE-FLOATs have their own unique tag (makingthem a
-	    little easier to recognize; on all platforms, CHARACTERs
-	    sharea tag with other immediate objects (unbound markers)
-	    but are easyto recognize (by looking at several of their
-	    low bits.)  The GCtreats any node with an immediate tag
-	    (and any node with a fixnumtag) as a leaf.</para>
-	  </listitem>
-          <listitem>
-	    <para>There are some advantages to treating everything
-	    else - memory-allocated objects that aren't CONS cells -
-	    uniformly.There are some disadvantages to that uniform
-	    treatment as well, and the treatment of "memory-allocated
-	    non-CONS objects" isn't entirely uniformaccross all
-	    OpenMCL implementations.  Let's first pretend that
-	    the treatment is uniform, then discuss the ways in which it
-	    isn't.The "uniform approach" is to treat all
-	    memory-allocated non-CONS objectsas if they were vectors;
-	    this use of the term is a little looser thanwhat's implied
-	    by the CL VECTOR type.  OpenMCL actually uses the
-	    term"uvector" to mean "a memory-allocated lisp object
-	    other than a CONS cell,whose first word is a header which
-	    describes the object's type andthe number of elements that
-	    it contains."  In this view, a SYMBOL isa UVECTOR, as is a
-	    STRING, a STANDARD-INSTANCE, a CL array or vector,a
-	    FUNCTION, and even a DOUBLE-FLOAT.In the PPC
-	    implementations (where things are a little more
-	    ... uniform),a single tag value is used to denote any
-	    uvector; in order to determinesomething more specific
-	    about the type of the object in question, it'snecessary to
-	    fetch the low byte of the header word from memory.  On
-	    thex86-64 platform, certain types of uvectors - SYMBOLs
-	    and FUNCTIONs -are given their own unique tags.  The good
-	    news about the x86-64 approachis that SYMBOLs and
-	    FUNCTIONs can be recognized without referencingmemory; the
-	    slightly bad news is that primitive operations that workon
-	    UVECTOR-tagged objects - like the function CCL:UVREF -
-	    don't workon SYMBOLs or FUNCTIONs on x86-64 (but -do- work
-	    on those types of objectsin the PPC ports.)The header word
-	    which precedes a UVECTOR's data in memory contains 8bits
-	    of type information in the low byte and either 24 or 56
-	    bits of"element-count" information in the rest of the
-	    word.  (This is wherethe sometimes-limiting value of 2^24
-	    for ARRAY-TOTAL-SIZE-LIMIT onPPC32 platforms comes from.)
-	    The low byte of the header - sometimescalled the uvector's
-	    subtag - is itself tagged (which means thatthe header is
-	    tagged.)  The (3 or 4) tag bits in the subtag are usedto
-	    determine whether the uvector's elements are nodes or
-	    immediates.(A UVECTOR whose elements are nodes is called a
-	    GVECTOR; a UVECTORwhose elements are immediates is called
-	    an IVECTOR.  This terminologycame from Spice Lisp, which
-	    was a predecessor of CMUCL.)Even though a uvector header
-	    is tagged, a header is not a node.  There'sno (supported)
-	    way to get your hands on one in lisp and doing so couldbe
-	    dangerous.  (If the value of a header wound up in a lisp
-	    noderegister and that register wound up getting pushed on
-	    a thread's valuestack, the GC might misinterpret that
-	    situation to mean that therewas a stack-allocated UVECTOR
-	    on the value stack.)</para>
-	  </listitem>
-        
-	</itemizedlist>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Heap-Allocation">
-      <title>Heap Allocation</title> <para>When the OpenMCL kernel
-      first starts up, a large contiguous chunk of the process's
-      address space is mapped as "anonymous, no access"
-      memory. ("Large" means different things in different contexts;
-      on LinuxPPC32, it means "about 1 gigabyte", on DarwinPPC32, it
-      means "about 2 gigabytes", and on current 64-bit platforms it
-      ranges from 128 to 512 gigabytes, depending on OS. These values
-      are both defaults and upper limits; the --heap-reserve
-      argument can be used to try to reserve less than the
-      default.)</para>
-      <para>Reserving address space that can't (yet) be read or
-      written to doesn't cost much; in particular, it doesn't require
-      that correspinding swap space or physical memory be available.
-      Marking the address range as being "mapped" helps to ensure that
-      other things (result from random calls to malloc(), dynamically
-      loaded shared libraries) won't be allocated in this region that
-      lisp has reserved for its own heap growth.</para>
-      <para>A small portion (around 1/32 on 32-bit platforms and 1/64
-      on 64-bit platforms) of that large chunk of address space is
-      reserved for GC data structures.  Memory pages reserved for
-      these data structures are mapped read-write as pages made
-      writable in the main portion of the heap.</para>
-      <para>The initial heap image is mapped into this reserved
-      address space and an additional (LISP-HEAP-GC-THRESHOLD) bytes
-      are mapped read-write.  GC data structures grow to match the
-      amount of GC-able memory in the initial image + the gc
-      threshold, and control is transferred to lisp code.  Inevitably,
-      that code spoils everything and starts consing; there are
-      basically three layers of memory allocation that can go
-      on.</para>
-
-      <sect2 id="Per-thread-object-allocation">
-	<title>Per-thread object allocation</title>
-        <para>Each lisp thread has a private "reserved memory
-        segment"; when a thread starts up, its reserved memory segment
-        is empty.  PPC ports maintain the highest unallocated addres
-        and he lowest allocated address in the current segment in
-        registers when running lisp code; on x86-664, these values are
-        maintained in the current threads's TCR.  (An "empty" heap
-        segment is one whose high pointer and low pointer are equal.)
-        When a thread is not in the midde of allocating something, the
-        low 3 or 4 bits of the high and low pointers are clear (the
-        pointers are doublenode-aligned.)</para>
-        <para>A thread tries to allocate an object whose physical size
-        in bytes is X and whose tag is Y by:</para>
-	<orderedlist>
-	  <listitem>
-	    <para>decrementing the "high" pointer by (- X Y)</para>
-	  </listitem>
-	  <listitem>
-	    <para>trapping if the high pointer is less than the low
-	    pointer</para>
-	  </listitem>
-	  <listitem>
-	    <para>using the (tagged) high pointer to initialize the
-	    object, if necessary</para>
-	  </listitem>
-	  <listitem>
-	    <para>clearing the low bits of the high pointer</para>
-	  </listitem>
-	</orderedlist>
-        <para>On PPC32, where the size of a CONS cell is 8 bytes and
-        the tag of a CONS cell is 1, machine code which sets the arg_z
-        register to the result of doing (CONS arg_y arg_z) looks
-        like:</para>
-        <programlisting>
-  (SUBI ALLOCPTR ALLOCPTR 7)    ; decrement the high pointer by (- 8 1)
-  (TWLLT ALLOCPTR ALLOCBASE)    ; trap if the high pointer is below the base
-  (STW ARG_Z -1 ALLOCPTR)       ; set the CDR of the tagged high pointer
-  (STW ARG_Y 3 ALLOCPTR)        ; set the CAR
-  (MR ARG_Z ALLOCPTR)           ; arg_z is the new CONS cell
-  (RLWINM ALLOCPTR ALLOCPTR 0 0 28)     ; clear tag bits
-</programlisting>
-        <para>On x86-64, the idea's similar but the implementation is
-        different.  The high and low pointers to the current thread's
-        reserved segment are kept in the TCR, which is addressed by
-        the gs segment register. An x86-64 CONS cell is 16 bytes wide
-        and has a tag of 3; we canonically use the temp0 register to
-        initialize the object</para>
-        <programlisting>
-  (subq ($ 13) ( (% gs) 216))  ; decrement allocptr
-  (movq ( (% gs) 216) (% temp0)); load allocptr into temp0
-  (cmpq ( (% gs) 224) (% temp0)) ; compare to allocabase
-  (jg L1)                       ; skip trap
-  (uuo-alloc)                   ; uh, don't skip trap
-L1
-  (andb ($ 240) ( (% gs) 216)) ; untag allocptr in the tcr
-  (movq (% arg_y) ( 5 (% temp0))) ; set the car
-  (movq (% arg_z) ( -3 (% temp0))); set the cdr
-  (movq (% temp0) (% arg_z))    ; return the cons
-	</programlisting>
-        <para>If we don't take the trap (if allocating 8-16 bytes
-        doesn't exhaust the thread's reserved memory segment), that's
-        a fairly short and simple instruction sequence.  If we do take
-        the trap, we'll have to do some additional work in order to
-        get a new segment for the current thread.</para>
-      </sect2>
-
-      <sect2 id="Allocation-of-reserved-heap-segments">
-	<title>Allocation of reserved heap segments</title>
-        <para>After lisp image is first mapped into memory - and after
-        each full GC - the lisp kernel ensures that
-        (LISP-HEAP-GC-TRESHOLD) additional bytes beyond the current
-        end of the heap are mapped read-write.</para>
-        <para>If a thread traps while trying to allocate memory, the
-        thread goes through the usual exception-handling protocol (to
-        ensure that any oher thread that GCs "sees" the state of the
-        trapping thread and to serialize exception handling.)  When
-        the exception handler runs, it determines the nature and size
-        of the failed allocation and tries to complete the allocation
-        on the thread's behalf (and leave it with a reasonably large
-        thread-specific memory segment so that the next small
-        allocation is unlikely to trap.</para>
-        <para>Depending on the size of the requested segment
-        allocation, the number of segment allocations that have
-        occurred since the last GC, and the EGC and GC thresholds, the
-        segment allocation trap handler may invoke a full or ephemeral
-        GC before returning a new segment.  It's worth noting that the
-        [E]GC is triggered based on the number of and size of these
-        segments that've been allocated since the last GC; it doesn't
-        have much to do with how "full" each of those per-thread
-        segments are.  It's possible for a large number of threads to
-        do fairly incidental memory allocation and trigger the GC as a
-        result; avoiding this involves tuning the per-thread
-        allocation quantum and the GC/EGC thresholds
-        appropriately.</para>
-      </sect2>
-
-      <sect2 id="Heap-growth">
-	<title>Heap growth</title>
-        <para>All OSes on which OpenMCL currently runs use an
-        "overcommit" memory allocation strategy by default (though
-        some of them provide ways of overriding that default.)  What
-        this means in general is that the OS doesn't necessarily
-        ensure that backing store is available when asked to map pages
-        as read-write; it'll often return a success indicator from the
-        mapping attempt (mapping the pages as "zero-fill,
-        copy-on-write"), and only try to allocate the backing store
-        (swap space and/or physical memory) when non-zero contents are
-        written to the pages.</para>
-        <para>It -sounds- like it'd be better to have the mmap() call
-        fail immediately, but it's actually a complicated issue.
-        (It's possible that other applications will stop using some
-        backing store before lisp code actually touches the pages that
-        need it, for instance.)  It's also not guaranteed that lisp
-        code would be able to "cleanly" signal an out-of-memory
-        condition if lisp is ... out of memory</para>
-        <para>I don't know that I've ever seen an abrupt out-of-memory failure that
-wasn't preceeded by several minutes of excessive paging activity.  The
-most expedient course in cases like this is to either (a) use less memory
-or (b) get more memory; it's generally hard to use memory that you don't
-have.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="GC-details">
-      <title>GC details</title>
-      <para>The GC uses a Mark/Compact algorithm; its
-      execution time is essentially a factor of the amount of live
-      data in the heap. (The somewhat better-known Mark/Sweep
-      algorithms don't compact the live data but instead traverse the
-      garbage to rebuild free-lists; their execution time is therefore
-      a factor of the total heap size.)</para>
-      <para>As mentioned in , two auxiliary data structures
-      (proportional to the size of the lisp heap) are maintained. These are</para>
-      <orderedlist>
-	<listitem>
-	  <para>the markbits bitvector, which contains a bit for
-	  everydoublenode in the dynamic heap (plus a few extra words
-	  for alignmentand so that sub-bitvectors can start on word
-	  boundaries.)</para>
-	</listitem>
-	<listitem>
-	  <para>the relocation table, which contains a native word for
-	  every 32 or 64 doublenodes in the dynamic heap, plus an
-	  extra word used to keep trackof the end of the heap.</para>
-	</listitem>
-      </orderedlist>
-      <para>The total GC space overhead is therefore on the order of
-      3% (2/64 or 1/32).</para>
-      <para>The general algorithm proceeds as follows:</para>
-
-      <sect2 id="Mark-phase">
-	<title>Mark phase</title>
-        <para>Each doublenode in the dynamic heap has a corresponding
-        bit in the markbits vector. (For any doublenode in the heap,
-        the index of its mark bit is determined by subtracing the
-        address of the start of the heap from the address of the
-        object and dividing the result by 8 or 16.) The GC knows the
-        markbit index of the free pointer, so determining that the
-        markbit index of a doubleword address is between the start of
-        the heap and the free pointer can be done with a single
-        unsigned comparison.</para>
-        <para>The markbits of all doublenodes in the dynamic heap are
-        zeroed before the mark phase begins. An object is
-        <emphasis>marked</emphasis> if the markbits of all of its
-        constituent doublewords are set and unmarked otherwise;
-        setting an object's markbits involves setting the corrsponding
-        markbits of all constituent doublenodes in the object.</para>
-        <para>The mark phase traverses each root. If the tag of the
-        value of the root indicates that it's a non-immediate node
-        whose address lies in the lisp heap, then:</para>
-	<orderedlist>
-	  <listitem>
-	    <para>If the object is already marked, do nothing.</para>
-	  </listitem>
-	  <listitem>
-	    <para>Set the object's markbit(s).</para>
-	  </listitem>
-	  <listitem>
-	    <para>If the object is an ivector, do nothing further.</para>
-	  </listitem>
-	  <listitem>
-	    <para>If the object is a cons cell, recursively mark its
-	    car and cdr.</para>
-	  </listitem>
-	  <listitem>
-	    <para>Otherwise, the object is a gvector. Recursively mark
-	    itselements.</para>
-	  </listitem>
-	</orderedlist>
-        <para>Marking an object thus involves ensuring that its mark
-        bits are set and then recursively marking any pointers
-        contained within the object if the object was originally
-        unmarked. If this recursive step was implemented in the
-        obvious manner, marking an object would take stack space
-        proportional to the length of the pointer chain from some root
-        to that object. Rather than storing that pointer chain
-        implicitly on the stack (in a series of recursive calls to the
-        mark subroutine), the OpenMCL marker uses mixture of recursion
-        and a technique called <emphasis>link inversion</emphasis> to
-        store the pointer chain in the objects themselves.  (Recursion
-        tends to be simpler and faster; if a recursive step notes that
-        stack space is becoming limited, the link-inversion technique
-        is used.)</para>
-        <para>Certain types of objects are treated a little specially:</para>
-	<orderedlist>
-	<listitem>
-	  <para>To support a feature called <emphasis>GCTWA
-              <footnote>
-		<para>I believe that theacronym comes from MACLISP,
-		where it stood for "Garbage Collection ofTruly
-		Worthless Atoms".</para>
-              </footnote>
-	      , </emphasis>the vector which contains the
-	      internalsymbols of the current package is marked on
-	      entry to the mark phasebut the symbols themselves are
-	      not marked at this time. Near the endof the mark phase,
-	      symbols referenced from this vector which are
-	      nototherwise marked are marked if and only if they're
-	      somehowdistinguishable from newly created symbols (by
-	      virtue of their havingfunction bindings, value bindings,
-	      plists, or other attributes.)</para>
-	</listitem>
-	<listitem>
-	  <para>Pools have their first element set to NIL before any
-	  otherelements are marked.</para>
-	</listitem>
-	<listitem>
-	  <para>All hash tables have certain fields (used to cache
-	  previous results) invalidated.</para>
-	</listitem>
-	<listitem>
-	  <para>Weak Hash Tables and other weak objects are put on a
-	  linkedlist as they're encountered; their contents are only
-	  retained if there are other (non-weak) references to
-	  them.</para>
-	</listitem>
-	</orderedlist>
-        <para>At the end of the mark phase, the markbits of all objects which
-	are transitively reachable from the roots are set and all other markbits
-	are clear.</para>
-      </sect2>
-
-      <sect2 id="Relocation-phase">
-	<title>Relocation phase</title>
-	<para>The <emphasis>forwarding address</emphasis> of a
-	doublenode in the dynamic heap is (&lt;its current address> -
-	(size_of_doublenode * &lt;the number of unmarked markbits that
-	precede it>)) or alternately (&lt;the base of the heap> +
-	(size_of_doublenode * &lt;the number of marked markbits that
-	preced it &gt;)). Rather than count the number of preceding
-	markbits each time, the relocation table is used to precompute
-	an approximation of the forwarding addresses for all
-	doublewords. Given this approximate address and a pointer into
-	the markbits vector, it's relatively easy to compute the exact
-	forwarding address.</para>
-	<para>The relocation table contains the forwarding addresses
-	of each <emphasis>pagelet</emphasis>, where a pagelet is 256
-	bytes (or 32 doublenodes). The forwarding address of the first
-	pagelet is the base of the heap. The forwarding address of the
-	second pagelet is the sum of the forwarding address of the
-	first and 8 bytes for each mark bit set in the first 32-bit
-	word in the markbits table. The last entry in the relocation
-	table contains the forwarding address that the freepointer
-	would have, e.g., the new value of the freepointer after
-	compaction.</para>
-	<para>In many programs, old objects rarely become garbage and
-	new objects often do. When building the relocation table, the
-	relocation phase notes the address of the first unmarked
-	object in the dynamic heap. Only the area of the heap between
-	the first unmarked object and the freepointer needs to be
-	compacted; only pointers to this area will need to be
-	forwarded (the forwarding address of all other pointers to the
-	dynamic heap is the address of that pointer.)  Often, the
-	first unmarked object is much nearer the free pointer than it
-	is to the base of the heap.</para>
-      </sect2>
-
-      <sect2 id="Forwarding-phase">
-	<title>Forwarding phase</title>
-        <para>The forwarding phase traverses all roots and the "old"
-        part of the dynamic heap (the part between the base of the
-        heap and the first unmarked object.) All references to objects
-        whose address is between the first unmarked object and the
-        free pointer are updated to point to the address the object
-        will have after compaction by using the relocation table and
-        the markbits vector and interpolating.</para>
-	<para>The relocation table entry for the pagelet nearest the
-	object is found. If the pagelet's address is less than the
-	object's address, the number of set markbits that precede the
-	object on the pagelet is used to determine the object's
-	address; otherwise, the number of set markbits the follow the
-	object on the pagelet is used.</para>
-        <para>Since forwarding views the heap as a set of doublewords,
-        locatives are (mostly) treated like any other pointers. (The
-        basic difference is that locatives may appear to be tagged as
-        fixnums, in which case they're treated as word-aligned
-        pointers into the object.)</para>
-        <para>If the forward phase changes the address of any hash
-        table key in a hash table that hashes by address (e.g., an EQ
-        hash table), it sets a bit in the hash table's header. The
-        hash table code will rehash the hash table's contents if it
-        tries to do a lookup on a key in such a table.</para>
-        <para>Profiling reveals that about half of the total time
-        spent in the GC is spent in the subroutine which determines a
-        pointer's forwarding address. Exploiting GCC-specific idioms,
-        hand-coding the routine, and inlining calls to it could all be
-        expected to improve GC performance.</para>
-      </sect2>
-
-      <sect2 id="Compact-phase">
-	<title>Compact phase</title>
-        <para>The compact phase compacts the area between the first
-        unmarked object and the freepointer so that it contains only
-        marked objects.  While doing so, it forwards any pointers it
-        finds in the objects it copies.</para>
-        <para>When the compact phase is finished, so is the GC (more
-        or less): the free pointer and some other data structures are
-        updated and control returns to the exception handler that
-        invoked the GC. If sufficient memory has been freed to satisfy
-        any allocation request that may have triggered the GC, the
-        exception handler returns; otherwise, a "seriously low on
-        memory" condition is signalled, possibly after releasing a
-        small emergency pool of memory.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="The-ephemeral-GC">
-      <title>The ephemeral GC</title>
-      <para>In the OpenMCL memory management scheme, the relative age
-      of two objects in the dynamic heap can be determined by their
-      addresses: if addresses X and Y are both addresses in the
-      dynamic heap, X is younger than Y (X was created more recently
-      than Y) if it is nearer to the free pointer (and farther from
-      the base of the heap) than Y.</para>
-      <para>Ephemeral (or generational) garbage collectors attempt to
-      exploit the following assumptions:</para>
-      <itemizedlist>
-	<listitem>
-	  <para>most newly created objects become garbage soon after
-	  they'recreated.</para>
-	</listitem>
-	<listitem>
-	  <para>most objects that have already survived several GCs
-	  are unlikely to ever become garbage.</para>
-	</listitem>
-	<listitem>
-	  <para>old objects can only point to newer objects as the
-	  result of adestructive modification (e.g., via
-	  SETF.)</para>
-	</listitem>
-      </itemizedlist>
-
-      <para>By concentrating its efforts on (frequently and quickly)
-      reclaiming newly created garbage, an ephemeral collector hopes
-      to postpone the more costly full GC as long as possible. It's
-      important to note that most programs create some long-lived
-      garbage, so an EGC can't typically eliminate the need for full
-      GC.</para>
-      <para>An EGC views each object in the heap as belonging to
-      exactly one <emphasis>generation</emphasis>; generations are
-      sets of objects that are related to each other by age: some
-      generation is the youngest, some the oldest, and there's an age
-      relationship between any intervening generations. Objects are
-      typically assigned to the youngest generation when first
-      allocated; any object that has survived some number of GCs in
-      its current generation is promoted (or
-      <emphasis>tenured</emphasis>) into an older generation.</para>
-      <para>When a generation is GCed, the roots consist of the
-      stacks, registers, and global variables as always and also of
-      any pointers to objects in that generation from other
-      generations. To avoid the need to scan those (often large) other
-      generations looking for such intergenerational references, the
-      runtime system must note all such intergenerational references
-      at the point where they're created (via Setf).<footnote><para>This is
-      sometimes called "The Write Barrier": all assignments which
-      might result in intergenerational references must be noted, as
-      if the other generations were write-protected.</para></footnote> The
-      set of pointers that may contain intergenerational references is
-      sometimes called <emphasis>the remembered set</emphasis>.</para>
-      <para>In OpenMCL's EGC, the heap is organized exactly the same
-      as otherwise; "generations" are merely structures which contain
-      pointers to regions of the heap (which is already ordered by
-      age.) When a generation needs to be GCed, any younger generation
-      is incorporated into it; all objects which survive a GC of a
-      given generation are promoted into the next older
-      generation. The only intergenerational references that can exist
-      are therefore those where an old object is modified to contain a
-      pointer to a new object.</para>
-      <para>The EGC uses exactly the same code as the full GC. When a
-      given GC is "ephemeral",</para>
-      <itemizedlist>
-        <listitem>
-	  <para>the "base of the heap" used to determine anobject's
-	  markbit address is the base of the generation
-	  being collected;</para>
-	</listitem>
-        <listitem>
-	  <para>the markbits vector is actually a pointer into the
-	  middle of the global markbits table; preceding entries in
-	  this table are used to note doubleword addresses in older
-	  generations that (may) contain intergenerational
-	  references;</para>
-	</listitem>
-        <listitem>
-	  <para>some steps (notably GCTWA and the handling of weak
-	  objects) are not performed;</para>
-	</listitem>
-        <listitem>
-	  <para>the intergenerational references table is used to
-	  findadditional roots for the mark and forward phases. If a
-	  bit is set inthe intergenerational references table, that
-	  means that thecorresponding doubleword (in some "old"
-	  generation, insome "earlier" part of the heap) may have had
-	  a pointerto an object in a younger generation stored into
-	  it.</para>
-	</listitem>
-      
-      </itemizedlist>
-      <para>The intergenerational references table is maintained
-      indirectly: whenever a setf operation that may introduce an
-      intergenerational reference occurs, a pointer to the doubleword
-      being stored into is pushed onto the <emphasis>memo
-      buffer</emphasis>, which is a stack whos top is addressed by the
-      memo register. Whenever the memo buffer overflows<tip><para>A
-      guard page at the end of the memo buffer simplifies overflow
-      detection.</para></tip> when the EGC is active, the handler
-      scans the buffer and sets bits in the intergenerational
-      references table for each doubleword address it finds in the
-      buffer that belongs to some generation other than the youngest;
-      the same scan is performed on entry to any ephemeral GC.  After
-      (possibly) performing this scan, the handler resets the memo
-      register to point to the bottom of the memo stack; this means
-      that when the EGC is inactive, the memo buffer is constantly
-      being filled and emptied for no apparent reason.</para>
-      <para>With one exception (the implicit setfs that occur on entry
-      to and exit from the binding of a special variable), all setfs
-      that might introduce an intergenerational reference must be
-      memoized.<tip><para>Note that the implicit setfs that occur when
-      initializing an object - as in the case of a call to cons or
-      vector - can't introduce intergenerational references, since the
-      newly created object is always younger than the objects used to
-      initialize it.</para></tip> It's always safe to push any cons
-      cell or gvector locative onto the memo stack; it's never safe to
-      push anything else.</para>
-      <para>Typically, the intergenerational references bitvector is
-      sparse: a relatively small number of old locations are stored
-      into, although some of them may have been stored into many
-      times. The routine that scans the memoization buffer does a lot
-      of work and usually does it fairly often; it uses a simple,
-      brute-force method but might run faster if it was smarter about
-      recognizing addresses that it'd already seen.</para>
-      <para>When the EGC mark and forward phases scan the
-      intergenerational reference bits, they can clear any bits that
-      denote doublewords that definitely do not contain
-      intergenerational references.</para>
-    </sect1>
-
-    <sect1 id="Fasl-files">
-      <title>Fasl files</title>
-      <para>The information in this section was current in November
-      2004.  Saving and loading of Fasl files is implemented in
-      xdump/faslenv.lisp, level-0/nfasload.lisp, and lib/nfcomp.lisp.
-      The information here is only an overview, which might help when
-      reading the source.</para>
-      <para>The OpenMCL Fasl format is forked from the old MCL Fasl
-      format; there are a few differences, but they are minor.  The
-      name "nfasload" comes from the fact that this is the so-called
-      "new" Fasl system, which was true in 1986 or so.  The format has
-      held up well, although it would certainly need extensions to
-      deal with 64-bit data, and some other modernization might be
-      possible.</para>
-      <para>A Fasl file begins with a "file header", which contains
-      version information and a count of the following "blocks".
-      There's typically only one "block" per Fasl file.  The blocks
-      are part of a mechanism for combining multiple logical files
-      into a single physical file, in order to simplify the
-      distribution of precompiled programs.  (Nobody seems to be doing
-      anything interesting with this feature, at the moment, probably
-      because it isn't documented.)</para>
-      <para>Each block begins with a header for itself, which just
-      describes the size of the data that follows.</para>
-      <para>The data in each block is treated as a simple stream of
-      bytes, which define a bytecode program.  The actual bytecodes,
-      "fasl operators", are defined in xdump/faslenv.lisp.  The
-      descriptions in the source file are terse, but, according to
-      Gary, "probably accurate".</para>
-      <para>Some of the operators are used to create a per-block
-      "object table", which is a vector used to keep track of
-      previously-loaded objects and simplify references to them.  When
-      the table is created, an index associated with it is set to
-      zero; this is analogous to an array fill-pointer, and allows the
-      table to be treated like a stack.</para>
-      <para>The low seven bits of each bytecode are used to specify
-      the fasl operator; currently, about fifty operators are defined.
-      The high byte, when set, indicates that the result of the
-      operation should be pushed onto the object table.</para>
-      <para>Most bytecodes are followed by operands; the operand data
-      is byte-aligned.  How many operands there are, and their type,
-      depend on the bytecode.  Operands can be indices into the object
-      table, immediate values, or some combination of these.</para>
-      <para>An exception is the bytecode #xFF, which has the symbolic
-      name ccl::$faslend; it is used to mark the end of the
-      block.</para>
-    </sect1>
-
-
-
-    <sect1 id="The-Objective-C-Bridge--1-">
-      <title>The Objective-C Bridge</title>
-
-      <sect2 id="How-OpenMCL-Recognizes-Objective-C-Objects">
-	<title>How OpenMCL Recognizes Objective-C Objects</title>
-        <para>In most cases, pointers to instances of Objective-C
-        classes are recognized as such; the recognition is (and
-        probably always will be) slightly heuristic. Basically, any
-        pointer that passes basic sanity checks and whose first word
-        is a pointer to a known ObjC class is considered to be an
-        instance of that class; the Objective-C runtime system would
-        reach the same conclusion.</para>
-        <para>It's certainly possible that a random pointer to an
-        arbitrary memory address could look enough like an ObjC
-        instance to fool the lisp runtime system, and it's possible
-        that pointers could have their contents change so that
-        something that had either been a true ObjC instance (or had
-        looked a lot like one) is changed (possibly by virtue of
-        having been deallocated.)</para>
-        <para>In the first case, we can improve the heuristics
-        substantially: we can make stronger assertions that a
-        particular pointer is really "of type :ID" when it's a
-        parameter to a function declared to take such a pointer as an
-        argument or a similarly declared function result; we can be
-        more confident of something we obtained via SLOT-VALUE of a
-        slot defined to be of type :ID than if we just dug a pointer
-        out of memory somewhere.</para>
-        <para>The second case is a little more subtle: ObjC memory
-        management is based on a reference-counting scheme, and it's
-        possible for an object to ... cease to be an object while lisp
-        is still referencing it.  If we don't want to deal with this
-        possibility (and we don't), we'll basically have to ensure
-        that the object is not deallocated while lisp is still
-        thinking of it as a first-class object. There's some support
-        for this in the case of objects created with MAKE-INSTANCE,
-        but we may need to give similar treatment to foreign objects
-        that are introduced to the lisp runtime in other ways (as
-        function arguments, return values, SLOT-VALUE results, etc. as
-        well as those instances that're created under lisp
-        control.)</para>
-        <para>This doesn't all work yet (in fact, not much of it works
-        yet); in practice, this has not yet been as much of a problem
-        as anticipated, but that may be because existing Cocoa code
-        deals primarily with relatively long-lived objects such as
-        windows, views, menus, etc.</para>
-      </sect2>
-
-      <sect2>
-	<title>Recommended Reading</title>
-
-	<variablelist>
-	  <varlistentry>
-	    <term>
-	      <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink>
-	    </term>
-	    
-	   <listitem>
-	     <para>
-	       This is the top page for all of Apple's documentation on
-	       Cocoa.  If you are unfamiliar with Cocoa, it is a good
-	       place to start.
-	     </para>
-	   </listitem>
-	</varlistentry>
-	<varlistentry>
-	  <term>
-	    <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink>
-	  </term>
-
-	  <listitem>
-	    <para>
-	      This is one of the two most important Cocoa references; it
-	      covers all of the basics, except for GUI programming.  This is
-	      a reference, not a tutorial.
-	    </para>
-	  </listitem>
-	</varlistentry>
-      </variablelist>
-      </sect2>
-    </sect1>
-  </chapter>
-
-
-  <chapter id="Modifying-OpenMCL">
-    <title>Modifying OpenMCL</title>
-
-    <sect1 id="Contributing-Code-Back-to-the-OpenMCL-Project">
-      <title>Contributing Code Back to the OpenMCL Project</title>
-      <para>This section is a placeholder, added as of August 2004.  The
-      full text is being written, and will be added as soon as it is
-      available.</para>
-    </sect1>
-
-    <sect1 id="Using-OpenMCL-in--development--and-in--user--mode">
-      <title>Using OpenMCL in "development" and in  "user" mode</title>
-
-      <para>As it's distributed, OpenMCL starts up with *PACKAGE* set
-      to the CL-USER package and with most predefined functions and
-      methods protected against accidental redefinition.  The package
-      setting is of course a requirement of ANSI CL, while the
-      protection protection is intended to catch certain types of
-      programming errors (accidentally redefining a CL or CCL
-      function) before those errors have a chance to do much
-      damage.</para>
-      <para>These settings may make using OpenMCL to develop OpenMCL a
-      bit more awkward, since much of that process assumes that the
-      CCL package is current (and a primary purpose of that process is
-      to redefine some "predefined, builtin functions".) The standard,
-      "routine" ways of building OpenMCL from sources (see ) -
-      COMPILE-CCL, XCOMPILE-CCL, and XLOAD-LEVEL-0 - bind *PACKAGE* to
-      the "CCL" package and enable the redefinition of predefined
-      functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and
-      XLOAD-LEVEL-0 are additionally now exported from the "CCL"
-      package.</para>
-      <para>Some other (more ad-hoc) ways of doing development on
-      OpenMCL - compiling and/or loading individual files,
-      incrementally redefining individual functions - may be awkward
-      unless one reverts to the mode of operation which was
-      traditionally offered in OpenMCL. (Some OpenMCL source files -
-      especially those that comprise the bootstrapping image sources
-      and the first few files in the "cold load" sequence - are
-      compiled and loaded in the "CCL" package but don't contain
-      (IN-PACKAGE "CCL") forms, since IN-PACKAGE doesn't work until
-      later in the cold load sequence.)</para>
-      <para>The somewhat bizarre behavior of both SET-USER-ENVIRONMENT
-      and SET-DEVELOPMENT-ENVIRONMENT with respect to the special
-      variables they affect is intended to allow those constructs to
-      take effect when the read-eval-print loop next returns to a
-      top-level '? ' prompt; the constructs can meaningfully be used
-      inside LOAD, for instance (recall that LOAD binds *PACKAGE*),
-      though using both constructs within the same LOAD call would
-      likely be pretty confusing.</para>
-      <para>"user" and "development" are otherwise very generic terms;
-      here they're intended to enforce the distinction between "using"
-      OpenMCL and "developing" it.</para>
-      <para>The initial environment from which OpenMCL images are
-      saved is one where (SET-USER-ENVIRONMENT T) has just been
-      called; in previous versions, it was effectively as if
-      (SET-DEVELOPMENT-ENVIRONMENT T) had just been called.</para>
-      <para>Hopefully, most users of OpenMCL can safely ignore these
-      issues most of the time. Note that doing (SET-USER-ENVIRONMENT
-      T) after loading one's own code (or 3rd-party code) into OpenMCL
-      would protect that code (as well as OpenMCL's) from accidental
-      redefinition; that may be useful in some cases.</para>
-    </sect1>
-
-    <sect1 id="Debugging-facilities-in-the-lisp-kernel">
-      <title>Debugging facilities in the lisp kernel</title>
-      <para> In a perfect world, something like this couldn't
-      happen:</para>
-      <programlisting>
-Welcome to OpenMCL Version x.y!
-? (defun foo (x)
-    (declare (cons x))
-    (cdr x))
-FOO
-
-? (foo -1) ;Oops. Too late ...
-Unhandled exception 11 at 0x300e90c8, context->regs at #x7ffff6b8
-Continue/Debugger/eXit &lt;enter&gt;?
-</programlisting>
-      <para>As you may have noticed, it's not a perfect world; it's rare
-that the cause (attempting to reference the CDR of -1, and therefore
-accessing unmapped memory near location 0) of this effect (an
-"Unhandled exception ..." message) is so obvious.</para>
-      <para>The addresses printed in the message above aren't very useful
-unless you're debugging the kernel with GDB (and they're often
-very useful if you are.)</para>
-      <para>Aside from causing an exception that the lisp kernel doesn't
-know how to handle, one can also enter the kernel debugger (more)
-deliberately:</para>
-      <programlisting>
-? (defun classify (n)
-     (cond ((&gt; n 0) "Greater")
-           ((&lt; n 0) "Less")
-           (t
-            ;;; Sheesh ! What else could it be ?
-            (ccl::bug "I give up. How could this happen ?"))))
-CLASSIFY
-
-? (classify 0)
-Bug in OpenMCL system code:
-I give up. How could this happen ?
-? for help
-[12345] OpenMCL kernel debugger:
-      </programlisting>
-      <para>CCL::BUG isn't quite the right tool for this example (a
-      call to BREAK or PRINT might do a better job of clearing up the
-      mystery), but it's sometimes helpful when those other tools
-      can't be used.  The lisp error system notices, for instance, if
-      attempts to signal errors themselves cause errors to be
-      signaled; this sort of thing can happen if CLOS or the I/O
-      system are broken or missing. After some small number of
-      recursive errors, the error system gives up and calls
-      CCL::BUG.</para>
-      <para>If one enters a '?' at the kernel debugger prompt, one
-      will see output like:</para>
-      <programlisting>
-(S)  Find and describe symbol matching specified name
-(B)  Show backtrace
-(X)  Exit from this debugger, asserting that any exception was handled
-(K)  Kill OpenMCL process
-(?)  Show this help
-</programlisting>
-      <para>CCL::BUG just does an FF-CALL into the lisp kernel.  If
-      the kernel debugger was invoked because of an unhandled
-      exception (such as an illegal memory reference) the OS kernel
-      saves the machine state ("context") in a data structure for us,
-      and in that case some additional options can be used to display
-      the contents of the registers at the point of the
-      exception. Another function - CCL::DBG - causes a special
-      exception to be generated and enters the lisp kernel debugger
-      with a non-null "context":</para>
-      <programlisting>
-? (defun classify2 (n)
-  (cond ((&gt; n 0) "Greater")
-        ((&lt; n 0) "Less")
-        (t (dbg n))))
-CLASSIFY2
-
-? (classify2 0)
-Lisp Breakpoint
- While executing: #&lt;Function CLASSIFY2 #x08476cfe>
-? for help
-[12345] OpenMCL kernel debugger: ?
-(G)  Set specified GPR to new value
-(A)  Advance the program counter by one instruction (use with caution!)
-(D)  Describe the current exception in greater detail
-(R)  Show raw GPR/SPR register values
-(L)  Show Lisp values of tagged registers
-(F)  Show FPU registers
-(S)  Find and describe symbol matching specified name
-(B)  Show backtrace
-(X)  Exit from this debugger, asserting that any exception was handled
-(P)  Propagate the exception to another handler (debugger or OS)
-(K)  Kill OpenMCL process
-(?)  Show this help
-</programlisting>
-      <para>CCL::DBG takes an argument, whose value is copied into the register
-that OpenMCL uses to return a function's primary value (arg_z, which
-is r23 on the PowerPC). If we were to choose the (L) option at this point,
-we'd see a dislay like:</para>
-      <programlisting>rnil = 0x01836015
-nargs = 0
-r16 (fn) = #&lt;Function CLASSIFY2 #x30379386>
-r23 (arg_z) = 0
-r22 (arg_y) = 0
-r21 (arg_x) = 0
-r20 (temp0) = #&lt;26-element vector subtag = 2F @#x303793ee>
-r19 (temp1/next_method_context) = 6393788
-r18 (temp2/nfn) = #&lt;Function CLASSIFY2 #x30379386>
-r17 (temp3/fname) = CLASSIFY2
-r31 (save0) = 0
-r30 (save1) = *TERMINAL-IO*
-r29 (save2) = 0
-r28 (save3) = (#&lt;RESTART @#x01867f2e> #&lt;RESTART @#x01867f56>)
-r27 (save4) = ()
-r26 (save5) = ()
-r25 (save6) = ()
-r24 (save7) = ()
-</programlisting>
-      <para>From this we can conclude that the problematic argument to CLASSIFY2
-was 0 (see r23/arg_z), and that I need to work on a better example.</para>
-      <para>The R option shows the values of the ALU (and PPC branch unit)
-registers in hex; the F option shows the values of the FPU registers.</para>
-      <para>The (B) option shows a raw stack backtrace; it'll try to
-identify foreign functions as well as lisp functions. (Foreign function
-names are guesses based on the nearest preceding exported symbol.)</para>
-      <para>If you ever unexpectedly find yourself in the "lisp kernel
-debugger", the output of the (L) and (B) options are often the most
-helpful things to include in a bug report.</para>
-    </sect1>
-
-    <sect1 id="Using-AltiVec-in-OpenMCL-LAP-functions">
-      <title>Using AltiVec in OpenMCL LAP functions</title>
-
-      <sect2 id="Overview--16-">
-	<title>Overview</title>
-        <para>It's now possible to use AltiVec instructions in PPC LAP
-        (assembler) functions.</para>
-        <para>The lisp kernel detects the presence or absence of
-        AltiVec and preserves AltiVec state on lisp thread switch and
-        in response to exceptions, but the implementation doesn't
-        otherwise use vector operations.</para>
-        <para>This document doesn't document PPC LAP programming in
-        general.  Ideally, there would be some document that
-        did.</para>
-        <para>This document does explain AltiVec register-usage
-        conventions in OpenMCL and explains the use of some lap macros
-        that help to enforce those conventions.</para>
-        <para>All of the global symbols described below are exported
-        from the CCL package. Note that lap macro names, ppc
-        instruction names, and (in most cases) register names are
-        treated as strings, so this only applies to functions and
-        global variable names.</para>
-        <para>Much of the OpenMCL support for AltiVec LAP programming
-        is based on work contributed to MCL by Shannon Spires.</para>
-      </sect2>
-
-      <sect2 id="Register-usage-conventions">
-	<title>Register usage conventions</title>
-        <para>OpenMCL LAP functions that use AltiVec instructions must
-        interoperate with each other and with C functions; that
-        suggests that they follow C AltiVec register usage
-        conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return
-        value, vr14-vr19 temporaries, vr20-vr31 callee-save
-        non-volatile registers.)</para>
-        <para>The EABI (Embedded Application Binary Interface) used in
-        LinuxPPC doesn't ascribe particular significance to the vrsave
-        special-purpose register; on other platforms (notably MacOS),
-        it's used as a bitmap which indicates to system-level code
-        which vector registers contain meaningful values.</para>
-        <para>The WITH-ALTIVEC-REGISTERS lapmacro generates code which
-        which saves, updates, and restores VRSAVE on platforms where
-        this is required (as indicated by the value of the special
-        variable which controls this) and ignores VRSAVE on platforms
-        that don't require it to be maintained.</para>
-        <para>On all PPC platforms, it's necessary to save any non-volatile
-vector registers (vr20 .. vr31) before assigning to them and to restore
-such registers before returning to the caller.</para>
-        <para>On platforms that require that VRSAVE be maintained, it's not
-necessary to mention the "use" of vector registers that're
-used as incoming parameters. It's not incorrect to mention their use
-in a WITH-ALTIVEC-REGISTERS form, but it may be unneccessary in many
-interesting cases. One can likewise assume that the caller of any function
-that returns a vector value (in vr2 has already set the apropriate bit in
-VRSAVE to indicate that this register is live. One could therefore write a
-leaf function that added the bytes in vr3 and vr2 and returned the result
-in vr2 as:</para>
-        <programlisting>
-(defppclapfunction vaddubs ((y vr3) (z vr2))
-  (vaddubs z y z)
-  (blr))
-</programlisting>
-        <para>When vector registers that aren't incoming parameters are used
-in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE
-and of saving/restoring any non-volatile vector registers:</para>
-        <programlisting>
-(defppclapfunction load-array ((n arg_z))
-  (check-nargs 1)
-  (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0
-    (li imm0 arch::misc-data-offset)
-    (lvx vr1 arg_z imm0) ; load MSQ
-    (lvsl vr27 arg_z imm0) ; set the permute vector
-    (addi imm0 imm0 16) ; address of LSQ
-    (lvx vr2 arg_z imm0) ; load LSQ
-    (vperm vr3 vr1 vr2 vr27) ; aligned result appears in VR3
-    (dbg t)) ; Look at result in some debugger
-  (blr))
-</programlisting>
-        <para>AltiVec registers are not preserved by CATCH and UNWIND-PROTECT.
-Since AltiVec is only accessible from LAP in OpenMCL and since LAP
-functions rarely use high- level control structures, this should rarely be
-a problem in practice.</para>
-        <para>LAP functions which use non-volatile vector registers and which call
-(Lisp ?) code which may use CATCH or UNWIND-PROTECT should save those
-vector registers before such a call and restore them on return. This is
-one of the intended uses of the WITH-VECTOR-BUFFER lap macro.</para>
-      </sect2>
-    </sect1>
-
-    <sect1 id="Development-Mode-Dictionary">
-      <title>Development-Mode Dictionary</title>
-
-      <refentry id="v_warn-if-redefine-kernel">
-	<indexterm zone="v_warn-if-redefine-kernel">
-	  <primary>*warn-if-redefine-kernel</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*WARN-IF-REDEFINE-KERNEL*</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>When true, attempts to redefine (via DEFUN or DEFMETHOD)
-	  functions and methods that are marked as being
-	  &#34;predefined&#34; signal continuable errors.</para>
-
-	  <para>Note that these are CERRORs, not warnings, and that
-	  no lisp functions or methods have been defined in the kernel
-	  in MCL or OpenMCL since 1987 or so.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_set-development-environment">
-	<indexterm zone="f_set-development-environment">
-	  <primary>set-development-environment</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>SET-DEVELOPMENT-ENVIRONMENT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>set-development-environment</function>
-	  &optional;
-	  unmark-builtin-functions</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Arranges that the outermost special bindings of *PACKAGE*
-	  and *WARN-IF-REDEFINE-KERNEL* restore values of the &#34;CCL&#34;
-	  package and NIL to these variables, respectively. If the optional
-	  argument is true, marks all globally defined functions and methods
-	  as being &#34;not predefined&#34; (this is a fairly expensive
-	  operation.)</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_set-user-environment">
-	<indexterm zone="f_set-user-environment">
-	  <primary>set-user-environment</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>SET-USER-ENVIRONMENT</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>set-user-environment</function>
-	  &optional; mark-builtin-functions</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Arranges that the outermost special bindings of *PACKAGE*
-	  and *WARN-IF-REDEFINE-KERNEL* restore values of the
-	  &#34;CL-USER&#34; package and T to these variables, respectively.
-	  If the optional argument is true, marks all globally defined
-	  functions and methods as being &#34;predefined&#34; (this is a
-	  fairly expensive operation.)</para>
-	</refsect1>
-      </refentry>
-      <refentry id="v_altivec-available">
-	<indexterm zone="v_altivec-available">
-	  <primary>*altivec-available*</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*ALTIVEC-AVAILABLE*</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-
-	<refsect1>
-	  <title>Description</title>
-	  <para>This variable is intitialized each time an OpenMCL session
-	  starts based on information provided by the lisp kernel. Its value
-	  is true if AltiVec is present and false otherwise. This variable
-	  shouldn't be set by user code.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="f_altivec-available-p">
-	<indexterm zone="f_altivec-available-p">
-	  <primary>altivec-available-p</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>ALTIVEC-AVAILABLE-P</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Function</refclass>
-	</refnamediv>
-	
-	<refsynopsisdiv>
-	  <synopsis><function>altivec-available-p</function></synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Returns non-NIL if AltiVec is available.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="v_altivec-lapmacros-maintain-vrsave-p">
-	<indexterm zone="v_altivec-lapmacros-maintain-vrsave-p">
-	  <primary>*altivec-lapmacros-maintain-vrsave-p*</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>Variable</refclass>
-	</refnamediv>
-	
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Intended to control the expansion of certain lap macros.
-	  Initialized to NIL on LinuxPPC; initialized to T on platforms
-	  (such as MacOS X/Darwin) that require that the VRSAVE SPR contain
-	  a bitmask of active vector registers at all times.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="lapm_with-altivec-registers">
-	<indexterm zone="lapm_with-altivec-registers">
-	  <primary>with-altivec-registers</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-ALTIVEC-REGISTERS</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>LAP Macro</refclass>
-	</refnamediv>
-
-	<refsynopsisdiv>
-	  <synopsis><function>with-altivec-registers</function>
-	  reglist &body; body</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>reglist</term>
-
-	      <listitem>
-		<para>A list of vector register names (vr0 .. vr31).</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>body</term>
-
-	      <listitem>
-		<para>A sequence of PPC LAP instructions.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-
-	  <para>Specifies the set of AltiVec registers used in body. If
-	  *altivec-lapmacros-maintain-vrsave-p* is true when the macro is
-	  expanded, generates code to save the VRSAVE SPR and updates VRSAVE
-	  to incude a bitmask generated from the specified register list.
-	  Generates code which saves any non-volatile vector registers which
-	  appear in the register list, executes body, and restores the saved
-	  non-volatile vector registers (and, if
-	  *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as
-	  well. Uses the IMM0 register (r3) as a temporary.</para>
-	</refsect1>
-      </refentry>
-
-      <refentry id="lapm_with-vector-buffer">
-	<indexterm zone="lapm_with-vector-buffer">
-	  <primary>with-vector-buffer</primary>
-	</indexterm>
-
-	<refnamediv>
-	  <refname>WITH-VECTOR-BUFFER</refname>
-	  <refpurpose></refpurpose>
-	  <refclass>LAP Macro</refclass>
-	</refnamediv>
-	
-	<refsynopsisdiv>
-	  <synopsis>with-vector-buffer base n &body; body</synopsis>
-	</refsynopsisdiv>
-
-	<refsect1>
-	  <title>Arguments and Values</title>
-
-	  <variablelist>
-	    <varlistentry>
-	      <term>base</term>
-
-	      <listitem>
-		<para>Any available general-purpose register.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>n</term>
-
-	      <listitem>
-		<para>An integer between 1 and 254, inclusive. (Should
-		typically be much, much closer to 1.) Specifies the size of
-		the buffer, in 16-byte units.</para>
-	      </listitem>
-	    </varlistentry>
-
-	    <varlistentry>
-	      <term>body</term>
-
-	      <listitem>
-		<para>A sequence of PPC LAP instructions.</para>
-	      </listitem>
-	    </varlistentry>
-	  </variablelist>
-	</refsect1>
-
-	<refsect1>
-	  <title>Description</title>
-	  <para>Generates code which allocates a 16-byte aligned buffer
-	  large enough to contain N vector registers; the GPR base points to
-	  the lowest address of this buffer. After processing body, the
-	  buffer will be deallocated. The body should preserve the value of
-	  base as long as it needs to reference the buffer. It's
-	  intended that base be used as a base register in stvx and lvx
-	  instructions within the body.</para>
-	</refsect1>
-      </refentry>
-    </sect1>
-  </chapter>
-  <index id="Symbol-Index"><title>Symbol Index</title></index>
-</book>
