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

  See the manual for passing command line arguments to this function.

`: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

Note that 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; &curr-lang;
, 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 &curr-lang; to a &cons-t; cell, whose &car; is the language (a &symbol-t;, one of the above), and whose &cdr; is the new locale directory.

More languages can be defined through the macro &deflang;
: `(&deflang; &lang-r;)`. 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 &def-i-l;
: `(&def-i-l; &symbol-r; &optional-amp; (default-language &t;))` and add language-dependent values through the macro &defloc;
: `(&defloc; &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 &localized;
: `(&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.

Encodings are also 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.

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

    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.

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

    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 to 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; 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` argument 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` argument 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.

#### Function &enc-charset;.

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

The function `(&enc-charset; &encoding-r;)` returns the charset of the &encoding-r;, as a &symbol-t; or a &string-t;. 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-t;, 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 &in-s;s. 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 &out-s;s. 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 &signal;s an &error-t;.

  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-t; of &character-t;s, i.e. a &string-t;. &start-r; is a nonnegative &integer-t; and defaults to &zero;. &end-r; is a nonnegative &integer-t; 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-t;, without the terminating &nl-c; character), and a &boolean-t; 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-r;, 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 (&zero; 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-t; of &character-t;s, i.e. a &string-t;. &start-r; is a nonnegative &integer-t; and defaults 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.

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

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

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

`(`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-t; of &integer-t;s. &start-r; is a nonnegative &integer-t; and defaults to 0. &end-r; is a nonnegative &integer-t; 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-t; of &integer-t;s. &start-r; is a nonnegative &integer-t; and defaults to 0. &end-r; is a nonnegative &integer-t; 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;. It is &setf;-able: you can change the value that the weak pointer points to.

&clisp; also has weak &hash-table-t;.

### 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 &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 &prompt; prints "package[n]> " where &pack-r; is the shortest (nick)name of the current package &package-var; if it is &not-e; 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, mostly 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.

#### Macro `EXT:WITH-GENSYMS`

Similar to its namesake from Paul Graham's book On Lisp, this macro is useful for writing other macros:

     (with-gensyms ("FOO-" bar baz zot) ...)

expands to

     (let ((bar (gensym "FOO-BAR-"))
           (baz (gensym "FOO-BAZ-"))
           (zot (gensym "FOO-ZOT-")))
       ...)

#### Function `EXT:REMOVE-PLIST`

Similar to &remove; and &remf;, this function removes some properties from a property list. It is non-destructve and thus can be used on &rest-amp; arguments to remove some keyword parameters, e.g.,

     (defmacro with-foo ((&key-amp; foo1 foo2) &body-amp; body)
       `(... ,foo1 ... ,foo2 ... ,@body))
     (defmacro with-foo-bar ((&rest-amp; opts &key-amp; bar1 bar2
                              &allow-other-keys-amp;)
                             &body-amp; body)
       `(with-foo (,@(remove-plist opts :bar1 :bar2)
          ... ,bar1 ... ,bar2 ... ,@body)))
     (defun foo-bar ()
       (with-foo-bar (:bar1 1 :foo2 2) ...))

here `WITH-FOO` does not receive the `:BAR1 1` argument from `FOO-BAR`.

#### Macros `EXT:WITH-HTML-OUTPUT` and `EXT:WITH-HTTP-OUTPUT`

Defined in `inspect.lisp`, these macros are useful for the rudimentary &http; server defined there.

### 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")`:

- &ansi;
- `CUSTOM:*APPLYHOOK*`
- `CUSTOM:*BREAK-ON-WARNINGS*`
- &browser;
- &browsers;
- `CUSTOM:*CLHS-ROOT-DEFAULT*`
- &fixnum-char-ansi;
- &compile-warn;
- &compiled-types;
- &curr-lang;
- &def-file-enc;
- &default-float-format;
- &default-tz;
- `CUSTOM:*DEFTYPE-DEPTH-LIMIT*`
- &dev-prefix;
- &editor;
- `CUSTOM:*ERROR-HANDLER*`
- `CUSTOM:*EVALHOOK*`
- &flocont;
- &foreign-enc;
- `CUSTOM:*INSPECT-BROWSER*`
- `CUSTOM:*INSPECT-FRONTEND*`
- `CUSTOM:*INSPECT-LENGTH*`
- `CUSTOM:*INSPECT-PRINT-LENGTH*`
- `CUSTOM:*INSPECT-PRINT-LEVEL*`
- `CUSTOM:*INSPECT-PRINT-LINES*`
- `CUSTOM:*LIB-DIRECTORY*`
- &load-comp;
- &load-echo;
- &load-lpt-db;
- &load-obs;
- &load-paths;
- &pathmerge;
- &misc-enc;
- `CUSTOM:*PACKAGE-TASKS-TREAT-SPECIALLY*`
- &parsename;
- &parsedot;
- &path-enc;
- &ppr-first-newline;
- &pr-closure;
- &pr-indent;
- &pathprint;
- `CUSTOM:*PRINT-PRETTY-FILL*`
- &pr-rpars;
- `CUSTOM:*PRINT-SYMBOLS-LONG*`
- &prompt;
- &count-ansi;
- &source-types;
- &suppress-check-redef;
- &sys-pack-list;
- &term-enc;
- &trace-indent;
- `CUSTOM:*USER-MAIL-ADDRESS*`
- &warn-fpc;
- `CUSTOM:*WITH-HTML-OUTPUT-DOCTYPE*`

Note that some of these variables are platform-specific.

You should set these variables (and do whatever other customization you see fit) in the file &config-file; in the build directory before building &clisp;. Alternatively, after building &clisp;, or if you are using a binary distribution of &clisp;, you can modify &config-file;, compile and load it, and then save the &mem-image;. Finally, you can create an RC (run control) file which is loaded whenever &clisp; is started (see the documentation for option `-norc` in your platform-specific copy of the manual page).

### Extensions-1.12. Code Walker

You can use `EXT:EXPAND-FORM` to expand all the macros, &symbol-macro;s, etc, in a single form:

     (expand-form '(macrolet ((bar (x) `(print ,x)))
                     (macrolet ((baz (x) `(bar ,x)))
                       (symbol-macrolet ((z 3))
                         (baz z)))))

returns two values: `(locally (print 3))` (the expansion) and &t; (an indicator that some expansion has actually been done).

This is sometimes called a code walker, except that the code walker would probably leave the &macrolet; and &symbol-macrolet; forms intact and just do the expansion.

## 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 &scr-win;
  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` &ws-r;)`

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

`(`SCREEN:WINDOW-CURSOR-POSITION` &ws-r;)`

  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` &ws-r; line column)`

  sets the position of the cursor in the window.

`(`SCREEN:CLEAR-WINDOW` &ws-r;)`

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

`(`SCREEN:CLEAR-WINDOW-TO-EOT` &ws-r;)`

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

`(`SCREEN:CLEAR-WINDOW-TO-EOL` &ws-r;)`

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

`(`SCREEN:DELETE-WINDOW-LINE` &ws-r;)`

  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` &ws-r;)`

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

`(`SCREEN:HIGHLIGHT-ON` &ws-r;)`

  switches highlighted output on.

`(`SCREEN:HIGHLIGHT-OFF` &ws-r;)`

  switches highlighted output off.

`(`SCREEN:WINDOW-CURSOR-ON` &ws-r;)`

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

`(`SCREEN:WINDOW-CURSOR-OFF` &ws-r;)`

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

### Extensions-2.2. External Modules

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

#### Modules on &win32;.

Everything described in the section will work verbatim on &win32; when using &cygwin; or &mingw;, except for one thing - you will need to replace the `run` extension in `lisp.run` with the &win32; executable extension `exe`.

For historical reasons, all examples appear to assume &unix; and use the `run` file type (extension) for the &clisp; run-time. This does &not-e; mean that they will not work on &win32;.

#### Overview

&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 &modset;s.

##### &linkset;

A &linkset;
is a directory containing:

`makevars`

  some &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; 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`

##### &modset;

A &modset;
is a directory containing:

`link.sh`

  some &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 &modset; directory is referred to as `$modulename/`.

`NEW_FILES`

  the space-separated list of files that belong to the &modset; 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 &modset;. Normally, every &c-file; file in the &modset; 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 &modset; 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.

#### Function &modinfo;

Function `(&modinfo; &optional-amp; &name-r; verbose)` allows one to inquire about what modules are available in the currently running image. When called without arguments, it returns the list of module names, starting with clisp. When &name-r; is supplied and names a module, 3 values are returned - &name-r;, subr-count, object-count. When verbose is non-&nil;, the full list of module lisp function names written in &c-lang; (Subrs) and the full list of internal lisp objects available in &c-lang; code are additionally returned for the total of 5 values.

#### Function &mod-dynload;

Platform dependent: some &unix; platforms only, compiled &with; compile-time flag `--with-dynamic-modules`.

Note that dynamic loading does not work on all operating systems (&dlopen; is required), and that `--with-dynamic-modules` precludes some efficiency optimizations which are on by default.

Function `(&mod-dynload; &filename-r; ({&name-r;}+))` loads a shared object file or library containing a number of named external &clisp; modules. This facility cannot be used to &dlopen; and access arbitrary shared libraries.

External modules for &clisp; are those which contain a `module__&name-r;__subr_tab`, among others. This serves to register external functions which operate on Lisp-level structures with &clisp;.

To use &dlopen; with modules, you should add `-fPIC` to the module's compilation options. Something like `cc -shared -o &name-r;.so &name-r;.o` may be needed to produce the shared object file.

#### 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 &modset;:

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

  - &amiga;

  - &linux;/&glibc;

  - &win32;

&clx;

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

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

  - new-clx, by Gilbert Baumann

    unk6@rz.uni-karlsruhe.de - faster, with additional features, but not quite complete yet.
oracle

  Access Oracle from &clisp;; by John Hinsdale

  hin@alma.com.
postgresql

  Access PostgreSQL from &clisp;.

queens

  Compute the number of solutions to the n-queens problem on a n*n checkboard (a toy example for the users to explore).

dirkey

  Directory Access

regexp

  The POSIX Regular Expressions matching, compiling, executing.

syscalls

  Use some system calls in a platform-independent way.

wildcard

  Shell (&sh;) globbing

&dirkey;

&regexp;

&syscalls;

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

Platform dependent: many &unix;, &win32;, &amiga; 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-t;; &cname-r; is a &string-t;.

`(&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;)`
  | | | `(&ro-k; boolean)`
  | | | `(:ALLOC &allocation;)`
  | | | `(:LIBRARY &string-t;)`

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

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

  `:LIBRARY` is the (optional) dynamic library which contains the variable.

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

  &option-r; ::== |  |
  --- | --- | ---
  |  | `(&name-k; &cname-r;)`
  | | | `(&arguments-k; {(&arg-r; &ctype-r; [&param-mode; [&allocation;]])}*)`
  | | | `(&ret-type-k; &ctype-r; [&allocation;])`
  | | | `(&lang-k; &lang-r;)`
  | | | `(:BUILT-IN &boolean-t;)`
  | | | `(:LIBRARY &string-t;)`

  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;. `:LIBRARY` is the (optional) dynamic library which contains the function. When the function is a &c-lang; built-in, the full prototype will be output (unless suppressed by &ffi-out-fun;).

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

  &option-r; ::== |  |
  --- | --- | ---
  |  | `(&name-k; &cname-r;)`
  | | | `(&arguments-k; {(&arg-r; &ctype-r; [&param-mode; [&allocation;]])}*)`
  | | | `(&ret-type-k; &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; (&symbol-r; &ctype-r;)*)`

  This form defines &name-r; to be both a &structure-class; and a foreign &c-lang; type with the given slots. &name-r; is a &symbol-t; (structure name) or a &list-t; whose &first; element is the structure name and the &rest; is options. Two options are supported at this time:

  `:TYPEDEF`

    means that the name of this structure is a &c-lang; type defined with `typedef` elsewhere.

  `:EXTERNAL`

    means that this structure is defined in a &c-file; file that you include with, e.g., `(&c-lines; "#include <filename.h>")`.

  These options determine how the struct is written to the &c-file;.
`(&def-c-enum; &name-r; {&symbol-r; | (&symbol-r; [&value-r;])}*)`

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

  You can use `(`FFI:ENUM-FROM-VALUE` &name-r; &value-r;)` and `(`FFI:ENUM-TO-VALUE` &name-r; &symbol-r;)` to convert between the numeric and symbolic representations (of course, the latter function boils down to &symbol-value; plus a check that the &symbol-r; is indeed a constant defined in the &def-c-enum; &name-r;).

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

  This form outputs the string `(&format; &nil; format-string {&arg-r;}*)` 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 &foreign-address-t;. This is useful as an argument to foreign functions expecting a parameter of &c-lang; type &c-pointer;.

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

  Return the &foreign-variable; object underlying the &cplace-r;. This is also an acceptable argument type to a &c-pointer; declaration.

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

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

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

`(&foreign-address-unsigned; &f-ent;)`
`(&unsigned-foreign-address; &number-r;)`

  &foreign-address-unsigned; returns the &integer-t; address embodied in the Lisp object of type &foreign-address-t;, &foreign-pointer-t;, &foreign-variable; or &foreign-function;.

  &unsigned-foreign-address; returns a &foreign-address-t; object pointing to the given &integer-t; address.

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

  &foreign-address; is both a type name and a selector/constructor function. It is the Lisp object type corresponding to a &c-pointer; external type declaration, e.g. a call-out function with `(&ret-type-k; &c-pointer;)` yields a Lisp object of type &foreign-address-t;.

  The function extracts the object of type &foreign-address-t; living within any &foreign-variable; or &foreign-function; object. If the &f-ent; already is a &foreign-address-t;, it returns it. If it is a &foreign-pointer-t; (e.g. a base foreign library address), it encapsulates it into a &foreign-address-t; object, as suitable for use with a &c-pointer; external type declaration. It does not construct addresses out of &number-t;s, &unsigned-foreign-address; must be used for that purpose.

`(&validp; &f-ent;)`
`(&setf; (&validp; &f-ent;) &value-r;)`

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

  You can invalidate a foreign object using `(&setf; &validp;)`. You cannot resurrect a zombie, nor can you kill a non-foreign object.

`(&foreign-pointer; &f-ent;)`
`(&setf; (&foreign-pointer; &f-ent;) &f-ptr;)`

  &foreign-pointer; returns the &foreign-pointer-t; associated with the Lisp object of type &foreign-address-t;, &foreign-pointer-t;, &foreign-variable; or &foreign-function;.

  `(&setf; &foreign-pointer;)` changes the &foreign-pointer-t; associated with the Lisp object of type &foreign-address-t;, &foreign-variable; or &foreign-function; to that of the other entity. When &f-ptr; is &copy-k;, a fresh &foreign-pointer-t; is allocated. &f-ent; still points to the same object. This is particularly useful with `(&setf; &validp;)`.

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

`(&with-foreign-string; (&f-addr; char-count byte-count &string-r; &key-amp; &encoding-r; null-terminated-p &start-r; &end-r;) &body-amp; &body-r;)`

  This forms converts a Lisp &string-r; according to the &encoding-r;, allocating space on the &c-lang; execution stack. &encoding-r; can be any &encoding;, e.g. `CHARSET:UTF-16` or &utf-8;, circumventing the usual 1:1 limit imposed on &foreign-enc;.

  &body-r; is then executed with the three variables &f-addr;, char-count and byte-count respectively bound to an untyped &foreign-address-t; (as known from the &c-pointer; foreign type specification) pointing to the stack location, the number of &character-t;s of the Lisp &string-r; that were considered and the number of &unsigned-byte-8; bytes that were allocated for it on the &c-lang; stack.

  When null-terminated-p is true, which is the default, a variable number of zero bytes is appended, depending on the encoding, e.g. 2 for &utf-8;, and accounted for in byte-count, and char-count is incremented by one.

  The &foreign-address-t; object bound to &f-addr; is invalidated upon the exit from the form.

  A stupid example (a quite costly interface to &mblen;):

      (with-foreign-string (fv elems bytes string
                            :encoding charset:jis... :null-terminated-p nil
                            :end 5)
       (declare (ignore fv elems))
       (format t "This string would take ~D bytes." bytes))

`(&parse-c-type; &ctype-r;)`
`(&deparse-c-type; &ctypei-r;)`

  Convert between the external (&list-t;) and internal (&vector-t;) &c-lang; type representations (used by &describe;).

`(&allocate-shallow; &ctype-r; &key-amp; &count-k; &ro-k;)`
`(&allocate-deep; &ctype-r; &cont-r; &key-amp; &count-k; &ro-k;)`
`(&foreign-free; &f-ent; &key-amp; :FULL)`
`(&foreign-allocate; &ctypei-r; &key-amp; :INITIAL-CONTENTS &count-k; &ro-k;)`

  Macro &allocate-shallow; allocates `(&sizeof; &ctype-r;)` bytes on the &c-lang; heap and zeroes them out (like &calloc;). When &count-k; is supplied, &ctype-r; is substituted with `(&c-array; &ctype-r; &count-r;)`, except when &ctype-r; is &character-t;, in which case `(&c-array-max; &character-t; &count-r;)` is used instead. When &ro-k; is supplied, the Lisp side is prevented from modifying the memory contents. This can be used as an indication that some foreign side is going to fill this memory (e.g. via &read-c;).

  Returns a &foreign-variable; object of the actual &ctype-r;, whose address part points to the newly allocated memory.

  &allocate-deep; will call &c-lang; &malloc; as many times as necessary to build a structure on the &c-lang; heap of the given &ctype-r;, initialized from the given &cont-r;.

  E.g., `(&allocate-deep; '&c-string; "ABCDE")` performs 2 allocations: one for a &c-lang; pointer to a string, another for the contents of that string. This would be useful in conjunction with a char** &c-lang; type declaration. `(&allocate-shallow; '&c-string;)` allocates room for a single pointer (probably 4 bytes).

  `(&allocate-deep; '&character-t; "ABCDEF" :count 10)` allocates and initializes room for the type `(&c-array-max; &character-t; 10)`, corresponding to char* or, more specifically, char[10] in &c-lang;.

  Function &foreign-free; deallocates memory at the address held by the given &f-ent;. If `:FULL` is supplied and the argument is of type &foreign-variable;, recursively frees the whole complex stucture pointed to by this variable.

  If given a &foreign-function; object that corresponds to a &clisp; callback, deallocates it. Callbacks are automatically created each time you pass a Lisp function via the &ffi-pac;.

  Use `(&setf; &validp;)` to disable further references to this address from Lisp. This is currently not done automatically. If the given pointer is already invalid, &foreign-free; (currently) signals an &error-t;. This may change to make it easier to integrate with &finalize;.

  Function &foreign-allocate; is a lower-level interface as it requires an internal &c-lang; type descriptor as returned by &parse-c-type;.

`(&with-c-place; (&var-r; &f-ent;) &body-r;)`

  Create a &place; out of the given &foreign-variable; object so operations on places (e.g. &cast;, &deref;, &slot; etc.) can be used within &body-r;. &with-c-var; appears as a composition of &with-foreign-object; and &with-c-place;.

  Such a &place; can be used to access memory referenced by a &f-ent; object:

      (setq foo (allocate-deep '(c-array uint8 3) rgb))
      (with-c-place (place foo) (element place 0))

&ffi-out-fun;
`FFI:*OUTPUT-C-VARIABLES*`

  &clisp; will write the extern declarations for foreign functions (defined with &def-call-out;) and foreign variables (defined with &def-c-var;) into the output &c-file; unless these variables are &nil;. They are &nil; by default, so the extern declarations are not &not-e; written; you are encouraged to use &c-lines; to include the appropriate &c-lang; headers. Set these variables to non-&nil; if the headers are not available or not usable.

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

Foreign &c-lang; types are used in the &ffi-pac;. They are &not-e; 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. When used as an argument, &nil; is accepted as a &c-pointer; and treated as &c-NULL;; when a function wants to return a &c-NULL; &c-pointer;, it actually returns &nil;.

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

  &class-r; may also be a &cons-t; of a &symbol-t; (as above) and a &list-t; of &def-c-struct; options.

`(&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;)`
`(&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-r; a-c-type [&param-mode; [&allocation;]])}*) (&ret-type-k; 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, and &c-NULL;/&nil; is recognized and accepted.

`(&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;.

&foreign-enc; governs conversion for any &ctype-r; involving &c-string; or &character-t; (but not char).

#### 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 the 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 &fresh; Lisp value. Foreign variables are defined using &def-c-var;.

#### Operations on foreign places

A &foreign-variable; &name-r; defined by &def-c-var;, &with-c-var; or &with-c-place; 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;, &offset;, &c-var-addr;, &c-var-object;, &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; | 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 and win32) have problems with this. The recommended workaround is to pass pointers; this is fully supported. See also this &clisp-list; message.

#### 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-k; (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 :typedef)
      (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

##### Variable size arguments: calling &gethostname; from &clisp;

       int gethostname
       char* name
       size_t namelen

follows a typical pattern of &c-lang; "out"-parameter convention - it expects a pointer to a buffer it is going to fill. So you must view this parameter as either &out-k; or &in-out-k;. Additionaly, one must tell the function the size of the buffer. Here namelen is just an &in-k; parameter. Sometimes this will be an &in-out-k; parameter, returning the number of bytes actually filled in.

So name is actually a pointer to an array of up to namelen characters, regardless of what the poor char* &c-lang; prototype says, to be used like a &c-lang; string (0-termination). &unix; specifies that "kost names are limited to HOST_NAME_MAX bytes", which is, of course, system dependent, but it appears that 256 is a common value.

In the present example, you can use allocation &alloca-k;, like you would do in &c-lang;: stack-allocate a temporary.

    (&def-c-call-out; gethostname
      (:arguments (name (&c-ptr; (&c-array-max; ffi:char 256))
    		    &out-k; &alloca-k;)
    	      (len ffi:int))
      (:return-type ffi:int))

    (defun myhostname ()
      (multiple-value-bind (success name)
          ;; &out-k; and &in-out-k; parameters are returned as multiple values
          (gethostname 256)
        (if (zerop success) name
    	(error ...)))) ;; &strerror;(&errno;)

    (defvar hostname (myhostname))

##### More examples

You can find more information and examples of the &clisp; &ffi-pac; in the following &clisp-list; messages:

- "variable size values"

- "variable length arrays"

### 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 λ 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)`

`(close-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 {&arg-r;}*)`

`(mlibcall function-name {&arg-r;}*)`

`(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-t;).

#### 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-e; regular &cl; types or &clos; classes.

&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-c; 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-t; 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-t; 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 &zero; 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-t; 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-r; &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-t;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 an binds a port to the socket. 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. Just like streams, &socket-server;s are closed at &gc;ion. You should not rely on this however, because &gc;ion times are not deterministic.

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

  Returns the host mask indicating which hosts can connect to this server and 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. Returns &t; when a connection is available (i.e., &so-accept; will not block) and &nil; on timeout.

`(&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)`). &signal;s an &error-t; 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;, so it will work for any &clisp; &stream-t; which is based on a &file-des;, e.g., &file-pipe-socket; and &kbd-in;.

  This is similar to &listen;, which checks only one &stream-t; and only for input, and &so-wait;, which works only with &socket-server;s.

  We define status for a &socket-server; or a &socket-stream; to be &error-k; if any i/o operation will cause an error.

  Additionally, for a &socket-server;, we define status to be &t; if a connection is available, i.e., is &so-accept; will not block, and &nil; otherwise.

  Additionally, for a &socket-stream;, we define status in the given &direction-r; (one of &input-k;, &output-k;, and &io-k;) to be

  #### Possible status values for various directions:

  &input-k; status:
    &nil;

      reading will block

    &input-k;

      some input is available

    &eof-k;

      the stream has reached its end

  &output-k; status:
    &nil;

      writing will block

    &output-k;

      output to the stream will not block

  &io-k; status:

    output status | input status
    --- | ---
    &nil; | &input-k; | &eof-k;
    &nil; | &nil; | &input-k; | &eof-k;
    &output-k; | &output-k; | &io-k; | &append-k;

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

  &socket-stream; or &socket-server;

    Returns the appropriate status, as defined above (&io-k; status for &socket-stream;)

  `(&socket-stream; . &direction-r;)`

    Return the status in the specified direction

  a list of the above

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

  If you want to avoid &cons;ing up a &fresh; list, you can make the elements of socket-stream-or-list to be `(&sost-r; &direction-r; . &x-r;)` or `(&sose-r; . &x-r;)`. Then &so-status; will destructively modify its argument and replace &x-r; or &nil; with the status and return the modified list. You can pass this modified list to &so-status; again.

  The optional arguments specify the timeout. &nil; means wait forever, &zero; means poll.

  The second value returned is the number of objects with non-&nil; status, i.e., actionable objects. &so-status; returns either due to a timeout or when this number is positive, i.e., if the timeout was &nil; and &so-status; did return, then the second value is positive.

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

  These two functions return information about the &socket-stream;.

`(&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 `(&simple-vector-t; 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-r;)`

  Some Internet protocols, such as &http;, provide for closing the connection in one &direction-r; using &shutdown;. This function provides an interface to this &unix; system call. &direction-r; should 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 &bidi-s;s (i.e., both &input-stream-p; and &output-stream-p; return &t; for them). &sost-shut; breaks this and turns its argument stream into an &in-s; (if &direction-r; is &output-k;) or &out-s; (if &direction-r; is &input-k;). Thus, the following important invariant is preserved: whenever

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

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

  the &stream-t; can be read from (e.g., with &read-char; or &read-byte;).
`(&so-opt; &sose-r; &rest-amp; {&option-r;}*)`

  Query and, optionally, set socket options using &getsockopt; and &setsockopt;. An &option-r; is a keyword, optionally followed by the new value. When the new value is not supplied, &setsockopt; is not called. For each option the old (or current, if new value was not supplied) value is returned. E.g., `(&so-opt; &sose-r; :SO-LINGER 1 :SO-RCVLOWAT)` returns 2 values: &nil;, the old value of the `:SO-LINGER` option, and 1, the current value of the `:SO-RCVLOWAT` option.

### Extensions-2.7. 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.

  #### Script execution

  - The script should contain Lisp forms, except in the `#!` line.

  - The file is loaded normally, through the function &load; (in particular, the name of the script file, which is `$0` in &sh;, can be found in &load-truename-var; and &load-pathname-var;).

  - Before it is loaded, the variable &args; is bound to a list of strings, representing the arguments given to the Lisp script (i.e., `$1` in &sh; becomes `(&car; &args;)` etc).

  - &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 (using &appease-cerrors;).

  - Non-continuable errors and &ctrl;C interrupts will terminate the execution of the Lisp script with an error status (using &exit-on-error;).

  - If you wish the script's contents to be compiled during loading, add `-C` to the &interp-args;.

  See also the manual.

  #### If nothing works

  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/local/bin/clisp:" >> /proc/sys/fs/binfmt_misc/register
      bash# echo ":CLISP:E::lisp::/usr/local/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.8. 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 &module;s 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 &module;s into a separate (non-&clisp;) program, with which your Lisp program will communicate via &socket-stream;s.

### Extensions-2.9. 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 &sh;. The command should be a simple command; a command list should be enclosed in "{ ... ; }" (for &sh;) or "( ... )" (for `/bin/csh`).

  &program-r;

    the program. The directories listed in the &env-var; `PATH` 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, default) 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, default) 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;. The default is &overwrite-k;.

  &wait-k;

    whether to wait for program termination or not (this is useful when no i/o to the process is needed); the default is &t;, i.e., synchronous execution.

  `: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-t; is returned. If &stream-k; was specified for both &input-k; and &output-k;, three Lisp &stream-t;s 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 &in-s; 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 &out-s; 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 &bidi-s; 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 &in-s; and the &out-s; that make up the &bidi-s;, respectively.

    Note that these three streams must be closed individually.

    Note that improper use of this function can lead to deadlocks. Use it at your own risk!

    A deadlock occurs if the command and your Lisp 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;, &so-status; instead of &read-line; and &read; on the input side, and complete every output operation by a &finish-output;. The same precautions must apply to the called command as well.

#### Printing

The macro &with-print;
:

    (&with-print; (&var-r; [&extfmt;])
      {&declaration-r;}*
      {&form-r;}*)

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

### Extensions-2.10. 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.11. 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;)))

Platform dependent: &unix; platforms only.

  When running under the &X;, you can create a &bidi-s;, which uses a new dedicated xterm, using the function &mk-xterm-io;
  :

        (&setq; &error-output-var;
          (&setq; &debug-io-var;
            (&mk-xterm-io;)))