# Extensions

## Extensions-1: Platform independent Extensions

### Extensions-1.1. Saving an Image

The function `(`EXT:SAVEINITMEM` &optional-amp; (&filename-r; "lispinit.mem") &key-amp; :QUIET :INIT-FUNCTION :LOCKED-PACKAGES :START-PACKAGE)` saves the running &clisp;'s memory to the file &filename-r;; extension &mem-file; is recommended (when &filename-r; does not have an extension, &mem-file; extension is automatically added).

`:QUIET`

  If this argument is not &nil;, the startup banner and the good-bye message will be suppressed.

`:INIT-FUNCTION`

  This argument specifies a function that will be executed at startup of the saved image, before entering the standard &repl;, thus, if you want to avoid the &repl;, you have to call `EXT:EXIT` at the end of the init function yourself.

`:LOCKED-PACKAGES`

  This argument specifies the packages to lock before saving the image; this is convenient for application delivery, when you do not want your users to mess up your product. This argument defaults to &sys-pack-list;.

`:START-PACKAGE`

  This argument specifies the starting value of &package-var; in the image being saved, and defaults to the current value of &package-var;.

You can use this memory image with the `-M` option. On &unix; systems, you may compress it with &gnu; `gzip` to save disk space.

### Extensions-1.2. Quitting &clisp;

The functions `(`EXT:EXIT` [errorp])`, `(`EXT:QUIT` [errorp])` and `(`EXT:BYE` [errorp])` - all synonymous - terminate &clisp;. If errorp is non-&nil;, &clisp; aborts with the supplied numeric error status, i.e., the OS environment is informed that the &clisp; session did not succeed.

### Extensions-1.3. Internationalization

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

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

#### The &ggettext;

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

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

`(&gettext; &msgid; &optional-amp; &domain; &category;)`

  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.

`(&ngettext; &msgid; msgid_plural &n-r; &optional-amp; &domain; &category;)`

  returns the plural form of the translation for of &msgid; and &n-r; in the given &domain;, depending on the given &category;. &msgid; and msgid_plural should be &ascii; strings, and are normally the English singular and English plural variant of the message, respectively.

##### Domain

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 `TEXTDOMAINDIR/l/LC_MESSAGES/domain.mo`, 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.

###### Function &textdomain;

`(&textdomain;)` 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. `(&setf; &textdomain;)` 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 `(&setf; &textdomain;)` is recommended only for programs that are so simple that they will never need more than one &domain;.

###### Function &textdomaindir;

`(&textdomaindir; &domain;)` is a place that returns the base directory, called `TEXTDOMAINDIR` above, where the message catalogs for the given &domain; are assumed to be installed. It is &setf;able. `(&setf; &textdomaindir;)` 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 `TEXTDOMAINDIR`s are not saved in a &mem-image;.

##### Category

The &category; argument of the &gettext; and &ngettext; functions denotes which locale facet the result should depend on. The default value is `:LC_MESSAGES`. Other possible values are `:LC_CTYPE`, `:LC_TIME`, `:LC_COLLATE`, `:LC_MONETARY`. 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 `TEXTDOMAINDIR/ll/category/domain.mo`.

##### Example

A non-internationalized program simulating a restaurant dialogue might look as follows.

###### prog.lisp

    (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)

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.

###### prog.lisp

    (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)

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

###### prog.lisp

    (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)

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

    bash$ xgettext -o prog.pot prog.lisp

Note: xgettext version 0.11 or higher is required here.

The message catalog template looks roughly like this.

###### prog.pot

    msgid "'Your command, please?', asked the waiter."
    msgstr ""

    msgid "a piece of cake"
    msgid_plural "%d pieces of cake"
    msgstr[0] ""
    msgstr[1] ""

Then a French translator creates a French message catalog

###### prog.fr.po

    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 "«Votre commande, s'il vous plait», dit le garç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"

and sends it to the program's maintainer.

The program's maintainer compiles the catalog as follows:

    bash$ mkdir -p ./fr/LC_MESSAGES
    bash$ msgfmt -o ./fr/LC_MESSAGES/prog.mo prog.fr.po

When a user in a french locale then runs the program

    bash$ clisp prog.lisp 2

she will get the output

        «Votre commande, s'il vous plait», dit le garçon.
        2 morceaux de gateau

#### The Language

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

The language &clisp; uses to communicate with the user can be one of

- `ENGLISH`
- `DEUTSCH` (i.e., German)
- `FRANÇAIS` (i.e., French)
- `ESPAÑOL` (i.e., Spanish)
- `NEDERLANDS` (i.e., Dutch)
- `&Rcy;&Ucy;&Scy;&Scy;&Kcy;&Icy;&Jcy;` (i.e. Russian)

This is controlled by the &symbol-macro; `CUSTOM:*CURRENT-LANGUAGE*`, which can be set at run time as well as using `-L` start-up option. If you wish to change the locale directory at run time too, you can do that by setting `CUSTOM:*CURRENT-LANGUAGE*` to a cons cell, whose &car; is the language (a symbol, one of the above), and whose &cdr; is the new locale directory.

More languages can be defined through the macro `I18N:DEFLANGUAGE`: `(`I18N:DEFLANGUAGE` lang)`. 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.

This works only for strings. For arbitrary language-dependent Lisp objects, you define one through the macro `I18N:DEFINTERNATIONAL`: `(`I18N:DEFINTERNATIONAL` &symbol-r; &optional-amp; (default-language &t;))` and add language-dependent values through the macro `I18N:DEFLOCALIZED`: `(`I18N:DEFLOCALIZED` &symbol-r; &lang-r; value-form)`

(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 `I18N:LOCALIZED`: `(`I18N:LOCALIZED` &symbol-r; &optional-amp; &lang-r;)`

### Extensions-1.4. Encodings

#### Introduction

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

An &encoding; is an object composed of the following facets:

character set

  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.

&line-term; mode

  This denotes the way newline characters are represented.

#### Character Sets

Platform dependent: Only in &clisp; built &without; compile-time flag &unicode;.

  Only one character set is understood: the platform's native (8-bit) character set. See Chapter 13.

Platform dependent: Only in &clisp; built &with; compile-time flag &unicode;.

  The following character sets are supported, as values of the corresponding (constant) symbol in the &charset-pac; package:

  - `UCS-2` = `UNICODE-16` = `UNICODE-16-BIG-ENDIAN`, the 16-bit basic multilingual plane of the &unicode; character set. Every character is represented as two bytes.

  - `UNICODE-16-LITTLE-ENDIAN`

  - `UCS-4` = `UNICODE-32` = `UNICODE-32-BIG-ENDIAN`, the 21-bit &unicode; character set. Every character is represented as four bytes.

  - `UNICODE-32-LITTLE-ENDIAN`

  - `UTF-8`, the 21-bit &unicode; character set. Every character is represented as one to four bytes. &ascii; characters represent themselves and need one byte per character. Most Latin/Greek/Cyrillic/Hebrew characters need two bytes per character. Most other characters need three bytes per character, and the rarely used remaining characters need four bytes per character. This is therefore, in general, the most space-efficient encoding of all of Unicode.

  - `UTF-16`, the 21-bit &unicode; character set. Every character in the 16-bit basic multilingual plane is represented as two bytes, and the rarely used remaining characters need four bytes per character. &charset-glibc-libiconv;

  - `UTF-7`, the 21-bit &unicode; character set. This is a stateful 7-bit encoding. Not all &ascii; characters represent themselves. &charset-glibc-libiconv;

  - `JAVA`, the 21-bit &unicode; character set. &ascii; characters represent themselves and need one byte per character. All other characters of the basic multilingual plane are represented by `\unnnn` sequences (nnnn a hexadecimal number) and need 6 bytes per character. The remaining characters are represented by `\uxxxx\uyyyy` and need 12 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 `\u` (backslash followed by lowercase Latin u) can be faithfully represented by this encoding.

  - `ASCII`, the well-known US-centric 7-bit character set (American Standard Code for Information Interchange - &ascii;).

  - `ISO-8859-1`, &ascii-iso-ext; 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.

  - `ISO-8859-2`, &ascii-iso-ext; Croatian, Czech, German, Hungarian, Polish, Slovak, Slovenian, and Sorbian languages.

  - `ISO-8859-3`, &ascii-iso-ext; Esperanto and Maltese languages.

  - `ISO-8859-4`, &ascii-iso-ext; Estonian, Latvian, Lithuanian and Sami (Lappish) languages.

  - `ISO-8859-5`, &ascii-iso-ext; Bulgarian, Byelorussian, Macedonian, Russian, Serbian, and Ukrainian languages.

  - `ISO-8859-6`, suitable for the Arabic language.

  - `ISO-8859-7`, &ascii-iso-ext; Greek language.

  - `ISO-8859-8`, &ascii-iso-ext; Hebrew language (without punctuation).

  - `ISO-8859-9`, &ascii-iso-ext; Turkish language.

  - `ISO-8859-10`, &ascii-iso-ext; Estonian, Icelandic, Inuit (Greenlandic), Latvian, Lithuanian, and Sami (Lappish) languages.

  - `ISO-8859-13`, &ascii-iso-ext; Estonian, Latvian, Lithuanian, Polish and Sami (Lappish) languages.

  - `ISO-8859-14`, &ascii-iso-ext; Irish Gaelic, Manx Gaelic, Scottish Gaelic, and Welsh languages.

  - `ISO-8859-15`, &ascii-iso-ext; ISO-8859-1 languages, with improvements for French, Finnish and the Euro.

  - `ISO-8859-16` &ascii-iso-ext; Rumanian language.

  - `KOI8-R`, &ascii-iso-ext; Russian language (very popular, especially on the internet).

  - `KOI8-U`, &ascii-iso-ext; Ukrainian language (very popular, especially on the internet).

  - `KOI8-RU`, &ascii-iso-ext; Russian language. &charset-libiconv;

  - `JIS_X0201`, a character set for the Japanese language.

  - `MAC-ARABIC`, &ascii-pl-ext;.

  - `MAC-CENTRAL-EUROPE`, &ascii-pl-ext;.

  - `MAC-CROATIAN`, &ascii-pl-ext;.

  - `MAC-CYRILLIC`, &ascii-pl-ext;.

  - `MAC-DINGBAT`, a platform specific character set.

  - `MAC-GREEK`, &ascii-pl-ext;.

  - `MAC-HEBREW`, &ascii-pl-ext;.

  - `MAC-ICELAND`, &ascii-pl-ext;.

  - `MAC-ROMAN` = `MACINTOSH`, &ascii-pl-ext;.

  - `MAC-ROMANIA`, &ascii-pl-ext;.

  - `MAC-SYMBOL`, a platform specific character set.

  - `MAC-THAI`, &ascii-pl-ext;.

  - `MAC-TURKISH`, &ascii-pl-ext;.

  - `MAC-UKRAINE`, &ascii-pl-ext;.

  - `CP437`, a DOS oldie, &ascii-pl-ext;.

  - `CP437-IBM`, an IBM variant of `CP437`.

  - `CP737`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Greek language.

  - `CP775`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for some Baltic languages.

  - `CP850`, a DOS oldie, &ascii-pl-ext;.

  - `CP852`, a DOS oldie, &ascii-pl-ext;.

  - `CP852-IBM`, an IBM variant of `CP852`.

  - `CP855`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Russian language.

  - `CP857`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Turkish language.

  - `CP860`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Portuguese language.

  - `CP860-IBM`, an IBM variant of `CP860`.

  - `CP861`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Icelandic language.

  - `CP861-IBM`, an IBM variant of `CP861`.

  - `CP862`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Hebrew language.

  - `CP862-IBM`, an IBM variant of `CP862`.

  - `CP863`, a DOS oldie, &ascii-pl-ext;.

  - `CP863-IBM`, an IBM variant of `CP863`.

  - `CP864`, a DOS oldie, meant to be suitable for the Arabic language.

  - `CP864-IBM`, an IBM variant of `CP864`.

  - `CP865`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for some Nordic languages.

  - `CP865-IBM`, an IBM variant of `CP865`.

  - `CP866`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Russian language.

  - `CP869`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Greek language.

  - `CP869-IBM`, an IBM variant of `CP869`.

  - `CP874`, a DOS oldie, &ascii-pl-ext;, meant to be suitable for the Thai language.

  - `CP874-IBM`, an IBM variant of `CP874`.

  - `WINDOWS-1250` = `CP1250`, &ascii-pl-ext;, heavily incompatible with ISO-8859-2.

  - `WINDOWS-1251` = `CP1251`, &ascii-pl-ext;, heavily incompatible with ISO-8859-5, meant to be suitable for the Russian language.

  - `WINDOWS-1252` = `CP1252`, a platform specific extension of the ISO-8859-1 character set.

  - `WINDOWS-1253` = `CP1253`, &ascii-pl-ext;, gratuitously incompatible with ISO-8859-7, meant to be suitable for the Greek language.

  - `WINDOWS-1254` = `CP1254`, a platform specific extension of the ISO-8859-9 character set.

  - `WINDOWS-1255` = `CP1255`, &ascii-pl-ext;, gratuitously incompatible with ISO-8859-8, suitable for the Hebrew language. &charset-glibc-libiconv;

  - `WINDOWS-1256` = `CP1256`, &ascii-pl-ext;, meant to be suitable for the Arabic language.

  - `WINDOWS-1257` = `CP1257`, &ascii-pl-ext;.

  - `WINDOWS-1258` = `CP1258`, &ascii-pl-ext;, meant to be suitable for the Vietnamese language. &charset-glibc-libiconv;

  - `HP-ROMAN8`, &ascii-pl-ext;.

  - `NEXTSTEP`, &ascii-pl-ext;.

  - `EUC-JP`, a multibyte character set for the Japanese language. &charset-glibc-libiconv;

  - `SHIFT-JIS`, a multibyte character set for the Japanese language. &charset-glibc-libiconv;

  - `CP932`, a Microsoft variant of `SHIFT-JIS`. &charset-glibc-libiconv;

  - `ISO-2022-JP`, a stateful 7-bit multibyte character set for the Japanese language. &charset-glibc-libiconv;

  - `ISO-2022-JP-2`, a stateful 7-bit multibyte character set for the Japanese language. This character set is only available on platforms with &glibc; 2.3 or newer or &libiconv;.

  - `ISO-2022-JP-1`, a stateful 7-bit multibyte character set for the Japanese language. &charset-libiconv;

  - `EUC-CN`, a multibyte character set for simplified Chinese. &charset-glibc-libiconv;

  - `HZ`, a stateful 7-bit multibyte character set for simplified Chinese. &charset-libiconv;

  - `GBK`, a multibyte character set for Chinese, &charset-glibc-libiconv;

  - `CP936`, a Microsoft variant of `GBK`. &charset-glibc-libiconv;

  - `GB18030`, a multibyte character set for Chinese, &charset-glibc-libiconv;

  - `EUC-TW`, a multibyte character set for traditional Chinese. &charset-glibc-libiconv;

  - `BIG5`, a multibyte character set for traditional Chinese. &charset-glibc-libiconv;

  - `CP950`, a Microsoft variant of `BIG5`. &charset-glibc-libiconv;

  - `BIG5-HKSCS`, a multibyte character set for traditional Chinese. &charset-glibc-libiconv;

  - `ISO-2022-CN`, a stateful 7-bit multibyte character set for Chinese. &charset-glibc-libiconv;

  - `ISO-2022-CN-EXT`, a stateful 7-bit multibyte character set for Chinese. &charset-glibc-libiconv;

  - `EUC-KR`, a multibyte character set for Korean. &charset-glibc-libiconv;

  - `CP949`, a Microsoft variant of `EUC-KR`. &charset-glibc-libiconv;

  - `ISO-2022-KR`, a stateful 7-bit multibyte character set for Korean. &charset-glibc-libiconv;

  - `JOHAB`, a multibyte character set for Korean used mostly on &dos;. &charset-glibc-libiconv;

  - `ARMSCII-8`, &ascii-iso-ext; Armenian. &charset-glibc-libiconv;

  - `GEORGIAN-ACADEMY`, &ascii-iso-ext; Georgian. &charset-glibc-libiconv;

  - `GEORGIAN-PS`, &ascii-iso-ext; Georgian. &charset-glibc-libiconv;

  - `TIS-620`, &ascii-iso-ext; Thai. &charset-glibc-libiconv;

  - `MULELAO-1`, &ascii-iso-ext; Laotian. &charset-libiconv;

  - `CP1133`, &ascii-iso-ext; Laotian. &charset-glibc-libiconv;

  - `VISCII`, &ascii-iso-ext; Vietnamese. &charset-glibc-libiconv;

  - `TCVN`, &ascii-iso-ext; Vietnamese. &charset-glibc-libiconv;

  Platform dependent: Only on &gnu; systems with &glibc; 2.2 or better and other systems (&unix; and &win32;) on which the &libiconv; &c-lang; library has been installed

    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 the `:CHARSET` argument.

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

    On &gnu; systems (such as GNU/Linux and GNU/Hurd) and on systems with &libiconv; you get this list by calling the program &iconv-u;: `iconv -l`.

    When an encoding is available both as a &enc-built-in; and through &iconv;, the &enc-built-in; is used, because it is more efficient and available across all platforms.

    The reason we use only &glibc; 2.2 or &libiconv; is that the other &iconv; implementations are broken in various ways and we do not want deal with random &clisp; crashes caused by those bugs. If your system supplies an &iconv; implementation which passes the &libiconv;'s test suite, please report that to clisp-list@sf.net and a future &clisp; version will use &iconv; on your system.

#### Line Terminators

##### The line terminator mode can be one of the following three keywords

keyword | newline representation
--- | ---
&unix-k; | Newline is represented by the &ascii; &lf-c; character (U000A).
&mac-k; | Newline is represented by the &ascii; &cr-c; character (U000D).
&dos-k; | Newline is represented by the &ascii; &cr-c; followed by the &ascii; &lf-c;.

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

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

See also 13.1.8 Treatment of Newline during Input and Output.

#### Function &make-encoding;.

The function `(&make-encoding; &key-amp; :charset :line-terminator :input-error-action :output-error-action)` returns an &encoding;. The `:charset` 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;.

The `:input-error-action` 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 #\uFFFD is typically used to indicate an error in the input sequence.

The `:output-error-action` 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 #\uFFFD can be used here only if it is encodable in the character set.

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.

#### Function &enc-charset;.

The function `(&enc-charset; &encoding-r;)` returns the charset of the &encoding-r;, as a symbol or a string. Note that `(&string; (&enc-charset; &encoding-r;))` is not necessarily a valid MIME name.

#### Default encodings.

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

##### Macro &def-file-enc;

The &symbol-macro; place &def-file-enc; is the encoding used for new &file-pipe-socket; streams, when no &extfmt; argument was specified.

Platform dependent: Only in &clisp; built &with; compile-time flag &unicode;.

  The following are &symbol-macro; places.

  &path-enc;

    is the encoding used for pathnames in the file system. Normally, this is a 1:1 encoding. Its &line-term; mode is ignored.

  &term-enc;

    is the encoding used for communication with the terminal, in particular by &terminal-io-var;.

  &misc-enc;

    is the encoding used for access to &env-var;s, command line options, and the like. Its &line-term; mode is ignored.

  &foreign-enc;

    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.

The default encoding objects are initialized as described in the &clisp; manual page

#### Converting between strings and byte vectors

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

`(`EXT:CONVERT-STRING-FROM-BYTES` byte-vector &encoding-r; &key-amp; &start-k; &end-k;)`

  converts the subsequence of byte-vector from &start-r; to &end-r; to a string, according to the given &encoding-r;, and returns the resulting string.

`(`EXT:CONVERT-STRING-TO-BYTES` &string-r; &encoding-r; &key-amp; &start-k; &end-k;)`

  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.

### Extensions-1.5. Defining new kinds of Streams

Two mechanisms are supported for creating new streams with user-defined behavior:

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

- You can create a new subclass of `gstream:generic-stream-controller` 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 `gstream:make-generic-stream`.

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

#### Gray streams

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.

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

##### Defined classes

&fu-st;

  This is a superclass of all user-defined streams. It is a subclass of &stream-t; and of &standard-object-t;. Its metaclass is &standard-class;.

&fu-st-in;

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

&fu-st-out;

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

&fu-st-char;

  This is a superclass of all user-defined streams whose &stream-element-type; is &character-t;. It is a subclass of &fu-st;. It defines a method on &stream-element-type; that returns &character-t;.

&fu-st-bin;

  This is a superclass of all user-defined streams whose &stream-element-type; is a subtype of &integer-t;. 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;.

`GRAY:FUNDAMENTAL-CHARACTER-INPUT-STREAM`

  This is a convenience class inheriting from both &fu-st-char; and &fu-st-in;.

`GRAY:FUNDAMENTAL-CHARACTER-OUTPUT-STREAM`

  This is a convenience class inheriting from both &fu-st-char; and &fu-st-out;.

`GRAY:FUNDAMENTAL-BINARY-INPUT-STREAM`

  This is a convenience class inheriting from both &fu-st-bin; and &fu-st-in;.

`GRAY:FUNDAMENTAL-BINARY-OUTPUT-STREAM`

  This is a convenience class inheriting from both &fu-st-bin; and &fu-st-out;.

##### general generic functions defined on streams

`(&stream-element-type; &stream-r;)`

  Returns the stream's element type, normally a subtype of &character-t; or &integer-t;.

  The method for &fu-st-char; returns &character-t;.

`((&setf; &stream-element-type;) new-element-type &stream-r;)`

  Changes the stream's element type.

  The default method signals an error.

  This function is a &clisp; extension (see setting &stream-element-type;)

`(&close; &stream-r; &key-amp; &abort-k;)`

  Closes the stream and flushes any associated buffers.

  When you define a primary method on this function, do not forget to &call-next-method;.

`(&open-stream-p; &stream-r;)`

  Returns true before the stream has been closed, and &nil; after the stream has been closed.

  You do not need to add methods to this function.

##### generic functions for character input

`(&st-rc; &stream-r;)`

  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.

  &need-defmethod;
`(&st-uc; &stream-r; &ch-r;)`

  Pushes &ch-r;, which must be the last character read from the &stream-r;, back onto the front of the &stream-r;.

  &need-defmethod;
`(&st-rcnh; &stream-r;)`

  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.

  The default method simply calls &st-rc;; this is sufficient for streams whose &st-rc; method never blocks.

`(`GRAY:STREAM-PEEK-CHAR` &stream-r;)`

  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.

  The default method calls &st-rc; and &st-uc;; this is sufficient for streams whose &st-rc; method has no side-effects.

`(`GRAY:STREAM-LISTEN` &stream-r;)`

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

  The default method calls &st-rcnh; and &st-uc;; this is sufficient for streams whose &st-rc; method has no side-effects.

`(`GRAY:STREAM-READ-CHAR-WILL-HANG-P` &stream-r;)`

  Returns &nil; if &st-rc; will return immediately. Otherwise it returns true.

  The default method calls &st-rcnh; and &st-uc;; this is sufficient for streams whose &st-rc; method has no side-effects.

  This function is a &clisp; extension (see &rcwhp;).

`(`GRAY:STREAM-READ-CHAR-SEQUENCE` &stream-r; &sequence-r; &optional-amp; [&start-r; [&end-r;]])`

  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 < &end-r; if the stream reached its end).

  &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 `(&length; &sequence-r;)`.

  The default method repeatedly calls &st-rc;; this is always sufficient if speed does not matter.

  This function is a &clisp; extension (see &rd-ch-seq;)

`(`GRAY:STREAM-READ-LINE` &stream-r;)`

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

  The default method repeatedly calls &st-rc;; this is always sufficient.

`(`gray:stream-clear-input` &stream-r;)`

  Clears all pending interactive input from the stream, and returns true if some pending input was removed.

  The default method does nothing and returns &nil;; this is sufficient for non-interactive streams.

##### generic functions for character output

`(&st-wc; &stream-r; &ch-r;)`

  Writes &ch-r;.

  &need-defmethod;
`(&st-lc; &stream-r;)`

  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.

  &need-defmethod;
`(`GRAY:STREAM-START-LINE-P` &stream-r;)`

  Returns true if the next character would be written at the start of a new line.

  The default method calls &st-lc; and compares its result with 0; this is sufficient for streams whose &st-lc; never returns &nil;.

`(`GRAY:STREAM-WRITE-CHAR-SEQUENCE` &stream-r; &sequence-r; &optional-amp; [&start-r; [&end-r;]])`

  Outputs the subsequence of &sequence-r; specified by &start-k; and &end-k; to &stream-r;.

  &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 `(&length; &sequence-r;)`.

  The default method repeatedly calls &st-wc;; this is always sufficient if speed does not matter.

  This function is a &clisp; extension (see &wr-ch-seq;)

`(`GRAY:STREAM-WRITE-STRING` &stream-r; &string-r; &optional-amp; [&start-r; [&end-r;]])`

  Outputs the subsequence of &string-r; specified by &start-k; and &end-k; to &stream-r;. Returns &string-r;.

  &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 `(&length; &string-r;)`.

  The default method calls `GRAY:STREAM-WRITE-CHAR-SEQUENCE`; this is always sufficient.

`(`GRAY:STREAM-TERPRI` &stream-r;)`

  Outputs a &nl-c; character.

  The default method calls &st-wc;; this is always sufficient.

`(`GRAY:STREAM-FRESH-LINE` &stream-r;)`

  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.

  The default method calls `GRAY:STREAM-START-LINE-P` and then `GRAY:STREAM-TERPRI` if necessary; this is always sufficient.

`(`GRAY:STREAM-FINISH-OUTPUT` &stream-r;)`

  Ensures that any buffered output has reached its destination, and then returns.

  The default method does nothing.

`(`GRAY:STREAM-FORCE-OUTPUT` &stream-r;)`

  Brings any buffered output on its way towards its destination, and returns without waiting until it has reached its destination.

  The default method does nothing.

`(`GRAY:STREAM-CLEAR-OUTPUT` &stream-r;)`

  Attempts to discard any buffered output which has not yet reached its destination.

  The default method does nothing.

`(`GRAY:STREAM-ADVANCE-TO-COLUMN` &stream-r; column)`

  Ensures that the next character will be written at column at least.

  The default method outputs an appropriate amount of space characters; this is sufficient for non-proportional output.

##### generic functions for binary input

`(&st-rb; &stream-r;)`

  Returns and consumes the next integer from the stream. Returns &eof-k; if the &eos; is reached.

  &need-defmethod;
`(&st-rbla; &stream-r;)`

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

  &need-defmethod;

  This function is a &clisp; extension (see &rbla;).

`(`GRAY:STREAM-READ-BYTE-WILL-HANG-P` &stream-r;)`

  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.

  The default method calls &st-rbla;; this is always sufficient.

`(`GRAY:STREAM-READ-BYTE-NO-HANG` &stream-r;)`

  To be called only if &stream-r;'s &stream-element-type; is &unsigned-byte-8; or &signed-byte-8;. Returns an &integer-t; 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.

  The default method calls &st-rb; if &st-rbla; returns true; this is always sufficient.

`(`GRAY:STREAM-READ-BYTE-SEQUENCE` &stream-r; &sequence-r; &optional-amp; [&start-r; [&end-r;]])`

  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 < &end-r; if the stream reached its end).

  &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 `(&length; &sequence-r;)`.

  The default method repeatedly calls &st-rb;; this is always sufficient if speed does not matter.

  This function is a &clisp; extension (see &rd-by-seq;).

##### generic functions for binary output

`(`GRAY:STREAM-WRITE-BYTE` &stream-r; &int-r;)`

  Writes &int-r;.

  &need-defmethod;
`(`GRAY:STREAM-WRITE-BYTE-SEQUENCE` &stream-r; &sequence-r; &optional-amp; [&start-r; [&end-r;]])`

  Outputs the subsequence of &sequence-r; specified by &start-k; and &end-k; to &stream-r;

  &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 `(&length; &sequence-r;)`.

  The default method repeatedly calls `GRAY:STREAM-WRITE-BYTE`; this is always sufficient if speed does not matter.

  This function is a &clisp; extension (see &wr-by-seq;).

#### Generic streams

This interface is &clisp; specific and now obsolete. Please use the Gray streams interface instead.

Generic streams are user programmable streams. The programmer interface:

`(`gstream:make-generic-stream` controller)`

  returns a generic stream.

`(`gstream:generic-stream-controller` &stream-r;)`

  returns a private object to which generic stream methods dispatch. The typical usage is to retrieve the object originally provided by the user in `gstream:make-generic-stream`.

`(`gstream:generic-stream-p` &stream-r;)`

  determines whether a stream is a generic stream, returning &t; if it is, &nil; otherwise.

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

`(`gstream:generic-stream-read-char` controller)`

  Returns and consumes the next character, &nil; at end of file. Takes one argument, the controller object.

`(`gstream:generic-stream-peek-char` controller)`

  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.

`(`gstream:generic-stream-read-byte` controller)`

  Returns and consumes the next integer, &nil; at end of file. Takes one argument, the controller object.

`(`gstream:generic-stream-read-char-will-hang-p` controller)`

  This generic function is used to query the stream's input status. It returns &nil; if `gstream:generic-stream-read-char` and `gstream:generic-stream-peek-char` will certainly return immediately. Otherwise it returns true.

`(`gstream:generic-stream-write-char` controller &ch-r;)`

  The first argument is the controller object. The second argument is the character to be written.

`(`gstream:generic-stream-write-byte` controller by)`

  The first argument is the controller object. The second argument is the integer to be written.

`(`gstream:generic-stream-write-string` controller &string-r; &start-r; &len-r;)`

  Writes the subsequence of &string-r; starting from &start-r; of length &len-r;. The first argument is the controller object.

`(`gstream:generic-stream-clear-input` controller)`
`(`gstream:generic-stream-clear-output` controller)`
`(`gstream:generic-stream-finish-output` controller)`
`(`gstream:generic-stream-force-output` controller)`
`(`gstream:generic-stream-close` controller)`

  Take one argument, the controller object.

### Extensions-1.6. Weak Pointers

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

`(`EXT:MAKE-WEAK-POINTER` &value-r;)`

  returns a fresh weak pointer referring to &value-r;.

`(`EXT:WEAK-POINTER-P` &object-r;)`

  returns true if the &object-r; is of type &weak-pointer;.

`(`EXT:WEAK-POINTER-VALUE` weak-pointer)`

  returns two values: The original value and &t;, if the value has not yet been &gc;ed, else &nil; and &nil;.

### Extensions-1.7. Finalization

Calling `(&finalize; &object-r; &func-r;)` has the effect that when the specified object is being &gc;ed, `(&funcall; &func-r; &object-r;)` will be executed.

Calling `(&finalize; &object-r; &func-r; guardian)` has a similar effect, but only as long as the "guardian" has not been &gc;ed: when &object-r; is being &gc;ed, `(&funcall; &func-r; &object-r; guardian)` will be executed. If the guardian is &gc;ed before &object-r; is, nothing happens.

Note: The time when the &object-r; is being &gc;ed 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 guardian) enter the "arena of live Lisp objects" again.

No finalization request will be executed more than once.

### Extensions-1.8. The Prompt

The variable `CUSTOM:*PROMPT*` 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 `CUSTOM:*PROMPT*` prints "package[n]> " where package 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 &n-r; is the ordinal number of the current prompt (hopefully, it will remain finite). To help you in constructing your own fancy prompts, two functions and one variable are provided:

function `EXT:PROMPT-NEW-PACKAGE`

  returns &package-var; or &nil; if the current package is the same as it was initially

function `EXT:PACKAGE-SHORT-NAME`

  takes one argument, a package, and returns its shortest name or nickname

variable `EXT:*COMMAND-INDEX*`

  contains the current prompt number; it is your responsibility to increment it (this variable is bound to 0 before saving the &mem-image;).

### Extensions-1.9. Maximum ANSI CL compliance

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:

- Setting &pathprint; to &t;.

- Setting &fixnum-char-ansi; to &t;.

- Setting &count-ansi; to &t;.

- Setting &pathmerge; to &t;.

- Setting &parsename; to &t;.

- Setting &flocont; to &t;.

Note that if you run &clisp; with the &ansi-opt; switch or set the &symbol-macro; &ansi; to &t; and then 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.,

- Setting &pathprint; to &nil;.

- Setting &fixnum-char-ansi; to &nil;.

- Setting &count-ansi; to &nil;.

- Setting &pathmerge; to &nil;.

- Setting &parsename; to &nil;.

- Setting &flocont; to &nil;.

### Extensions-1.10. Additional Fancy Macros

&clisp; comes with some extension macros, defined in the file `macros3.lisp` and loaded from the file `init.lisp` during `make`:

#### Macro &ethe;

`(&ethe; &val-type-r; &form-r;)` enforces a type check in both interpreted and compiled code.

#### Macros &letf; & &letf-star;

These macros are similar to &let; and &let-star;, respectively, except that they can bind places, even places with multiple values. Example:

     (letf (((values a b) form)) ...)

is equivalent to

     (multiple-value-bind (a b) form ...)

while

    (letf (((first l) 7)) ...)

is approximately equivalent to

     (&let-star; ((#:g1 l) (#:g2 (first #:g1)))
       (&unwind-protect; (&progn; (&setf; (first #:g1) 7) ...)
          (&setf; (first #:g1) #:g2)))

#### Macro `EXT:WITH-COLLECT`

Similar to the &loop;'s `collect` construct, except that it is looks more "Lispy" and can appear arbitrarily deep. It defines local macros (with &macrolet;) which collect objects given to it into lists, which are then returned as multiple values. E.g.,

     (ext:with-collect (c0 c1)
       (dotimes (i 10) (if (oddp i) (c0 i) (c1 i))))

returns two lists `(1 3 5 7 9)` and `(0 2 4 6 8)` as multiple values.

### Extensions-1.11. Customizing &clisp; behavior.

The user-customizable variables are located in the package &custom-pac; and thus can be listed using `(&apropos; "" "CUSTOM")`.

## Extensions-2: Platform specific Extensions

### Extensions-2.1. Random Screen Access

Platform dependent: &unix;, &amiga;, &dos;, &os2;, &win32; platforms only.

`(`screen:make-window`)`

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

`(`screen:with-window` . &body-r;)`

  binds `screen:*window*` 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.

`(`screen:window-size` window-stream)`

  returns the window's size, as two values: height (= ymax+1) and width (= xmax+1).

`(`screen:window-cursor-position` window-stream)`

  returns the position of the cursor in the window, as two values: line (≥0, ≤ymax, 0 means top), column (≥0, ≤xmax, 0 means left margin).

`(`screen:set-window-cursor-position` window-stream line column)`

  sets the position of the cursor in the window.

`(`screen:clear-window` window-stream)`

  clears the window's contents and puts the cursor in the upper left corner.

`(`screen:clear-window-to-eot` window-stream)`

  clears the window's contents from the cursor position to the end of window.

`(`screen:clear-window-to-eol` window-stream)`

  clears the window's contents from the cursor position to the end of line.

`(`screen:delete-window-line` window-stream)`

  removes the cursor's line, moves the lines below it up by one line and clears the window's last line.

`(`screen:insert-window-line` window-stream)`

  inserts a line at the cursor's line, moving the lines below it down by one line.

`(`screen:highlight-on` window-stream)`

  switches highlighted output on.

`(`screen:highlight-off` window-stream)`

  switches highlighted output off.

`(`screen:window-cursor-on` window-stream)`

  makes the cursor visible, a cursor block in most implementations.

`(`screen:window-cursor-off` window-stream)`

  makes the cursor invisible, in implementations where this is possible.

### Extensions-2.2. External Modules

Platform dependent: &unix; platforms only.

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

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

`clisp-link` needs a directory containing:

- `modules.d`

- `modules.c`

- `clisp.h`

`clisp-link` expects to find these files in a subdirectory `linkkit/` of the current directory. This can be overridden by the &env-var; `CLISP_LINKKIT`.

`clisp-link` operates on &clisp; &linkset;s and on module sets.

A &linkset; is a directory containing:

`makevars`

  some `/bin/sh` commands, setting the variables

  `CC`

    the &c-lang; compiler

  `CFLAGS`

    flags for the &c-lang; compiler, when compiling

  `CLFLAGS`

    flags for the &c-lang; compiler, when linking

  `LIBS`

    libraries to use when linking

  `X_LIBS`

    additional X window system libraries to use

  `RANLIB`

    the ranlib command

  `FILES`

    the list of files needed when linking

`modules.h`

  the list of modules contained in this &linkset;

`modules.o`

  the compiled list of modules contained in this &linkset;

all the `FILES`

  listed in `makevars`

`lisp.run`

  the executable

&lispinit;

  the &mem-image;

To run a &clisp; contained in some &linkset; `dir`, call `dir/lisp.run -M dir/lispinit.mem`

A module set is a directory containing:

`link.sh`

  some `/bin/sh` commands, which prepare the directory before linking, and set the variables `NEW_FILES`, `NEW_LIBS`, `NEW_MODULES`, `TO_LOAD` and optionally `TO_PRELOAD`

and any other files

  needed by `link.sh`

Note that in `link.sh` the module set directory is referred to as `$modulename/`.

`NEW_FILES`

  the space-separated list of files that belong to the module set and will belong to every new &linkset;.

`NEW_LIBS`

  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 &linkset;.

`NEW_MODULES`

  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.

`TO_LOAD`

  the space-separated list of Lisp files to load before building the &lispinit; belonging to a new &linkset;.

`TO_PRELOAD` (optional)

  the space-separated list of Lisp files to load into an intermediate &lispinit; file, before building the &lispinit; belonging to a new &linkset;. This variable is usually used for defining Lisp packages which must be present when the new &c-file; files are initialized. E.g., the &def-call-in; functions must reside in already defined packages; see the call-in example.

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

The command `clisp-link add-module-set module-dir source-dir destination-dir` combines a &linkset; in source-dir and a module in module-dir to a new &linkset;, in a directory destination-dir which is newly created.

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

#### Example

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

1. Create a new module set:

       $ clisp-link create-module-set linux /somewhere/bindings/linux.c

   Modify the newly created `linux/link.sh` to add `-lm`; to the libraries: replace

       NEW_LIBS="$file_list"

   with

       NEW_LIBS="$file_list -lm"

   Modify the newly created `linux/link.sh` to load `linux.fas` before saving the &mem-image;: replace

       TO_LOAD=''

   with

       TO_LOAD='/somewhere/bindings/linux.fas'

2. Compile `linux.lisp`, creating `linux.c`:

       $ clisp -c /somewhere/bindings/linux.lisp

3. Create a new &linkset;:

       $ clisp-link add-module-set linux base base+linux

4. Run and try it:

       $ base+linux/lisp.run -M base+linux/lispinit.mem > (linux::stat "/tmp")

#### Modules included in the distribution.

The following modules come with the distribution of &clisp;:

bindings

  Call the operating system functions from &clisp;. The following platforms are supported:

  - AmigaOS

  - Linux/libc5

  - Linux/libc6

CLX

  Call Xlib functions from &clisp;. Two implementations are supplied:

  - mit-clx, from MIT ftp://ftp.x.org/R5contrib/CLX.R5.02.tar.Z

  - new-clx, by Gilbert Baumann <unk6@rz.uni-karlsruhe.de>.

oracle

  Access Oracle from &clisp;; by John Hinsdale <hin@alma.com>.

postgresql632, postgresql642

  Access PostgreSQL from &clisp;.

queens

  Compute the number of solutions to the n-queens problem on a n*n checkboard.

regexp

  The POSIX Regular Expressions matching, compiling, executing.

wildcard

  Shell globbing

&regexp;

### Extensions-2.3. The Foreign Function Call Facility

Platform dependent: many &unix;, &win32; platforms only.

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 `lisp.a`.

All symbols relating to the foreign function interface are exported from the package &ffi-pac;. To use them, `(&use-package; "FFI")`.

Special &ffi-pac; forms may appear anywhere in the Lisp file.

#### Overview

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

##### special &ffi-pac; forms; &name-r; is any Lisp symbol; &cname-r; is a string.

`(`def-c-type` &name-r; &ctype-r;)`

  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.

`(`def-c-var` &name-r; {&option-r;}*)`

  #####

  &option-r; ::== |  |
  --- | --- | ---
  |  | `(&name-k; &cname-r;)`
  | | | `(&type-k; &ctype-r;)`
  | | | `(:read-only boolean)`
  | | | `(:alloc &allocation;)`

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

  The &name-k; 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.

  The &type-k; option specifies the variable's foreign type.

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

  The `:alloc` 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.

`(&def-call-out; &name-r; {&option-r;}*)`

  #####

  &option-r; ::== |  |
  --- | --- | ---
  |  | `(&name-k; &cname-r;)`
  | | | `(&arguments-k; {(arg-name &ctype-r; [&param-mode; [&allocation;]])}*)`
  | | | `(:return-type &ctype-r; [&allocation;])`
  | | | `(&lang-k; &lang-r;)`

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

`(&def-call-in; &name-r; {&option-r;}*)`

  #####

  &option-r; ::== |  |
  --- | --- | ---
  |  | `(&name-k; &cname-r;)`
  | | | `(&arguments-k; {(arg-name &ctype-r; [&param-mode; [&allocation;]])}*)`
  | | | `(:return-type &ctype-r; [&allocation;])`
  | | | `(&lang-k; &lang-r;)`

  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 `#'&name-r;`.

`(&def-c-call-out; &name-r; {&option-r;}*)`

  This is equivalent to &def-call-out; with &lang-k; &stdc-k;. deprecated.

`(&def-c-call-in; &name-r; {&option-r;}*)`

  This is equivalent to &def-call-in; with &lang-k; &stdc-k;. deprecated.

`(&def-c-struct; &name-r; (ident &ctype-r;)*)`

  This form defines &name-r; to be both a &structure-class; and a foreign &c-lang; type with the given slots.

`(&def-c-enum; &name-r; {ident | (ident [&value-r;])}*)`

  This form defines idents as constants, similarly to the &c-lang; declaration enum { ident [= &value-r;], ... };

`(&c-lines; format-string {argument}*)`

  This form outputs the string `(&format; &nil; format-string {argument}*)` to the &c-lang; output file. This is a rarely needed low-level facility.

`(&element; &cplace-r; index&sub-1; ... index&sub-n;)`

  Array element: If &cplace-r; is of foreign type `(c-array &ctype-r; dim&sub-1; ... dim&sub-n;)` and 0 ≤ index&sub-1; < dim&sub-1;, ..., 0 ≤ index&sub-n; < dim&sub-n;, this will be the place corresponding to `(&aref; &cplace-r; index&sub-1; ... index&sub-n;)` or `&cplace-r;[index&sub-1;]...[index&sub-n;]`. It is a place of type &ctype-r;. If &cplace-r; is of foreign type `(&c-array-max; &ctype-r; dim)` and 0 ≤ index < dim, this will be the place corresponding to `(&aref; &cplace-r; index)` or `&cplace-r;[index]`. It is a place of type &ctype-r;.

`(&deref; &cplace-r;)`

  Dereference pointer: If &cplace-r; is of foreign type `(&c-ptr; &ctype-r;)` or `(&c-ptr-null; &ctype-r;)`, this will be the place the pointer points to. It is a place of type &ctype-r;. For `(&c-ptr-null; &ctype-r;)`, the &cplace-r; may not be &c-NULL;.

`(&slot; &cplace-r; slot-name)`

  Struct or union component: If &cplace-r; is of foreign type `(&c-struct; &class-r; ... (slot-name &ctype-r;) ...)` or of type `(&c-union; ... (slot-name &ctype-r;) ...)`, this will be of type &ctype-r;.

`(&cast; &cplace-r; &ctype-r;)`

  Type change: A place denoting the same memory locations as the original &cplace-r;, but of type &ctype-r;.

`(&offset; &cplace-r; &offset-r; &ctype-r;)`

  Type change and displacement: return a place denoting a memory locations displaced from the original &cplace-r; by an &offset-r; counted in bytes, with type &ctype-r;. This can be used to resize an array, e.g. of &ctype-r; `(&c-array; uint16 &n-r;)` via `(&offset; &cplace-r; 0 '(&c-array; uint16 &k-r;))`.

`(&c-var-addr; &cplace-r;)`

  Return the address of &cplace-r; as a Lisp object of type FFI:FOREIGN-ADDRESS. This is useful as an argument to foreign functions expecting a parameter of &c-lang; type &c-pointer;.

`(&typeof; &cplace-r;)`

  returns the &ctype-r; corresponding to the &cplace-r;.

`(&sizeof; &ctype-r;)`, `(&sizeof; &cplace-r;)`

  The first form returns the size and alignment of a &c-lang; type &ctype-r;, measured in bytes.

  The second form returns the size and alignment of the &c-lang; type of &cplace-r;, measured in bytes.

`(&bitsizeof; &ctype-r;)`, `(&bitsizeof; &cplace-r;)`

  The first form returns the size and alignment of the &c-lang; type &ctype-r;, measured in bits.

  The second form returns the size and alignment of the &c-lang; type of &cplace-r;, measured in bits.

`(&validp; &f-ent;)`

  This predicate returns &nil; if the &f-ent; (e.g. the Lisp equivalent of a &c-pointer;) refers to a pointer which is invalid because it comes from a previous Lisp session. It returns &t; if &f-ent; can be used within the current Lisp process (thus it returns &t; for all non-foreign arguments).

`(&foreign-address-null; &f-ent;)`

  This predicate returns &nil; if the &f-ent; referes to the &c-NULL; address (and thus &f-ent; should probably not be passed to most foreign functions).

`(&with-foreign-object; (&var-r; &ctype-r; [initarg]) &body-r;)`
`(&with-c-var; (&var-r; &ctype-r; [initarg]) &body-r;)`

  These forms allocate space on the &c-lang; execution stack, bind respectively a FFI:FOREIGN-VARIABLE object or a local &symbol-macro; to &var-r; and execute &body-r;.

  When initarg is not supplied, they allocate space only for `(&sizeof; &ctype-r;)` bytes. This space is filled with zeroes. E.g., using a &ctype-r; of &c-string; or even `(&c-ptr; (&c-array; uint8 32))` (!) both allocate place for a single pointer, initialized to &c-NULL;.

  When initarg is supplied, they allocate space for an arbitrarily complex set of structures rooted in &ctype-r;. Therefore, &c-array-max;, `#()` and `""` are your friends for creating a pointer to the empty arrays:

      (with-c-var (v '(c-ptr (c-array-max uint8 32)) #())
        (setf (element (deref v) 0) 127) v)

  &ctype-r; is evaluated, making creation of variable sized buffers easy:

      (with-c-var (fv `(c-array uint8 ,(length my-vector)) my-vector)
        (print fv))

#### (Foreign) &c-lang; types

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

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

##### the predefined &c-lang; types (&ctype-r;)

simple-c-type

  ##### the simple &c-lang; types

  Lisp name | Lisp equivalent | &c-lang; equivalent | ILU equivalent | Comment
  --- | --- | --- | --- | ---
  &nil; | &nil; | void |  | as a result type only
  &boolean-t; | &boolean-t; | int | BOOLEAN
  &character-t; | &character-t; | char | SHORT CHARACTER
  char | &integer-t; | signed char
  uchar | &integer-t; | unsigned char
  short | &integer-t; | short
  ushort | &integer-t; | unsigned short
  int | &integer-t; | int
  uint | &integer-t; | unsigned int
  long | &integer-t; | long
  ulong | &integer-t; | unsigned long
  uint8 | &unsigned-byte-8; | uint8 | BYTE
  sint8 | &signed-byte-8; | sint8
  uint16 | &unsigned-byte-16; | uint16 | SHORT CARDINAL
  sint16 | &signed-byte-16; | sint16 | SHORT INTEGER
  uint32 | &unsigned-byte-32; | uint32 | CARDINAL
  sint32 | &signed-byte-32; | sint32 | INTEGER
  uint64 | `(&unsigned-byte-t; 64)` | uint64 | LONG CARDINAL | does not work on all platforms
  sint64 | `(&signed-byte-t; 64)` | sint64 | LONG INTEGER | does not work on all platforms
  &single-float-t; | &single-float-t; | float
  &double-float-t; | &double-float-t; | double

&c-pointer;

  This type corresponds to what &c-lang; calls void*, an opaque pointer.

&c-string;

  This type corresponds to what &c-lang; calls char*, a zero-terminated string. Its Lisp equivalent is a string, without the trailing zero character.

`(&c-struct; &class-r; (ident&sub-1; c-type&sub-1;) ... (ident&sub-n; c-type&sub-n;))`

  This type is equivalent to what &c-lang; calls struct { c-type&sub-1; ident&sub-1;; ...; c-type&sub-n; ident&sub-n;; }. Its Lisp equivalent is: if &class-r; is &vector-t;, a &simple-vector-t;; if &class-r; is &list-t;, a list; if &class-r; is a symbol naming a structure or &clos; class, an instance of this class, with slots of names ident&sub-1;, ... ,ident&sub-n;.

`(&c-union; (ident&sub-1; c-type&sub-1;) ... (ident&sub-n; c-type&sub-n;))`

  This type is equivalent to what &c-lang; calls union { c-type&sub-1; ident&sub-1;; ...; c-type&sub-n; ident&sub-n;; }. Conversion to and from Lisp assumes that a value is to be viewed as being of c-type&sub-1;.

`(&c-array; &ctype-r; dim&sub-1; ... dim&sub-n;)`

  This type is equivalent to what &c-lang; calls &ctype-r; [dim&sub-1;] ... [dim&sub-n;]. 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 `(&c-ptr; (&c-array; ...))` for this argument's type.

`(&c-array-max; &ctype-r; &maxdim-r;)`

  This type is equivalent to what &c-lang; calls &ctype-r; [&maxdim-r;], 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.

`(&c-function; (&arguments-k; {(arg-name a-c-type [&param-mode; [&allocation;]])}*) (`:return-type` r-c-type [&allocation;]) (&lang-k; &lang-r;))`

  This type designates a &c-lang; function that can be called according to the given prototype `(r-c-type (*) (a-c-type&sub-1;, ...))`. Conversion between &c-lang; functions and Lisp functions is transparent.

`(&c-ptr; &ctype-r;)`

  This type is equivalent to what &c-lang; calls &ctype-r; *: a pointer to a single item of the given &ctype-r;.

`(&c-ptr-null; &ctype-r;)`

  This type is also equivalent to what &c-lang; calls &ctype-r; *: a pointer to a single item of the given &ctype-r;, with the exception that &c-lang; &c-NULL; corresponds to Lisp &nil;.

`(&c-array-ptr; &ctype-r;)`

  This type is equivalent to what &c-lang; calls &ctype-r; (*)[]: a pointer to a zero-terminated array of items of the given &ctype-r;.

#### The choice of the &c-lang; flavor.

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

The default language is set using the macro `FFI:DEFAULT-FOREIGN-LANGUAGE`. If this macro has not been called in the current compilation unit (usually a file), a warning is issued and &stdc-k; is used for the rest of the unit.

#### Foreign variables

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 `(&eql; &x-r; &x-r;)` 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;.

#### Operations on foreign places

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

#### Foreign functions

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

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

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

#### Argument and result passing conventions

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

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

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

##### allocation policy

&allocation; | meaning
--- | ---
&none-k; | no storage is allocated.
&alloca-k; | allocation of storage on the stack, which has dynamic extent.
&malloc-free-k; | storage will be allocated via &malloc; and freed via &free;.

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.

For call-out functions:
  For arguments passed from Lisp to &c-lang;:
    If &allocation; is &malloc-free-k;:

      Lisp allocates the storage using &malloc; and never deallocates it. The &c-lang; function is supposed to call &free; when done with it.

    If &allocation; is &alloca-k;:

      Lisp allocates the storage on the stack, with dynamic extent. It is freed when the &c-lang; function returns.

    If &allocation; is &none-k;:

      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.

  For results passed from &c-lang; to Lisp:
    If &allocation; is &malloc-free-k;:

      Lisp calls &free; on it when done.

    If &allocation; is &none-k;:

      Lisp does nothing.

For call-in functions:
  For arguments passed from &c-lang; to Lisp:
    If &allocation; is &malloc-free-k;:

      Lisp calls &free; on it when done.

    If &allocation; is &alloca-k; or &none-k;:

      Lisp does nothing.

  For results passed from Lisp to &c-lang;:
    If &allocation; is &malloc-free-k;:

      Lisp allocates the storage using &malloc; and never deallocates it. The &c-lang; function is supposed to call &free; when done with it.

    If &allocation; is &none-k;:

      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.

Platform dependent: &amiga; platforms only.

  &allocation; may not be &malloc-free-k; because there is no commonly used &malloc;/&free; library function.

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

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.

See also &foreign-enc;.

#### Parameter Mode

A function parameter's &param-mode; may be

&in-k; (means: read-only):

  The caller passes information to the callee.

&out-k; (means: write-only):

  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.

`:IN-OUT` (means: read-write):

  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.

The default is &in-k;.

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

#### Examples

##### Simple declarations and access

The &c-lang; declaration

    struct foo {
        int a;
        struct foo * b[100];
    };

corresponds to

    (def-c-struct foo
      (a int)
      (b (c-array (c-ptr foo) 100)))

The element access

    struct foo f;
    f.b[7].a

corresponds to

    (declare (type foo f))
    (foo-a (aref (foo-b f) 7)) or (slot-value (aref (slot-value f 'b) 7) 'a)

##### external &c-lang; variable and some accesses

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

    extern struct bar * my_struct;

    my_struct->x++;
    my_struct->a = 5;
    my_struct = my_struct->n;

corresponds to

    (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)))

##### Calling an external function

On &ansi; &c-lang; systems, &stdlib-h; contains the declarations:

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

This translates to

    (def-c-struct div_t
      (quot int)
      (rem int))
    (default-foreign-language :stdc)
    (def-call-out div (:arguments (numer int) (denom int))
      (:return-type div_t))

Sample call from within Lisp:

    > (div 20 3)
    #S(DIV_T :QUOT 6 :REM 2)

##### Another example for calling an external function

Suppose the following is defined in a file `cfun.c`:

    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->x = %d\n", r->x);
      printf("r->s = %s\n", r->s);
      for (j = 0; j < 10; j++) printf("a[%d] = %d.\n", j, a[j]);
      r2 = (struct cfunr *) malloc (sizeof (struct cfunr));
      r2->x = i+5;
      r2->s = "A C string";
      return r2;
    }

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

    (&defpackage; "TEST-C-CALL" (:use "LISP" "FFI"))
    (&in-package; "TEST-C-CALL")
    (def-c-struct cfunr (x int) (s c-string))
    (default-foreign-language :stdc)
    (def-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)))

Use the module facility:

    $ 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
    > (test-c-call::call-cfun)
    i = 5
    s = A Lisp string
    r->x = 10
    r->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")
    >
    $ rm -r base+cfun

Note that there is a memory leak here: The return value `r2` of `cfun()` is &malloc;ed but never &free;d. Specifying

    (:return-type (c-ptr cfunr) :malloc-free)

is not an alternative because this would also

`free(r2->x)` but `r2->x` is a pointer to static data.

##### Calling Lisp from &c-lang;

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

    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 < n; i++) array[i] = sorted_array[i];
        free(sorted_array);
    }

This is accompanied by `sort2.lisp`:

    (&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 #'<))

To test this, use the following test file `sorttest.lisp`:

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

Now try

    $ 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`. Create a file `package.lisp` containing the form `(&defpackage; "FFI-TEST" (:use "LISP" "FFI"))` and add `package.lisp` to `TO_PRELOAD` in `link.sh`. Proceed:

    $ 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
    > (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

### Extensions-2.4. The Amiga Foreign Function Call Facility

Platform dependent: &amiga; platforms only.

#### Another Foreign Function Interface

All symbols relating to the simple foreign function interface are exported from the package &affi-pac;. To use them, `(&use-package; "AFFI")`.

#### Design issues

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

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.

The &affi-pac; does no tracking of resources. Use &finalize;.

#### Overview

These are the &affi-pac; forms:

`(declare-library-base keyword-base library-name)`

`(require-library-functions library-name [(:import {string-name}*)])`

`(open-library base-symbol)`

`(clos-library base-symbol)`

`(with-open-library (base-symbol | library-name) {&form-r;}*)`

`(defflibfun function-name base-symbol offset mask result-type {argument-type}*)`

`(declare-library-function function-name library-name {&option-r;}*)`

`(flibcall function-name {argument}*)`

`(mlibcall function-name {argument}*)`

`(mem-read address result-type [offset])`

`(mem-write address &type-r; &value-r; [offset])`

`(mem-write-vector address vector [offset])`

`(nzero-pointer-p &value-r;)`

Except for `with-open-library`, `declare-library-function` and `mlibcall`, all of the above are functions.

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 &affi-pac;. The link between this symbol and the OS-level library name is established by `declare-library-base`. 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.

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

A function is contained in a library. Every function is referred to by a symbol. A function is defined through `defflibfun` or `declare-library-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. `require-library-functions` loads the complete set of functions defined in a library file. Symbols are created in the package &affi-pac; and imported into the current package.

`flibcall` and `mlibcall` call library functions. `mlibcall` 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.

`mem-read` reads an arbitrary address (with offset for structure references) and returns the given type.

`mem-write` writes an arbitrary address. `mem-write-vector` copies the content of a Lisp &string-t; or &unsigned-byte-vec; into memory.

`nzero-pointer-p` tests for non-&c-NULL; pointers in all recognized representations (&null-t;, &unsigned-byte-t; and &foreign-pointer;).

#### Foreign Libraries

`declare-library-base` ought to be wrapped in an `(&eval-when; (compile eval load) ...)` form and come before any function is referenced, because the library base symbol must be known.

`open-library` tries to open the library referenced by the base symbol. Therefore it must have been preceded with `declare-library-base`. The call returns &nil; on failure. `open-library` calls nest. Every successful call must be matched by `close-library`. `with-open-library` 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.

&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 `AFFI::*LIBRARIES-ALIST*`.

#### (Foreign) &c-lang; types

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

##### foreign &c-lang; types used in &affi-pac;

&affi-pac; name | Lisp equivalent | &c-lang; equivalent | Comment
--- | --- | --- | ---
&nil; | &nil; | void | as a result type for functions only
4 | &unsigned-byte-32; | unsigned long |
2 | &unsigned-byte-16; | unsigned short |
1 | &unsigned-byte-8; | unsigned char |
-4 | &signed-byte-32; | long |
-2 | &signed-byte-16; | short |
-1 | &signed-byte-8; | signed char |
0 | &boolean-t; | BOOL | as a result type for functions only
* | opaque | void* |
&external-k; | opaque | void* |
&string-t; | &string-t; or &vector-t; | char* |
&io-k; | &string-t; or &vector-t; | char* |

Objects of type &string-t; 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 &read; 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-t;) type parameters). Arguments of type &integer-t; and &foreign-pointer; are always acceptable where a &string-t; or &io-k; type is specified.

See also &foreign-enc;.

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 `nzero-pointer-p` for &c-NULL; tests.

#### Foreign functions

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

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

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 `1` and a6 number `#xF`. A &nil; mask is reserved for stack-based calls (unimplemented).

The &affi-pac; type `0` is only acceptable as a function result type and yields either &t; or &nil;. The difference between `*` and &external-k; is the following: `*` 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-t; 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.

`(declare-library-function &name-r; library-name {&option-r;}*)`

&option-r; ::==

  #####

  | `(:offset library-offset)`
  | | `(&arguments-k; {(arg-name &affi-pac;-type register)}*)`
  | | `(:return-type &affi-pac;-type)`

register ::==

  `:d0` | `:d1` | ... | `:d7` | `:a0` | ... | `:a6`

declares a named library function for further reference through `flibcall` and `mlibcall`.

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

#### Memory access

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

`(affi:mem-write address &type-r; &value-r; [offset])` writes integers (&affi-pac; type -4, -2, -1, 1, 2 and 4) or pointer values (type *), but not vectors to the specified memory address.

`(affi:mem-write-vector address vector [offset])` can write memory from the given vector (of type &string-t; or &unsigned-byte-vec;).

#### Function Definition Files

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

As `affi:require-library-functions` 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 example 4 below.

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

#### Hints

By using appropriate &eval-when; forms for `affi:declare-library-base` and `affi:require-library-functions` and not using `affi:flibcall`, it is possible to write code that only loads library function definition files at compile-time. See example 1 below.

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

#### Caveats

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 `affi1.lisp`) were to change, the low-level part (`affi.d`) should remain untouched as all it knows are &integer-t;s and &foreign-pointer;s, no &symbol-t;s. The difficulty is just to get the library base value at run-time. Feel free to suggest enhancements to this facility!

#### Examples

NB: These examples are somewhat specific to the Amiga.

##### Using a predefined library function file

    (&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)))

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

##### Using flibcall

    (&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)

##### Be fully dynamic, defining library bases ourselves

    (&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)))

##### Some sample function definitions

    (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)))

### Extensions-2.5. ARexx

Platform dependent: &amiga; platforms only.

&clisp; comes with a small yet extensible and powerful ARexx interface.

`(rexx-do-command "return address()" :string &t; :result &t;)`

  tells you the name of the &clisp; ARexx port. The default extension for &clisp; ARexx scripts is `cl`.

`(rexx-do-command &command-r; &key-amp; :string :result :token :io :host)`

  -> `(RC &optional-amp; result)`, or &nil; on failure

`(rexx-run-command &command-r; &key-amp; :string :token)`

  -> &t;, or &nil; on failure

`(rexx-send-command &command-r; &key-amp; :string :result :token :io :host)`

  -> arexx-msg-handle, or &nil; on failure

`(rexx-wait-sent-command arexx-msg-handle)`

  -> `(RC &optional-amp; result)`, or &nil; on failure

`(rexx-loop)`

  -> no return, use the `exit-loop.cl` ARexx script to abort the loop

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

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

ARexx server mode: Like Ispell, Csh and SKsh, you can run it in server mode by calling `(rexx-loop)`. You can then only exit with the ARexx `exit-loop.cl` script.

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

### Extensions-2.6. Socket Streams

Platform dependent: &unix;, &win32; platforms only.

`(&sose; &optional-amp; [port-or-socket])`

  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-t;) or a &socket-stream; (from whose peer the connections will be made).

`(&sose-close; &sose-r;)`

  Closes down the server socket.

`(&sose-port; &sose-r;)`

  Returns the port which was bound using &sose;.

`(&so-wait; &sose-r; &timeout-opt;)`

  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.

`(&so-accept; &sose-r; &key-amp; &eltype; &extfmt; &buffered; &timeout-k;)`

  Creates the server-side two-way stream for the connection. Waits for an attempt to connect to the server for no more than &timeout-k; seconds (which may be a non-negative real number or a list `(sec usec)` or a pair `(sec . usec)`). Signals an &error; if no connection is made in that time.

`(&so-connect; port &optional-amp; [&host-r;] &key-amp; &eltype; &extfmt; &buffered; &timeout-k;)`

  Attempts to create a client-side two-way &socket-stream;. Blocks until the server accepts the connection, for no more than &timeout-k; seconds. If it is 0, returns immediately and (probably) blocks on the next i/o operation (you can use &so-status; to check whether it will actually block).

`(&so-status; socket-stream-or-list &timeout-opt;)`

  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 &select;). This is similar to &listen;, which checks only one stream and only for input, and &so-wait;, which works only with &socket-server;s.

  #### Possible values of socket-stream-or-list

  &socket-stream; or &socket-server;

    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;

  `(&socket-stream; . direction)`

    Return the appropriate keyword (&input-k;, &output-k; or &io-k;) if some input/output is possible on the &socket-stream; in the specified direction (which should be one of &input-k;, &output-k; or &io-k;).

  a list of the above

    Return a list of values, one for each element of the argument list (a la &mapcar;)

  The optional arguments specify the timeout. &nil; means wait forever, `0` 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).

  For each &socket-stream; this function returns

  #### Return values of &so-status;

  &nil;

    when no information is available or no operation is possible

  &error-k;

    when an i/o operation will cause an error

  &input-k;

    when you can only read from the stream

  &output-k;

    when you can only write to the stream

  &io-k;

    when you can both read from and write to the stream

`(&sost-host; &sost-r;)`
`(&sost-port; &sost-r;)`

  These two functions return information about the &socket-stream;. For a server, &sost-host; returns &nil;.

`(&service-port; &optional-amp; service-name (protocol "tcp"))`

  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 service-name and protocol, or all services as the list of vectors of &length; 4, if service-name is not given or is &default-k; or &nil;.

`(&sost-peer; &sost-r; [do-not-resolve-p])`

  Given a socket 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.

  When the optional second argument is non-&nil;, the hostname resolution is disabled and just the IP address is returned, without the FQDN (Fully Qualified Domain Name).

`(&sost-local; &sost-r; [do-not-resolve-p])`

  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 &sost-r;.

`(&sost-shut; &sost-r; direction)`

  Some Internet protocols, such as HTTP, provide for closing the connection in one direction using &shutdown;. This function provides an interface to this &unix; system call. direction can be &input-k; or &output-k;. Note that you should still call &close; after you are done with your &sost-r;; this is best accomplished by using &with-open-stream;.

  All &socket-stream;s are &io-k; streams (i.e., both &input-stream-p; and &output-stream-p; return &t; for them). &sost-shut; breaks this: the invariant is that whenever

  - a stream is open (i.e., &open-stream-p; returns &t;) and

  - a stream is an &input-k; stream (i.e., &input-stream-p; returns &t;)

  the stream can be read from (e.g., with &read-char; or &read-byte;). This is not the case for a &socket-stream; which was shut down in the &input-k; direction: it is still open (for output) but it cannot be read from.

### Extensions-2.7. System Calls

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

`(`POSIX:RESOLVE-HOST-IPADDR` &optional-amp; &host-r;)`

  Returns the hostent 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 `/etc/hosts` file on a &unix; system or `${windir}/system32/etc/hosts` on a Win32 system). This is an interface to &gethostbyname;/&gethostbyaddr;.

`(`POSIX:FILE-STAT` &path-r; &optional-amp; link-p)`

  Return the stat struct. &path-r; can be a &stream-t;, a &pathname-t;, a &string-t; or a &number-t; (on a &unix; system, meaning file descriptor). The first slot of the struct returned is the string or the number on which &stat;/&fstat;/&lstat; 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.

  [&unix; systems only at this time, patches are welcome.]

`(`POSIX:USER-DATA` &optional-amp; user)`

  Return the passwd struct (name, encoded password, UID, GID, full name, home directory, shell). When user is &nil;, return all users. When user 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 `c:\command.com` for DOS) is returned.

  [&unix; systems only at this time, patches are welcome.]

`(`POSIX:SYSINFO`)`

  Return a struct describing the OS, derived from &uname; and &sysconf;.

`(`POSIX:RESOURCE-USAGE-LIMITS`)`

  Return 3 structs describing the resources usage and limits, derived from &getrlimit; and &getrusage;.

`(`POSIX:ERF` &real-r;)`
`(`POSIX:ERFC` &real-r;)`
`(`POSIX:J0` &real-r;)`
`(`POSIX:J1` &real-r;)`
`(`POSIX:JN` &int-r; &real-r;)`
`(`POSIX:Y0` &real-r;)`
`(`POSIX:Y1` &real-r;)`
`(`POSIX:YN` &int-r; &real-r;)`
`(`POSIX:GAMMA` &real-r;)`
`(`POSIX:LGAMMA` &real-r;)`

  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.

  [&unix; systems only at this time, patches are welcome.]

`(`POSIX:STREAM-LOCK` &stream-r; lock-p &key-amp; (:BLOCK &t;) (:SHARED &nil;))`

  This is an interface to the &flock; system call. It sets or removes a discretionary file lock for the file associated with &stream-r;, depending on lock-p. When block is &nil;, the call is non-blocking, and when the file is already locked, it signals an error. When shared is non-&nil;, then lock can be shared between several callers. Several processes can set a shared lock, but only one can set an exclusive (i.e., non-shared) lock.

  [&unix; systems only at this time, patches are welcome.]

`(`POSIX:COPY-FILE` source-path destination-path &key-amp; :METHOD :PRESERVE :IF-EXISTS :IF-DOES-NOT-EXIST)`

  This is an interface to the &symlink; (when method is `:SYMLINK`), &link; (when it is `:HARDLINK`), and &rename; (when it is `:RENAME`) system calls, as well as, you guessed it, a generic file copy utility (when method is `:COPY`).

  Both source-path and destination-path may be wild.

`(`POSIX:DUPLICATE-HANDLE` fd1 &optional-amp; fd2)`

  This is an interface to the &dup; system calls on &unix; systems and to `DuplicateHandle` system call on &win32;.

### Extensions-2.8. Quickstarting delivery with &clisp;

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

&unix;

  &clisp; can act as a script interpreter.

Desktop environments such as KDE, GNOME, or Windows.

  Files created with &clisp; can be associated with the &clisp; executables so that clicking on them would make &clisp; execute the appropriate code.

Linux kernel with `CONFIG_BINFMT_MISC=y`

  Associate the extensions &fasl-file; and &lisp-file; with &clisp;; then you can make the files executable and run them from the command line.

&amiga;

  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 `Join`) into one file.

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 &cat;) into one file; the techniques then apply to that concatenated file.

Platform dependent: &unix; platforms only.

  On Unix, a text file (&fasl-file; or &lisp-file;) can be made executable by adding a first line of the form

      #!&interp-r; [&interp-args;]

  and using &chmod; to make the script executable. &clisp; can be used as a script interpreter under the following circumstances:

  - The &interp-r; must be the full pathname of &clisp;. The recommended path is `/usr/local/bin/clisp`, and if &clisp; is actually installed elsewhere, making `/usr/local/bin/clisp` be a symbolic link to the real &clisp;.

  - 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; `make install` will install &clisp-cmd; as a real executable.

  - On some platforms, the first line which specifies the interpreter is limited in length:

    - max. 32 characters on SunOS 4,

    - max. 80 characters on HP-UX,

    - max. 127 characters on Linux.

    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.

  - On Solaris and HP-UX, only the first interpreter-arg is passed to the &interp-r;. In order to pass more than one option (for example, `-Msomewhere.mem` and `-C`) 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.

  The script should contain Lisp forms, except in the `#!` line. The file is loaded normally, through the function &load;. Before it is loaded, the variable `ext:*args*` 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 &ctrl;C 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 `-C` to the &interp-args;.

  Another, quite inferior, alternative is to put the following into a file:

      #!/bin/sh
      exec clisp <<EOF
      (lisp-form)
      (another-lisp-form)
      (yet-another-lisp-form)
      EOF

  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.

Platform dependent: &win32; platforms only.

  There are two different ways to make &clisp; "executables" for Windows platforms.

  - Associate the &mem-file; extension with `c:\clisp\lisp.exe -B c:\clisp -M %s`.

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

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

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

Platform dependent: &linux; platforms only.

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

      bash# echo ":CLISP:E::fas::/usr/bin/clisp:" >> /proc/sys/fs/binfmt_misc/register
      bash# echo ":CLISP:E::lisp::/usr/bin/clisp:" >> /proc/sys/fs/binfmt_misc/register

  Then you can do the following:

      bash$ cat << EOF > 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$

  Please read `/usr/src/linux/Documentation/binfmt_misc.txt` for details.

Platform dependent: &amiga; platforms only.

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

  - Using IconEdit, create a project icon.

  - Set the tool to `lisp:lisp.run` (or wherever the binary is located).

  - Define a tooltype named ARGS set to `-M *` for a &mem-image; project icon or to `-M lisp:lispinit.mem -i *` for a source or compiled lisp file. The startup code will replace an isolated * token with the file name.

  - Alternatively, you may want to have a function `main` in your files and set the ARGS tooltype to `-M lisp:lispinit.mem -i * -x (main)`.

  - You might want to add more command line options to the ARGS tooltype.

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

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

### Extensions-2.9. Application delivery with &clisp;

Some ways of packaging &clisp; programs are discussed in the section Quickstarting delivery with &clisp;.

&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 `COPYRIGHT` 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 `COPYRIGHT` file when in doubt.

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.

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

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

- Programs distributed as Lisp source or &fasl-file; files can be distributed without restrictions coming from &clisp;.

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

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

### Extensions-2.10. Shell, Pipes and Printing

#### Shell

Platform dependent: &unix;, &acorn;, &dos;, &os2;, platforms only.

  `(&exec; &program-r; arg&sub-1; arg&sub-2; ...)` executes an external program. Its name is &program-r; (a full pathname). It is given the strings arg&sub-1;, arg&sub-2;, ... as arguments.

Platform dependent: &amiga; platforms only.

  `(&exec; &command-r;)` executes a given &command-r; using the operating system's shell.

Platform dependent: &unix;, &amiga;, &acorn;, &dos;, &os2;, &win32; platforms only.

  `(&shell; [&command-r;])` calls the operating system's shell. `(&shell;)` calls the shell for interactive use. `(&shell; &command-r;)` calls the shell only for execution of the one given &command-r;.

Platform dependent: &unix;, &os2;, &win32; platforms only.

  The functions &run-cmd; and &run-prog; are the general interface to &shell; and the above:

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

  `(&run-prog; &program-r; &key-amp; &arguments-k; &input-k; &output-k; &if-output-exists; &wait-k;)` runs an external program.

  &command-r;

    the shell command.

    Platform dependent: &unix; platforms only.

      The shell the command is passed to is the value of the &env-var; `SHELL`, which normally is `/bin/sh`. The command should be a simple command; a command list should be enclosed in "{ ... ; }" (for `/bin/sh`) or "( ... )" (for `/bin/csh`).

  &program-r;

    the program. The directories listed in the `PATH` &env-var; will be searched for it.

  &arguments-k;

    a list of arguments (strings) that are given to the program.

  &input-k;

    where the program's input is to come from: either `:TERMINAL` (the standard input) or &stream-k; (a Lisp stream to be created) or a pathname (an input file) or &nil; (no input at all).

  &output-k;

    where the program's output is to be sent to: either `:TERMINAL` (the standard output) or &stream-k; (a Lisp stream to be created) or a pathname (an output file) or &nil; (ignore the output).

  &if-output-exists;

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

  &wait-k;

    wether to wait for program termination or not (this is useful when no i/o to the process is needed).

  `:MAY-EXEC`

    pass `exec` to the underlying shell (&unix; only).

  `:INDIRECTP`

    use a shell to run the command, e.g., `(&run-prog; "dir" :indirectp &t;)` will run the shell built-in command `DIR`. (&win32;/&os2; only).

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

#### Pipes

Platform dependent: &unix;, &os2;, &win32; platforms only.
  `(&mk-pipe-in; &command-r; &key-amp; &eltype; &extfmt; &buffered;)`

    returns an input stream that will supply the output from the execution of the given operating system command.

  `(&mk-pipe-out; &command-r; &key-amp; &eltype; &extfmt; &buffered;)`

    returns an output stream that will pass its output as input to the execution of the given operating system command.

  `(&mk-pipe-io; &command-r; &key-amp; &eltype; &extfmt; &buffered;)`

    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.

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

    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.

#### Printing

The macro `EXT:WITH-OUTPUT-TO-PRINTER`:

    (ext:with-output-to-printer (&var-r; [&extfmt;])
      {&declaration-r;}*
      {&form-r;}*)

binds the variable &var-r; to an output stream that sends its output to the printer.

### Extensions-2.11. Directory Access

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

#### valid directory key types

:win32

  &win32; registry access

:gnome

  gnome-config access

:ldap

  LDAP interface via OpenLDAP or compatible

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

`(&dkey-open; &dkey-r; &path-r; &key-amp; (&direction-k; &input-k;) &if-does-not-exist;`

  Open the directory key under &dkey-r;, which should be either an open directory key or a valid &dk-t;. The meaning of the &direction-k; and &if-does-not-exist; keyword arguments is the same as for &open;.

`(&dkey-close; &dkey-r;)`

  Close the directory key. The preferred way is to use the &wdkey-open; macro.

`(&wdkey-open; (&var-r; &dkey-r; &path-r; &rest-amp; options) &body-amp; &body-r;)`

  Open the directory key (by calling &dkey-open; on &dkey-r;, &path-r; and options), bind it to &var-r;, execute &body-r;, then close it with &dkey-close;.

`(`LDAP:DIR-KEY-TYPE` &dkey-r;)`

  Return the &dk-t; of the directory key

`(`LDAP:DIR-KEY-PATH` &dkey-r;)`

  Return the path of this directory key, which is the &path-r; argument of &dkey-open; if &dkey-r; was a &dk-t; or the concatenation of the &path-r; argument and the `ldap:dir-key-path` of &dkey-r;.

`(`LDAP:DIR-KEY-DIRECTION` &dkey-r;)`

  One of &input-k;, &output-k; and &io-k;, indicating the permitted operation on this key and its derivatives.

`(`LDAP:DIR-KEY-CLOSED-P` &dkey-r;)`

  Check whether the key has been closed. It is not an error to close a closed key.

`(`LDAP:DIR-KEY-SUBKEY-DELETE` &dkey-r; subkey)` `(`LDAP:DIR-KEY-VALUE-DELETE` &dkey-r; attribute)`

  Delete the specified subkey or attribute.

`(`LDAP:DIR-KEY-SUBKEY` &dkey-r;)` `(`LDAP:DIR-KEY-ATTRIBUTES` &dkey-r;)`

  Return the list of the subkeys or attributes.

`(`LDAP:DIR-KEY-VALUE` &dkey-r; attribute &optional-amp; default)`

  Return the value of the specified attribute, similar to &gethash; and &setf;able just like &gethash;.

`(`LDAP:DIR-KEY-INFO` &dkey-r;)`

  Return some information about the directory key. This is highly platform-dependent and will probably be removed or replaced or modified in the future.

`(&wdkey-search; (key-iter atribute-iter &dkey-r; &path-r; &key-amp; `:scope`) &body-amp; &body-r;)`

  This is the main way to iterate over the subtree under the key &dkey-r;+&path-r;.

  key-iter is a non-&nil; symbol and is bound via &macrolet; to a macro, each call of which returns the next subkey.

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

  The `:scope` keyword argument specifies the scope of the search and can be

  `:self`

    iterate over the key itself

  `:level`

    iterate over the children of the key

  `:tree`

    iterate over the subtree

  &wdkey-search; is used to implement `LDAP:DIR-KEY-VALUES`, `LDAP:DIR-KEY-CHILDREN` and `LDAP:DIR-KEY-DUMP-TREE` in `dirkey.lisp`.

### Extensions-2.12. Operating System Environment.

Most modern operating systems support &env-var;s that associate strings (variables) with other strings (values). These variables are somewhat similar to the &special-dec; variables in &cl;: their values are inherited by the processes from their parent process.

You can access your OS &env-var;s using the function `(&getenv; &optional-amp; &string-r;)`, where &string-r; is the name of the &env-var;. When &string-r; is omitted or &nil;, all the &env-var;s and their values are returned in an &alist;.

You can change the value of existing &env-var;s or create new ones using `(&setf; (&getenv; &string-r;) new-value)`.

### Extensions-2.13. Other

Platform dependent: &amiga; platforms only.

  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

        (&setq; &error-output-var;
          (&setq; &debug-io-var;
            (&open; "CON:0/0/500/300/CLISP-Debugger/AUTO/CLOSE"
                    &direction-k; &io-k;)))

  at startup.