<?xml version="1.0" encoding="UTF-8"?>

<part id="extensions"><title>Extensions</title>

<chapter id="p-indep">
 <title>Extensions-1: Platform independent Extensions</title>

<section id="image"><title>Extensions-1.1. Saving an Image</title>

<para>The function
  <literal role="sexp">(<function>ext:saveinitmem</function>
    &optional-amp; (&filename-r; "lispinit.mem")
    &key-amp; :quiet :init-function :locked-packages)</literal>
saves the running &clisp;'s memory to the file &filename-r;;
extension &mem-file; is recommended.
If the <constant>:quiet</constant> argument is not &nil;, the startup
banner and the good-bye message will be suppressed.
The <constant>:init-function</constant> argument specifies a function
that will be executed at startup of the saved image.
When &filename-r; does not have an extension,
&mem-file; extension is automatically used.
The <constant>:locked-packages</constant> argument specifies the
packages to lock before saving the image; this is convenient for
application delivery, when you do not want your user to mess up your
product.  This argument defaults to &sys-pack-list;.
The starting package of the new image is the one in which you were when
you invoked <function>ext:saveinitmem</function>.</para>

</section>

<section id="quit"><title>Extensions-1.2. Quitting &clisp;</title>

<para>The functions <literal role="sexp">(<function>ext:exit</function>
 [<replaceable>errorp</replaceable>])</literal>, <literal
 role="sexp">(<function>ext:quit</function>
 [<replaceable>errorp</replaceable>])</literal> and <literal
 role="sexp">(<function>ext:bye</function>
 [<replaceable>errorp</replaceable>])</literal> - all synonymous -
 terminate &clisp;.  If <replaceable>errorp</replaceable> is non-&nil;,
 &clisp; aborts with error status, i.e., the environment is informed
 that the &clisp; session did not succeed.</para>

</section>

<section id="i18n"><title>Extensions-1.3. Internationalization</title>

<para>Internationalization means to prepare a program so that it can
use multiple national languages and national cultural conventions
without requiring further source code changes.  Localization means
providing the data - mostly textual translations - necessary for an
internationalized program to work in a particular language and with
particular cultural conventions.</para>

<para>&clisp; is internationalized, and is localized for the languages
English, German, French, Spanish and Dutch.
&clisp; also supports internationalized Lisp programs, through
&ggettext;.</para>

<section id="ggettext"><title>The &ggettext;</title>

<para>&ggettext; is a set of functions, included in &clisp; or the
&c-lang; library, which permit looking up translations of strings
through message catalogs. It is also a set of tools which makes the
translation maintenance easy for the translator and the program
maintainer.</para>

<para>The &ggettext; functions are available in &clisp; in the
&i18n-pac; package, which is &re-export;ed from the &ext-pac;
package.</para>

<variablelist>
 <varlistentry id="gettext"><term><literal role="sexp">(&gettext;
  &msgid; &optional-amp; &domain; &category;)</literal></term>
  <listitem><simpara>returns the translation of the message &msgid;,
  in the given &domain;, depending on the given &category;.
  &msgid; should be an ASCII string, and is normally the English message.
  </simpara></listitem></varlistentry>
 <varlistentry id="ngettext"><term><literal role="sexp">(&ngettext;
  &msgid; <replaceable>msgid_plural</replaceable>
  &n-r; &optional-amp; &domain; &category;)</literal></term>
  <listitem><simpara>returns the plural form of the translation for of
   &msgid; and &n-r; in the given &domain;, depending on the given
   &category;.  &msgid; and <replaceable>msgid_plural</replaceable>
   should be ASCII strings, and are normally the English singular and
   English plural variant of the message, respectively.
   </simpara></listitem></varlistentry>
</variablelist>

<section id="domain"><title>Domain</title>
 <para>The &domain; is a string identifier denoting the program that
is requesting the translation.  The pathname of the message catalog
depends on the &domain;: usually it is located at
<filename>TEXTDOMAINDIR/l/LC_MESSAGES/domain.mo</filename>, where
&l-r; is the ISO 639 code of the language.
The notion of &domain; allows several Lisp programs running in the same
image to request translations independently of each other.</para>

<para id="textdomain"><literal role="sexp">(&textdomain;)</literal> is a
place that returns the default &domain;, used when no &domain;
argument is passed to the &gettext; and &ngettext; functions.
It is &setf;able.
<literal role="sexp">(&setf; &textdomain;)</literal> is usually used
during the startup phase of a program.
Note that the default &domain; is not saved in a &mem-image;.
The use of <literal role="sexp">(&setf; &textdomain;)</literal> is
recommended only for programs that are so simple that they will never
need more than one &domain;.</para>

<para id="textdomaindir"><literal role="sexp">(&textdomaindir;
&domain;)</literal> is a place that returns the base
directory, called <filename>TEXTDOMAINDIR</filename> above, where the
message catalogs for the given &domain; are assumed to be installed.
It is &setf;able.
<literal role="sexp">(&setf; &textdomaindir;)</literal> is usually used
during the startup phase of a program, and should be used because only
the program knows where its message catalogs are installed.
Note that the <filename>TEXTDOMAINDIR</filename>s
are not saved in a &mem-image;.</para>

</section>

<section id="category"><title>Category</title>
<para>The &category; argument of the &gettext; and &ngettext;
functions denotes which locale facet the result should depend on.
The default value is <constant>:LC_MESSAGES</constant>.
Other possible values are <constant>:LC_CTYPE</constant>,
<constant>:LC_TIME</constant>, <constant>:LC_COLLATE</constant>,
<constant>:LC_MONETARY</constant>.
The use of these values is useful for users who have a
character/time/collation/money handling set differently from the usual
message handling.
Note that when a &category; argument is used, the message catalog
location depends on the &category;: it will be expected at
<filename>TEXTDOMAINDIR/ll/category/domain.mo</filename>.</para>
</section>

<section id="i18n-example"><title>Example</title>

<para>A non-internationalized program simulating a restaurant dialogue
might look as follows.</para>

<example><title>prog.lisp</title>
<programlisting>
(setq n (parse-integer (first *args*)))

(format t "~A~%" "'Your command, please?', asked the waiter.")

(format t "~@?~%"
          (if (= n 1) "a piece of cake" "~D pieces of cake")
          n)
</programlisting></example>

<para>After being internationalized, all strings are wrapped in
&gettext; calls, and &ngettext; is used for plurals.
Also, &textdomaindir; is assigned a value; in our case, for simplicity,
the current directory.</para>

<example><title>prog.lisp</title>
<programlisting>
(setf (textdomain) "prog")
(setf (textdomaindir "prog") "./")

(setq n (parse-integer (first *args*)))

(format t "~A~%"
          (gettext "'Your command, please?', asked the waiter."))

(format t "~@?~%"
          (ngettext "a piece of cake" "~D pieces of cake" n)
          n)
</programlisting></example>

<para>For ease of reading, it is customary to define an abbreviation
for the &gettext; function.  An underscore is customary.</para>

<example><title>prog.lisp</title>
<programlisting>
(setf (textdomaindir "prog") "./")
(defun _ (msgid) (gettext msgid "prog"))

(setq n (parse-integer (first *args*)))

(format t "~A~%"
          (_"'Your command, please?', asked the waiter."))

(format t "~@?~%"
          (ngettext "a piece of cake" "~D pieces of cake" n "prog")
          n)
</programlisting></example>

<para>Now the program's maintainer creates a message catalog template
through the command

<screen>
bash$ xgettext -o prog.pot prog.lisp
</screen>

Note: xgettext version 0.11 or higher is required here.</para>

<para>The message catalog template looks roughly like this.</para>

<example><title>prog.pot</title>
<programlisting>
msgid "'Your command, please?', asked the waiter."
msgstr ""

msgid "a piece of cake"
msgid_plural "%d pieces of cake"
msgstr[0] ""
msgstr[1] ""
</programlisting></example>

<para>Then a French translator creates a French message catalog</para>

<example><title>prog.fr.po</title>
<programlisting>
msgid ""
msgstr ""
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

msgid "'Your command, please?', asked the waiter."
msgstr "&laquo;Votre commande, s'il vous plait&raquo;, dit le gar&ccedil;on."

# Les gateaux allemands sont les meilleurs du monde.
msgid "a piece of cake"
msgid_plural "%d pieces of cake"
msgstr[0] "un morceau de gateau"
msgstr[1] "%d morceaux de gateau"
</programlisting></example>

<para>and sends it to the program's maintainer.</para>

<para>The program's maintainer compiles the catalog as follows:

<screen>
bash$ mkdir -p ./fr/LC_MESSAGES
bash$ msgfmt -o ./fr/LC_MESSAGES/prog.mo prog.fr.po
</screen></para>

<para>When a user in a french locale then runs the program

<screen>
bash$ clisp prog.lisp 2
</screen>

she will get the output

<screen>
    &laquo;Votre commande, s'il vous plait&raquo;, dit le gar&ccedil;on.
    2 morceaux de gateau
</screen>
</para>

</section>

</section>

<section id="language"><title>The Language</title>

<para>Warning: The facilities described in this section will work
only for the languages for which &clisp; itself is already
localized.</para>

<para>The language &clisp; uses to communicate with the user can be one of
<simplelist columns="1">
 <member><constant>ENGLISH</constant></member>
 <member><constant>DEUTSCH</constant> (i.e., German)</member>
 <member><constant>FRAN&Ccedil;AIS</constant> (i.e., French)</member>
 <member><constant>ESPA&Ntilde;OL</constant> (i.e., Spanish)</member>
 <member><constant>NEDERLANDS</constant> (i.e. Dutch)</member>
</simplelist></para>

<para>This is controlled by the &symbol-macro; <emphasis
 role="strong"><varname>CUSTOM:*CURRENT-LANGUAGE*</varname></emphasis>,
 which can be set at run time as well as using <ulink
 url="clisp.html#opt-lang"><option>-L</option></ulink> start-up option.
 If you wish to change the <ulink url="clisp.html#opt-locale">locale
 directory</ulink> at run time too, you can do that by
 setting <varname>CUSTOM:*CURRENT-LANGUAGE*</varname> to a cons cell,
 whose &car; is the language (a symbol, one of the above), and whose
 &cdr; is the new locale directory.</para>

<para>More languages can be defined through the macro <emphasis
 role="strong"><function>I18N:DEFLANGUAGE</function></emphasis>:
 <literal role="sexp">(<function>I18N:DEFLANGUAGE</function>
 <replaceable>lang</replaceable>)</literal>.  For such an additional
 language to take effect, you must install the corresponding message
 catalog, or translate the messages yourself, using &ggettext; and
 &emacs; (or &xemacs;) po-mode.</para>

<para>This works only for strings.  For arbitrary language-dependent
 Lisp objects, you define one through the macro <emphasis
 role="strong"><function>I18N:DEFINTERNATIONAL</function></emphasis>:
 <literal role="sexp">(<function>I18N:DEFINTERNATIONAL</function>
 &symbol-r; &optional-amp;
 (<replaceable>default-language</replaceable> &t;))</literal> and add
 language-dependent values through the macro <emphasis
 role="strong"><function>I18N:DEFLOCALIZED</function></emphasis>:
 <literal role="sexp">(<function>I18N:DEFLOCALIZED</function>
 &symbol-r; &lang-r; <replaceable>value-form</replaceable>)</literal></para>

<para>(One such form for each language.  Languages without an assigned
 value will be treated like the default-language.)  You can then access
 the localized value by calling <emphasis
 role="strong"><function>I18N:LOCALIZED</function></emphasis>: <literal
 role="sexp">(<function>I18N:LOCALIZED</function>
 &symbol-r; &optional-amp; &lang-r;)</literal></para>

</section>

</section>

<section id="encoding"><title>Extensions-1.4. Encodings</title>

<section id="encodings-intro"><title>Introduction</title>

<para>An <emphasis>encoding</emphasis> describes the correspondence
 between &character-class;s and raw bytes during input/output via
 &stream-class;s with &stream-element-type; &character-class;.</para>

<para>An &encoding; is an object composed of the following facets:
<variablelist>
 <varlistentry><term><link linkend="charset">character set</link></term>
  <listitem><simpara>This denotes both the set of characters that
   can be represented and passed through the I/O channel, and the way
   these characters translate into raw bytes.  In this context, for
   example, "UTF-8" and "UCS-4" are considered different, although they
   can represent the same set of characters.
  </simpara></listitem></varlistentry>
 <varlistentry><term>&line-term; mode</term>
  <listitem><simpara>This denotes the way newline characters are
   represented.</simpara></listitem></varlistentry>
</variablelist></para>

</section>

<section id="charset"><title>Character Sets</title>

<variablelist>
<!-- #ifndef UNICODE -->
<varlistentry><term>Platform dependent: Only in &clisp; built
  &without; compile-time flag &unicode;.</term>
<listitem><simpara>Only one character set is understood: the platform's
 native (8-bit) character set.  See <link linkend="characters">Chapter
 13</link>.</simpara></listitem></varlistentry>
<!-- #else -->
<varlistentry id="charset-symbols"><term>Platform dependent:
  Only in &clisp; built &with; compile-time flag &unicode;.</term>
<listitem><para>The following character sets are supported, as values
 of the corresponding (constant) symbol in the &charset-pac; package:
<itemizedlist id="charset-symbol-list">
  <listitem id="charset-UCS-2"><simpara><literal>UCS-2</literal>
   = <literal>UNICODE-16</literal> = <literal>UNICODE-16-BIG-ENDIAN</literal>,
   the 16-bit &unicode; character set. Every character is represented
   as two bytes.</simpara></listitem>
  <listitem id="charset-UNICODE-16-LITTLE-ENDIAN"><simpara><literal>UNICODE-16-LITTLE-ENDIAN</literal>
    </simpara></listitem>
  <listitem id="charset-UCS-4"><simpara><literal>UCS-4</literal>
   = <literal>UNICODE-32</literal> = <literal>UNICODE-32-BIG-ENDIAN</literal>,
   the 32-bit &unicode; character set. Every character is represented as
   four bytes. Note that &clisp; understands only those characters which
   are already contained in the 16-bit &unicode; character set.
   </simpara></listitem>
  <listitem id="charset-UNICODE-32-LITTLE-ENDIAN"><simpara><literal>UNICODE-32-LITTLE-ENDIAN</literal>
    </simpara></listitem>
  <listitem id="charset-UTF-8"><simpara><literal>UTF-8</literal>,
      the 16-bit &unicode; character set. Every character is represented
      as one to three bytes. ASCII characters represent themselves and need
      one byte per character. Most Latin/Greek/Cyrillic/Hebrew characters
      need two bytes per character, and the remaining characters need three
      bytes per character. This is therefore, in general, the most
      space-efficient encoding of all of Unicode-16.
    </simpara></listitem>
<!-- #ifdef GNU_LIBICONV -->
  <listitem id="charset-UTF-16"><simpara><literal>UTF-16</literal>,
      the 16-bit &unicode; character set. Every character is represented
      as two bytes.</simpara></listitem>
  <listitem id="charset-UTF-7"><simpara><literal>UTF-7</literal>,
      the 16-bit &unicode; character set. This is a stateful 7-bit encoding.
      Not all ASCII characters represent themselves.
    </simpara></listitem>
<!-- #endif /* GNU_LIBICONV */ -->
  <listitem id="charset-JAVA"><simpara><literal>JAVA</literal>,
      the 16-bit &unicode; character set.
      ASCII characters represent themselves and need one byte per character.
      All other characters are represented
      by <literal>\u<replaceable>nnnn</replaceable></literal> sequences
      (<replaceable>nnnn</replaceable> a hexadecimal number)
      and need 6 bytes per character. While this encoding is very comfortable
      for editing Unicode files using only ASCII aware tools and editors, it
      cannot faithfully represent all &unicode; text. Only text which
      does not contain <literal>\u</literal> (backslash followed by
      lowercase Latin u) can be faithfully represented by this encoding.
    </simpara></listitem>
  <listitem id="charset-ASCII"><simpara><literal>ASCII</literal>,
      the well-known US-centric 7-bit character set (American Standard
      Code for Information Interchange).
    </simpara></listitem>
  <listitem id="charset-ISO-8859-1"><simpara><literal>ISO-8859-1</literal>,
      an extension of the ASCII character set, suitable for the
      Afrikaans, Albanian, Basque, Breton, Catalan, Cornish, Danish, Dutch,
      English, Faeroese, Finnish, French, Frisian, Galician, German,
      Greenlandic, Icelandic, Irish, Italian, Latin, Luxemburgish, Norwegian,
      Portuguese, Raeto-Romanic, Scottish, Spanish, and Swedish languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-2"><simpara><literal>ISO-8859-2</literal>,
      an extension of the ASCII character set, suitable for the Croatian,
      Czech, German, Hungarian, Polish, Slovak, Slovenian, and Sorbian
      languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-3"><simpara><literal>ISO-8859-3</literal>,
      an extension of the ASCII character set, suitable for the
      Esperanto and Maltese languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-4"><simpara><literal>ISO-8859-4</literal>,
      an extension of the ASCII character set, suitable for the
      Estonian, Latvian, Lithuanian and Sami (Lappish) languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-5"><simpara><literal>ISO-8859-5</literal>,
      an extension of the ASCII character set, suitable for the Bulgarian,
      Byelorussian, Macedonian, Russian, Serbian, and Ukrainian languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-6"><simpara><literal>ISO-8859-6</literal>,
      suitable for the Arabic language.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-7"><simpara><literal>ISO-8859-7</literal>,
      an extension of the ASCII character set, suitable for the Greek
      language.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-8"><simpara><literal>ISO-8859-8</literal>,
      an extension of the ASCII character set, suitable for the Hebrew
      language (without punctuation).
    </simpara></listitem>
  <listitem id="charset-ISO-8859-9"><simpara><literal>ISO-8859-9</literal>,
      an extension of the ASCII character set, suitable for the Turkish
      language.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-10"><simpara><literal>ISO-8859-10</literal>,
      an extension of the ASCII character set, suitable for the Estonian,
      Icelandic, Inuit (Greenlandic), Latvian, Lithuanian, and Sami (Lappish)
      languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-13"><simpara><literal>ISO-8859-13</literal>,
      an extension of the ASCII character set, suitable for the Estonian,
      Latvian, Lithuanian, Polish and Sami (Lappish) languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-14"><simpara><literal>ISO-8859-14</literal>,
      an extension of the ASCII character set, suitable for Irish Gaelic,
      Manx Gaelic, Scottish Gaelic, and Welsh languages.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-15"><simpara><literal>ISO-8859-15</literal>,
      an extension of the ASCII character set, suitable for the ISO-8859-1
      languages, with improvements for French, Finnish and the Euro.
    </simpara></listitem>
  <listitem id="charset-ISO-8859-16"><simpara><literal>ISO-8859-16</literal>
      an extension of the ASCII character set, suitable for the Rumanian
      language.
    </simpara></listitem>
  <listitem id="charset-KOI8-R"><simpara><literal>KOI8-R</literal>,
      an extension of the ASCII character set,
      a popular character set for the Russian language.
    </simpara></listitem>
  <listitem id="charset-KOI8-U"><simpara><literal>KOI8-U</literal>,
      an extension of the ASCII character set,
      a popular character set for the Ukrainian language.
    </simpara></listitem>
<!-- #ifdef GNU_LIBICONV -->
  <listitem id="charset-KOI8-RU"><simpara><literal>KOI8-RU</literal>,
      an extension of the ASCII character set, suitable for Russian
      (this is the standard Russian encoding on the Internet)
    </simpara></listitem>
<!-- #endif /* GNU_LIBICONV */ -->
  <listitem><simpara><literal>JIS_X0201</literal>,
      a character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-MAC-ARABIC"><simpara><literal>MAC-ARABIC</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-CENTRAL-EUROPE"><simpara><literal>MAC-CENTRAL-EUROPE</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-CROATIAN"><simpara><literal>MAC-CROATIAN</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-CYRILLIC"><simpara><literal>MAC-CYRILLIC</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-DINGBAT"><simpara><literal>MAC-DINGBAT</literal>,
      a platform specific character set.
    </simpara></listitem>
  <listitem id="charset-MAC-GREEK"><simpara><literal>MAC-GREEK</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-HEBREW"><simpara><literal>MAC-HEBREW</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-ICELAND"><simpara><literal>MAC-ICELAND</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-ROMAN"><simpara><literal>MAC-ROMAN</literal>
   = <literal>MACINTOSH</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-ROMANIA"><simpara><literal>MAC-ROMANIA</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-SYMBOL"><simpara><literal>MAC-SYMBOL</literal>,
      a platform specific character set.
    </simpara></listitem>
  <listitem id="charset-MAC-THAI"><simpara><literal>MAC-THAI</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-TURKISH"><simpara><literal>MAC-TURKISH</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-MAC-UKRAINE"><simpara><literal>MAC-UKRAINE</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-CP437"><simpara><literal>CP437</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-CP437-IBM"><simpara><literal>CP437-IBM</literal>,
     an IBM variant of <literal>CP437</literal>.
    </simpara></listitem>
  <listitem id="charset-CP737"><simpara><literal>CP737</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Greek language.
    </simpara></listitem>
  <listitem id="charset-CP775"><simpara><literal>CP775</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for some Baltic languages.
    </simpara></listitem>
  <listitem id="charset-CP850"><simpara><literal>CP850</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-CP852"><simpara><literal>CP852</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-CP852-IBM"><simpara><literal>CP852-IBM</literal>,
   an IBM variant of <literal>CP852</literal>.
    </simpara></listitem>
  <listitem id="charset-CP855"><simpara><literal>CP855</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Russian language.
    </simpara></listitem>
  <listitem id="charset-CP857"><simpara><literal>CP857</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Turkish language.
    </simpara></listitem>
  <listitem id="charset-CP860"><simpara><literal>CP860</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Portuguese language.
    </simpara></listitem>
  <listitem id="charset-CP860-IBM"><simpara><literal>CP860-IBM</literal>,
   an IBM variant of <literal>CP860</literal>.
    </simpara></listitem>
  <listitem id="charset-CP861"><simpara><literal>CP861</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Icelandic language.
    </simpara></listitem>
  <listitem id="charset-CP861-IBM"><simpara><literal>CP861-IBM</literal>,
   an IBM variant of <literal>CP861</literal>.
    </simpara></listitem>
  <listitem id="charset-CP862"><simpara><literal>CP862</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Hebrew language.
    </simpara></listitem>
  <listitem id="charset-CP862-IBM"><simpara><literal>CP862-IBM</literal>,
   an IBM variant of <literal>CP862</literal>.
    </simpara></listitem>
  <listitem id="charset-CP863"><simpara><literal>CP863</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-CP863-IBM"><simpara><literal>CP863-IBM</literal>,
   an IBM variant of <literal>CP863</literal>.
    </simpara></listitem>
  <listitem id="charset-CP864"><simpara><literal>CP864</literal>, a DOS oldie,
      meant to be suitable for the Arabic language.
    </simpara></listitem>
  <listitem id="charset-CP864-IBM"><simpara><literal>CP864-IBM</literal>,
   an IBM variant of <literal>CP864</literal>.
    </simpara></listitem>
  <listitem id="charset-CP865"><simpara><literal>CP865</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for some Nordic languages.
    </simpara></listitem>
  <listitem id="charset-CP865-IBM"><simpara><literal>CP865-IBM</literal>,
   an IBM variant of <literal>CP865</literal>.
    </simpara></listitem>
  <listitem id="charset-CP866"><simpara><literal>CP866</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Russian language.
    </simpara></listitem>
  <listitem id="charset-CP869"><simpara><literal>CP869</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Greek language.
    </simpara></listitem>
  <listitem id="charset-CP869-IBM"><simpara><literal>CP869-IBM</literal>,
   an IBM variant of <literal>CP869</literal>.
    </simpara></listitem>
  <listitem id="charset-CP874"><simpara><literal>CP874</literal>, a DOS oldie,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Thai language.
    </simpara></listitem>
  <listitem id="charset-CP874-IBM"><simpara><literal>CP874-IBM</literal>,
   an IBM variant of <literal>CP874</literal>.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1250"><simpara><literal>WINDOWS-1250</literal>
   = <literal>CP1250</literal>,
      a platform specific extension of the ASCII character set,
      heavily incompatible with ISO-8859-2.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1251"><simpara><literal>WINDOWS-1251</literal>
   = <literal>CP1251</literal>,
      a platform specific extension of the ASCII character set,
      heavily incompatible with ISO-8859-5,
      meant to be suitable for the Russian language.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1252"><simpara><literal>WINDOWS-1252</literal>
   = <literal>CP1252</literal>,
      a platform specific extension of the ISO-8859-1 character set.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1253"><simpara><literal>WINDOWS-1253</literal>
   = <literal>CP1253</literal>,
      a platform specific extension of the ASCII character set,
      gratuitously incompatible with ISO-8859-7,
      meant to be suitable for the Greek language.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1254"><simpara><literal>WINDOWS-1254</literal>
   = <literal>CP1254</literal>,
      a platform specific extension of the ISO-8859-9 character set.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1255"><simpara><literal>WINDOWS-1255</literal>
   = <literal>CP1255</literal>,
      a platform specific extension of the ASCII character set,
      gratuitously incompatible with ISO-8859-8,
      suitable for the Hebrew language.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1256"><simpara><literal>WINDOWS-1256</literal>
   = <literal>CP1256</literal>,
      a platform specific extension of the ASCII character set,
      meant to be suitable for the Arabic language.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1257"><simpara><literal>WINDOWS-1257</literal>
   = <literal>CP1257</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-WINDOWS-1258"><simpara><literal>WINDOWS-1258</literal>
   = <literal>CP1258</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-HP-ROMAN8"><simpara><literal>HP-ROMAN8</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
  <listitem id="charset-NEXTSTEP"><simpara><literal>NEXTSTEP</literal>,
      a platform specific extension of the ASCII character set.
    </simpara></listitem>
<!-- #ifdef GNU_LIBICONV -->
  <listitem id="charset-EUC-JP"><simpara><literal>EUC-JP</literal>,
      a multibyte character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-SHIFT-JIS"><simpara><literal>SHIFT-JIS</literal>,
      a multibyte character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-CP932"><simpara><literal>CP932</literal>,
      a Microsoft variant of <literal>SHIFT-JIS</literal>.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-JP"><simpara><literal>ISO-2022-JP</literal>,
      a stateful 7-bit multibyte character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-JP-2"><simpara><literal>ISO-2022-JP-2</literal>,
      a stateful 7-bit multibyte character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-JP-1"><simpara><literal>ISO-2022-JP-1</literal>,
      a stateful 7-bit multibyte character set for the Japanese language.
    </simpara></listitem>
  <listitem id="charset-EUC-CN"><simpara><literal>EUC-CN</literal>,
      a multibyte character set for simplified Chinese.
    </simpara></listitem>
  <listitem id="charset-HZ"><simpara><literal>HZ</literal>,
      a stateful 7-bit multibyte character set for simplified Chinese.
    </simpara></listitem>
  <listitem id="charset-GBK"><simpara><literal>GBK</literal>,
      a multibyte character set for Chinese,
    </simpara></listitem>
  <listitem id="charset-CP936"><simpara><literal>CP936</literal>,
      a Microsoft variant of <literal>GBK</literal>.
    </simpara></listitem>
  <listitem id="charset-GB18030"><simpara><literal>GB18030</literal>,
      a multibyte character set for Chinese,
    </simpara></listitem>
  <listitem id="charset-EUC-TW"><simpara><literal>EUC-TW</literal>,
      a multibyte character set for traditional Chinese.
    </simpara></listitem>
  <listitem id="charset-BIG5"><simpara><literal>BIG5</literal>,
      a multibyte character set for traditional Chinese.
    </simpara></listitem>
  <listitem id="charset-CP950"><simpara><literal>CP950</literal>,
      a Microsoft variant of <literal>BIG5</literal>.
    </simpara></listitem>
  <listitem id="charset-BIG5HKSCS"><simpara><literal>BIG5HKSCS</literal>,
      a multibyte character set for traditional Chinese.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-CN"><simpara><literal>ISO-2022-CN</literal>,
      a stateful 7-bit multibyte character set for Chinese.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-CN-EXT"><simpara><literal>ISO-2022-CN-EXT</literal>,
      a stateful 7-bit multibyte character set for Chinese.
    </simpara></listitem>
  <listitem id="charset-EUC-KR"><simpara><literal>EUC-KR</literal>,
      a multibyte character set for Korean.
    </simpara></listitem>
  <listitem id="charset-CP949"><simpara><literal>CP949</literal>,
      a Microsoft variant of <literal>EUC-KR</literal>.
    </simpara></listitem>
  <listitem id="charset-ISO-2022-KR"><simpara><literal>ISO-2022-KR</literal>,
      a stateful 7-bit multibyte character set for Korean.
    </simpara></listitem>
  <listitem id="charset-ARMSCII-8"><simpara><literal>ARMSCII-8</literal>,
      an extension of the ASCII character set, suitable for Armenian.
    </simpara></listitem>
  <listitem id="charset-GEORGIAN-ACADEMY"><simpara><literal>GEORGIAN-ACADEMY</literal>,
      an extension of the ASCII character set, suitable for Georgian.
    </simpara></listitem>
  <listitem id="charset-GEORGIAN-PS"><simpara><literal>GEORGIAN-PS</literal>,
      an extension of the ASCII character set, suitable for Georgian.
    </simpara></listitem>
  <listitem id="charset-TIS-620"><simpara><literal>TIS-620</literal>,
      an extension of the ASCII character set, suitable for Thai.
    </simpara></listitem>
  <listitem id="charset-MULELAO-1"><simpara><literal>MULELAO-1</literal>,
      an extension of the ASCII character set, suitable for Laotian.
    </simpara></listitem>
  <listitem id="charset-CP1133"><simpara><literal>CP1133</literal>,
      an extension of the ASCII character set, suitable for Laotian.
    </simpara></listitem>
  <listitem id="charset-VISCII"><simpara><literal>VISCII</literal>,
      an extension of the ASCII character set, suitable for Vietnamese.
    </simpara></listitem>
  <listitem id="charset-TCVN"><simpara><literal>TCVN</literal>,
      an extension of the ASCII character set, suitable for Vietnamese.
    </simpara></listitem>
<!-- #endif /* GNU_LIBICONV */ -->
</itemizedlist>

<!-- #ifdef /* HAVE_ICONV */ -->
<variablelist>
<varlistentry id="iconv"><term>[&clisp; comes with it own implementation
   of &iconv;, so the following is more or less obsolete now.]
    (Platform dependent: Only on &unix; systems having the &c-lang;
     library function &iconv;).</term>
<listitem><simpara>The character sets provided by the library function
 &iconv; can also be used as encodings.  To create such an encoding,
 call &make-encoding; with the character set name (a string) as
 <constant>:charset</constant> argument.</simpara>

 <simpara>These encodings are not assigned to global variables, since
 there is no portable way to get the list of all character sets
 supported by &iconv;.</simpara>

 <simpara>On &gnu; systems (such as GNU/Linux and GNU/Hurd), you get
 this list by calling the <emphasis>program</emphasis>
 iconv: <command>iconv --list</command>.
 &gnu; glibc-2.1 supports in particular, among others:</simpara>

<itemizedlist id="gnu-extra-charset-list">
  <listitem id="charset-EUC-JP-gnu"><simpara><literal>EUC-JP</literal> and
  <literal>SHIFT-JIS</literal>, for the Japanese language,</simpara></listitem>
  <listitem id="charset-EUC-CN-gnu"><simpara><literal>EUC-CN</literal>,
  <literal>EUC-TW</literal>, <literal>BIG5</literal> and
  <literal>GB</literal>, for the Chinese language,</simpara></listitem>
  <listitem id="charset-EUC-KR-gnu"><simpara><literal>EUC-KR</literal> and
  <literal>ISO-2022-KR</literal>, for the Korean language.</simpara></listitem>
</itemizedlist>

<para>HP-UX systems support in particular, among others:</para>
<itemizedlist id="hpux-extra-charset-list">
  <listitem id="charset-eucJP"><simpara><literal>eucJP</literal> and
  <literal>sjis</literal>, for the Japanese language,</simpara></listitem>
  <listitem id="charset-eucTW"><simpara><literal>eucTW</literal>,
  <literal>big5</literal> and <literal>chinese-gb</literal>,
  for the Chinese language,</simpara></listitem>
  <listitem id="charset-eucKR"><simpara><literal>eucKR</literal>,
  for the Korean language.</simpara></listitem>
</itemizedlist>

<simpara>AIX 4.2 systems support in particular, among others:</simpara>
<itemizedlist id="aix-extra-charset-list">
  <listitem id="charset-IBM-eucJP"><simpara><literal>IBM-eucJP</literal>,
  for the Japanese language,</simpara></listitem>
  <listitem id="charset-IBM-eucTW"><simpara><literal>IBM-eucTW</literal>,
  for the Chinese language,</simpara></listitem>
  <listitem id="charset-IBM-eucKR"><simpara><literal>IBM-eucKR</literal>,
  for the Korean language.</simpara></listitem>
</itemizedlist>

<simpara>On Solaris systems, you can forget about &iconv;-based
 encodings, because all the possible encodings are already
 &enc-built-in;.  (Solaris knows about Japanese, Chinese and Korean
 encodings, but can convert them only to/from UTF-8, not to/from UCS-2,
 which is the &clisp;'s internal encoding.)</simpara>

<simpara>On IRIX systems, you can forget about &iconv;-based encodings
 as well, because all the interesting possible encodings are already
 &enc-built-in;.</simpara>

<simpara>On OSF/1 systems, &iconv;-based encodings are not usable at
 all.</simpara>

<simpara>When an encoding is available as a &enc-built-in; and through
 &iconv;, the &enc-built-in; is preferred, because it is more efficient
 and available across platforms.</simpara>

</listitem></varlistentry></variablelist>
<!-- #endif /* HAVE_ICONV */ -->
</para></listitem></varlistentry>

<!-- #endif /* UNICODE */ -->
</variablelist>

</section>

<section id="newline"><title>Line Terminators</title>

<table id="newline-table" frame="all"><title>The line terminator mode
  can be one of the following three keywords</title>
 <tgroup cols="2" colsep="1" rowsep="1" align="center">
<thead><row><entry>keyword</entry>
            <entry>newline representation</entry></row></thead>
<tbody>
<row><entry>&unix-k;</entry><entry>Newline is represented by the ASCII
     &lf-c; character (<keycode>U000A</keycode>).</entry></row>
<row><entry>&mac-k;</entry><entry>Newline is represented by the ASCII
     &cr-c; character (<keycode>U000D</keycode>).</entry></row>
<row><entry>&dos-k;</entry><entry>Newline is represented by the ASCII
     &cr-c; followed by the ASCII &lf-c;.</entry></row>
</tbody></tgroup></table>

<para>Windows programs typically use the &dos-k; line terminator,
 sometimes they also accept &unix-k; line terminators or produce
 &mac-k; line terminators.</para>

<para>The line terminator mode is relevant only for output (writing to a
 &file-pipe-socket;).  During input, all three kinds of line terminators
 are recognized.  If you do not want this, i.e., if you really want to
 distinguish &lf-c;, &cr-c; and &cr-c;/&lf-c;, you have to resort to
 binary input (function &read-byte;).</para>

<para>See also <link linkend="clhs-newline">13.1.8 Treatment of Newline
 during Input and Output</link>.</para>

</section>

<section id="make-encoding"><title>Function &make-encoding;</title>

<para>The function
  <literal role="sexp">(&make-encoding; &key-amp; :charset
     :line-terminator :input-error-action :output-error-action)</literal>
 returns an &encoding;. The <constant>:charset</constant> argument may be
 an encoding, a string, or &default-k;.
 The possible values for the &line-term; argument are the
 keywords &unix-k;, &mac-k;, &dos-k;.</para>

<para>The <constant>:input-error-action</constant> specifies what
 happens when an invalid byte sequence is encountered while converting
 bytes to characters.  Its value can be &error-k;, &ignore-k; or a
 character to be used instead.  The &unicode; character
 <keysym>#\uFFFD</keysym> is typically used to indicate an error in the
 input sequence.</para>

<para>The <constant>:output-error-action</constant> specifies what
 happens when an invalid character is encountered while converting
 characters to bytes.  Its value can be &error-k;, &ignore-k;, a byte to
 be used instead, or a character to be used instead.  The &unicode;
 character <keysym>#\uFFFD</keysym> can be used here only if it is
 encodable in the character set.</para>

<para>Encodings are types.  As such, they represent the set of
 characters encodable in the character set.  In this context, the way
 characters are translated into raw bytes is ignored, and the line
 terminator mode is ignored as well.  &typep; and &subtypep; can be used
 on encodings.</para>

<para>Besides every &file-pipe-socket; stream containing an encoding,
 the following &symbol-macro; places contain global &encoding;s:</para>

<formalpara id="def-file-enc"><title>&def-file-enc;</title>
<para>The &symbol-macro; place &def-file-enc; is the encoding used for
 new &file-pipe-socket; streams, when no &extfmt; argument was
 specified.</para></formalpara>

<!-- #ifdef UNICODE -->
<variablelist>
<varlistentry><term>Platform dependent: Only in &clisp; built
  &with; compile-time flag &unicode;.</term>
<listitem><simpara>The following are &symbol-macro; places.</simpara>
<variablelist>
<varlistentry id="path-enc"><term>&path-enc;</term>
 <listitem><simpara>is the encoding used for pathnames in the file
 system. Normally, this is a 1:1 encoding.  Its &line-term; mode is ignored.
 </simpara></listitem></varlistentry>
<varlistentry id="term-enc"><term>&term-enc;</term>
 <listitem><simpara>is the encoding used for communication with the
  terminal, in particular by &terminal-io-var;.
 </simpara></listitem></varlistentry>
<varlistentry id="misc-enc"><term>&misc-enc;</term>
 <listitem><simpara>is the encoding used for access to environment
 variables, command line options, and the like.
 Its &line-term; mode is ignored.
 </simpara></listitem></varlistentry>
<!-- #if defined(HAVE_AFFI) || defined(DYNAMIC_FFI) -->
<varlistentry id="foreign-enc"><term>&foreign-enc;</term>
 <listitem><simpara>is the encoding for characters and strings passed
 through the &ffi-pac; (some plaforms only).
 Its value must be a 1:1 encoding, i.e., an encoding in which every
 character is represented by one byte.
</simpara></listitem></varlistentry>
<!-- #endif -->
</variablelist></listitem></varlistentry>
</variablelist>
<!-- #endif -->

<para>The default encoding objects are initialized as described in the
 &clisp; <ulink url="clisp.html#opt-enc">manual page</ulink></para>

</section>

<section id="string-byte">
   <title>Converting between strings and byte vectors</title>

<para>Encodings can also be used to convert directly between strings and
their corresponding byte vector representation according to that encoding.
</para>

<variablelist>

<varlistentry><term><literal role="sexp">
 (<function>EXT:CONVERT-STRING-FROM-BYTES</function>
  <replaceable>byte-vector</replaceable> &encoding-r;
  &key-amp; &start-k; &end-k;)</literal></term>
 <listitem><simpara>converts the subsequence of
  <replaceable>byte-vector</replaceable> from &start-r; to &end-r; to a
  string, according to the given &encoding-r;, and returns the resulting
  string.</simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">
 (<function>EXT:CONVERT-STRING-TO-BYTES</function>
  &string-r; &encoding-r; &key-amp; &start-k; &end-k;)</literal></term>
 <listitem><simpara>converts the subsequence of &string-r; from
  &start-r; to &end-r; to a &unsigned-byte-vec;,
  according to the given &encoding-r;, and returns the resulting byte
  vector.</simpara></listitem></varlistentry>

</variablelist>

</section>
</section>

<section id="clos-stream">
  <title>Extensions-1.5. Defining new kinds of Streams</title>

<para>Two mechanisms are supported for creating new streams with
user-defined behavior:
<itemizedlist>
 <listitem><simpara>You can create a new subclass of &fu-st; and define
  methods for the elementary stream operations on it.  These generic
  functions all have a name starting with the prefix "stream-".
  </simpara></listitem>
 <listitem><simpara>You can create a new subclass of
  <classname>gstream:generic-stream-controller</classname> and define
  methods for the elementary stream operations on it.  These generic
  functions all have a name starting with the prefix
  "generic-stream-".  The stream itself is a different object, created
  using the function <function>gstream:make-generic-stream</function>.
  </simpara></listitem>
</itemizedlist></para>

<para>The <function>fundamental-stream</function> API is based on the
 &gray-streams; proposal by David N. Gray and is supported by most &cl;
 implementations currently in use.
 The <classname>gstream:generic-stream-controller</classname>
 API is &clisp; specific and is now obsolete.</para>

<section id="gray"><title>Gray streams</title>

<para>This interface permits the definition of new classes of streams,
and programming their behavior by defining methods for the elementary
stream operations.  It is based on the proposal &gray-streams; of David
N. Gray to X3J13.</para>

<para>All symbols defined by this interface, starting with the prefix
 "fundamental-" or "stream-", are exported from the package
 &gray-pac; and re-exported from &ext-pac;.</para>

<variablelist><title>Defined classes</title>
 <varlistentry id="fu-st"><term>&fu-st;</term>
  <listitem><simpara>This is a superclass of all user-defined streams.
   It is a subclass of &stream-class; and of &standard-object-class;.
   Its metaclass is &standard-class;.</simpara></listitem></varlistentry>
 <varlistentry id="fu-st-in"><term>&fu-st-in;</term>
  <listitem><simpara>This is a superclass of all user-defined input streams.
   It is a subclass of &fu-st;.  The built-in function &input-stream-p;
   returns true on instances of this class.  This means that when you
   define a new stream class capable of doing input, you have to make it
   a subclass of &fu-st-in;.</simpara></listitem></varlistentry>
 <varlistentry id="fu-st-out"><term>&fu-st-out;</term>
  <listitem><simpara>This is a superclass of all user-defined output streams.
   It is a subclass of &fu-st;.  The built-in function &output-stream-p;
   returns true on instances of this class.  This means that when you
   define a new stream class capable of doing output, you have to make
   it a subclass of &fu-st-out;.</simpara></listitem></varlistentry>
 <varlistentry id="fu-st-char"><term>&fu-st-char;</term>
  <listitem><simpara>This is a superclass of all user-defined streams
   whose &stream-element-type; is &character-class;.  It is a subclass of
   &fu-st;.  It defines a method on &stream-element-type; that returns
   &character-class;.</simpara></listitem></varlistentry>
 <varlistentry id="fu-st-bin"><term>&fu-st-bin;</term>
  <listitem><simpara>This is a superclass of all user-defined streams
   whose &stream-element-type; is a subtype of &integer-class;.  It is a
   subclass of &fu-st;.  When you define a subclass of &fu-st-bin;,
   you have to provide a method on &stream-element-type;.
  </simpara></listitem></varlistentry>
 <varlistentry>
    <term><classname>GRAY:FUNDAMENTAL-CHARACTER-INPUT-STREAM</classname></term>
  <listitem><simpara>This is a convenience class inheriting from both
   &fu-st-char; and &fu-st-in;.</simpara></listitem></varlistentry>
 <varlistentry>
   <term><classname>GRAY:FUNDAMENTAL-CHARACTER-OUTPUT-STREAM</classname></term>
  <listitem><simpara>This is a convenience class inheriting from both
   &fu-st-char; and &fu-st-out;.</simpara></listitem></varlistentry>
 <varlistentry>
    <term><classname>GRAY:FUNDAMENTAL-BINARY-INPUT-STREAM</classname></term>
  <listitem><simpara>This is a convenience class inheriting from both
   &fu-st-bin; and &fu-st-in;.</simpara></listitem></varlistentry>
 <varlistentry>
    <term><classname>GRAY:FUNDAMENTAL-BINARY-OUTPUT-STREAM</classname></term>
  <listitem><simpara>This is a convenience class inheriting from both
   &fu-st-bin; and &fu-st-out;.</simpara></listitem></varlistentry>
</variablelist>

<variablelist><title>general generic functions defined on streams</title>
 <varlistentry><term><literal role="sexp">(&stream-element-type;
    &stream-r;)</literal></term>
  <listitem><simpara>Returns the stream's element type, normally a
   subtype of &character-class; or &integer-class;.</simpara>
  <simpara>The method for &fu-st-char; returns &character-class;.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp">((&setf; &stream-element-type;)
    <replaceable>new-element-type</replaceable> &stream-r;)</literal></term>
  <listitem><simpara>Changes the stream's element type.</simpara>
   <simpara>The default method signals an error.</simpara>
   <simpara>This function is a &clisp; extension (see <link
    linkend="stream-eltype">setting &stream-element-type;</link>)</simpara>
   </listitem></varlistentry>
 <varlistentry><term><literal role="sexp">(&close;
    &stream-r; &key-amp; &abort-k;)</literal></term>
  <listitem><simpara>Closes the stream and flushes any associated buffers.
   </simpara><simpara>When you define a primary method on this
    function, do not forget to &call-next-method;.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp">(&open-stream-p;
    &stream-r;)</literal></term>
  <listitem><simpara>Returns true before the stream has been closed, and
    &nil; after the stream has been closed.</simpara>
   <simpara>You do not need to add methods to this function.</simpara>
   </listitem></varlistentry>
</variablelist>

<variablelist><title>generic functions for character input</title>
 <varlistentry id="st-rc"><term><literal
    role="sexp">(&st-rc; &stream-r;)</literal></term>
  <listitem><simpara>If a character was pushed back using &st-uc;,
   returns and consumes it.  Otherwise returns and consumes the next
   character from the stream. Returns &eof-k; if the &eos; is reached.
   </simpara>&need-defmethod;</listitem></varlistentry>
 <varlistentry id="st-uc"><term><literal
    role="sexp">(&st-uc; &stream-r; &ch-r;)</literal></term>
  <listitem><simpara>Pushes &ch-r;, which must be the last character
   read from the &stream-r;, back onto the front of the &stream-r;.
   </simpara>&need-defmethod;</listitem></varlistentry>
 <varlistentry id="st-rcnh"><term><literal
    role="sexp">(&st-rcnh; &stream-r;)</literal></term>
  <listitem><simpara>Returns a character or &eof-k;, like &st-rc;, if
   that would return immediately.  If &st-rc;'s value is not available
   immediately, returns &nil; instead of waiting.</simpara><simpara>
   The default method simply calls &st-rc;; this is sufficient for streams
   whose &st-rc; method never blocks.</simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>GRAY:STREAM-PEEK-CHAR</function> &stream-r;)</literal></term>
  <listitem><simpara>If a character was pushed back using &st-uc;,
   returns it.  Otherwise returns the next character from the stream,
   avoiding any side effects &st-rc; would do.  Returns &eof-k; if the
   &eos; is reached.</simpara>
  <simpara>The default method calls &st-rc; and &st-uc;; this is
   sufficient for streams whose &st-rc; method has no
   side-effects.</simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>GRAY:STREAM-LISTEN</function> &stream-r;)</literal></term>
  <listitem><simpara>If a character was pushed back using &st-uc;,
   returns it.  Otherwise returns the next character from the stream, if
   already available.  If no character is available immediately, or if
   &eos; is reached, returns &nil;.</simpara>
  <simpara>The default method calls &st-rcnh; and &st-uc;; this is
   sufficient for streams whose &st-rc; method has no
   side-effects.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-READ-CHAR-WILL-HANG-P</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Returns &nil; if &st-rc; will return immediately.
   Otherwise it returns true.</simpara>
  <simpara>The default method calls &st-rcnh; and &st-uc;; this is
   sufficient for streams whose &st-rc; method has no side-effects.</simpara>
  <simpara>This function is a &clisp; extension (see &rcwhp;).</simpara>
  </listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>GRAY:STREAM-READ-CHAR-SEQUENCE</function> &stream-r;
   &sequence-r; &optional-amp; [&start-r; [&end-r;]])</literal></term>
  <listitem><simpara>Fills the subsequence of &sequence-r; specified by
   &start-k; and &end-k; with characters consecutively read from &stream-r;.
   Returns the index of the first element of &sequence-r; that was not
   updated (= &end-r; or &lt; &end-r; if the stream reached its end).
   </simpara><simpara>&sequence-r; is an array of characters, i.e. a
   string.  &start-r; is a nonnegative integer and default to 0.
   &end-r; is a nonnegative integer or &nil; and defaults to &nil;,
   which stands for <literal role="sexp">(&length; &sequence-r;)</literal>.
   </simpara><simpara>The default method repeatedly calls &st-rc;; this
   is always sufficient if speed does not matter.</simpara>
   <simpara>This function is a &clisp; extension (see
    &rd-ch-seq;)</simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>GRAY:STREAM-READ-LINE</function> &stream-r;)</literal></term>
  <listitem><simpara>Reads a line of characters, and return two values: the
   line (a string, without the terminating &nl-c; character), and a boolean
   value which is true if the line was terminated by &eos; instead of &nl-c;.
   </simpara><simpara>The default method repeatedly calls &st-rc;; this
   is always sufficient.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gray:stream-clear-input</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Clears all pending interactive input from the
   stream, and returns true if some pending input was removed.</simpara>
  <simpara>The default method does nothing and returns &nil;; this is
   sufficient for non-interactive streams.</simpara></listitem></varlistentry>
</variablelist>

<variablelist><title>generic functions for character output</title>
 <varlistentry id="st-wc"><term><literal
    role="sexp">(&st-wc; &stream-r; &ch-r;)</literal></term>
  <listitem><simpara>Writes &ch-r;.
   </simpara>&need-defmethod;</listitem></varlistentry>
 <varlistentry id="st-lc"><term><literal
    role="sexp">(&st-lc; &stream-r;)</literal></term>
  <listitem><simpara>Returns the column number where the next character
   would be written (0 stands for the first column), or &nil; if that is
   not meaningful for this stream.
   </simpara>&need-defmethod;</listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-START-LINE-P</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Returns true if the next character would be
   written at the start of a new line.</simpara>
  <simpara>The default method calls &st-lc; and compares its result with
   0; this is sufficient for streams whose &st-lc; never returns &nil;.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-WRITE-CHAR-SEQUENCE</function>
                 &stream-r; &sequence-r;
                 &optional-amp; [&start-r; [&end-r;]])</literal></term>
  <listitem><simpara>Outputs the subsequence of &sequence-r; specified
   by &start-k; and &end-k; to &stream-r;.</simpara>
   <simpara>&sequence-r; is an array of characters, i.e. a string.
   &start-r; is a nonnegative integer and default to 0.  &end-r; is a
   nonnegative integer or &nil; and defaults to &nil;, which stands
   for <literal role="sexp">(&length; &sequence-r;)</literal>.
   </simpara><simpara>The default method repeatedly calls &st-wc;; this
   is always sufficient if speed does not matter.
   </simpara><simpara>This function is a &clisp; extension
    (see &wr-ch-seq;)</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-WRITE-STRING</function>
                 &stream-r; &string-r;
                 &optional-amp; [&start-r; [&end-r;]])</literal></term>
  <listitem><simpara>Outputs the subsequence of &string-r; specified by
   &start-k; and &end-k; to &stream-r;.  Returns &string-r;.</simpara>
   <simpara>&string-r; is a string.  &start-r; is a nonnegative integer
   and default to 0.  &end-r; is a nonnegative integer or &nil; and
   defaults to &nil;, which stands for <literal role="sexp">(&length;
   &string-r;)</literal>.</simpara>
  <simpara>The default method calls
   <function>GRAY:STREAM-WRITE-CHAR-SEQUENCE</function>;
   this is always sufficient.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-TERPRI</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Outputs a &nl-c; character.</simpara>
  <simpara>The default method calls &st-wc;; this is always
   sufficient.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-FRESH-LINE</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Possibly outputs a &nl-c; character, so as to ensure
   that the next character would be written at the start of a new line.
   Returns true if it did output a &nl-c; character.</simpara>
  <simpara>The default method calls
   <function>GRAY:STREAM-START-LINE-P</function> and then
   <function>GRAY:STREAM-TERPRI</function> if necessary; this is always
   sufficient.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-FINISH-OUTPUT</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Ensures that any buffered output has reached its
   destination, and then returns.</simpara>
  <simpara>The default method does nothing.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-FORCE-OUTPUT</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Brings any buffered output on its way towards its
   destination, and returns without waiting until it has reached its
   destination.</simpara>
  <simpara>The default method does nothing.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-CLEAR-OUTPUT</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>Attempts to discard any buffered output which has
   not yet reached its destination.</simpara>
  <simpara>The default method does nothing.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-ADVANCE-TO-COLUMN</function>
                 &stream-r; <replaceable>column</replaceable>)</literal></term>
  <listitem><simpara>Ensures that the next character will be written at
   <replaceable>column</replaceable> at least.</simpara>
  <simpara>The default method outputs an appropriate amount of space
   characters; this is sufficient for non-proportional output.</simpara>
  </listitem></varlistentry>
</variablelist>

<variablelist><title>generic functions for binary input</title>
 <varlistentry id="st-rb"><term><literal
    role="sexp">(&st-rb; &stream-r;)</literal></term>
  <listitem><simpara>Returns and consumes the next integer from the
   stream. Returns &eof-k; if the &eos; is reached.</simpara>
   &need-defmethod;</listitem></varlistentry>
 <varlistentry id="st-rbla"><term><literal
    role="sexp">(&st-rbla; &stream-r;)</literal></term>
  <listitem><simpara>To be called only if &stream-r;'s
   &stream-element-type; is &unsigned-byte-8; or &signed-byte-8;.
   Returns &t; if &st-rb; would return immediately with an
   &integer-class; result.  Returns &eof-k; if the &eos; is already
   known to be reached.  If &st-rb;'s value is not available
   immediately, returns &nil; instead of waiting.</simpara>
   &need-defmethod;<simpara>This function is a &clisp; extension (see
   &rbla;).</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-READ-BYTE-WILL-HANG-P</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>To be called only if &stream-r;'s
   &stream-element-type; is &unsigned-byte-8; or &signed-byte-8;.
   Returns &nil; if &st-rb; will return immediately.
   Otherwise it returns true.</simpara>
   <simpara>The default method calls &st-rbla;; this is always sufficient.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-READ-BYTE-NO-HANG</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>To be called only if &stream-r;'s
   &stream-element-type; is &unsigned-byte-8; or &signed-byte-8;.
   Returns an &integer-class; or &eof-k;, like &st-rb;, if that would
   return immediately.  If &st-rb;'s value is not available immediately,
   returns &nil; instead of waiting.</simpara>
   <simpara>The default method calls &st-rb; if &st-rbla; returns true;
   this is always sufficient.</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-READ-BYTE-SEQUENCE</function>
                 &stream-r; &sequence-r;
                 &optional-amp; [&start-r; [&end-r;]])</literal></term>
  <listitem><simpara>Fills the subsequence of &sequence-r; specified by
   &start-k; and &end-k; with integers consecutively read from
   &stream-r;.  Returns the index of the first element of &sequence-r;
   that was not updated (= &end-r; or &lt; &end-r; if the stream reached
   its end).</simpara>
   <simpara>&sequence-r; is an array of integers.  &start-r; is a
   nonnegative integer and default to 0.  &end-r; is a nonnegative
   integer or &nil; and defaults to &nil;, which stands for <literal
   role="sexp">(&length; &sequence-r;)</literal>.</simpara>
   <simpara>The default method repeatedly calls &st-rb;; this is always
   sufficient if speed does not matter.</simpara>
   <simpara>This function is a &clisp; extension (see
   &rd-by-seq;).</simpara></listitem></varlistentry>
</variablelist>

<variablelist><title>generic functions for binary output</title>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-WRITE-BYTE</function>
                 &stream-r; &int-r;)</literal></term>
  <listitem><simpara>Writes &int-r;.</simpara>
   &need-defmethod;</listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>GRAY:STREAM-WRITE-BYTE-SEQUENCE</function>
                 &stream-r; &sequence-r;
                 &optional-amp; [&start-r; [&end-r;]])</literal></term>
  <listitem><simpara>Outputs the subsequence of &sequence-r; specified
   by &start-k; and &end-k; to &stream-r;</simpara>
  <simpara>&sequence-r; is an array of integers.  &start-r; is a
   nonnegative integer and default to 0.  &end-r; is a nonnegative
   integer or &nil; and defaults to &nil;, which stands for <literal
   role="sexp">(&length; &sequence-r;)</literal>.</simpara>
  <simpara>The default method repeatedly calls
   <function>GRAY:STREAM-WRITE-BYTE</function>; this is always
   sufficient if speed does not matter.</simpara>
  <simpara>This function is a &clisp; extension (see
   &wr-by-seq;).</simpara></listitem></varlistentry>
</variablelist>

</section>

<!-- #ifdef GENERIC_STREAMS -->
<section id="gstream"><title>Generic streams</title>

<para>This interface is &clisp; specific and now obsolete.  Please use
 the <link linkend="gray">Gray streams</link> interface instead.</para>

<para>Generic streams are user programmable streams.
 The programmer interface:</para>

<variablelist>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:make-generic-stream</function>
                 <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara>returns a generic stream.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-controller</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>returns a private object to which generic stream
   methods dispatch.  The typical usage is to retrieve the object
   originally provided by the user in
   <function>gstream:make-generic-stream</function>.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-p</function>
                 &stream-r;)</literal></term>
  <listitem><simpara>determines whether a stream is a generic stream,
   returning &t; if it is, &nil; otherwise.
  </simpara></listitem></varlistentry>
</variablelist>

<para>In order to specify the behavior of a generic stream, the user
 must define &clos; methods on the following &clos; generic
 functions.  The function
 <function>gstream:generic-stream-<replaceable>xyz</replaceable></function>
 corresponds to the &cl; function
 <function><replaceable>xyz</replaceable></function>.  They all take a
 controller and some number of arguments.</para>

<variablelist>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-read-char</function>
                 <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara> Returns and consumes the next character, &nil; at
    end of file.  Takes one argument, the controller object.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-peek-char</function>
                 <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara> Returns the next character, &nil; at end of file.  A
   second value indicates whether the side effects associated with
   consuming the character were executed: &t; means that a full
   &read-char; was done, &nil; means that no side effects were done.
   Takes one argument, the controller object.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-read-byte</function>
                 <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara>Returns and consumes the next integer, &nil; at end
   of file.  Takes one argument, the controller object.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>gstream:generic-stream-read-char-will-hang-p</function>
     <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara>This generic function is used to query the stream's
   input status.  It returns &nil; if
   <function>gstream:generic-stream-read-char</function> and
   <function>gstream:generic-stream-peek-char</function> will certainly
   return immediately.  Otherwise it returns true.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-write-char</function>
                 <replaceable>controller</replaceable> &ch-r;)</literal></term>
  <listitem><simpara>The first argument is the controller object.
   The second argument is the character to be written.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-write-byte</function>
                 <replaceable>controller</replaceable>
                 <replaceable>by</replaceable>)</literal></term>
  <listitem><simpara>The first argument is the controller object.
   The second argument is the integer to be written.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-write-string</function>
                 <replaceable>controller</replaceable>
                 &string-r; &start-r; &len-r;)</literal></term>
  <listitem><simpara>Writes the subsequence of &string-r; starting from
   &start-r; of length &len-r;.
   The first argument is the controller object.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>gstream:generic-stream-clear-input</function>
                 <replaceable>controller</replaceable>)</literal>
  <literal role="sexp"
   >(<function>gstream:generic-stream-clear-output</function>
     <replaceable>controller</replaceable>)</literal>
  <literal role="sexp"
   >(<function>gstream:generic-stream-finish-output</function>
     <replaceable>controller</replaceable>)</literal>
  <literal role="sexp"
   >(<function>gstream:generic-stream-force-output</function>
     <replaceable>controller</replaceable>)</literal>
  <literal role="sexp"
   >(<function>gstream:generic-stream-close</function>
     <replaceable>controller</replaceable>)</literal></term>
  <listitem><simpara>Take one argument, the controller object.
 </simpara></listitem></varlistentry>
</variablelist>
<!-- #endif -->

</section>
</section>


<section id="weak"><title>Extensions-1.6. Weak Pointers</title>

<para>A weak pointer is an object holding a reference to a given object,
 without keeping the latter from being &gc;ed.</para>

<variablelist>
<varlistentry><term><literal
   role="sexp">(<function>EXT:MAKE-WEAK-POINTER</function>
   &value-r;)</literal></term>
 <listitem><simpara>returns a fresh weak pointer referring to
  &value-r;.</simpara></listitem></varlistentry>
<varlistentry><term><literal
   role="sexp">(<function>EXT:WEAK-POINTER-P</function>
   &object-r;)</literal></term>
 <listitem><simpara>returns true if the &object-r; is of type &weak-pointer;.
 </simpara></listitem></varlistentry>
<varlistentry><term><literal
    role="sexp">(<function>EXT:WEAK-POINTER-VALUE</function>
    <replaceable>weak-pointer</replaceable>)</literal></term>
 <listitem><simpara>returns two values: The original value and &t;, if
    the value has not yet been &gc;ed, else &nil; and &nil;.
  </simpara></listitem></varlistentry>
</variablelist>

</section>


<section id="final"><title>Extensions-1.7. Finalization</title>

<para>Calling <literal role="sexp">(&finalize; &object-r;
 &func-r;)</literal> has the effect that when the specified object is
 being &gc;ed, <literal role="sexp">(&funcall; &func-r;
 &object-r;)</literal> will be executed.</para>

<para>Calling <literal role="sexp">(&finalize; &object-r; &func-r;
 <replaceable>guardian</replaceable>)</literal> has a similar effect,
 but only as long as the "guardian" has not been &gc;ed: When &object-r;
 is being &gc;ed, <literal role="sexp">(&funcall; &func-r; &object-r;
 <replaceable>guardian</replaceable>)</literal> will be executed.  If
 the guardian is &gc;ed before &object-r; is, nothing happens.</para>

<para>Note: The time when <quote>the &object-r; is being &gc;ed</quote>
 is not defined deterministically.  (Actually, it might possibly never
 occur.)  It denotes a moment at which no references to &object-r; exist
 from other Lisp objects.  When the &func-r; is called, &object-r; (and
 possibly <replaceable>guardian</replaceable>) enter the "arena of live
 Lisp objects" again.</para>

<para>No finalization request will be executed more than once.</para>

</section>


<section id="prompt"><title>Extensions-1.8. The Prompt</title>

<para>The variable <emphasis
 role="strong"><varname>custom:*prompt*</varname></emphasis> controls the
 appearance of the prompt.  When its value is a function, it is called
 and its value is printed with &princ;.  Otherwise, the value itself is
 printed with &princ;.  The default value of
 <varname>custom:*prompt*</varname> prints
 <prompt>"package[nn]&gt;&nbsp;"</prompt> where
 <replaceable>package</replaceable> is the shortest (nick)name of the
 current package &package-var; if it is the same as it was in the
 beginning or if it does not contain symbol &t; (it is assumed that in
 the latter case you would want to keep in mind that your current
 package is something weird); and <replaceable>nn</replaceable> is the
 ordinal number of the current prompt (hopefully, it will remain
 finite).  To help you in constructing your own fancy prompts, two
 functions are provided: <emphasis
 role="strong"><function>ext:prompt-new-package</function></emphasis>,
 returning &package-var; or &nil; if the current package is the same as
 it was initially; and <emphasis
 role="strong"><function>ext:package-short-name</function></emphasis>
 taking one argument, a package, and returning its shortest name or
 nickname.  Also, a variable <emphasis
 role="strong"><varname>ext:*command-index*</varname></emphasis>
 contains the current prompt number, it is your responsibility to
 increment it
 (this variable is bound to 0 before saving the &mem-image;).</para>

</section>


<section id="ansi"><title>Extensions-1.9. Maximum ANSI CL compliance</title>

<para>Some &ansi-cl; features are turned off by default for backwards
 compatibility.
 They can be switched on, all at once by setting the &symbol-macro;
 &ansi; to &t;, or they can be switched on individually.
 Setting &ansi; to &t; implies the following:</para>

<itemizedlist>
 <listitem><simpara>Setting &pathprint; to &t;.</simpara></listitem>
 <listitem><simpara>Setting &fixnum-char-ansi; to &t;.</simpara></listitem>
 <listitem><simpara>Setting &count-ansi; to &t;.</simpara></listitem>
 <listitem><simpara>Setting &pathmerge; to &t;.</simpara></listitem>
 <listitem><simpara>Setting &parsename; to &t;.</simpara></listitem>
 <listitem><simpara>Setting &flocont; to &t;.</simpara></listitem>
</itemizedlist>

<para>Please note that if you run &clisp; with the &ansi-opt; switch or
 set the &symbol-macro; &ansi; to &t; and save &mem-image;, then all
 subsequent invocations of &clisp; with this image will be as if with
 &ansi-opt; (regardless whether you actually supply the &ansi-opt; switch).
 You can always set the &symbol-macro; &ansi; to &nil;,
 or invoke &clisp; with the &traditional-opt; switch,
 reversing the above settings, i.e.,</para>

<itemizedlist>
 <listitem><simpara>Setting &pathprint; to &nil;.</simpara></listitem>
 <listitem><simpara>Setting &fixnum-char-ansi; to &nil;.</simpara></listitem>
 <listitem><simpara>Setting &count-ansi; to &nil;.</simpara></listitem>
 <listitem><simpara>Setting &pathmerge; to &nil;.</simpara></listitem>
 <listitem><simpara>Setting &parsename; to &nil;.</simpara></listitem>
 <listitem><simpara>Setting &flocont; to &nil;.</simpara></listitem>
</itemizedlist>

</section>


<section id="macros3"><title>Extensions-1.10. Additional Fancy Macros</title>

<para>If you uncomment the <literal role="sexp">(&load;
 "macros3")</literal> line in the file <filename>init.lisp</filename>
 before doing <command>make</command>, or load the file
 <filename>macros3.lisp</filename> into a running &clisp;, you can
 use the following macros:</para>

<formalpara id="ethe"><title>&ethe;</title>
<para><literal role="sexp">(&ethe; &val-type-r; &form-r;)</literal>
 enforces a type check in both interpreted and compiled code.
 </para></formalpara>

<formalpara id="letf"><title>Macros &letf; &amp; &letf-star;</title>
<para>These macros are similar to &let; and &let-star;, respectively,
 except that they can bind places, even places with multiple values.
 Example:

<programlisting>
 (letf (((values a b) form)) ...)
</programlisting>

is equivalent to

<programlisting>
 (multiple-value-bind (a b) form ...)
</programlisting>

while

<programlisting>
(letf (((first l) 7)) ...)
</programlisting>

is approximately equivalent to

<programlisting>
 (&let-star; ((#:g1 l) (#:g2 (first #:g1)))
   (&unwind-protect; (&progn; (&setf; (first #:g1) 7) ...)
      (&setf; (first #:g1) #:g2)))
</programlisting>
</para></formalpara>

<formalpara id="with-collect">
     <title><function>ext:with-collect</function></title>
<para>Similar to the &loop;'s <constant>collect</constant> instruction,
 except that it is more "Lispy" in appearance and can appear arbitrarily
 deep.  It defines local macros (with &macrolet;) which collect objects
 given to it in lists, which are then returned as multiple values.  E.g.,

<programlisting>
 (ext:with-collect (c0 c1)
   (dotimes (i 10) (if (oddp i) (c0 i) (c1 i))))
</programlisting>

returns two lists <literal role="sexp">(1 3 5 7 9)</literal> and
<literal role="sexp">(0 2 4 6 8)</literal> as multiple values.
</para></formalpara>

<para>You might want to add a <literal role="sexp">(&load;
 "macros3")</literal> statement to your <ulink
 url="clisp.html#opt-norc"><filename>.clisprc</filename></ulink>
 file if you do not want to dump your own &mem-image;.</para>

</section>

<section id="customize">
  <title>Extensions-1.11. Customizing &clisp; behavior.</title>

<para>The user-customizable variables are located in the package
 &custom-pac; and thus can be listed using
   <literal role="sexp">(&apropos; "" "CUSTOM")</literal>
</para>

</section>

</chapter>

<!-- #if defined(SCREEN) || defined(AMIGAOS) || defined(GRAPHICS) || defined(UNIX) || defined(DYNAMIC_FFI) || defined(SOCKET_STREAMS) -->

<chapter id="platform">
   <title>Extensions-2: Platform specific Extensions</title>

<!-- #if defined(SCREEN) || defined(AMIGAOS) -->

<section id="screen"><title>Extensions-2.1. Random Screen Access</title>
<subtitle>Platform dependent: &unix;, &amiga;, &dos;, &os2;, &win32;
   platforms only.</subtitle>

<variablelist>
 <varlistentry><term><literal
    role="sexp">(<function>screen:make-window</function>)</literal></term>
  <listitem><simpara>returns a "window stream".  As long as this stream
   is open, the terminal is in cbreak/noecho mode.  &terminal-io-var;
   should not be used for input or output during this time.
   (Use &with-kbd; and &kbd-in; instead.)
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:with-window</function>
                 . &body-r;)</literal></term>
  <listitem><simpara>binds <emphasis
   role="strong"><varname>screen:*window*</varname></emphasis> to a
   window stream and executes &body-r;.  The stream is guaranteed to be
   closed when the body is left.  During its execution,
   &terminal-io-var; should not be used, as above.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:window-size</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>returns the window's size, as two values:
   height (= y<subscript>max</subscript>+1) and width (=
   x<subscript>max</subscript>+1).
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:window-cursor-position</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>returns the position of the cursor in the window,
   as two values: line (&ge;0, &le;y<subscript>max</subscript>, 0 means
   top), column (&ge;0, &le;x<subscript>max</subscript>, 0 means left
   margin).</simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:set-window-cursor-position</function>
                 <replaceable>window-stream</replaceable>
                 <replaceable>line</replaceable>
                 <replaceable>column</replaceable>)</literal></term>
  <listitem><simpara>sets the position of the cursor in the window.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:clear-window</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>clears the window's contents and puts the cursor in
   the upper left corner.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:clear-window-to-eot</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>clears the window's contents from the cursor
   position to the end of window.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:clear-window-to-eol</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>clears the window's contents from the cursor
   position to the end of line.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:delete-window-line</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>removes the cursor's line, moves the lines below it
   up by one line and clears the window's last line.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:insert-window-line</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>inserts a line at the cursor's line, moving the
   lines below it down by one line.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:highlight-on</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>switches highlighted output on.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:highlight-off</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>switches highlighted output off.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:window-cursor-on</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>makes the cursor visible, a cursor block in most
   implementations.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>screen:window-cursor-off</function>
                 <replaceable>window-stream</replaceable>)</literal></term>
  <listitem><simpara>makes the cursor invisible, in implementations
   where this is possible.
  </simpara></listitem></varlistentry>
</variablelist>
</section>
<!-- #endif -->

<!-- #ifdef UNIX -->
<section id="modules"><title>Extensions-2.2. External Modules</title>
<subtitle>Platform dependent: &unix; platforms only.</subtitle>

<para>&clisp; has a facility for adding external modules (written in
 &c-lang;, for example).  It is invoked through
 <command>clisp-link</command>.</para>

<para>A module is a piece of external code which defines extra Lisp
 objects, symbols and functions.  A module name must consist of the
 characters <filename>A</filename>-<filename>Z</filename>,
 <filename>a</filename>-<filename>z</filename>, <filename>_</filename>,
 <filename>0</filename>-<filename>9</filename>.  The module name
 <quote>clisp</quote> is reserved.  Normally a module name is derived
 from the corresponding file name.</para>

<para><command>clisp-link</command> needs a directory containing:
<itemizedlist>
  <listitem><simpara><filename>modules.d</filename></simpara></listitem>
  <listitem><simpara><filename>modules.c</filename></simpara></listitem>
  <listitem><simpara><filename>clisp.h</filename></simpara></listitem>
</itemizedlist>
<command>clisp-link</command> expects to find these files in a subdirectory
<filename>linkkit/</filename> of the current directory. This can be overridden
by the environment variable <envar>CLISP_LINKKIT</envar>.</para>

<para><command>clisp-link</command> operates on &clisp; linking sets and
 on module sets.</para>

<para>A <emphasis role="strong">linking set</emphasis> is a directory
 containing:</para>

<variablelist>
<varlistentry><term><filename>makevars</filename></term>
 <listitem><para>some <command>/bin/sh</command> commands, setting
  the variables
<variablelist><varlistentry><term><envar>CC</envar></term>
       <listitem><simpara>the &c-lang; compiler
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>CFLAGS</envar></term>
       <listitem><simpara>flags for the &c-lang; compiler, when compiling
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>CLFLAGS</envar></term>
       <listitem><simpara>flags for the &c-lang; compiler, when linking
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>LIBS</envar></term>
       <listitem><simpara>libraries to use when linking
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>X_LIBS</envar></term>
       <listitem><simpara>additional X window system libraries to use
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>RANLIB</envar></term>
       <listitem><simpara>the ranlib command
   </simpara></listitem></varlistentry>
 <varlistentry><term><envar>FILES</envar></term>
       <listitem><simpara>the list of files needed when linking
   </simpara></listitem></varlistentry>
  </variablelist></para></listitem></varlistentry>
 <varlistentry><term><filename>modules.h</filename></term>
  <listitem><simpara>the list of modules contained in this linking set
  </simpara></listitem></varlistentry>
 <varlistentry><term><filename>modules.o</filename></term>
  <listitem><simpara>the compiled list of modules contained in this linking set
  </simpara></listitem></varlistentry>
 <varlistentry><term>all the <filename>FILES</filename></term>
  <listitem><simpara>listed in <filename>makevars</filename>
  </simpara></listitem></varlistentry>
 <varlistentry><term><filename>lisp.run</filename></term>
       <listitem><simpara>the executable</simpara></listitem></varlistentry>
 <varlistentry><term>&lispinit;</term>
     <listitem><simpara>the &mem-image;</simpara></listitem></varlistentry>
</variablelist>

<para>To run a &clisp; contained in some linking set
 <filename>dir</filename>, call
 <command><replaceable>dir</replaceable>/lisp.run -M
 <replaceable>dir</replaceable>/lispinit.mem</command></para>

<para>A <emphasis role="strong">module set</emphasis> is a directory
containing:</para>

<variablelist>
<varlistentry><term><command>link.sh</command></term>
 <listitem><simpara>some <command>/bin/sh</command> commands, which
  prepare the directory before linking, and set the variables
  <envar>NEW_FILES</envar>, <envar>NEW_LIBS</envar>,
  <envar>NEW_MODULES</envar>, <envar>TO_LOAD</envar> and optionally
  <envar>TO_PRELOAD</envar></simpara></listitem></varlistentry>
<varlistentry><term>and any other files</term>
 <listitem><simpara>needed by <command>link.sh</command>
 </simpara></listitem></varlistentry>
</variablelist>

<para>Note that in <command>link.sh</command> the module set directory
 is referred to as <varname>$modulename/</varname>.</para>

<variablelist>
<varlistentry><term><envar>NEW_FILES</envar></term>
 <listitem><simpara>the space-separated list of files that
  belong to the module set and will belong to every new linking set.
 </simpara></listitem></varlistentry>
<varlistentry><term><envar>NEW_LIBS</envar></term>
 <listitem><simpara>the space-separated list of files or
  &c-lang; compiler switches that need to be passed to the &c-lang;
  compiler when linking the lisp.run belonging to a new linking set.
 </simpara></listitem></varlistentry>
<varlistentry><term><envar>NEW_MODULES</envar></term>
 <listitem><simpara>the space-separated list of the module names
  belonging to the module set.  Normally, every &c-file; file in the
  module set defines a module of its own.  The module name is derived
  from the file name.</simpara></listitem></varlistentry>
<varlistentry><term><envar>TO_LOAD</envar></term>
 <listitem><simpara>the space-separated list of Lisp files to load
  before building the &lispinit; belonging to a new linking set.
 </simpara></listitem></varlistentry>
<varlistentry><term><envar>TO_PRELOAD</envar> (optional)</term>
 <listitem><simpara>the space-separated list of Lisp files to load into
  an intermediate &lispinit; file, before building the &lispinit;
  belonging to a new linking set.  This variable is usually used for
  defining Lisp packages which must be present when the new &c-file;
  files are initialized.</simpara></listitem></varlistentry>
</variablelist>

<para>The command <command>clisp-link create-module-set
 <replaceable>module-dir</replaceable>
 <replaceable>file1.c</replaceable> ...</command> creates a module set
 in <replaceable>module-dir</replaceable> which refers (via symbolic
 links) to <replaceable>file1.c</replaceable> etc.  The files are
 expected to be modules of their own.</para>

<para>The command <command>clisp-link add-module-set
 <replaceable>module-dir</replaceable>
 <replaceable>source-dir</replaceable>
 <replaceable>destination-dir</replaceable></command> combines a linking
 set in <replaceable>source-dir</replaceable> and a module in
 <replaceable>module-dir</replaceable> to a new linking set, in a
 directory <replaceable>destination-dir</replaceable> which is newly
 created.</para>

<para>The command <command>clisp-link run <replaceable>source-dir</replaceable>
 <replaceable>module-dir</replaceable> ...</command> runs the linking
 set in <replaceable>source-dir</replaceable>, with the module in
 <replaceable>module-dir</replaceable> loaded.  More than one module can
 be specified.  If &clisp; has been built with the configuration option
 <option>--with-dynamic-modules</option>, the loading will be performed
 through dynamic loading.  Otherwise - this is much slower - a temporary
 linking set will be created and deleted afterwards.  Note that dynamic
 loading does not work on all operating systems, and that
 <option>--with-dynamic-modules</option> precludes some efficiency
 optimizations which are on by default.</para>

<section id="mod-set-example"><title>Example</title>

<para>To link in the &ffi-pac; bindings for the GNU/Linux operating
 system, the following steps are needed.  (Step 1 and step 2 need not be
 executed in this order.)</para>

<orderedlist numeration="arabic">
<listitem><para>Create a new module set:

<programlisting>$ clisp-link create-module-set linux /<replaceable>somewhere</replaceable>/bindings/linux.c</programlisting>

 Modify the newly created <filename>linux/link.sh</filename> to add
 <option>-lm</option>; to the libraries: replace
<programlisting>NEW_LIBS="$file_list"</programlisting>
   with
<programlisting>NEW_LIBS="$file_list -lm"</programlisting>

   Modify the newly created <filename>linux/link.sh</filename> to load
   <filename>linux.fas</filename> before saving the &mem-image;:
   replace
<programlisting>TO_LOAD=''</programlisting>
   with
<programlisting>TO_LOAD='/<replaceable>somewhere</replaceable>/bindings/linux.fas'</programlisting></para></listitem>

<listitem><para>Compile <filename>linux.lisp</filename>, creating
  <filename>linux.c</filename>:

<programlisting>$ clisp -c /<replaceable>somewhere</replaceable>/bindings/linux.lisp</programlisting></para></listitem>

<listitem><para>Create a new linking set:
<programlisting>$ clisp-link add-module-set linux base base+linux</programlisting></para></listitem>

<listitem><para>Run and try it:

<programlisting>$ base+linux/lisp.run -M base+linux/lispinit.mem &gt; (linux::stat "/tmp")</programlisting></para></listitem>

</orderedlist>
<!-- #endif -->

</section>

<section id="included-modules">
   <title>Modules included in the distribution.</title>

<para>The following modules come with the distribution of
&clisp;:</para>

<variablelist>
 <varlistentry><term>bindings</term>
  <listitem><para>Call the operating system functions from &clisp;.  The
   following platforms are supported:
   <itemizedlist>
    <listitem><simpara>AmigaOS</simpara></listitem>
    <listitem><simpara>Linux/libc5</simpara></listitem>
    <listitem><simpara>Linux/libc6</simpara></listitem>
   </itemizedlist></para></listitem></varlistentry>
 <varlistentry><term>CLX</term>
  <listitem><para>Call Xlib functions from &clisp;.  Two
   implementations are supplied:
   <itemizedlist>
    <listitem><simpara>mit-clx, from MIT
     <ulink url="ftp://ftp.x.org/R5contrib/CLX.R5.02.tar.Z"
                >ftp://ftp.x.org/R5contrib/CLX.R5.02.tar.Z</ulink>
    </simpara></listitem>
    <listitem><simpara>new-clx, by <ulink
    url="http://www.uni-karlsruhe.de/~unk6/">Gilbert Baumann</ulink>
    <ulink url="mailto:unk6@rz.uni-karlsruhe.de"
                  >&lt;unk6@rz.uni-karlsruhe.de&gt;</ulink>.
    </simpara></listitem>
   </itemizedlist></para></listitem></varlistentry>
 <varlistentry><term>postgresql632, postgresql642</term>
  <listitem><simpara>Access <ulink
   url="http://www.PostgreSQL.org/">PostgreSQL</ulink> from &clisp;.
  </simpara></listitem></varlistentry>
 <varlistentry><term>queens</term>
  <listitem><simpara>Compute the number of solutions to the n-queens
   problem on a n*n checkboard.
  </simpara></listitem></varlistentry>
 <varlistentry><term><link linkend="regexp">regexp</link></term>
  <listitem><simpara>The <ulink url="regexp.html">POSIX Regular
   Expressions</ulink> matching, compiling, executing.
  </simpara></listitem></varlistentry>
 <varlistentry><term><ulink url="wildcard.html">wildcard</ulink></term>
  <listitem><simpara>Shell globbing</simpara></listitem></varlistentry>
</variablelist>

&regexp;

</section>
</section>


<!-- #ifdef DYNAMIC_FFI -->
<section id="dffi">
  <title>Extensions-2.3. The Foreign Function Call Facility</title>
<subtitle>Platform dependent: many &unix;, &win32; platforms only.</subtitle>

<para>A foreign function description is written as a Lisp file, and when
 compiled it produces a &c-file; file which is then compiled by the
 &c-lang; compiler and may be linked together with
 <filename>lisp.a</filename>.</para>

<para>All symbols relating to the foreign function interface are
 exported from the package &ffi-pac;.  To use them,
 <literal role="sexp">(&use-package; "FFI")</literal>.</para>

<para>Special &ffi-pac; forms may appear anywhere in the Lisp file.</para>

<section id="dffi-overview"><title>Overview</title>

<para>These are the special &ffi-pac; forms.  We have taken a pragmatic
 approach: the only foreign languages we support for now are &c-lang;
 and ANSI &c-lang;.</para>

<variablelist><title>special &ffi-pac; forms; &name-r; is any Lisp
   symbol; &cname-r; is a string.</title>
<varlistentry id="def-c-type">
  <term><literal role="sexp">(<function>def-c-type</function>
        &name-r; &ctype-r;)</literal></term>
 <listitem><simpara>This form makes &name-r; a shortcut for &ctype-r;.
  Note that &ctype-r; may already refer to name.
  Forward declarations of types are not possible, however.
 </simpara></listitem></varlistentry>

<varlistentry id="def-c-var">
  <term><literal role="sexp">(<function>def-c-var</function>
        &name-r; {&option-r;}*)</literal></term>
<listitem><table frame="all" role="bnf"><title/>
 <tgroup cols="3" colsep="1" rowsep="1" align="left"><thead><row>
 <entry>&option-r; ::==</entry><entry/><entry/></row></thead><tbody>
<row><entry/><entry/><entry><literal role="sexp">(:name
   &cname-r;)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:type
  &ctype-r;)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:read-only
  <replaceable>boolean</replaceable>)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:alloc
  &allocation;)</literal></entry></row>
</tbody></tgroup></table>

<simpara>This form defines a foreign variable.  &name-r; is the Lisp
 name, a regular Lisp symbol.</simpara>

<simpara>The <constant>:name</constant> option specifies the name, as
 seen from &c-lang;, as a string.  If not specified, it is derived from
 the print name of the Lisp name.</simpara>

<simpara>The <constant>:type</constant> option specifies the variable's
 foreign type.</simpara>

<simpara>If the <constant>:read-only</constant> option is specified and
non-&nil;, it will be impossible to change the variable's value from
within Lisp (using &setq; or similar).</simpara>

<simpara>The <constant>:alloc</constant> option can be either &none-k;
 or &malloc-free-k; and defaults to &none-k;.  If it is &malloc-free-k;,
 any values of type &c-string;, &c-ptr;, &c-ptr-null;, &c-array-ptr;
 within the foreign value are assumed to be pointers to
 &malloc;-allocated storage, and when &setq; replaces an old value by a
 new one, the old storage is freed using &free; and the new storage
 allocated using &malloc;.  If it is &none-k;, &setq; assumes that the
 pointers point to good storage (not &c-NULL;!) and overwrites the old
 values by the new ones.  This is dangerous (just think of overwriting a
 string with a longer one or storing some data in a &c-NULL; pointer...)
 and deprecated.</simpara>

</listitem></varlistentry>

<varlistentry id="def-call-out"><term><literal role="sexp">(&def-call-out;
              &name-r; {&option-r;}*)</literal></term>
<listitem><table frame="all" role="bnf"><title/>
 <tgroup cols="3" colsep="1" rowsep="1" align="left">
 <thead><row><entry>&option-r; ::==</entry>
 <entry/><entry/></row></thead><tbody>
<row><entry/><entry/><entry><literal role="sexp">(:name
   &cname-r;)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:arguments
   {(<replaceable>arg-name</replaceable> &ctype-r;
    [&param-mode; [&allocation;]])}*)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:return-type
   &ctype-r; [&allocation;])</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(&lang-k;
   &lang-r;)</literal></entry></row>
</tbody></tgroup></table>

<simpara>This form defines a named call-out function (a foreign function
 called from Lisp: control flow temporarily leaves Lisp).  Any Lisp
 function call to <function>#'&name-r;</function>
 is redirected to call the &c-lang; function &cname-r;.
</simpara></listitem></varlistentry>

<varlistentry id="def-call-in"><term><literal role="sexp">(&def-call-in;
              &name-r; {&option-r;}*)</literal></term>
<listitem><table frame="all" role="bnf"><title/>
 <tgroup cols="3" colsep="1" rowsep="1" align="left">
 <thead><row><entry>&option-r; ::==</entry>
 <entry/><entry/></row></thead><tbody>
<row><entry/><entry/><entry><literal role="sexp">(:name
   &cname-r;)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:arguments
   {(<replaceable>arg-name</replaceable> &ctype-r;
    [&param-mode; [&allocation;]])}*)</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(:return-type
   &ctype-r; [&allocation;])</literal></entry></row>
<row><entry/><entry>|</entry><entry><literal role="sexp">(&lang-k;
   &lang-r;)</literal></entry></row>
</tbody></tgroup></table>

<simpara>This form defines a named call-in function (i.e., a Lisp
 function called from the foreign language: control flow temporary
 enters Lisp).  Any &c-lang; function call to the &c-lang; function
 &cname-r; is redirected to call the &cl; function
 <function>#'&name-r;</function>.</simpara></listitem></varlistentry>

<varlistentry id="def-c-call-out"><term><literal role="sexp">(&def-c-call-out;
        &name-r; {&option-r;}*)</literal></term>
<listitem><simpara>This is equivalent to &def-call-out; with
   &lang-k; &stdc-k;.</simpara></listitem></varlistentry>

<varlistentry id="def-c-call-in"><term><literal role="sexp">(&def-c-call-in;
        &name-r; {&option-r;}*)</literal></term>
<listitem><simpara>This is equivalent to &def-call-in; with
   &lang-k; &stdc-k;.</simpara></listitem></varlistentry>

<varlistentry id="def-c-struct"><term><literal role="sexp">(&def-c-struct;
   &name-r; (<replaceable>ident</replaceable> &ctype-r;)*)</literal></term>
 <listitem><simpara>This form defines &name-r; to be both a
  &structure-class; and a foreign &c-lang; type with the given slots.
 </simpara></listitem></varlistentry>

<varlistentry id="def-c-enum"><term><literal role="sexp">(&def-c-enum;
        &name-r; {<replaceable>ident</replaceable> |
                  (<replaceable>ident</replaceable>
                  [&value-r;])}*)</literal></term>
 <listitem><simpara>This form defines <replaceable>ident</replaceable>s
  as constants, similarly to the &c-lang; declaration <type>enum {
  <replaceable>ident</replaceable> [= &value-r;],
  ... };</type></simpara></listitem></varlistentry>

<varlistentry id="c-lines"><term><literal role="sexp">(&c-lines;
                <replaceable>format-string</replaceable>
                {<replaceable>argument</replaceable>}*)</literal></term>
 <listitem><simpara>This form outputs the string <literal
  role="sexp">(&format; &nil; <replaceable>format-string</replaceable>
  {<replaceable>argument</replaceable>}*)</literal> to the &c-lang;
  output file.  This is a rarely needed low-level facility.
 </simpara></listitem></varlistentry>

<varlistentry id="element"><term><literal role="sexp">(&element;
     &cplace-r; <replaceable>index&sub-1;</replaceable> ...
     <replaceable>index&sub-n;</replaceable>)</literal></term>
<listitem><simpara>Array element: If &cplace-r; is of foreign type
  <literal role="sexp">(c-array &ctype-r;
  <replaceable>dim&sub-1;</replaceable>
  ... <replaceable>dim&sub-n;</replaceable>)</literal>
  and 0 &le; <replaceable>index&sub-1;</replaceable>
  &lt; <replaceable>dim&sub-1;</replaceable>, ..., 0
  &le; <replaceable>index&sub-n;</replaceable> &lt;
  <replaceable>dim&sub-n;</replaceable>, this will be
  the place corresponding to <literal role="sexp">(&aref;
  &cplace-r; <replaceable>index&sub-1;</replaceable>
  ... <replaceable>index&sub-n;</replaceable>)</literal> or
  <varname>&cplace-r;[<replaceable>index&sub-1;</replaceable>]...[<replaceable>index&sub-n;</replaceable>]</varname>.
  It is a place of type &ctype-r;.
  If &cplace-r; is of foreign type <literal role="sexp">(&c-array-max;
  &ctype-r; <replaceable>dim</replaceable>)</literal> and 0 &le;
  <replaceable>index</replaceable> &lt; <replaceable>dim</replaceable>,
  this will be the place corresponding to <literal role="sexp">(&aref;
  &cplace-r; <replaceable>index</replaceable>)</literal> or
  <varname>&cplace-r;[<replaceable>index</replaceable>]</varname>.
  It is a place of type &ctype-r;.
</simpara></listitem></varlistentry>

<varlistentry id="deref"><term><literal role="sexp">(&deref;
                &cplace-r;)</literal></term>
<listitem><simpara>Dereference pointer: If
  &cplace-r; is of foreign type
  <literal role="sexp">(&c-ptr; &ctype-r;)</literal> or
  <literal role="sexp">(&c-ptr-null; &ctype-r;)</literal>,
  this will be the place the pointer points to.
  It is a place of type &ctype-r;.
  For <literal role="sexp">(&c-ptr-null; &ctype-r;)</literal>,
  the &cplace-r; may not be &c-NULL;.
</simpara></listitem></varlistentry>

<varlistentry id="slot"><term><literal role="sexp">(&slot;
       &cplace-r; <replaceable>slot-name</replaceable>)</literal></term>
<listitem><simpara>Struct or union component: If &cplace-r; is of
  foreign type <literal role="sexp">(&c-struct; &class-r;
  ... (<replaceable>slot-name</replaceable> &ctype-r;) ...)</literal> or
  of type <literal role="sexp">(&c-union;
  ... (<replaceable>slot-name</replaceable> &ctype-r;) ...)</literal>,
  this will be of type &ctype-r;.
  </simpara></listitem></varlistentry>

<varlistentry id="cast"><term><literal role="sexp">(&cast;
           &cplace-r; &ctype-r;)</literal></term>
<listitem><simpara>Type change: A place denoting the same memory
  locations as the original &cplace-r;, but of type &ctype-r;.
 </simpara></listitem></varlistentry>

<varlistentry id="typeof"><term><literal role="sexp">(&typeof;
    &cplace-r;)</literal></term>
<listitem><simpara>returns the &ctype-r; corresponding to the &cplace-r;.
  </simpara></listitem></varlistentry>

<varlistentry id="sizeof">
  <term><literal role="sexp">(&sizeof; &ctype-r;)</literal>,
        <literal role="sexp">(&sizeof; &cplace-r;)</literal></term>
<listitem><simpara>The first form returns the size and alignment of a
  &c-lang; type &ctype-r;, measured in bytes.</simpara>
  <simpara>The second form returns the size and alignment of the
  &c-lang; type of &cplace-r;, measured in bytes.
  </simpara></listitem></varlistentry>

<varlistentry id="bitsizeof">
  <term><literal role="sexp">(&bitsizeof; &ctype-r;)</literal>,
        <literal role="sexp">(&bitsizeof; &cplace-r;)</literal></term>
<listitem><simpara>The first form returns the size and alignment of the
  &c-lang; type &ctype-r;, measured in bits.</simpara>
  <simpara>The second form returns the size and alignment of the
  &c-lang; type of &cplace-r;, measured in bits.
 </simpara></listitem></varlistentry>

<varlistentry id="validp"><term><literal role="sexp">(&validp;
                <replaceable>foreign-entity</replaceable>)</literal></term>
<listitem><simpara>This predicate returns &nil; if the
  <replaceable>foreign-entity</replaceable> (e.g. the Lisp equivalent of
  a <function>c-pointer</function>) refers to a pointer which is invalid
  because it comes from a previous Lisp session.  It returns &t; if
  <replaceable>foreign-entity</replaceable> can be used within the
  current Lisp process.</simpara></listitem></varlistentry>
</variablelist>

</section>

<section id="dffi-types"><title>(Foreign) &c-lang; types</title>

<para>Foreign &c-lang; types are used in the &ffi-pac;.
They are <emphasis>not</emphasis> regular &cl; types or &clos;
classes.</para>

<para>A &ctype-r; is either a predefined &c-lang; type or the name of a
 type defined by &def-c-type;.</para>

<variablelist><title>the predefined &c-lang; types (&ctype-r;)</title>
<varlistentry id="simple-c-type">
   <term><replaceable>simple-c-type</replaceable></term>
<listitem><table frame="all"><title>the simple &c-lang; types</title>
 <tgroup cols="5" colsep="1" rowsep="1" align="center">
 <thead><row><entry>Lisp name</entry><entry>Lisp equivalent</entry>
 <entry>&c-lang; equivalent</entry><entry>ILU
 equivalent</entry><entry>Comment</entry></row></thead><tbody>
<row><entry>&nil;</entry><entry>&nil;</entry><entry><type>void</type></entry>
   <entry/><entry>as a result type only</entry></row>
<row><entry>&boolean-type;</entry><entry>&boolean-type;</entry>
   <entry><type>int</type></entry><entry><type>BOOLEAN</type></entry></row>
<row><entry>&character-class;</entry><entry>&character-class;</entry>
   <entry><type>char</type></entry>
   <entry><type>SHORT CHARACTER</type></entry></row>
<row><entry><type>char</type></entry><entry>&integer-class;</entry>
   <entry><type>signed char</type></entry></row>
<row><entry><type>uchar</type></entry><entry>&integer-class;</entry>
   <entry><type>unsigned char</type></entry></row>
<row><entry><type>short</type></entry><entry>&integer-class;</entry>
   <entry><type>short</type></entry></row>
<row><entry><type>ushort</type></entry><entry>&integer-class;</entry>
   <entry><type>unsigned short</type></entry></row>
<row><entry><type>int</type></entry><entry>&integer-class;</entry>
   <entry><type>int</type></entry></row>
<row><entry><type>uint</type></entry><entry>&integer-class;</entry>
   <entry><type>unsigned int</type></entry></row>
<row><entry><type>long</type></entry><entry>&integer-class;</entry>
   <entry><type>long</type></entry></row>
<row><entry><type>ulong</type></entry><entry>&integer-class;</entry>
   <entry><type>unsigned long</type></entry></row>
<row><entry><type>uint8</type></entry><entry>&unsigned-byte-8;</entry>
   <entry><type>uint8</type></entry><entry><type>BYTE</type></entry></row>
<row><entry><type>sint8</type></entry><entry>&signed-byte-8;</entry>
   <entry><type>sint8</type></entry></row>
<row><entry><type>uint16</type></entry><entry>&unsigned-byte-16;</entry>
   <entry><type>uint16</type></entry>
   <entry><type>SHORT CARDINAL</type></entry></row>
<row><entry><type>sint16</type></entry><entry>&signed-byte-16;</entry>
   <entry><type>sint16</type></entry>
   <entry><type>SHORT INTEGER</type></entry></row>
<row><entry><type>uint32</type></entry><entry>&unsigned-byte-32;</entry>
   <entry><type>uint32</type></entry><entry><type>CARDINAL</type></entry></row>
<row><entry><type>sint32</type></entry><entry>&signed-byte-32;</entry>
   <entry><type>sint32</type></entry><entry><type>INTEGER</type></entry></row>
<row><entry><type>uint64</type></entry>
   <entry><literal role="sexp">(&unsigned-byte-type; 64)</literal></entry>
   <entry><type>uint64</type></entry><entry><type>LONG CARDINAL</type></entry>
   <entry>does not work on all platforms</entry></row>
<row><entry><type>sint64</type></entry>
   <entry><literal role="sexp">(&signed-byte-type; 64)</literal></entry>
   <entry><type>sint64</type></entry><entry><type>LONG INTEGER</type></entry>
   <entry>does not work on all platforms</entry></row>
<row><entry>&single-float-type;</entry><entry>&single-float-type;</entry>
   <entry><type>float</type></entry></row>
<row><entry>&double-float-type;</entry><entry>&double-float-type;</entry>
   <entry><type>double</type></entry></row>
</tbody></tgroup></table></listitem></varlistentry>

<varlistentry id="c-pointer"><term>&c-pointer;</term>
 <listitem><simpara>This type corresponds to what &c-lang; calls
  <type>void*</type>, an opaque pointer.
 </simpara></listitem></varlistentry>

<varlistentry id="c-string"><term>&c-string;</term>
 <listitem><simpara>This type corresponds to what &c-lang; calls
  <type>char*</type>, a zero-terminated string.  Its Lisp equivalent is
  a string, without the trailing zero character.
 </simpara></listitem></varlistentry>

<varlistentry id="c-struct"><term><literal role="sexp">(&c-struct; &class-r;
  (<replaceable>ident&sub-1;</replaceable>
   <replaceable>c-type&sub-1;</replaceable>) ...
  (<replaceable>ident&sub-n;</replaceable>
   <replaceable>c-type&sub-n;</replaceable>))</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
 <type>struct { <replaceable>c-type&sub-1;</replaceable>
 <replaceable>ident&sub-1;</replaceable>; ...;
 <replaceable>c-type&sub-n;</replaceable>
 <replaceable>ident&sub-n;</replaceable>; }</type>.
 Its Lisp equivalent is: if &class-r; is &vector-class;, a
 &simple-vector-type;; if &class-r; is &list-class;, a list; if
 &class-r; is a symbol naming a structure or &clos; class, an instance
 of this class, with slots of names <replaceable>ident&sub-1;</replaceable>,
 ... ,<replaceable>ident&sub-n;</replaceable>.
 </simpara></listitem></varlistentry>

<varlistentry id="c-union"><term><literal role="sexp">(&c-union;
  (<replaceable>ident&sub-1;</replaceable>
   <replaceable>c-type&sub-1;</replaceable>) ...
  (<replaceable>ident&sub-n;</replaceable>
   <replaceable>c-type&sub-n;</replaceable>))</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
  <type>union { <replaceable>c-type&sub-1;</replaceable>
  <replaceable>ident&sub-1;</replaceable>; ...;
  <replaceable>c-type&sub-n;</replaceable>
  <replaceable>ident&sub-n;</replaceable>;
  }</type>.
  Conversion to and from Lisp assumes that a value is to be viewed as
  being of <replaceable>c-type&sub-1;</replaceable>.
 </simpara></listitem></varlistentry>

<varlistentry id="c-array"><term><literal role="sexp">(&c-array;
   &ctype-r; <replaceable>dim&sub-1;</replaceable> ...
   <replaceable>dim&sub-n;</replaceable>)</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
  <type>&ctype-r; [<replaceable>dim&sub-1;</replaceable>]
  ... [<replaceable>dim&sub-n;</replaceable>]</type>.
  Note that when an array is passed as an argument to a function in
  &c-lang;, it is actually passed as a pointer; you therefore have to
  write <literal role="sexp">(&c-ptr; (&c-array; ...))</literal> for this
  argument's type.</simpara></listitem></varlistentry>

<varlistentry id="c-array-max"><term><literal role="sexp">(&c-array-max;
  &ctype-r; &maxdim-r;)</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
  <type>&ctype-r; [&maxdim-r;]</type>, an array containing up to
  &maxdim-r; elements.
  The array is zero-terminated if it contains less than &maxdim-r; elements.
  Conversion from Lisp of an array with more than &maxdim-r; elements
  silently ignores the superfluous elements.
  </simpara></listitem></varlistentry>

<varlistentry id="c-function"><term><literal
   role="sexp">(&c-function; (&arguments-k;
      {(<replaceable>arg-name</replaceable> <replaceable>a-c-type</replaceable>
        [&param-mode; [&allocation;]])}*)
    (<constant>:return-type</constant> <replaceable>r-c-type</replaceable>
       [&allocation;])
    (&lang-k; &lang-r;))</literal></term>
 <listitem><simpara>This type designates a &c-lang; function that can be
  called according to the given prototype <literal
  role="sexp">(<replaceable>r-c-type</replaceable> (*)
  (<replaceable>a-c-type&sub-1;</replaceable>, ...))</literal>.
  Conversion between &c-lang; functions and Lisp functions
  is transparent.</simpara></listitem></varlistentry>

<varlistentry id="c-ptr"><term><literal role="sexp">(&c-ptr;
              &ctype-r;)</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
  <type>&ctype-r; *</type>: a pointer to a single item of the given
  &ctype-r;.</simpara></listitem></varlistentry>

<varlistentry id="c-ptr-null"><term><literal
   role="sexp">(&c-ptr-null; &ctype-r;)</literal></term>
 <listitem><simpara>This type is also equivalent to what &c-lang; calls
  <type>&ctype-r; *</type>: a pointer to a single item of the given
  &ctype-r;, with the exception that &c-lang; &c-NULL; corresponds to
  Lisp &nil;.</simpara></listitem></varlistentry>

<varlistentry id="c-array-ptr"><term><literal
   role="sexp">(&c-array-ptr; &ctype-r;)</literal></term>
 <listitem><simpara>This type is equivalent to what &c-lang; calls
  <type>&ctype-r; (*)[]</type>: a pointer to a zero-terminated array of
  items of the given &ctype-r;.</simpara></listitem></varlistentry>
</variablelist>
</section>

<section id="c-flavor"><title>The choice of the &c-lang; flavor.</title>

<para>&c-function;, &def-call-in;, &def-call-out; take &lang-k; argument.
The &lang-r; is either &c-k; (denotes K&amp;R &c-lang;) or &stdc-k;
(denotes ANSI &c-lang;) or &stdc-sc-k; (denotes ANSI &c-lang;
with <emphasis>stdcall</emphasis> calling convention).
It specifies whether the &c-lang; function (caller or callee) has been
compiled by a K&amp;R &c-lang; compiler or by an ANSI &c-lang; compiler,
and possibly the calling convention.</para></section>

<section id="dffi-variables"><title>Foreign variables</title>

<para>Foreign variables are variables whose storage is allocated in the
 foreign language module.  They can nevertheless be evaluated and
 modified through &setq;, just as normal variables can, except that the
 range of allowed values is limited according to the variable's foreign
 type.  Note that for a foreign variable &x-r; the form <literal
 role="sexp">(&eql; &x-r; &x-r;)</literal> is not necessarily true,
 since every time &x-r; is evaluated its foreign value is converted to a
 freshly created Lisp value.  Foreign variables are defined using
 &def-c-var;.</para>

</section>

<section id="dffi-places"><title>Operations on foreign places</title>

<para>A foreign variable &name-r; defined by &def-c-var; defines a
 "place", i.e., a form which can also be used as argument to &setf;.
 (An "lvalue" in &c-lang; terminology.)  The following operations are
 available on foreign places: &element;, &deref;, &slot;, &cast;,
 &typeof;, &sizeof;, &bitsizeof;.</para>

</section>

<section id="dffi-functions"><title>Foreign functions</title>

<para>Foreign functions are functions which are defined in the foreign
 language.  There are <emphasis>named foreign functions</emphasis>
 (imported via &def-call-out; or created via &def-call-in;) and
 <emphasis>anonymous foreign functions</emphasis>; they arise through
 conversion of function pointers.</para>

<para>A <emphasis>"call-out"</emphasis> function is a foreign function
 called from Lisp: control flow temporarily leaves Lisp.  A
 <emphasis>"call-in"</emphasis> function is a Lisp function called from
 the foreign language: control flow temporary enters Lisp.</para>

<para>The following forms define foreign functions: &def-call-in;,
 &def-call-out;, &def-c-call-in;, &def-c-call-out;.</para>

</section>

<section id="allocation"><title>Argument and result passing conventions</title>

<para>When passed to and from functions, allocation of arguments and
 results is handled as follows:</para>

<para>Values of &simple-c-type;, &c-pointer; are passed on the stack,
 with dynamic extent. The &allocation; is effectively ignored.</para>

<para>Values of type &c-string;, &c-ptr;, &c-ptr-null;, &c-array-ptr;
 need storage.  The &allocation; specifies the allocation policy:</para>

<table frame="all"><title>allocation policy</title>
 <tgroup cols="2" colsep="1" rowsep="1" align="left">
 <thead><row><entry>&allocation;</entry>
        <entry>meaning</entry></row></thead><tbody>
<row><entry>&none-k;</entry>
   <entry>no storage is allocated.</entry></row>
<row><entry>&alloca-k;</entry><entry>allocation of storage on the
   stack, which has dynamic extent.</entry></row>
<row><entry>&malloc-free-k;</entry><entry>storage will be allocated via
   &malloc; and freed via &free;.</entry></row>
</tbody></tgroup></table>

<para>If no &allocation; is specified, the default &allocation; is
 &none-k; for most types, but &alloca-k; for &c-string; and &c-ptr; and
 &c-ptr-null; and &c-array-ptr; and for &out-k; arguments. [Subject to
 change!]  The &malloc-free-k; policy provides the ability to pass
 arbitrarily nested structs containing pointers pointing to structs
 ... within a single conversion.</para>

<variablelist>
<varlistentry><term>For call-out functions:</term>
<listitem><variablelist>
 <varlistentry><term>For arguments passed from Lisp to &c-lang;:</term>
  <listitem><variablelist>
   <varlistentry><term>If &allocation; is &malloc-free-k;:</term>
    <listitem><simpara>Lisp allocates the storage using &malloc; and
     never deallocates it.  The &c-lang; function is supposed to call
     &free; when done with it.</simpara></listitem></varlistentry>
   <varlistentry><term>If &allocation; is &alloca-k;:</term>
    <listitem><simpara>Lisp allocates the storage on the stack, with
     dynamic extent.  It is freed when the &c-lang; function returns.
    </simpara></listitem></varlistentry>
   <varlistentry><term>If &allocation; is &none-k;:</term>
    <listitem><simpara>Lisp assumes that the pointer already points to a
     valid area of the proper size and puts the result value there.
     This is dangerous! and deprecated.
    </simpara></listitem></varlistentry></variablelist>
  </listitem></varlistentry>
 <varlistentry><term>For results passed from &c-lang; to Lisp:</term>
  <listitem><variablelist>
   <varlistentry><term>If &allocation; is &malloc-free-k;:</term>
    <listitem><simpara>Lisp calls &free; on it when done.
    </simpara></listitem></varlistentry>
   <varlistentry><term>If &allocation; is &none-k;:</term>
    <listitem><simpara>Lisp does nothing.
    </simpara></listitem></varlistentry></variablelist>
  </listitem></varlistentry></variablelist></listitem></varlistentry>
<varlistentry><term>For call-in functions:</term>
 <listitem><variablelist>
  <varlistentry><term>For arguments passed from &c-lang; to Lisp:</term>
   <listitem><variablelist>
    <varlistentry><term>If &allocation; is &malloc-free-k;:</term>
     <listitem><simpara>Lisp calls &free; on it when done.
     </simpara></listitem></varlistentry>
    <varlistentry><term>If &allocation; is &alloca-k; or &none-k;:</term>
     <listitem><simpara>Lisp does nothing.
     </simpara></listitem></varlistentry></variablelist>
   </listitem></varlistentry>
  <varlistentry><term>For results passed from Lisp to &c-lang;:</term>
   <listitem><variablelist>
    <varlistentry><term>If &allocation; is &malloc-free-k;:</term>
     <listitem><simpara>Lisp allocates the storage using &malloc; and
      never deallocates it.  The &c-lang; function is supposed to call
      &free; when done with it.</simpara></listitem></varlistentry>
   <varlistentry><term>If &allocation; is &none-k;:</term>
    <listitem><simpara>Lisp assumes that the pointer already points to a
     valid area of the proper size and puts the result value there.
     This is dangerous! and deprecated.
    </simpara></listitem></varlistentry></variablelist>
 </listitem></varlistentry></variablelist></listitem></varlistentry>
</variablelist>

<para id="param-mode">A function parameter's &param-mode; may be</para>

<variablelist>
 <varlistentry><term>&in-k; (means: read-only):</term>
  <listitem><simpara>The caller passes information to the callee.
  </simpara></listitem></varlistentry>
 <varlistentry><term>&out-k; (means: write-only):</term>
  <listitem><simpara>The callee passes information back to the caller on
   return.  When viewed as a Lisp function, there is no Lisp argument
   corresponding to this, instead it means an additional return value.
  </simpara></listitem></varlistentry>
 <varlistentry><term><constant>:IN-OUT</constant> (means: read-write):</term>
  <listitem><simpara>Information is passed from the caller to the callee
   and then back to the caller.  When viewed as a Lisp function, the
   &out-k; value is returned as an additional multiple value.
  </simpara></listitem></varlistentry>
</variablelist>

<para>The default is &in-k;.</para>

<para>[Currently, only &in-k; is fully implemented.  &out-k; works only
 with &allocation; = &alloca-k;.]</para>

<variablelist>
<varlistentry><term>Platform dependent: &amiga; platforms only.</term>
<listitem><simpara>&allocation; may not be &malloc-free-k; because there
 is no commonly used &malloc;/&free; library function.</simpara>

 <simpara>The &allocation; may be followed by a register specification,
 any of the symbols <constant>:d0</constant>, <constant>:d1</constant>,
 <constant>:d2</constant>, <constant>:d3</constant>,
 <constant>:d4</constant>, <constant>:d5</constant>,
 <constant>:d6</constant>, <constant>:d7</constant>,
 <constant>:a0</constant>, <constant>:a1</constant>,
 <constant>:a2</constant>, <constant>:a3</constant>,
 <constant>:a4</constant>, <constant>:a5</constant>,
 <constant>:a6</constant>, each representing one 680x0 register.
 This works only for integral types: integers, pointers, &c-string;,
 &c-function;.
</simpara></listitem></varlistentry></variablelist>

<para>Passing &c-struct;, &c-union;, &c-array;, &c-array-max; values as
 arguments (not via pointers) is only possible to the extent the &c-lang;
 compiler supports it. Most &c-lang; compilers do it right, but some
 &c-lang; compilers (such as gcc on hppa) have problems with this.</para>

<!-- #ifdef UNICODE -->
<para>See also &foreign-enc;.</para>
<!-- #endif -->

</section>

<section id="dffi-examples"><title>Examples</title>

<example><title>Simple declarations and access</title>

<para>The &c-lang; declaration

<programlisting>
struct foo {
    int a;
    struct foo * b[100];
};
</programlisting>

corresponds to

<programlisting>
(def-c-struct foo
  (a int)
  (b (c-array (c-ptr foo) 100)))
</programlisting></para>

<para>The element access

<programlisting>
struct foo f;
f.b[7].a
</programlisting>

corresponds to

<programlisting>
(declare (type foo f))
(foo-a (aref (foo-b f) 7)) or (slot-value (aref (slot-value f 'b) 7) 'a)
</programlisting></para></example>

<example><title>external &c-lang; variable and some accesses</title>

<para><programlisting>
struct bar {
    short x, y;
    char a, b;
    int z;
    struct bar * n;
};

extern struct bar * my_struct;

my_struct-&gt;x++;
my_struct-&gt;a = 5;
my_struct = my_struct-&gt;n;
</programlisting>

corresponds to

<programlisting>
(def-c-struct bar
  (x short)
  (y short)
  (a char)
  (b char) ; or (b character) if it represents a character, not a number
  (z int)
  (n (c-ptr bar)))

(def-c-var my_struct (:type (c-ptr bar)))

(setq my_struct (let ((s my_struct)) (incf (slot-value s 'x)) s))
or (incf (slot my_struct 'x))
(setq my_struct (let ((s my_struct)) (setf (slot-value s 'a) 5) s))
or (setf (slot my_struct 'a) 5)
(setq my_struct (slot-value my_struct 'n))
or (setq my_struct (deref (slot my_struct 'n)))
</programlisting></para></example>

<example><title>Calling an external function</title>

<para>On ANSI &c-lang; systems, <filename>stdlib.h</filename> contains
the declarations:

<programlisting>
typedef struct {
  int quot;   /* Quotient */
  int rem;    /* Remainder */
} div_t;
extern div_t div (int numer, int denom);
</programlisting>

This translates to

<programlisting>
(def-c-struct div_t
  (quot int)
  (rem int))
(def-c-call-out div (:arguments (numer int) (denom int))
                    (:return-type div_t))
</programlisting>

Sample call from within Lisp:

<programlisting>
&gt; (div 20 3)
#S(DIV :QUOT 6 :REM 2)
</programlisting></para></example>

<example><title>Another example for calling an external function</title>

<para>Suppose the following is defined in a file
 <filename>cfun.c</filename>:

<programlisting>
struct cfunr { int x; char *s; };
struct cfunr * cfun (int i,char *s,struct cfunr * r,int a[10]) {
  int j;
  struct cfunr * r2;
  printf("i = %d\n", i);
  printf("s = %s\n", s);
  printf("r-&gt;x = %d\n", r-&gt;x);
  printf("r-&gt;s = %s\n", r-&gt;s);
  for (j = 0; j &lt; 10; j++) printf("a[%d] = %d.\n", j, a[j]);
  r2 = (struct cfunr *) malloc (sizeof (struct cfunr));
  r2-&gt;x = i+5;
  r2-&gt;s = "A C string";
  return r2;
}
</programlisting>

It is possible to call this function from Lisp using the file
<filename>callcfun.lisp</filename> (do not call it
<filename>cfun.lisp</filename> - &compile-file; would overwrite
<filename>cfun.c</filename>) whose contents is:

<programlisting>
(&defpackage; "TEST-C-CALL" (:use "LISP" "FFI"))
(&in-package; "TEST-C-CALL")
(def-c-struct cfunr (x int) (s c-string))
(def-c-call-out cfun (:arguments (i int)
                                 (s c-string)
                                 (r (c-ptr cfunr) :in :alloca)
                                 (a (c-ptr (c-array int 10)) :in :alloca))
                     (:return-type (c-ptr cfunr)))
(defun call-cfun ()
  (cfun 5 "A Lisp string" (make-cfunr :x 10 :s "Another Lisp string")
        '#(0 1 2 3 4 5 6 7 8 9)))
</programlisting>

Use the module facility:

<programlisting>
$ clisp-link create-module-set cfun callcfun.c
$ cc -O -c cfun.c
$ cd cfun
$ ln -s ../cfun.o cfun.o
Add cfun.o to NEW_LIBS and NEW_FILES in link.sh.
$ cd ..
$ base/lisp.run -M base/lispinit.mem -c callcfun.lisp
$ clisp-link add-module-set cfun base base+cfun
$ base+cfun/lisp.run -M base+cfun/lispinit.mem -i callcfun
&gt; (test-c-call::call-cfun)
i = 5
s = A Lisp string
r-&gt;x = 10
r-&gt;s = Another Lisp string
a[0] = 0.
a[1] = 1.
a[2] = 2.
a[3] = 3.
a[4] = 4.
a[5] = 5.
a[6] = 6.
a[7] = 7.
a[8] = 8.
a[9] = 9.
#S(TEST-C-CALL::CFUNR :X 10 :S "A C string")
&gt;
$ rm -r base+cfun
</programlisting></para>

<para>Note that there is a memory leak here: The return value
<varname>r2</varname> of <function>cfun()</function> is
&malloc;ed but never &free;d. Specifying

<programlisting>
(:return-type (c-ptr cfunr) :malloc-free)
</programlisting>

is not an alternative because this would also

<function>free(r2-&gt;x)</function> but <varname>r2-&gt;x</varname> is a
pointer to static data.</para></example>

<example><title>call-in</title>

<para>To sort an array of double-floats using the Lisp function
 <function>sort</function> instead of the &c-lang; library function
 <function>qsort()</function>, one can use the following interface code
 <filename>sort1.c</filename>.  The main problem is to pass a
 variable-sized array.

<programlisting>
extern void lispsort_begin (int);
void* lispsort_function;
void lispsort_double (int n, double * array) {
    double * sorted_array;
    int i;
    lispsort_begin(n); /* store #'sort2 in lispsort_function */
    sorted_array = ((double * (*) (double *)) lispsort_function) (array);
    for (i = 0; i &lt; n; i++) array[i] = sorted_array[i];
    free(sorted_array);
}
</programlisting>

This is accompanied by <filename>sort2.lisp</filename>:

<programlisting>
(&defpackage; "FFI-TEST" (:use "LISP" "FFI"))
(&in-package; "FFI-TEST")
(def-call-in lispsort_begin (:arguments (n int))
                            (:return-type nil)
                            (:language :stdc))
(def-c-var lispsort_function (:type c-pointer))
(defun lispsort_begin (n)
  (setf (cast lispsort_function
              `(c-function
                 (:arguments (v (c-ptr (c-array double-float ,n))))
                 (:return-type (c-ptr (c-array double-float ,n))
                               :malloc-free)))
        #'sort2))
(defun sort2 (v)
  (declare (type vector v))
  (sort v #'&lt;))
</programlisting>

To test this, use the following test file <filename>sorttest.lisp</filename>:

<programlisting>
(def-call-out sort10
              (:name "lispsort_double")
              (:language :stdc)
              (:arguments (n int)
                          (array (c-ptr (c-array double-float 10))
                                 :in-out)))
</programlisting>

Now try

<programlisting>
$ clisp-link create-module-set sort sort2.c sorttest.c
$ cc -O -c sort1.c
$ cd sort
$ ln -s ../sort1.o sort1.o
Add sort1.o to NEW_LIBS and NEW_FILES in link.sh.
$ cd ..
$ base/lisp.run -M base/lispinit.mem -c sort2.lisp sorttest.lisp
$ clisp-link add-module-set sort base base+sort
$ base+sort/lisp.run -M base+sort/lispinit.mem -i sort2 sorttest
&gt; (sort10 10 '#(0.501d0 0.528d0 0.615d0 0.550d0 0.711d0
                0.523d0 0.585d0 0.670d0 0.271d0 0.063d0))
#(0.063d0 0.271d0 0.501d0 0.523d0 0.528d0 0.55d0 0.585d0 0.615d0 0.67d0 0.711d0)
$ rm -r base+sort
</programlisting></para></example>

</section>
</section>
<!-- #endif -->


<!-- #ifdef HAVE_AFFI -->

<section id="affi">
  <title>Extensions-2.4. The Amiga Foreign Function Call Facility</title>
<subtitle>Platform dependent: &amiga; platforms only.</subtitle>

<formalpara><title>Another Foreign Function Interface</title>
<para>All symbols relating to the simple foreign function interface are
 exported from the package &affi-pac;. To use them,
 <literal role="sexp">(&use-package; "AFFI")</literal>.</para>
</formalpara>

<section id="affi-design"><title>Design issues</title>

<para>&affi-pac; was designed to be small in size but powerful enough to
use most library functions.  Lisp files may be compiled to &fasl-file;
files without the need to load function definition files at run-time and
without external &c-lang; or linker support.
&mem-image;s can be created, provided that the function libraries are
opened at run-time.</para>

<para>Therefore, &affi-pac; supports only primitive &c-lang; types (integers
8, 16 and 32 bits wide, signed or unsigned, pointers) and defines no new
types or classes.  Foreign functions are not first-class objects (you
can define a lambda yourself), name spaces are separate.</para>

<para>The &affi-pac; does no tracking of resources.  Use &finalize;.</para>

</section>

<section id="affi-overview"><title>Overview</title>

<para>These are the &affi-pac; forms:</para>

<para><literal role="sexp">(declare-library-base
 <replaceable>keyword-base</replaceable>
 <replaceable>library-name</replaceable>)</literal></para>

<para><literal role="sexp">(require-library-functions
 <replaceable>library-name</replaceable> [(:import
 {<replaceable>string-name</replaceable>}*)])</literal></para>

<para><literal role="sexp">(open-library
 <replaceable>base-symbol</replaceable>)</literal></para>

<para><literal role="sexp">(clos-library
 <replaceable>base-symbol</replaceable>)</literal></para>

<para><literal role="sexp">(with-open-library
 (<replaceable>base-symbol</replaceable> |
 <replaceable>library-name</replaceable>)
 {&form-r;}*)</literal></para>

<para><literal role="sexp">(defflibfun
 <replaceable>function-name</replaceable>
 <replaceable>base-symbol</replaceable>
 <replaceable>offset</replaceable> <replaceable>mask</replaceable>
 <replaceable>result-type</replaceable>
 {<replaceable>argument-type</replaceable>}*)</literal></para>

<para><literal role="sexp">(declare-library-function
 <replaceable>function-name</replaceable>
 <replaceable>library-name</replaceable>
 {&option-r;}*)</literal></para>

<para><literal role="sexp">(flibcall <replaceable>function-name</replaceable>
 {<replaceable>argument</replaceable>}*)</literal></para>

<para><literal role="sexp">(mlibcall <replaceable>function-name</replaceable>
 {<replaceable>argument</replaceable>}*)</literal></para>

<para><literal role="sexp">(mem-read <replaceable>address</replaceable>
 <replaceable>result-type</replaceable>
 [<replaceable>offset</replaceable>])</literal></para>

<para><literal role="sexp">(mem-write <replaceable>address</replaceable>
 &type-r; &value-r; [<replaceable>offset</replaceable>])</literal></para>

<para><literal role="sexp">(mem-write-vector
 <replaceable>address</replaceable> <replaceable>vector</replaceable>
 [<replaceable>offset</replaceable>])</literal></para>

<para><literal role="sexp">(nzero-pointer-p &value-r;)</literal></para>

<para>Except for <function>with-open-library</function>,
<function>declare-library-function</function> and
<function>mlibcall</function>, all of the above are functions.</para>

<para>A library contains a collection of functions.  The library is
referred to by a symbol referred as library-base at the &affi-pac;
level.  This symbol is created in the package <quote>&affi-pac;</quote>.
The link between this symbol and the OS-level library name is
established by <function>declare-library-base</function>.  To avoid
multiple package conflicts, this and only this function requires the
symbol-name to be in the &kwd-pac; package. The function returns the
library-base.</para>

<para>A library may be opened by <function>open-library</function> and
 closed by <function>close-library</function>. An opened library must be
 closed. <function>with-open-library</function> is provided to
 automatically close the library for you, thus it is much safer to
 use.</para>

<para>A function is contained in a library.  Every function is referred
to by a symbol.  A function is defined through
<function>defflibfun</function> or
<function>declare-library-function</function> by giving the function
name, the library-base, an offset into the library, a mask (or &nil;)
for register-based library calls, the result type and all
parameter-types.  <function>require-library-functions</function> loads
the complete set of functions defined in a library file. Symbols are
created in the package <quote>&affi-pac;</quote> and imported into the
current package.</para>

<para><function>flibcall</function> and <function>mlibcall</function>
call library functions. <function>mlibcall</function> is a macro that
does a few checks at macroexpansion time and allows the compiler to
inline the call, not requiring the foreign function to be defined again
at load or execution time. The use of this macro is advertised wherever
possible.</para>

<para><function>mem-read</function> reads an arbitrary address (with
offset for structure references) and returns the given type.</para>

<para><function>mem-write</function> writes an arbitrary
address. <function>mem-write-vector</function> copies the content of a
Lisp &string-class; or &unsigned-byte-vec; into memory.</para>

<para><function>nzero-pointer-p</function> tests for
non-&c-NULL; pointers in all recognized representations
(&null-class;, &unsigned-byte-type; and &foreign-pointer;).</para>

</section>

<section id="affi-libs"><title>Foreign Libraries</title>

<para><function>declare-library-base</function> ought to be wrapped in an
<literal role="sexp">(&eval-when; (compile eval load) ...)</literal>
form and come before any function is referenced, because the library
base symbol must be known.</para>

<para><function>open-library</function> tries to open the library
referenced by the base symbol.  Therefore it must have been preceded
with <function>declare-library-base</function>.  The call returns &nil;
on failure. <function>open-library</function> calls nest.  Every
successful call must be matched by <function>close-library</function>.
<function>with-open-library</function> does this for you and also allows
you to specify the library by name, provided that its base has been
declared.  It is recommended to use this macro and to reference the
library by name.</para>

<para>&clisp; will not close libraries for you at program exit.  [A
previous version did so but now &affi-pac; is a module and there are no
module exit functions.]  Programmers, watch
<function>AFFI::*LIBRARIES-ALIST*</function>.</para>

</section>

<section id="affi-types"><title>(Foreign) &c-lang; types</title>

<para>The following foreign &c-lang; types are used in &affi-pac;.
They are <emphasis>not</emphasis> regular &cl; types or &clos;
classes.</para>

<table frame="all"><title>foreign &c-lang; types used in &affi-pac;</title>
 <tgroup cols="5" colsep="1" rowsep="1" align="center">
 <thead><row><entry>&affi-pac; name</entry><entry>Lisp equivalent</entry>
 <entry>&c-lang; equivalent</entry><entry>Comment</entry></row></thead><tbody>
<row><entry>&nil;</entry><entry>&nil;</entry><entry><type>void</type></entry>
  <entry>as a result type for functions only</entry></row>
<row><entry><type>4</type></entry><entry>&unsigned-byte-32;</entry>
  <entry><type>unsigned long</type></entry><entry/></row>
<row><entry><type>2</type></entry><entry>&unsigned-byte-16;</entry>
  <entry><type>unsigned short</type></entry><entry/></row>
<row><entry><type>1</type></entry><entry>&unsigned-byte-8;</entry>
  <entry><type>unsigned char</type></entry><entry/></row>
<row><entry><type>-4</type></entry><entry>&signed-byte-32;</entry>
  <entry><type>long</type></entry><entry/></row>
<row><entry><type>-2</type></entry><entry>&signed-byte-16;</entry>
  <entry><type>short</type></entry><entry/></row>
<row><entry><type>-1</type></entry><entry>&signed-byte-8;</entry>
  <entry><type>signed char</type></entry><entry/></row>
<row><entry><type>0</type></entry><entry>&boolean-type;</entry>
  <entry><type>BOOL</type></entry>
  <entry>as a result type for functions only</entry></row>
<row><entry><type>*</type></entry><entry>opaque</entry>
  <entry><type>void*</type></entry><entry/></row>
<row><entry>&external-k;</entry><entry>opaque</entry>
  <entry><type>void*</type></entry><entry/></row>
<row><entry>&string-class;</entry>
  <entry>&string-class; or &vector-class;</entry>
  <entry><type>char*</type></entry><entry/></row>
<row><entry>&io-k;</entry>
  <entry>&string-class; or &vector-class;</entry>
  <entry><type>char*</type></entry><entry/></row>
</tbody></tgroup></table>

<para>Objects of type &string-class; are copied and passed
&c-NULL;-terminated on the execution stack.  On return, a Lisp string is
allocated and filled from the address returned (unless &c-NULL;).
Functions with &io-k; parameters are passed the address of the Lisp
string or unsigned byte vector. These are not &c-NULL;-terminated!
This is useful for functions like like <function>read()</function> which
do not need an array at a constant address longer than the dynamic
extent of the call (it is dangerous to define callback functions with
&io-k; (or &string-class;) type parameters).
Arguments of type &integer-class; and &foreign-pointer; are always
acceptable where a &string-class; or &io-k; type is specified.</para>

<!-- #ifdef UNICODE -->
<para>See also &foreign-enc;.</para>
<!-- #endif -->

<para>To meet the design goals, predefined types and objects were
used. As such, pointers were represented as integers. Now that there is
the &foreign-pointer; type, both representations may be used on input.
The pointer type should be therefore considered as opaque.
Use <function>nzero-pointer-p</function> for &c-NULL; tests.</para>

</section>

<section id="affi-functions"><title>Foreign functions</title>

<para>Foreign Functions are declared either through
<function>defflibfun</function> or
<function>declare-library-function</function>.  The former is closer to
the low-level implementation of the interface, the latter is closer to
the other &ffi-pac;.</para>

<para><function>defflibfun</function> requires the library base symbol
and register mask to be specified,
<function>declare-library-function</function> requires the library name
and computes the mask from the declaration of the arguments.</para>

<para>The value of mask is implementation-dependent. On the Amiga, it is
an integer whose hexadecimal value is the reverse of the function
argument register numbers, where d0 has number <literal>1</literal>
and a6 number <literal>#xF</literal>.  A &nil; mask is reserved for
stack-based calls (unimplemented).</para>

<para>The &affi-pac; type <literal>0</literal> is only acceptable as a
function result type and yields either &t; or &nil;. The difference
between <function>*</function> and &external-k; is the following:
<function>*</function> uses integers, &external-k; uses
&foreign-pointer; as function result-type (except from &nil; for a
&c-NULL; pointer) and refuses objects of type &string-class; or
&unsigned-byte-vec; as input.  Thus &external-k; provides some security
on the input and the ability to use &finalize; for resource-tracking on
the output side.</para>

<para><literal role="sexp">(declare-library-function &name-r;
 <replaceable>library-name</replaceable> {&option-r;}*)</literal>

<variablelist>
 <varlistentry><term>&option-r; ::==</term>
 <listitem><table frame="all" role="bnf"><title/>
  <tgroup cols="3" colsep="1" rowsep="1" align="left"><tbody>
  <row><entry/><entry><literal role="sexp">(:offset
    <replaceable>library-offset</replaceable>)</literal></entry></row>
  <row><entry>|</entry><entry><literal role="sexp">(&arguments-k;
    {(<replaceable>arg-name</replaceable>
    <replaceable>&affi-pac;-type</replaceable>
    <replaceable>register</replaceable>)}*)</literal></entry></row>
  <row><entry>|</entry><entry><literal role="sexp">(:return-type
    <replaceable>&affi-pac;-type</replaceable>)</literal></entry></row>
</tbody></tgroup></table></listitem></varlistentry>
<varlistentry><term><replaceable>register</replaceable> ::==</term>
 <listitem><simpara><constant>:d0</constant> | <constant>:d1</constant>
 | ... | <constant>:d7</constant> | <constant>:a0</constant> | ... |
 <constant>:a6</constant></simpara></listitem></varlistentry></variablelist>

declares a named library function for further reference through
<function>flibcall</function> and <function>mlibcall</function>.</para>

<para><function>mlibcall</function> should be the preferred way of
calling foreign functions (when they are known at compile-time) as
macroexpansion-time checks may be performed and the call can be sort of
inlined.</para>

</section>

<section id="affi-memory-access"><title>Memory access</title>

<para><literal role="sexp">(affi:mem-read <replaceable>address</replaceable>
&type-r;
<replaceable>offset</replaceable>)</literal> can read 8, 16 and 32 bit
signed or unsigned integers (&affi-pac; types <type>-4</type>,
<type>-2</type>, <type>-1</type>, <type>1</type>, <type>2</type>,
<type>4</type>), a pointer (<type>*</type>), a &c-NULL;-terminated
string (<type>string</type>) or, if the type argument is of type
&string-class; or &unsigned-byte-vec;, it can fill this vector.
&external-k; is not an acceptable type as no object can be created by
using <function>affi:mem-read</function>.</para>

<para><literal role="sexp">(affi:mem-write
<replaceable>address</replaceable> &type-r; &value-r;
[<replaceable>offset</replaceable>])</literal> writes integers (&affi-pac;
type <type>-4</type>, <type>-2</type>, <type>-1</type>, <type>1</type>,
<type>2</type> and <type>4</type>) or pointer values (type
<type>*</type>), but not vectors to the specified memory address.</para>

<para><literal role="sexp">(affi:mem-write-vector
<replaceable>address</replaceable> <replaceable>vector</replaceable>
[<replaceable>offset</replaceable>])</literal> can write memory from the
given vector (of type &string-class; or &unsigned-byte-vec;).</para>

</section>

<section id="affi-func-def"><title>Function Definition Files</title>

<para><function>affi:require-library-functions</function> will &require; a
file of name derived from thelibrary name and with type
<filename>affi</filename>. It may be used to import all names into the
current package or only a given subset identified by string names, using
the <constant>:import</constant> keyword (recommended use).
Some definition files for standard Amiga libraries are provided.
See <link linkend="affi-ex-1-predefined">example 1</link> below.</para>

<para>As <function>affi:require-library-functions</function> loads a
global file which you, the programmer, may have not defined, you may
consider declaring every function yourself to be certain what the return
and argument types are.
See <link linkend="affi-ex-4-sample">example 4</link> below.</para>

<para>The file <filename>read-fd.lisp</filename> defines the function
<function>make-partial-fd-file</function> with which the provided
<filename>.affi</filename> files have been prepared from the original
Amiga FD files (located in the directory <filename>FD:</filename>).
They must still be edited as the function cannot know whether a function
accepts a <function>*</function>, &io-k;,
<function>string</function> or &external-k; argument and because files
in <filename>FD:</filename> only contain a register specification, not
the width of integer arguments (<literal>-4</literal>,
<literal>-2</literal>, <literal>-1</literal>, <literal>1</literal>,
<literal>2</literal>, or <literal>4</literal>).</para>

</section>

<section id="affi-hints"><title>Hints</title>

<para>By using appropriate &eval-when; forms for
<function>affi:declare-library-base</function> and
<function>affi:require-library-functions</function> and not using
<function>affi:flibcall</function>, it is possible to write code that
only loads library function definition files at compile-time.
See <link linkend="affi-ex-1-predefined">example 1</link> below.</para>

<para>Do not rely on &finalize; to free resources for you, as &clisp;
does not call finalizers when it exits, use &unwind-protect;.</para>

</section>

<section id="affi-caveats"><title>Caveats</title>

<para>You can consider the library bases being symbols in need of being
imported from the package &affi-pac; originating from a brain-damage, causing
the usual symbol headaches when using foreign functions calls within
macros.  Luckily, even if the high-level interface (or its
implementation in <filename>affi1.lisp</filename>) were to change, the
low-level part (<filename>affi.d</filename>) should remain untouched as
all it knows are &integer-class;s and &foreign-pointer;s, no &symbol-class;s.
The difficulty is just to get the library base value at run-time.
Feel free to suggest enhancements to this facility!</para>

</section>

<section id="affi-examples"><title>Examples</title>
<subtitle>NB: These examples are somewhat specific to the Amiga.</subtitle>

<example id="affi-ex-1-predefined">
   <title>Using a predefined library function file</title>

<para><programlisting>
(&defpackage; "AFFI-TEST" (:use "LISP" "AFFI"))
(&in-package; "AFFI-TEST")

;; SysBase is the conventional name for exec.library
;; It is only enforced by the file loaded by REQUIRE-LIBRARY-FUNCTIONS
(eval-when (compile eval load)
  (declare-library-base :SysBase "exec.library")) ;keyword avoids name conflicts

;; using only MLIBCALL allows not to load definitions at load-time
(eval-when (compile eval)
  (require-library-functions "exec.library"
    :import '("FindTask")))

(with-open-library ("exec.library")
  (print (mlibcall FindTask 0)))
</programlisting>

This file can be used in interpreted and compiled mode.
Compiled, it will have inlined the library function calls.
</para></example>

<example id="affi-ex-2-flibcall"><title>Using flibcall</title>
<programlisting>
(&defpackage; "AFFI-TEST" (:use "LISP" "AFFI"))
(&in-package; "AFFI-TEST")

(eval-when (compile eval load)
  ;; keyword avoids name conflicts
  (declare-library-base :SysBase "exec.library"))

;; The load situation permits the use of flibcall
(eval-when (eval compile load)
  (require-library-functions "exec.library"))

(unless (open-library 'SysBase) (error "No library for SysBase"))
(flibcall (if t 'FindTask 'Debug) 0)
(close-library 'SysBase)
</programlisting></example>

<example id="affi-ex-3-dynamic">
   <title>Be fully dynamic, defining library bases ourselves</title>
<programlisting>
(&defpackage; "AFFI-TEST" (:use "LISP" "AFFI"))
(&in-package; "AFFI-TEST")

(eval-when (compile eval load)
  (defvar mylib (declare-library-base :foobase "foo.library")))
(eval-when (eval compile load)          ;eval allows mlibcall, load flibcall
  (defflibfun 'foo1 mylib -30 '#xA '* 'string)
  (defflibfun 'foo2 mylib -36 '#x21 0 * 4))

(defun foo (name)
  (when (open-library mylib)
    (list (mlibcall foo1 name) (flibcall 'foo2 name 123213))
    (close-library mylib)))
</programlisting></example>

<example id="affi-ex-4-sample"><title>Some sample function definitions</title>
<programlisting>
(defflibfun 'FindTask 'SysBase -294 #xA '* 'string)
(eval-library-function FindTask "exec.library"
  (:offset -294)
  (:return-type *)
  (:arguments
   (name   string   :A1)))
(declare-library-function NameFromLock "dos.library"
  (:offset -402)
  (:return-type 0)
  (:arguments
   (lock   4   :D1)
   (buffer :io :D2)
   (len    4   :D3)))

(eval-when (compile eval)
  (defconstant GVF_LOCAL_ONLY (ash 1 9))
  (defflibfun 'SetVar 'DosBase -900 #x5432 0 'string 'string -4 4))
(defun setvar (name value)
  (with-open-library (DosBase)
    ;; length of -1 means find length of &c-NULL;-terminated-string
    (mlibcall SetVar name value -1 GVF_LOCAL_ONLY)))
</programlisting></example>
</section>
</section>
<!-- #endif -->

<!-- #ifdef AMIGAOS -->
<section id="rexx"><title>Extensions-2.5. ARexx</title>
<subtitle>Platform dependent: &amiga; platforms only.</subtitle>

<para>&clisp; comes with a small yet extensible and powerful ARexx
 interface.</para>

<variablelist>
<varlistentry><term><literal role="sexp">(rexx-do-command
   "return address()" :string &t; :result &t;)</literal></term>
 <listitem><simpara>tells you the name of the &clisp; ARexx port.  The
  default extension for &clisp; ARexx scripts is <filename>cl</filename>.
 </simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(rexx-do-command
   &command-r; &key-amp; :string :result :token :io :host)</literal></term>
 <listitem><simpara> -&gt; <literal role="sexp">(RC &optional-amp;
  <replaceable>result</replaceable>)</literal>, or &nil; on failure
</simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(rexx-run-command
  &command-r; &key-amp; :string :token)</literal></term>
 <listitem><simpara> -&gt; &t;, or &nil; on failure
</simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(rexx-send-command
   &command-r; &key-amp; :string :result :token :io :host)</literal></term>
 <listitem><simpara> -&gt; <replaceable>arexx-msg-handle</replaceable>,
  or &nil; on failure</simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(rexx-wait-sent-command
   <replaceable>arexx-msg-handle</replaceable>)</literal></term>
 <listitem><simpara> -&gt; <literal role="sexp">(RC &optional-amp;
   <replaceable>result</replaceable>)</literal>, or &nil; on failure
</simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(rexx-loop)</literal></term>
 <listitem><simpara> -&gt; no return, use the
  <filename>exit-loop.cl</filename> ARexx script to abort the loop
</simpara></listitem></varlistentry>

</variablelist>

<para>&command-r; may be a string denoting a command with optional
arguments or a vector of strings thus denoting an ARexx function call.
The first element in the vector is the function name, the others are the
up to 15 arguments.</para>

<para>Messages may be sent to an arbitrary ARexx host, special cases are
&nil; (meaning <function>"REXX"</function>, the default) and &t;
(<function>"AREXX"</function> for asynchronous execution).</para>

<para>ARexx server mode: Like Ispell, Csh and SKsh, you can run it in
server mode by calling <literal role="sexp">(rexx-loop)</literal>. You
can then only exit with the ARexx <filename>exit-loop.cl</filename>
script.</para>

<para>Restrictions: Currently &clisp; is not able to wait for input from
several sources, e.g. both a console and ARexx, at the same time.</para>

</section>
<!-- #endif -->

<section id="socket"><title>Extensions-2.6. Socket Streams</title>
<subtitle>Platform dependent: &unix;, &win32; platforms only.</subtitle>
<!-- #ifdef SOCKET_STREAMS -->

<variablelist>
 <varlistentry id="sose"><term><literal role="sexp">(&sose; &optional-amp;
                 [<replaceable>port-or-socket</replaceable>])</literal></term>
  <listitem><simpara>This function creates a socket, binds a port to the
   socket, and then listens for connect attempts.  The server exists to
   watch for client connect attempts.  The optional argument is either a
   port (positive &fixnum-type;) or a &socket-stream; (from whose peer the
   connections will be made).
  </simpara></listitem></varlistentry>
 <varlistentry id="sose-close"><term><literal role="sexp">(&sose-close;
                 &sose-r;)</literal></term>
  <listitem><simpara>Closes down the server socket.
  </simpara></listitem></varlistentry>
 <varlistentry id="sose-port"><term><literal role="sexp">(&sose-port;
                 &sose-r;)</literal></term>
  <listitem><simpara>Returns the port which was bound using
   &sose;.</simpara></listitem></varlistentry>
 <varlistentry id="so-wait"><term><literal role="sexp">(&so-wait; &sose-r;
                 &timeout-arg;)</literal></term>
  <listitem id="timeout"><simpara>Wait for a fixed time for a connection
   on the &sose-r; (a &socket-server;).
   Without a timeout argument, &so-wait; blocks indefinitely.
   When timeout is zero, poll.</simpara></listitem></varlistentry>
 <varlistentry id="so-accept"><term><literal role="sexp">(&so-accept;
          &sose-r; &key-amp; &eltype; &extfmt; &buffered;)</literal></term>
  <listitem><simpara>Creates the server-side two-way stream for the connection.
  </simpara></listitem></varlistentry>
 <varlistentry id="so-connect"><term><literal role="sexp">(&so-connect;
    <replaceable>port</replaceable> &optional-amp; [&host-r;] &key-amp;
    &eltype; &extfmt; &buffered;)</literal></term>
  <listitem><simpara>Attempts to create a client-side two-way &socket-stream;.
   Blocks until the server accepts the connections.
  </simpara></listitem></varlistentry>
 <varlistentry id="so-status"><term><literal role="sexp">(&so-status;
                 <replaceable>socket-stream-or-list</replaceable>
                 &timeout-arg;)</literal></term>
  <listitem><simpara>Checks whether it is possible to read from or write
   to a &socket-stream; or whether a connection is available on a
   &socket-server; without blocking.  (For the cognoscenti:
   this is the interface to <function>select(2)</function>).
   This is similar to &listen;, which checks only one stream and only for
   input, and &so-wait;, which works only with &socket-server;s.</simpara>
   <variablelist><title>Possible values of
       <replaceable>socket-stream-or-list</replaceable></title>
    <varlistentry><term>&socket-stream; or &socket-server;</term>
     <listitem><simpara>Returns &t; if a connection on the
      &socket-server; is available; or &input-k;, &output-k; or &io-k;
      if some input/output is possible on the &socket-stream;
     </simpara></listitem></varlistentry>
    <varlistentry><term><literal role="sexp">(&socket-stream;
       . <replaceable>direction</replaceable>)</literal></term>
     <listitem><simpara>Return the appropriate keyword (&input-k;,
      &output-k; or &io-k;) if some input/output is possible on the
      &socket-stream; in the specified <replaceable>direction</replaceable>
      (which should be one of &input-k;, &output-k; or &io-k;).
     </simpara></listitem></varlistentry>
    <varlistentry><term>a list of the above</term>
     <listitem><simpara>Return a list of values, one for each element of the
      argument list (a la &mapcar;)</simpara></listitem></varlistentry>
   </variablelist>
   <simpara>The optional arguments specify the timeout. &nil; means wait
   forever, <literal>0</literal> means poll.  Note that this function
   never waits for input or output to arrive, only for information on
   input or output presense (so that &read-char; or &write-char; will
   not block) to become available (or a connection to become
   possible).</simpara>
   <simpara>For each &socket-stream; this function returns</simpara>
   <variablelist><title>Return values of &so-status;</title>
    <varlistentry><term>&nil;</term>
     <listitem><simpara>when no information is available or no operation
      is possible</simpara></listitem></varlistentry>
    <varlistentry><term>&error-k;</term>
     <listitem><simpara>when an i/o operation will cause an error
     </simpara></listitem></varlistentry>
    <varlistentry><term>&input-k;</term>
     <listitem><simpara>when you can only read from the stream
     </simpara></listitem></varlistentry>
    <varlistentry><term>&output-k;</term>
     <listitem><simpara>when you can only write to the stream
     </simpara></listitem></varlistentry>
    <varlistentry><term>&io-k;</term>
     <listitem><simpara>when you can both read from and write to the stream
     </simpara></listitem></varlistentry>
  </variablelist></listitem></varlistentry>
 <varlistentry id="sost-hopo">
   <term><literal role="sexp">(&sost-host; &sost-r;)</literal>,
         <literal role="sexp">(&sost-port; &sost-r;)</literal></term>
  <listitem><simpara>These two functions return information about the
   &socket-stream;.  For a server, &sost-host; returns &nil;.
  </simpara></listitem></varlistentry>
 <varlistentry id="service-port"><term><literal role="sexp">(&service-port;
                 &optional-amp; <replaceable>service-name</replaceable>
                 (<replaceable>protocol</replaceable> "tcp"))</literal></term>
  <listitem><simpara>A convenience function for looking up a port given
   the service name.  It returns the servent struct as multiple values
   (name, list of aliases, port, protocol) for the given
   <replaceable>service-name</replaceable> and
   <replaceable>protocol</replaceable>, or all services as the list of
   vectors of &length; 4, if <replaceable>service-name</replaceable> is
   not given or is &default-k; or &nil;.
  </simpara></listitem></varlistentry>
 <varlistentry id="sost-peer"><term><literal role="sexp">(&sost-peer;
    &sost-r; [<replaceable>do-not-resolve-p</replaceable>])</literal></term>
  <listitem><simpara>Given a stream, this function returns the name of
   the host on the opposite side of the connection and its port number;
   the server-side can use this to see who connected.</simpara>
   <simpara>When the optional second argument is non-&nil;, the hostname
   resolution is disabled and just the IP address is returned, without
   the <acronym>FQDN</acronym> (Fully Qualified Domain Name).
   </simpara></listitem></varlistentry>
 <varlistentry id="sost-local"><term><literal role="sexp">(&sost-local;
    &sost-r; [<replaceable>do-not-resolve-p</replaceable>])</literal></term>
  <listitem><simpara>The dual to &sost-peer; - same information,
   host name and port number, but for the local host.
   The difference from &sost-host; and &sost-port; is that this function
   asks the OS (and thus returns the correct trusted values) while the
   other two are just accessors to the internal data structure, and
   basically return the arguments given to the function which created
   the &socket-stream;.</simpara></listitem></varlistentry>
</variablelist>
<!-- #endif -->
</section>

<section id="syscalls"><title>Extensions-2.7. System Calls</title>

<para>When &clisp; is configured with an option
 <option>--with-export-syscalls</option>, some system calls are
 available from lisp, in package &posix-pac;.</para>

<variablelist>
 <varlistentry><term><literal
    role="sexp">(<function>posix:resolve-host-ipaddr</function>
    &optional-amp; &host-r;)</literal></term>
 <listitem><simpara>Returns the <type>hostent</type> struct (name,
   list of aliases, list of IP addresses as dotted quads (for IPv4) or
   coloned octets (for IPv6), address type - IPv4 or IPv6).
   When &host-r; is omitted or &default-k;, return the data for the
   current host. When &host-r; is given and is &nil;, all the
   host database is returned as a list (this would be the contents of the
   <filename>/etc/hosts</filename> file on a UNIX system or
   <filename>${windir}/system32/etc/hosts</filename> on a Win32 system).
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
      role="sexp">(<function>posix:file-stat</function> &path-r;
      &optional-amp; <replaceable>link-p</replaceable>)</literal></term>
 <listitem><simpara>Return the stat struct.  &path-r; can
   be a &stream-class;, a &pathname-class;, a &string-class; or a
   &number-class; (on a &unix; system, meaning file descriptor).  The
   first slot of the struct returned is the string or the number on which
   <function>stat(2)</function>/<function>fstat(2)</function>/<function>lstat(2)</function>
   was called.  The other 13 slots are numbers, members of the stat
   struct: device, inode, protection, number of hard links, owner's UID,
   owner's GID, device type, total size (bytes), blocksize for
   filesystem I/O, number of blocks allocated, atime, mtime, ctime (as
   the number of seconds since 1900-01-01).  If the system does not
   support a particular field (e.g., Win32 does not have hard links),
   &nil; (or the default, like 1 for the number of hard links for Win32
   or DOS) is returned.
   </simpara><simpara>[UNIX systems only at this time, patches are welcome.]
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
    role="sexp">(<function>posix:user-data</function>
    &optional-amp; <replaceable>user</replaceable>)</literal></term>
 <listitem><simpara>Return the passwd struct (name, encoded password,
   UID, GID, full name, home directory, shell).  When
   <replaceable>user</replaceable> is &nil;, return all users.  When
   <replaceable>user</replaceable> is &default-k; or
   not supplied, return the information about the current user.  If the
   system does not support a particular field (e.g., Win32 does not have
   a concept of a shell), &nil; (or the default, like
   <filename>c:\command.com</filename> for DOS) is returned.
   </simpara><simpara>[UNIX systems only at this time, patches are welcome.]
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
   role="sexp">(<function>posix:sysinfo</function>)</literal></term>
 <listitem><simpara>Return a struct describing the OS, derived from
   <function>uname(2)</function> and <function>sysconf(3)</function>.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
   role="sexp">(<function>posix:resource-usage-limits</function>)</literal>
   </term>
  <listitem><simpara>Return 3 structs describing the resources usage and
    limits, derived from <function>getrlimit(2)</function> and
    <function>getrusage(3)</function>.
  </simpara></listitem></varlistentry>
 <varlistentry><term>
   <literal role="sexp">(<function>posix:erf</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:erfc</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:j0</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:j1</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:jn</function>
                         &int-r; &real-r;)</literal>
   <literal role="sexp">(<function>posix:y0</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:y1</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:yn</function>
                         &int-r; &real-r;)</literal>
   <literal role="sexp">(<function>posix:gamma</function> &real-r;)</literal>
   <literal role="sexp">(<function>posix:lgamma</function>
                         &real-r;)</literal></term>
 <listitem><simpara>Compute the error functions, Bessel functions and
   Gamma.  These functions are required by the POSIX standard and should
   be available in libm.so.  Please note that these functions do not
   provide lisp-style error handling and precision, and do all the
   computations at the double float level.
  </simpara><simpara>[UNIX systems only at this time, patches are welcome.]
 </simpara></listitem></varlistentry>
</variablelist>

</section>


<section id="quickstart">
   <title>Extensions-2.8. Quickstarting delivery with &clisp;</title>

<para>This section describes four ways to turn &clisp; programs into
 executable programs, which can be started as quickly as executables
 written in other languages.</para>

<variablelist>
 <varlistentry><term>UNIX</term>
  <listitem><simpara>&clisp; can act as a script interpreter.
  </simpara></listitem></varlistentry>
 <varlistentry><term>Desktop environments such as <ulink
    url="http://www.kde.org">KDE</ulink>, <ulink
    url="http://www.gnome.org">GNOME</ulink>, or Windows.</term>
  <listitem><simpara>Files created with &clisp; can be associated with
   the &clisp; executables so that clicking on them would make &clisp;
   execute the appropriate code.</simpara></listitem></varlistentry>
 <varlistentry><term>Linux kernel with
               <option>CONFIG_BINFMT_MISC=y</option></term>
  <listitem><simpara>Associate the extensions &fasl-file;
   and &lisp-file; with &clisp;; then you can make the
   files executable and run them from the command line.
  </simpara></listitem></varlistentry>
 <varlistentry><term>&amiga;</term>
  <listitem><simpara>Files created with &clisp; can be associated with a
   Workbench project icon so that clicking on them would make &clisp;
   execute the appropriate code.  Note that several &fasl-file; files
   can be concatenated (using <function>Join</function>) into one file.
  </simpara></listitem></varlistentry>
</variablelist>

<para>These four techniques apply to a single &lisp-file; or &fasl-file; file.
 If your application is made up of several &lisp-file; or &fasl-file; files,
 you can simply concatenate them (using <command>cat</command>(1))
 into one file; the techniques then apply to that concatenated file.</para>

<variablelist>
<!-- #ifdef UNIX -->
<varlistentry><term>Platform dependent: &unix; platforms only.</term>
<listitem><para>On Unix, a text file (&fasl-file; or &lisp-file;) can be
 made executable by adding a first line of the form
 <programlisting>#!&interp-r; [&interp-args;]</programlisting>
 and using <command>chmod</command>(1) to make the script executable.
 &clisp; can be used as a script interpreter under the following
 circumstances:</para>

<itemizedlist>
<listitem><simpara>The &interp-r; must be the full pathname of &clisp;.
 The recommended path is <filename>/usr/local/bin/clisp</filename>,
 and if &clisp; is actually installed elsewhere, making
 <filename>/usr/local/bin/clisp</filename> be a symbolic link to the
 real &clisp;.</simpara></listitem>
<listitem><simpara>The &interp-r; must be a real executable, not a script.
 Unfortunately, in the binary distributions of &clisp; on Solaris,
 &clisp-cmd; is a shell script because a &c-lang; compiler cannot be
 assumed to be installed on this platform.  If you do have a &c-lang;
 compiler installed, build &clisp; from the source yourself;
 <command>make install</command> will install &clisp-cmd; as a real
 executable.</simpara></listitem>
<listitem><para>On some platforms, the first line which specifies the
 interpreter is limited in length:
   <itemizedlist>
     <listitem><simpara>max. 32 characters on SunOS 4,</simpara></listitem>
     <listitem><simpara>max. 80 characters on HP-UX,</simpara></listitem>
     <listitem><simpara>max. 127 characters on Linux.</simpara></listitem>
   </itemizedlist>
   Characters exceeding this limit are simply cut off by the system.
   At least 128 characters are accepted on Solaris, IRIX, AIX, OSF/1.
   There is no workaround: You have to keep the interpreter pathname
   and arguments short.</para></listitem>
<listitem><simpara>On Solaris and HP-UX, only the first
 <replaceable>interpreter-arg</replaceable> is passed to the
 &interp-r;.  In order to pass more than one
 option (for example, <option>-Msomewhere.mem</option> and
 <option>-C</option>) to &clisp;, separate them by hard spaces (ISO
 Latin-1 character 160) instead of normal spaces.  (But the separator
 between &interp-r; and &interp-args; must still be a normal space!)
 &clisp; will split the &interp-args; at hard spaces and at normal
 spaces.</simpara></listitem>
</itemizedlist>

<para>The script should contain Lisp forms, except in the
 <literal>#!</literal> line.
 The file is loaded normally, through the function &load;.
 Before it is loaded, the variable <emphasis
 role="strong"><varname>ext:*args*</varname></emphasis> is bound to a
 list of strings, representing the arguments given to the Lisp script.
 &standard-input-var; and &standard-output-var; are bound, as usual, to
 the Unix standard input and output.  &error-output-var; is bound to the
 Unix error output.  Continuable errors will be turned to warnings.
 Non-continuable errors and
 <keycombo>&ctrl;<keysym>C</keysym></keycombo> interrupts
 will terminate the execution of the Lisp script with an error status.
 If you wish the script's contents to be compiled during loading, add
   <ulink url="clisp.html#opt-load-comp"><option>-C</option></ulink>
 to the &interp-args;.</para>

<para>Another, quite inferior, alternative is to put the following into
 a file:</para>

<programlisting>
#!/bin/sh
exec clisp &lt;&lt;EOF
(lisp-form)
(another-lisp-form)
(yet-another-lisp-form)
EOF
</programlisting>

<para>The problem with this approach is that the return values of each form
will be printed to the standard output.  Another problem is that no user
input will be available.</para>
</listitem></varlistentry>
<!-- #endif -->

<!-- #ifdef WIN32 -->
<varlistentry><term>Platform dependent: &win32; platforms only.</term>

<listitem><simpara>There are two different ways to make &clisp;
 "executables" for Windows platforms.</simpara>

<itemizedlist>
 <listitem><simpara>Associate the &mem-file; extension with
   <command>c:\clisp\lisp.exe -B c:\clisp -M %s</command>.
  </simpara></listitem>
 <listitem><simpara>Associate the &fasl-file; extension with
   <command>c:\clisp\lisp.exe -B c:\clisp -M c:\clisp\lispinit.mem
    -i %s</command>.
    Alternatively, you may want to have a function
    <function>main</function> in your &fasl-file; files and associate
    the &fasl-file; extension with <command>c:\clisp\lisp.exe -B
    c:\clisp -M c:\clisp\lispinit.mem -i %s -x (main)</command>.
  </simpara></listitem>
</itemizedlist>

<para>Then clicking on the compiled lisp file (with &fasl-file;
 extension) will load the file (thus executing all the code in the
 file), while the clicking on a &clisp; &mem-image; (with &mem-file;
 extension) will start clisp with the given &mem-image;.</para>

<para>Note that &clisp; is distributed with a file
 <filename>install.bat</filename>, which creates a file
 <filename>clisp.bat</filename> on your desktop and also associates
 &fasl-file;, &lisp-file;, and &mem-file; files with &clisp;.</para>

</listitem></varlistentry>
<!-- #endif -->

<varlistentry><term>Platform dependent: &linux; platforms only.</term>

<listitem><para>You have to build your kernel with
 <option>CONFIG_BINFMT_MISC=y</option> and
 <option>CONFIG_PROC_FS=y</option>.  Then you will have a
 <filename>/proc/sys/fs/binfmt_misc/</filename> directory and you will
 be able to do (as <literal>root</literal>; you might want to put
 these lines into <filename>/etc/rc.d/rc.local</filename>):

<screen>
bash# echo ":CLISP:E::fas::/usr/bin/clisp:" &gt;&gt; /proc/sys/fs/binfmt_misc/register
bash# echo ":CLISP:E::lisp::/usr/bin/clisp:" &gt;&gt; /proc/sys/fs/binfmt_misc/register
</screen></para>

<para>Then you can do the following:
<screen>
bash$ cat &lt;&lt; EOF &gt; hello.lisp
(print "hello, world!")
EOF
bash$ clisp -c hello.lisp

Compiling file hello.lisp ...

Compilation of file hello.lisp is finished.
0 errors, 0 warnings
bash$ chmod +x hello.fas
bash$ hello.fas

"hello, world!"
bash$
</screen></para>

<para>Please read
 <filename>/usr/src/linux/Documentation/binfmt_misc.txt</filename> for
 details.</para>
</listitem></varlistentry>

<!-- #ifdef AMIGAOS -->
<varlistentry><term>Platform dependent: &amiga; platforms only.</term>

<listitem><para>Using a Workbench project file, the &mem-image;s,
 source and binary files can be made "executable".

<itemizedlist>
 <listitem><simpara>Using IconEdit, create a project icon.</simpara></listitem>
 <listitem><simpara>Set the tool to <filename>lisp:lisp.run</filename>
  (or wherever the binary is located).</simpara></listitem>
 <listitem><simpara>Define a tooltype named
  <replaceable>ARGS</replaceable> set to <option>-M *</option>
  for a &mem-image; project icon or to <option>-M lisp:lispinit.mem
  -i *</option> for a source or compiled lisp file.  The startup code
  will replace an isolated <token>*</token> token with the file
  name.</simpara></listitem>
 <listitem><simpara>Alternatively, you may want to have a function
  <function>main</function> in your files and set the
  <replaceable>ARGS</replaceable> tooltype to <option>-M
  lisp:lispinit.mem -i * -x (main)</option>.</simpara></listitem>
 <listitem><simpara>You might want to add more <ulink
  url="clisp.html">command line options</ulink> to the
  <replaceable>ARGS</replaceable> tooltype.</simpara></listitem>
</itemizedlist>

 Clicking on the compiled lisp file (with &fasl-file; suffix) will load
 the image and the file (thus executing all the code in the file), while
 clicking on the &clisp;'s &mem-image; (with &mem-file; suffix) with
 start &clisp; with the given &mem-image;.</para>

<para>You might want to add a tooltype named
 <replaceable>WINDOW</replaceable> which names the console window that
 &terminal-io-var; will be bound to, for example
 <filename>CON:0/0/500/300/CLISP-Listener/AUTO/CLOSE</filename>, or
 <filename>TCP:20002</filename>.</para></listitem></varlistentry>

<!-- #endif -->
</variablelist>

</section>

<section id="app-dev">
  <title>Extensions-2.9. Application delivery with &clisp;</title>

<para>Some ways of packaging &clisp; programs are discussed in the
 section <link linkend="quickstart">Quickstarting delivery with
 &clisp;</link>.</para>

<para>&clisp; is Free Software, covered by the &gnu; &gpl;, with special
 terms governing the distribution of applications that run in &clisp;.
 The precise terms can be found in the <filename>COPYRIGHT</filename>
 file contained in the source and binary distributions of &clisp;.  Here
 is an informal clarification what these terms mean in practice.  Please
 refer to the said <filename>COPYRIGHT</filename> file when in
 doubt.</para>

<para>In many cases, &clisp; does not force an application to be covered
 by the &gnu; &gpl;. Nevertheless, we encourage you to release your software
 under an open source copyright. The benefits of such a copyright for
 your users are numerous, in particular they are free to modify the
 application when their needs/requirements change, and they are free to
 recompile the application when they upgrade their machine or operating
 system.</para>

<para>&clisp; extensions, i.e. programs which need to access
 non-portable &clisp; internal symbols (in the packages &sys-pac;,
 &clos-pac;, &ffi-pac;, ...), must be covered by &gnu; &gpl; as
 well.</para>

<para>Other programs running in &clisp; have to or need not to be placed
 under &gnu; &gpl;, depending on their distribution form:

<itemizedlist>
 <listitem><simpara>Programs distributed as Lisp source or
  &fasl-file; files can be distributed without restrictions coming from
  &clisp;.</simpara></listitem>
 <listitem><simpara>Programs distributed as &clisp; &mem-image;s can be
  distributed only if accompanied with the non-&clisp; &fasl-file; files
  which make up the &mem-image;, and a &make-file;
  for rebuilding the &mem-image;.</simpara></listitem>
 <listitem><simpara>If you need to distribute a modified &clisp;
  executable (for example, incorporating additional modules written in
  &c-lang;), you must distribute its full source under &gnu; &gpl;.
  If you are not satisfied with this, you can instead put the additional
  modules into a separate (non-&clisp;) program, with which your Lisp
  program will communicate via &socket-stream;s.</simpara></listitem>
</itemizedlist></para>

</section>

<section id="shell"><title>Extensions-2.10. Shell, Pipes and Printing</title>

<section id="exec"><title>Shell</title>

<variablelist>
<!-- #if defined(UNIX) || defined(MSDOS) || defined(RISCOS) -->
<varlistentry><term>Platform dependent: &unix;, &acorn;, &dos;, &os2;,
   platforms only.</term>
 <listitem><simpara><literal role="sexp">(&exec; &program-r;
       <replaceable>arg&sub-1;</replaceable>
       <replaceable>arg&sub-2;</replaceable> ...)</literal>
   executes an external program.
   Its name is &program-r; (a full pathname).
   It is given the strings <replaceable>arg&sub-1;</replaceable>,
   <replaceable>arg&sub-2;</replaceable>, ... as arguments.
 </simpara></listitem></varlistentry>
<!-- #endif -->
<!-- #ifdef AMIGAOS -->
<varlistentry><term>Platform dependent: &amiga; platforms only.</term>
 <listitem><simpara><literal role="sexp">(&exec; &command-r;)</literal>
   executes a given &command-r; using the operating system's shell.
 </simpara></listitem></varlistentry>
<!-- #endif -->

<!-- #ifdef HAVE_SHELL -->
<varlistentry><term>Platform dependent: &unix;, &amiga;,
   &acorn;, &dos;, &os2;, &win32; platforms only.</term>
 <listitem><simpara><literal role="sexp">(&shell; [&command-r;])</literal>
   calls the operating system's shell. <literal
   role="sexp">(&shell;)</literal> calls the shell for interactive use.
   <literal role="sexp">(&shell; &command-r;)</literal> calls the shell
   only for execution of the one given &command-r;.
 </simpara></listitem></varlistentry>
<!-- #endif -->

<!-- #ifdef PIPES2 -->
<varlistentry id="run-prog"><term>Platform dependent: &unix;, &os2;, &win32;
   platforms only.</term>
 <listitem><simpara>The functions &run-cmd; and &run-prog; are the
   general interface to &shell; and the above:</simpara>

   <simpara><literal role="sexp">(&run-cmd; &command-r; &key-amp;
   &input-k; &output-k; &if-output-exists; &wait-k;)</literal>
   runs a shell command (including shell built-in commands,
   like <command>DIR</command> on &win32;/&os2;
   and <command>for/do/done</command> on &unix;).</simpara>

   <simpara><literal role="sexp">(&run-prog; &program-r; &key-amp;
   &arguments-k; &input-k; &output-k; &if-output-exists; &wait-k;)</literal>
   runs an external program.</simpara>

  <variablelist>
   <varlistentry><term>&command-r;</term>
    <listitem><simpara>the shell command.</simpara>
<!-- #ifdef UNIX -->
     <variablelist>
      <varlistentry><term>Platform dependent: &unix; platforms only.</term>
      <listitem><simpara>The shell the command is passed to is the value
       of the environment variable <envar>SHELL</envar>, which normally
       is <filename>/bin/sh</filename>.
       The command should be a <quote>simple command</quote>;
       a <quote>command list</quote> should be enclosed in "{
       ... ; }" (for <filename>/bin/sh</filename>) or "( ... )" (for
       <filename>/bin/csh</filename>).
     </simpara></listitem></varlistentry></variablelist>
<!-- #endif -->
    </listitem></varlistentry>
   <varlistentry><term>&program-r;</term>
    <listitem><simpara>the program.  The directories listed in the
     <envar>PATH</envar> environment variable will be searched for it.
    </simpara></listitem></varlistentry>
   <varlistentry><term>&arguments-k;</term>
    <listitem><simpara>a list of arguments (strings) that are given to the
     program.</simpara></listitem></varlistentry>
   <varlistentry><term>&input-k;</term>
    <listitem><simpara>where the program's input is to come from: either
     <constant>:TERMINAL</constant> (the standard input) or &stream-k;
     (a Lisp stream to be created) or a pathname (an input file) or
     &nil; (no input at all).</simpara></listitem></varlistentry>
   <varlistentry><term>&output-k;</term>
    <listitem><simpara>where the program's output is to be sent to: either
     <constant>:TERMINAL</constant> (the standard output) or &stream-k;
     (a Lisp stream to be created) or a pathname (an output file) or
     &nil; (ignore the output).</simpara></listitem></varlistentry>
   <varlistentry><term>&if-output-exists;</term>
    <listitem><simpara>what to do if the &output-k; file already
     exists.  The possible values are &overwrite-k;, &append-k;,
     &error-k;, with the same meaning as for &open;.
    </simpara></listitem></varlistentry>
   <varlistentry><term>&wait-k;</term>
    <listitem><simpara>wether to wait for program termination or not
     (this is useful when no i/o to the process is needed).
    </simpara></listitem></varlistentry>
<!-- #ifdef UNIX -->
   <varlistentry><term><constant>:MAY-EXEC</constant></term>
    <listitem><simpara>pass <command>exec</command> to the underlying
    shell (&unix; only).</simpara></listitem></varlistentry>
<!-- #endif -->
<!-- #ifdef WIN32 -->
   <varlistentry><term><constant>:INDIRECTP</constant></term>
    <listitem><simpara>use a shell to run the command, e.g.,
    <literal role="sexp">(&run-prog; "dir" :indirectp &t;)</literal>
    will run the shell built-in command <command>DIR</command>.
    (&win32;/&os2; only).</simpara></listitem></varlistentry>
<!-- #endif -->
  </variablelist>

<para>If &stream-k; was specified for &input-k; or &output-k;, a Lisp
 stream is returned.  If &stream-k; was specified for &input-k; and
 &output-k;, three Lisp streams are returned, as for the function
 &mk-pipe-io;.  This use of &run-prog; can cause deadlocks, see
 &mk-pipe-io;.</para>
</listitem></varlistentry>
<!-- #endif -->
 </variablelist>
</section>

<section id="pipe"><title>Pipes</title>

<!-- #ifdef PIPES -->
<variablelist>
<varlistentry><term>Platform dependent: &unix;, &os2;, &win32;
    platforms only.</term>
<listitem><variablelist>
 <varlistentry><term><literal role="sexp">(&mk-pipe-in;
    &command-r; &key-amp; &eltype; &extfmt; &buffered;)</literal></term>
<listitem><simpara>returns an input stream that will supply the output
  from the execution of the given operating system command.
  </simpara></listitem></varlistentry>

<varlistentry><term><literal role="sexp">(&mk-pipe-out;
   &command-r; &key-amp; &eltype; &extfmt; &buffered;)</literal></term>
<listitem><simpara>returns an output stream that will pass its output as
   input to the execution of the given operating system command.
  </simpara></listitem></varlistentry>

<!-- #ifdef PIPES2 -->
<varlistentry><term><literal role="sexp">(&mk-pipe-io;
   &command-r; &key-amp; &eltype; &extfmt; &buffered;)</literal></term>
<listitem><simpara>returns three values.  The first value is a
  bidirectional stream that will simultaneously pass its output as input
  to the execution of the given operating system command and supply the
  output from this command as input. The second and third value will be
  the input stream and the output stream that make up the I/O stream,
  respectively.  Note that they must be closed individually.</simpara>

 <simpara>Warning: Improper use of this function can lead to
  deadlocks.  Use it at your own risk!</simpara>

 <simpara>A deadlock occurs if the command and your program either both
  try to read from each other at the same time or both try to write to
  each other at the same time. To avoid deadlocks, it is recommended
  that you fix a protocol between the command and your program and avoid
  any hidden buffering: use &read-char;, &read-char-no-hang;, &listen;
  instead of &read-line; and &read; on the input side, and complete
  every output operation by a &finish-output;. The same cautions must
  apply to the called command as well.</simpara></listitem></varlistentry>
<!-- #endif -->
</variablelist></listitem></varlistentry>
</variablelist>
<!-- #endif -->
</section>

<section id="hardcopy"><title>Printing</title>

<para>The macro <emphasis
 role="strong"><function>EXT:WITH-OUTPUT-TO-PRINTER</function></emphasis>:
<programlisting>
(ext:with-output-to-printer (&var-r; [&extfmt;])
  {&declaration-r;}*
  {&form-r;}*)
</programlisting>
 binds the variable &var-r; to an output stream
 that sends its output to the printer.</para>
</section>
</section>

<!-- #ifdef DIR_KEY -->
<section id="dir-key"><title>Extensions-2.11. Directory Access</title>

<para>When &clisp; is configured with an option
 <option>--with-dir-key</option>, some directory access is available
 from lisp, in package &ldap-pac;.  3 types of directory keys
 may exist, depending on the compilation environment.</para>

<variablelist id="dir-key-type"><title>valid directory key types</title>
 <varlistentry><term>:win32</term>
  <listitem><simpara>&win32; registry access
  </simpara></listitem></varlistentry>
 <varlistentry><term>:gnome</term>
  <listitem><simpara><ulink url="http://developer.gnome.org/doc/API/libgnome/gnome-gnome-config.html">gnome-config</ulink> access
  </simpara></listitem></varlistentry>
 <varlistentry><term>:ldap</term>
  <listitem><simpara>LDAP interface via
   <ulink url="http://www.openldap.org">OpenLDAP</ulink> or compatible
  </simpara></listitem></varlistentry>
</variablelist>

<para>The following functions and macros are exported (please note that
these features are experimental and the API may be modified in the
future).</para>

<variablelist>
 <varlistentry id="dir-key-open"><term><literal role="sexp">(&dkey-open;
   &dkey-r; &path-r; &key-amp; (&direction-k; &input-k;)
   &if-does-not-exist;</literal></term>
  <listitem><simpara>Open the directory key under &dkey-r;, which should
   be either an open directory key or a valid &dk-type;.
   The meaning of the &direction-k; and &if-does-not-exist; keyword
   arguments is the same as for &open;.
  </simpara></listitem></varlistentry>
 <varlistentry id="dir-key-close"><term><literal
   role="sexp">(&dkey-close; &dkey-r;)</literal></term>
  <listitem><simpara>Close the directory key.  The preferred way is to
   use the &wdkey-open; macro.</simpara></listitem></varlistentry>
 <varlistentry id="with-dir-key-open"><term><literal
   role="sexp">(&wdkey-open; (&var-r; &dkey-r; &path-r; &rest-amp;
    <replaceable>options</replaceable>) &body-amp; &body-r;)</literal></term>
  <listitem><simpara>Open the directory key (by calling &dkey-open;
   on &dkey-r;, &path-r; and <replaceable>options</replaceable>), bind
   it to &var-r;, execute &body-r;, then close it with &dkey-close;.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>LDAP:DIR-KEY-TYPE</function> &dkey-r;)</literal></term>
  <listitem><simpara>Return the &dk-type; of the directory key
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
   role="sexp">(<function>LDAP:DIR-KEY-PATH</function>
                &dkey-r;)</literal></term>
  <listitem><simpara>Return the path of this directory key, which is the
   &path-r; argument of &dkey-open; if &dkey-r; was a &dk-type; or the
   concatenation of the &path-r; argument and the
   <function>ldap:dir-key-path</function> of &dkey-r;.
   </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>LDAP:DIR-KEY-DIRECTION</function> &dkey-r;)</literal></term>
  <listitem><simpara>One of &input-k;, &output-k; and &io-k;, indicating
   the permitted operation on this key and its derivatives.
   </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>LDAP:DIR-KEY-CLOSED-P</function> &dkey-r;)</literal></term>
  <listitem><simpara>Check whether the key has been closed.
   It is not an error to close a closed key.
   </simpara></listitem></varlistentry>
 <varlistentry><term><literal
   role="sexp">(<function>LDAP:DIR-KEY-SUBKEY-DELETE</function>
     &dkey-r; <replaceable>subkey</replaceable>)</literal>
   <literal role="sexp">(<function>LDAP:DIR-KEY-VALUE-DELETE</function>
     &dkey-r; <replaceable>attribute</replaceable>)</literal></term>
  <listitem><simpara>Delete the specified subkey or attribute.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>LDAP:DIR-KEY-SUBKEY</function> &dkey-r;)</literal>
  <literal role="sexp">(<function>LDAP:DIR-KEY-ATTRIBUTES</function>
                &dkey-r;)</literal></term>
  <listitem><simpara>Return the list of the subkeys or attributes.
  </simpara></listitem></varlistentry>
 <varlistentry><term><literal
   role="sexp">(<function>LDAP:DIR-KEY-VALUE</function> &dkey-r;
    <replaceable>attribute</replaceable> &optional-amp;
    <replaceable>default</replaceable>)</literal></term>
  <listitem><simpara>Return the value of the specified attribute,
   similar to &gethash; and &setf;able just like &gethash;.
   </simpara></listitem></varlistentry>
 <varlistentry><term><literal role="sexp"
   >(<function>LDAP:DIR-KEY-INFO</function> &dkey-r;)</literal></term>
  <listitem><simpara>Return some information about the directory key.
   This is highly platform-dependent and will probably be removed or
   replaced or modified in the future.</simpara></listitem></varlistentry>
 <varlistentry id="with-dir-key-search"><term><literal
   role="sexp">(&wdkey-search; (<replaceable>key-iter</replaceable>
                 <replaceable>atribute-iter</replaceable>
                 &dkey-r; &path-r; &key-amp; <constant>:scope</constant>)
                 &body-amp; &body-r;)</literal></term>
  <listitem><simpara>This is the main way to iterate over the subtree
   under the key &dkey-r;+&path-r;.</simpara>
   <simpara><replaceable>key-iter</replaceable> is a non-&nil; symbol
    and is bound via &macrolet; to a macro, each call of which returns
    the next subkey.</simpara>
   <simpara><replaceable>atribute-iter</replaceable> is a symbol and is
    bound, when non-&nil;, to a macro, each call of which returns two
   values - the next attribute and its value.</simpara>
   <para>The <constant>:scope</constant> keyword argument specifies the
    scope of the search and can be
   <variablelist>
    <varlistentry><term><constant>:self</constant></term>
     <listitem><simpara>iterate over the key itself
     </simpara></listitem></varlistentry>
    <varlistentry><term><constant>:level</constant></term>
     <listitem><simpara>iterate over the children of the key
     </simpara></listitem></varlistentry>
    <varlistentry><term><constant>:tree</constant></term>
     <listitem><simpara>iterate over the subtree
     </simpara></listitem></varlistentry></variablelist></para>
   <simpara>&wdkey-search; is used to implement
    <function>LDAP:DIR-KEY-VALUES</function>,
    <function>LDAP:DIR-KEY-CHILDREN</function> and
    <function>LDAP:DIR-KEY-DUMP-TREE</function> in
    <filename>dirkey.lisp</filename>.
    </simpara></listitem></varlistentry>
</variablelist>

</section>
<!-- #endif -->

<!-- #ifdef AMIGAOS -->
<section id="other"><title>Extensions-2.12. Other</title>

<variablelist>
<varlistentry><term>Platform dependent: &amiga; platforms only.</term>
<listitem><para>To have &debug-io-var; and &error-output-var; point
 to separate console windows (thus keeping your standard console window
 clean from error messages) you can use
<programlisting>
  (&setq; &error-output-var;
    (&setq; &debug-io-var;
      (&open; "CON:0/0/500/300/CLISP-Debugger/AUTO/CLOSE"
              &direction-k; &io-k;)))
</programlisting>
at startup.
</para></listitem></varlistentry></variablelist>
</section>
<!-- #endif -->

</chapter>
<!-- #endif -->

</part>
