# CLISP implementation notes

###

### Dr. Bruno Haible

### Dr. Sam Steingold

These notes are covered by the GNU GFDL:

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being this section [FIXME], with the Front-Cover Texts being this section [FIXME], and with the Back-Cover Texts being this section [FIXME]. A copy of the license is not yet [FIXME] included in the section entitled "GNU Free Documentation License".

##

These notes discuss the CLISP implementation of Common Lisp by

> Dr Bruno Haible
> Louisenstraße 103
> Bad Homburg
> D-61348 Germany
> http://clisp.cons.org/~haible

and

> Dr Michael Stoll
> Westerwaldweg 22
> Remagen-Oberwinter
> D-53424 Germany
> http://www.math.uni-duesseldorf.de/home/stoll

The current maintainers are

> Dr Bruno Haible

and

> Dr Sam Steingold
> `<sds@clisp.cons.org>`
> http://clisp.cons.org/~sds

This implementation is mostly conforming to the [ANSI CL standard] available on-line as the [Common Lisp HyperSpec] (but the printed ANSI document remains the authoritative source of information). [ANSI CL standard] supersedes the earlier specifications [CLtL1] and [CLtL2].

These notes document the differences between the CLISP implementation of Common Lisp and the [ANSI CL standard], and some implementation details. This document is indexed in parallel to the [Common Lisp HyperSpec].

# Chapters or the [Common Lisp HyperSpec]

## Chapter 1. Introduction [CLHS-1]

## Special Symbols [CLHS-1.4.1.3]

The final delimiter of an interactive stream: On Unix, the user has to type Ctrl-D at the beginning of a line. On DOS or Win32, the user has to type Ctrl-Z, followed by Return. This final delimiter is never actually seen by programs; no need to test for #\^D or #\^Z - use `READ-CHAR-NO-HANG` to check for end of stream. Calling `CLEAR-INPUT` on the stream removes the `end-of-stream` state, thus making it available for further input.

A newline character can be entered by the user by pressing the Newline key or, on the numeric keypad, the Enter key.

## Error Terminology [CLHS-1.4.2]

Safety settings are ignored; therefore where the standard uses the phrase “should signal an error”, an `ERROR` is signaled.

## Class Precedence Lists [CLHS-1.4.4.5]

The class precedence lists of the system classes `CLASS` `BUILT-IN-CLASS`, `STRUCTURE-CLASS`, `STANDARD-CLASS`, `STANDARD-METHOD` contain the class `STRUCTURE-OBJECT` instead of the class `STANDARD-OBJECT`.

## Symbols in the Package “COMMON-LISP” [CLHS-1.9]

The 28 symbols missing from the “COMMON-LISP” package (out of 978 specified by the [ANSI CL standard]):

`*PRINT-LINES*` | `*PRINT-MISER-WIDTH*` | `*PRINT-PPRINT-DISPATCH*`
`CALL-METHOD` | `CHANGE-CLASS` | `COPY-PPRINT-DISPATCH`
`DEFINE-METHOD-COMBINATION` | `ENSURE-GENERIC-FUNCTION` | `INVALID-METHOD-ERROR`
`MAKE-INSTANCES-OBSOLETE` | `MAKE-LOAD-FORM-SAVING-SLOTS` | `MAKE-LOAD-FORM`
`MAKE-METHOD` | `METHOD-COMBINATION-ERROR` | `METHOD-COMBINATION`
`PPRINT-DISPATCH` | `PPRINT-EXIT-IF-LIST-EXHAUSTED` | `PPRINT-FILL`
`PPRINT-INDENT` | `PPRINT-LINEAR` | `PPRINT-LOGICAL-BLOCK`
`PPRINT-NEWLINE` | `PPRINT-POP` | `PPRINT-TAB`
`PPRINT-TABULAR` | `SET-PPRINT-DISPATCH` | `UPDATE-INSTANCE-FOR-DIFFERENT-CLASS`
`UPDATE-INSTANCE-FOR-REDEFINED-CLASS` |  |

## Chapter 2. Syntax [CLHS-2]

## Symbols as Tokens [CLHS-2.3.4]

A "reserved token", i.e., a token that has potential number syntax but cannot be interpreted as a number, is interpreted as symbol when being read.

When creating a symbol from a token, no character attributes are removed.

## Valid Patterns for Tokens [CLHS-2.3.5]

When a token with package markers is read, then no checking is done whether the package part and the symbol-name part do not have number syntax. (What's the purpose of this check?) So we consider tokens like USER:: or :1 or LISP::4711 or 21:3 as symbols.

## Double-Quote [CLHS-2.4.5]

When a string is read, no character attributes are removed.

## Backquote [CLHS-2.4.6]

The backquote read macro also works when nested. Example:

       (EVAL ``(,#'(LAMBDA () ',a) ,#'(LAMBDA () ',b)))
     = (EVAL `(list #'(LAMBDA () ',a) #'(LAMBDA () ',b)))
     = (EVAL (list 'list (list 'function (list 'lambda nil (list 'quote a)))
                         (list 'function (list 'lambda nil (list 'quote b)))))

Multiple backquote combinations like `,,@` or `,@,@` are not implemented. Their use would be confusing anyway.

## Sharpsign [CLHS-2.4.8]

Reader macros are also defined for the following:

Additional reader macros

Macro: #,

Meaning: load-time evaluation

Macro: #Y

Meaning: function objects and file encodings

Macro: #"

Meaning: pathname

## Chapter 3. Evaluation and Compilation [CLHS-3]

All the functions built by `FUNCTION`, `COMPILE` and the like are atoms. There are built-in functions written in C, compiled functions (both of type `COMPILED-FUNCTION`) and interpreted functions (of type `FUNCTION`).

## Evaluation [CLHS-3.1]

### Introduction to Environments [CLHS-3.1.1]

`EXT:THE-ENVIRONMENT` As in Scheme, the macro `(`ext:the-environment`)` returns the current lexical environment. This works only in interpreted code and is not compilable!

`(ext:eval-env `form` `&OPTIONAL` `env`)` evaluates a form in a given lexical environment, just as if the form had been a part of the program that the environment came from.

## Compilation [CLHS-3.2]

### Compiler Terminology [CLHS-3.2.1]

CLISP compiles to platform-independent byte-code.

### Compiler Macros [CLHS-3.2.2.1]

Compiler macros are expanded in the compiled code only, and ignored by the interpreter.

### Definition of Similarity [CLHS-3.2.4.2.2]

Hash tables are externalizable objects.

## Declarations [CLHS-3.3]

The declarations `(`TYPE` `type` `variable` ...)`, `(`FTYPE` `type` `function` ...)`, `(`OPTIMIZE` (`quality` `value`) ...)` are ignored by the interpreter and the compiler.

The [ANSI CL standard] declaration `(`OPTIMIZE` (debug ...))` is legal.

The [ANSI CL standard] declaration `(`IGNORABLE` `variable` ...)` affects the variable binding for the variable `variable`. The compiler will not warn about the variable, regardless whether it is used or not.

### Additional declarations

The declaration `(compile)` has the effect that the current form is compiled prior to execution. Examples:

     (LOCALLY (DECLARE (compile)) form)

executes a compiled version of form.

    (LET ((x 0))
      (FLET ((inc () (DECLARE (compile)) (INCF x))
             (dec () (DECF x)))
        (VALUES #'inc #'dec)))

returns two functions. The first is compiled and increments `x`, the second is interpreted (slower) and decrements the same `x`.

The type assertion `(`THE` `value-type` `form`)` enforces a type check in interpreted code. No type check is done in compiled code. See also the `ext:ethe` macro.

## Lambda Lists [CLHS-3.4]

### Boa Lambda Lists [CLHS-3.4.6]

The initial value of an `&AUX` variable in a boa lambda list is the value of the corresponding slot's initial form.

## The Evaluation and Compilation Dictionary [CLHS-3.8]

### Declaration `SPECIAL`

`(`PROCLAIM` '(`SPECIAL` `variable`))` declarations may not be undone. The same holds for `DEFVAR`, `DEFPARAMETER` and `DEFCONSTANT` declarations.

It is an error if a `DEFCONSTANT` variable is bound at the moment the `DEFCONSTANT` is executed, but `DEFCONSTANT` does not check this.

Constants may not be bound dynamically or lexically.

### Macro `EVAL-WHEN`

`EVAL-WHEN` also accepts the situations `(not eval)` and `(not compile)`.

## Chapter 4. Types and Classes [CLHS-4]

## Types [CLHS-4.2]

### Type Specifiers [CLHS-4.2.3]

The general form of the `COMPLEX` type specifier is `(`COMPLEX` `type-of-real-part` `type-of-imaginary-part`)`. The type specifier `(`COMPLEX` `type`)` is equivalent to `(`COMPLEX` `type` `type`)`.

The [ANSI CL standard] type specifier `(`REAL` `low` `high`)` denotes the real numbers between `low` and `high`.

`DEFTYPE` lambda lists are subject to destructuring (nested lambda lists are allowed, as in `DEFMACRO`) and may contain a `&WHOLE` marker, but not an `&ENVIRONMENT` marker.

`(`ext:type-expand-1` `typespec`)` If `typespec` is a user-defined type, `ext:type-expand-1` will expand it once and return two values: the expansion and `T`. If `typespec` is not a user-defined type, then the two values `typespec` and `NIL` are returned.

`(`ext:type-expand` `typespec`)` This is similar to `(`ext:type-expand-1` `typespec`)`, but repeatedly expands `typespec` until it is no longer a user-defined type. A second value of `T` or `NIL` is returned as for `ext:type-expand-1`, indicating whether the original `typespec` was a user-definedtype.

The possible results of `TYPE-OF` are:

- `CONS`

- `SYMBOL`, `NULL`, `BOOLEAN`

- `FIXNUM`, `BIGNUM`, `RATIONAL`, `SHORT-FLOAT`, `SINGLE-FLOAT`, `DOUBLE-FLOAT`, `LONG-FLOAT`, `COMPLEX`

- `CHARACTER`, `BASE-CHAR`

- `(`ARRAY` `element-type` `dimensions`)`, `(`SIMPLE-ARRAY` `element-type` `dimensions`)`

- `(`VECTOR` `T` `size`)`, `(`SIMPLE-VECTOR` `size`)`

- `(`STRING` `size`)`, `(`SIMPLE-STRING` `size`)`

- `(`BASE-STRING` `size`)`, `(`SIMPLE-BASE-STRING` `size`)`

- `(`BIT-VECTOR` `size`)`, `(`SIMPLE-BIT-VECTOR` `size`)`

- `FUNCTION`, `COMPILED-FUNCTION`

- `STREAM`, `FILE-STREAM`, `SYNONYM-STREAM`, `BROADCAST-STREAM`, `CONCATENATED-STREAM`, `TWO-WAY-STREAM`, `ECHO-STREAM`, `STRING-STREAM`

- `PACKAGE`, `HASH-TABLE`, `READTABLE`, `PATHNAME`, `LOGICAL-PATHNAME`, `RANDOM-STATE`, `byte`

- `special-operator`, `load-time-eval`, `symbol-macro`, `encoding`, `foreign-pointer`, `foreign-address`, `foreign-variable`, `foreign-function`

- `weak-pointer`, `read-label`, `frame-pointer`, `system-internal`

- `address` (should not occur)

- any other symbol (structure types or CLOS classes)

- a class (CLOS classes without proper name)

## Classes [CLHS-4.3]

The CLOS symbols are `EXPORT`ed from the package “CLOS” and thus normally visible in all user packages. If you do not want them (for example, if you want to use the PCL implementation of CLOS instead of the native one), do `(`UNUSE-PACKAGE` "CLOS")`.

## Deviations from [ANSI CL standard]

`DEFCLASS` It is required that the superclasses of a class be defined before the `DEFCLASS` form for the class is evaluated.

`DEFCLASS` supports the option `:metaclass` `STRUCTURE-CLASS`. This option is necessary in order to define a subclass of a `DEFSTRUCT`-defined structure type using `DEFCLASS` instead of `DEFSTRUCT`.

When `CALL-NEXT-METHOD` is called with arguments, the rule that the ordered set of applicable methods must be the same as for the original arguments is enforced by the implementation only in interpreted code.

There is a generic function `clos:no-primary-method` (similar to `NO-APPLICABLE-METHOD`) which is called when a generic function of the class `STANDARD-GENERIC-FUNCTION` is invoked and no primary method on that generic function is applicable.

`clos:generic-flet` and `clos:generic-labels` are implemented as macros, not as special operators. They are not imported into the packages “COMMON-LISP-USER” and “COMMON-LISP” because of the [ANSI CL standard] issue GENERIC-FLET-POORLY-DESIGNED:DELETE.

The function `ENSURE-GENERIC-FUNCTION` is not implemented.

`ADD-METHOD` can put methods into other generic functions than the one the method came from.

`PRINT-OBJECT` is only called on objects of type `STANDARD-OBJECT` and `STRUCTURE-OBJECT`. It is not called on other objects, like `CONS`es and `NUMBER`s, due to the performance concerns.

`DOCUMENTATION` still has the [CLtL1] implementation.

## Standard Metaclasses [CLHS-4.3.1.1]

Among those classes listed in Figure 4-8, only the following are instances of `BUILT-IN-CLASS`:

- `T`

- `CHARACTER`

- `NUMBER`, `COMPLEX`, `REAL`, `FLOAT`, `RATIONAL`, `RATIO`, `INTEGER`

- `SEQUENCE`

- `ARRAY`, `VECTOR`, `BIT-VECTOR` `STRING`

- `LIST`, `CONS`

- `SYMBOL`, `NULL`

- `FUNCTION`, `GENERIC-FUNCTION`, `STANDARD-GENERIC-FUNCTION`

- `HASH-TABLE`

- `PACKAGE`

- `PATHNAME`, `LOGICAL-PATHNAME`

- `RANDOM-STATE`

- `READTABLE`

- `STREAM`, `BROADCAST-STREAM`, `CONCATENATED-STREAM`, `ECHO-STREAM`, `STRING-STREAM`, `FILE-STREAM`, `SYNONYM-STREAM`, `TWO-WAY-STREAM`

## Defining Classes [CLHS-4.3.2]

`DEFCLASS` supports the `:metaclass` option. Possible values are `STANDARD-CLASS` (the default) and `STRUCTURE-CLASS` (which creates structure classes, like `DEFSTRUCT` does).

## Redefining Classes [CLHS-4.3.6]

Redefining classes is not supported. The function `UPDATE-INSTANCE-FOR-REDEFINED-CLASS` is not implemented.

## Integrating Types and Classes [CLHS-4.3.7]

The class `METHOD-COMBINATION` is not implemented.

## Chapter 5. Data and Control Flow [CLHS-5]

## The Data and Control Flow Dictionary [CLHS-5.3]

`PROG1`, `PROG2`, `AND`, `OR`, `PSETQ`, `WHEN`, `UNLESS`, `COND`, `CASE`, `MULTIPLE-VALUE-LIST`, `MULTIPLE-VALUE-BIND`, `MULTIPLE-VALUE-SETQ` are implemented as special operators and, as such, are rather efficient.

`DESTRUCTURING-BIND` does not perform full error checking.

### Function `EQ`

`EQ` compares `CHARACTER`s and `FIXNUM`s as `EQL` does. No unnecessary copies are made of `CHARACTER`s and `NUMBER`s. Nevertheless, one should use `EQL` as it is more portable across Common Lisp implementations.

`(let ((x y)) (eq x x))` always returns `T`, regardless of `y`.

### Function `SYMBOL-FUNCTION`

`(`SETF` (`SYMBOL-FUNCTION` `symbol`) `object`)` requires `object` to be either a function, a `SYMBOL-FUNCTION` return value or a lambda expression. The lambda expression is thereby immediately converted to a function.

### Macro `SETF`

Additional places:

`FUNCALL`

  `(`SETF` (`FUNCALL` #'`symbol` ...) `object`)` and `(`SETF` (`FUNCALL` '`symbol` ...) `object`)` are equivalent to `(`SETF` (`symbol` ...) `object`)`.

`PROGN`

  `(`SETF` (`PROGN` `form` ... `place`) `object`)`

`LOCALLY`

  `(`SETF` (`LOCALLY` `declaration` ... `form` ... `place`) `object`)`

`IF`

  `(`SETF` (`IF` `condition` `place1` `place2`) `object`)`

`GET-DISPATCH-MACRO-CHARACTER`

  `(`SETF` (`GET-DISPATCH-MACRO-CHARACTER` ...) ...)` calls `SET-DISPATCH-MACRO-CHARACTER`.

`ext:long-float-digits`:

  `(`SETF` (`ext:long-float-digits`) `digits`)` sets the default mantissa length of long floats to `digits` bits.

`VALUES-LIST`

  `(`SETF` (`VALUES-LIST` `list`) `form`)` is equivalent to `(`VALUES-LIST` (`SETF` `list` (`MULTIPLE-VALUE-LIST` `form`)))`

`&KEY` markers in `DEFSETF` lambda lists are supported, but the corresponding keywords must appear literally in the program text.

`(`GET-SETF-EXPANSION` `form` `&OPTIONAL` `env`)`, `(ext:get-setf-method `form` `&OPTIONAL` `env`)`, and `(ext:get-setf-method-multiple-value `form` `&OPTIONAL` `env`)` receive as optional argument the environment necessary for macro expansions. In `DEFINE-SETF-EXPANDER` and `ext:define-setf-method` lambda lists, one can specify `&ENVIRONMENT` and a variable, which will be bound to the environment. This environment should be passed to all calls of `GET-SETF-EXPANSION`, `ext:get-setf-method` and `ext:get-setf-method-multiple-value`. If this is done, even local macros will be interpreted as places correctly.

Attempts to modify read-only data will signal an error. Program text and quoted constants loaded from files are considered read-only data. This check is only performed for strings, not for conses, other kinds of arrays, and user-defined data types.

See also the `ext:letf` and `ext:letf*` macros.

### Special Operator `FUNCTION`

`(`FUNCTION` `symbol`)` returns the local function definition established by `FLET` or `LABELS`, if it exists, otherwise the global function definition.

`(`SPECIAL-OPERATOR-P` `symbol`)` returns `NIL` or `T`. If it returns `T`, then `(`SYMBOL-FUNCTION` `symbol`)` returns the (useless) special operator handler.

### Macro `DEFINE-SYMBOL-MACRO`

The macro `DEFINE-SYMBOL-MACRO` establishes `symbol-macro`s with global scope (as opposed to `symbol-macro`s defined with `SYMBOL-MACROLET`, which have local scope): `(`DEFINE-SYMBOL-MACRO` `symbol` `expansion`)`.

The function `ext:symbol-macro-expand` tests for a `symbol-macro`: If `symbol` is defined as a `symbol-macro`, `(ext:symbol-macro-expand `symbol`)` returns two values, `T` and the expansion, otherwise it returns `NIL`.

Calling `BOUNDP` on a symbol defined as a `symbol-macro` returns `T`.

Calling `SYMBOL-VALUE` on a symbol defined as a `symbol-macro` returns the value of the expansion. Calling `SET` on a symbol defined as a `symbol-macro` calls `SETF` on the expansion.

Calling `MAKUNBOUND` on a symbol defined as a `symbol-macro` removes the `symbol-macro` definition.

### Macro `LAMBDA`

`LAMBDA-LIST-KEYWORDS` `(`&OPTIONAL` `&REST` `&KEY` `&ALLOW-OTHER-KEYS` `&AUX` `&BODY` `&WHOLE` `&ENVIRONMENT`)`

Platform dependent

CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU
--- | --- | --- | ---
`CALL-ARGUMENTS-LIMIT` | 216=65536 | 232=4294967296
`MULTIPLE-VALUES-LIMIT` | 27=128
`LAMBDA-PARAMETERS-LIMIT` | 216=65536 | 232=4294967296

### Macros `DEFUN` & `DEFMACRO`

`DEFUN` and `DEFMACRO` are allowed in non-toplevel positions. As an example, consider the old ([CLtL1]) definition of `GENSYM`:

    (let ((gensym-prefix "G")
          (gensym-count 1))
      (defun gensym (&optional (x nil s))
        (when s
          (cond ((stringp x) (setq gensym-prefix x))
                ((integerp x)
                 (if (minusp x)
                   (error "~S: index ~S is negative" 'gensym x)
                   (setq gensym-count x)))
                (t (error "~S: argument ~S of wrong type" 'gensym x))))
        (prog1
          (make-symbol
            (concatenate 'string
              gensym-prefix
              (write-to-string gensym-count :base 10 :radix nil)))
          (incf gensym-count))))

## Chapter 6. Iteration [CLHS-6]

No notes.

## Chapter 7. Objects [CLHS-7]

Changing the class of a given instance is not supported. The functions `CHANGE-CLASS`, `UPDATE-INSTANCE-FOR-DIFFERENT-CLASS`, `MAKE-INSTANCES-OBSOLETE` are not implemented.

Only the `STANDARD` method combination is implemented.

User-defined method combination is not supported. The macros `DEFINE-METHOD-COMBINATION`, `CALL-METHOD` and the functions `INVALID-METHOD-ERROR`, `METHOD-COMBINATION-ERROR` are not implemented.

## Chapter 8. Structures [CLHS-8]

The `:print-function` option should contain a lambda expression `(`LAMBDA` (structure stream depth) (declare (ignore depth)) ...)` This lambda expression names a function whose task is to output the external representation of structure onto the stream. This may be done by outputting text onto the stream using `WRITE-CHAR`, `WRITE-STRING`, `WRITE`, `PRIN1`, `PRINC`, `PRINT`, `PPRINT`, `FORMAT` and the like. The following rules must be obeyed:

- The value of `*PRINT-ESCAPE*` must be respected.

- The value of `*PRINT-PRETTY*` should not and cannot be respected, since the pretty-print mechanism is not accessible from outside.

- The value of `*PRINT-CIRCLE*` need not be respected. This is managed by the system. (But the print-circle mechanism handles only those objects that are (direct or indirect) components of structure.)

- The value of `*PRINT-LEVEL*` is respected by `WRITE`, `PRIN1`, `PRINC`, `PRINT`, `PPRINT`, `FORMAT` instructions `~A`, `~S`, `~W`, and `FORMAT` instructions `~R`, `~D`, `~B`, `~O`, `~X`, `~F`, `~E`, `~G`, `~$` with not-numerical arguments. Therefore the print-level mechanism works automatically if only these functions are used for outputting objects and if they are not called on objects with nesting level > 1. (The print-level mechanism does not recognize how many parentheses you have output. It only counts how many times it was called recursively.)

- The value of `*PRINT-LENGTH*` must be respected, especially if you are outputting an arbitrary number of components.

- The value of `*PRINT-READABLY*` must be respected. Remember that the values of `*PRINT-ESCAPE*`, `*PRINT-LEVEL*`, `*PRINT-LENGTH*` are ignored if `*PRINT-READABLY*` is true. The value of `*PRINT-READABLY*` is respected by `PRINT-UNREADABLE-OBJECT`, `WRITE`, `PRIN1`, `PRINC`, `PRINT`, `PPRINT`, `FORMAT` instructions `~A`, `~S`, `~W`, and `FORMAT` instructions `~R`, `~D`, `~B`, `~O`, `~X`, `~F`, `~E`, `~G`, `~$` with not-numerical arguments. Therefore `*PRINT-READABLY*` will be respected automatically if only these functions are used for printing objects.

- You need not worry about the values of `*PRINT-BASE*`, `*PRINT-RADIX*`, `*PRINT-CASE*`, `*PRINT-GENSYM*`, `*PRINT-ARRAY*`, `custom:*print-closure*`, `custom:*print-rpars*`, `custom:*print-indent-lists*`.

The `:inherit` option is exactly like `:include` except that it does not create new accessors for the inherited slots.

## Chapter 9. Conditions [CLHS-9]

When an error occurred, you are in a break loop. You can evaluate forms as usual. The help command (or help key if there is one) lists the available debugging commands.

`ext:muffle-cerrors` The macro `(`ext:muffle-cerrors` {`form`}*)` executes the `form`s. When a continuable error occurs, no message is printed. Instead, the `CONTINUE` restart is invoked.

`ext:appease-cerrors` The macro `(`ext:appease-cerrors` {`form`}*)` executes the `form`s. When a continuable error occurs, the error is printed as a warning and the `CONTINUE` restart is invoked.

`ext:exit-on-error` The macro `(`ext:exit-on-error` {`form`}*)` executes the `form`s. When a non-continuable error or a Ctrl-C interrupt occurs, the error is printed and CLISP terminates with an error status.

`ext:with-restarts` The macro `ext:with-restarts` is like `RESTART-CASE`, except that the forms are specified after the restart clauses instead of before them, and the restarts created are not implicitly associated to any condition. `(`ext:with-restarts` ({`restart-clause`}*) {`form`}*)` is therefore equivalent to `(`RESTART-CASE` (`PROGN` {`form`}*) {`restart-clause`}*)`.

## Embedded Newlines in Condition Reports [CLHS-9.1.3.1.3]

The error message prefix for the first line is "*** - ". There is no prefix for subsequent error lines. The aesthetics of condition reports containing an object, which requires newlines when pretty printing is enabled, is undefined.

## The Conditions Dictionary [CLHS-9.2.]

`RESTART-CASE` In `RESTART-CASE` clauses the argument list can also be specified after the keyword/value pairs instead of before them. The syntax therefore is

`(`RESTART-CASE` `form` {`restart-clause`}*)`

`restart-clause` ::==

         (restart-name arglist {keyword value}* {form}*)
         | (restart-name {keyword value}* arglist {form}*)

`COMPUTE-RESTARTS` `COMPUTE-RESTARTS` and `FIND-RESTART` behave as specified in [ANSI CL standard]: If the optional condition argument is non-`NIL`, only restarts associated with that condition and restarts associated to no condition at all are considered. Therefore the effect of associating a restart to a condition is not to activate it, but to hide it from other conditions. This makes the syntax dependent implicit association performed by `RESTART-CASE` nearly obsolete.

## Chapter 10. Symbols [CLHS-10]

No notes.

## Chapter 11. Packages [CLHS-11]

The [ANSI CL standard] packages present in CLISP

“COMMON-LISP”

  with the nicknames `"CL"` and `"LISP"`

“COMMON-LISP-USER”

  with the nicknames `"CL-USER"` and `"USER"`

“KEYWORD”

  with the nickname `""`

The package “COMMON-LISP” `EXPORT`s only those symbols from the [ANSI CL standard] that are actually implemented.

## The COMMON-LISP-USER Package [CLHS-11.1.2.2]

The “COMMON-LISP-USER” package uses the “COMMON-LISP” and “EXT” packages.

## Implementation-Defined Packages [CLHS-11.1.2.4]

The following additional packages exist:

Implementation-Defined Packages

“CLOS”

  `EXPORT`s all CLOS specific symbols, including some additional symbols.

“SYSTEM”

  has the nicknames “SYS” and “COMPILER”, and has no `EXPORT`ed symbols. It defines many system internals.

“EXT”

  is the umbrella package for all extensions: it imports and `re-export`s all the external symbols in all CLISP extensions, so a simple `(`USE-PACKAGE` "EXT")` is enough to make all the extensions available in the current package. This package uses packages (in addition to “COMMON-LISP”): “LDAP” “POSIX” “SOCKET” “GSTREAM” “GRAY” “I18N” “CUSTOM”.

“CHARSET”

  defines and `EXPORT`s some character sets, for use with `make-encoding` and as `:external-format` argument.

“FFI”

  implements the foreign function interface. Some platforms only.

“SCREEN”

  defines an API for random screen access. Some platforms only.

All pre-existing packages except “COMMON-LISP-USER” belong to the implementation, in the sense that doing side-effects on them or on their symbols causes undefined behavior.

## The Packages Dictionary [CLHS-11.2.]

### Function `MAKE-PACKAGE`

For `MAKE-PACKAGE`, the default value of the `:use` argument is `("COMMON-LISP")`.

`MAKE-PACKAGE` accepts a keyword argument `:case-sensitive`. Similarly, `DEFPACKAGE` accepts an option `:case-sensitive`. When its value is non-`NIL`, the package will be case sensitive, i.e., the reader will not case-convert symbol names before looking them up or creating them in this package. The package names are still subject to `(`READTABLE-CASE` `*READTABLE*`)`, though.

#### `ext:re-export`

The function `(`re-export` `FROM-PACK` `TO-PACK`)` re-exports all external symbols from `FROM-PACK` also from `TO-PACK`, provided it already uses `FROM-PACK`.

## Chapter 12. Numbers [CLHS-12]

## Numeric Types

The type `NUMBER` is the disjoint union of the types `REAL` and `COMPLEX`. (“exhaustive partition”)

The type `REAL` is the disjoint union of the types `RATIONAL` and `FLOAT`.

The type `RATIONAL` is the disjoint union of the types `INTEGER` and `RATIO`.

The type `INTEGER` is the disjoint union of the types `FIXNUM` and `BIGNUM`.

The type `FLOAT` is the disjoint union of the types `SHORT-FLOAT`, `SINGLE-FLOAT`, `DOUBLE-FLOAT` and `LONG-FLOAT`.

## Number Concepts [CLHS-12.1]

### Byte Operations on Integers [CLHS-12.1.1.3.2]

Byte specifiers are objects of type `byte`, not `INTEGER`s.

### Rule of Float Substitutability [CLHS-12.1.3.3]

When a mathematical function may return an exact (rational) or inexact (floating-point) result, it always returns the exact result.

### Floating-point Computations [CLHS-12.1.4]

There are four floating point types: `SHORT-FLOAT`, `SINGLE-FLOAT`, `DOUBLE-FLOAT` and `LONG-FLOAT`:

floating point types

type | sign | mantissa | exponent | comment
--- | --- | --- | --- | ---
`SHORT-FLOAT` | 1 bit | 16+1 bits | 8 bits | immediate
`SINGLE-FLOAT` | 1 bit | 23+1 bits | 8 bits | IEEE format
`DOUBLE-FLOAT` | 1 bit | 52+1 bits | 11 bits | IEEE format
`LONG-FLOAT` | 1 bit | >=64 bits | 32 bits | variable length

The single and double float formats are those of the IEEE standard (1981), except that CLISP does not support features like `+0`, `-0`, `+inf`, `-inf`, gradual underflow, `NaN`, etc. (Common Lisp does not make use of these features.) This is why `*FEATURES*` does not contain the `:IEEE-FLOATING-POINT` keyword.

Long floats have variable mantissa length, which is a multiple of 16 (or 32, depending on the word size of the processor). The default length used when long floats are read is given by the place `(`ext:long-float-digits`)`. It can be set by `(`SETF` (`ext:long-float-digits`) `nnn`)`, where `nnn` is a positive integer. E.g., `(`SETF` (`ext:long-float-digits`) 3322)` sets the default precision of long floats to 1000 decimal digits.

#### Rule of Float Precision Contagion [CLHS-12.1.4.4]

The floating point contagion is controlled by the variable `custom:*floating-point-contagion-ansi*`. When it is non-`NIL`, contagion is done as per the [ANSI CL standard]: `SHORT-FLOAT` → `SINGLE-FLOAT` → `DOUBLE-FLOAT` → `LONG-FLOAT`.

Rationale:

  See it pragmatically: save what you can and let others worry about the rest.

Brief:

  Common Lisp knows the number's precision, not accuracy, so preserving the precision can be accomplished reliably, while anything relating to the accuracy is just a speculation - only the user (programmer) knows what it is in each case.

Detailed:

  A float is an approximation of a real number. One can think of it as a random variable with the mean equal to itself and standard deviation equal to half the last significant digit. E.g., `1.5` is actually `1.5+-0.05`. Consider adding `1.5` and `1.75`. [ANSI CL standard] requires that `(+ 1.5 1.75)` return `3.25`, while traditional CLISP would return `3.3`. The implied random variables are: `3.25+-0.005` and `3.3+-0.05`. Note that the traditional CLISP way does lie about the mean: the mean is `3.25` and nothing else, while the standard way could be lying about the deviation (accuracy): if the implied accuracy of `1.5 (0.05)` is its actual accuracy, then the accuracy of the result cannot be smaller that that. Therefore, since Common Lisp has no way of knowing the actual accuracy, [ANSI CL standard] (and all the other standard engineering programming languages, like C, FORTRAN etc) decides that keeping the accuracy correct is the business of the programmer, while the language should preserve what it can - the precision.

Experience:

  Rounding errors accumulate, and if a computation is conducted with insufficient precision, an outright incorrect result can be returned. (E.g., `E(x2) - E(x)2` can be negative!) The user should not mix floats of different precision (that's what `custom:*warn-on-floating-point-contagion*` is for), but one should not be penalized for this too harshly.

When `custom:*floating-point-contagion-ansi*` is `NIL`, the traditional CLISP method is used, namely the result of an arithmetic operation whose arguments are of different float types is rounded to the float format of the shortest (least precise) of the arguments: `RATIONAL` → `LONG-FLOAT` → `DOUBLE-FLOAT` → `SINGLE-FLOAT` → `SHORT-FLOAT` (in contrast to 12.1.4.4 Rule of Float Precision Contagion!)

Rationale:

  See it mathematically. Add intervals: `{1.0 ± 1e-8} + {1.0 ± 1e-16} = {2.0 ± 1e-8}`. So, if we add `1.0s0` and `1.0d0`, we should get `2.0s0`.

Brief:

  Do not suggest accuracy of a result by giving it a precision that is greater than its accuracy.

Example:

  `(- (+ 1.7 `PI`) `PI`)` should not return `1.700000726342836417234L0`, it should return `1.7f0` (or `1.700001f0` if there were rounding errors).

Experience:

  If in a computation using thousands of short floats, a long float (like `PI`) happens to be used, the long precision should not propagate throughout all the intermediate values. Otherwise, the long result would look precise, but its accuracy is only that of a short float; furthermore much computation time would be lost by calculating with long floats when only short floats would be needed.

`custom:*warn-on-floating-point-contagion*` If the variable `custom:*warn-on-floating-point-contagion*` is non-`NIL`, a warning is emitted for every coercion involving different floating-point types.

`custom:*default-float-format*` When rational numbers are to be converted to floats (due to `FLOAT`, `COERCE`, `SQRT` or a transcendental function), the result type is given by the variable `custom:*default-float-format*`.

`ext:without-floating-point-underflow` The macro `(`ext:without-floating-point-underflow` {`form`}*)` executes the `form`s, with errors of type `FLOATING-POINT-UNDERFLOW` inhibited. Floating point operations will silently return zero instead of signalling an error of type `FLOATING-POINT-UNDERFLOW`.

### Complex Computations [CLHS-12.1.5]

Complex numbers can have a real part and an imaginary part of different types. For example, `(sqrt -9.0)` evaluates to the number `#C(0 3.0)`, which has a real part of exactly `0`, not only `0.0` (which would mean "approximately 0").

The type specifier for this is `(`COMPLEX` `INTEGER` `SINGLE-FLOAT`)`, and `(`COMPLEX` `type-of-real-part` `type-of-imaginary-part`)` in general.

The type specifier `(`COMPLEX` `type`)` is equivalent to `(`COMPLEX` `type` `type`)`.

### Rule of Canonical Representation for Complex Rationals [CLHS-12.1.5.3]

Complex numbers can have a real part and an imaginary part of different types. If the imaginary part is `EQL` to `0`, the number is automatically converted to a real number.

This has the advantage that `(let ((x (sqrt -9.0))) (* x x))` - instead of evaluating to `#C(-9.0 0.0)`, with `x` = `#C(0.0 3.0)` - evaluates to `#C(-9.0 0)` = `-9.0`, with `x` = `#C(0 3.0)`.

## The Numbers Dictionary [CLHS-12.2]

`UPGRADED-COMPLEX-PART-TYPE` `UPGRADED-COMPLEX-PART-TYPE` always returns `T`, since a `COMPLEX` number in CLISP can always have `REALPART` and `IMAGPART` of any type.

### Additional Integer Functions

`ext:!` `(`ext:!` `n`)` returns the factorial of `n`, `n` being a nonnegative `INTEGER`.

`ext:exquo` `(`ext:exquo` `x` `y`)` returns the integer quotient `x/y` of two integers `x`,`y`, and signals an error when the quotient is not integer. (This is more efficient than `/`.)

`ext:xgcd` `(`ext:xgcd` `x1` ... `xn`)` returns the values `g`, `k1`, ..., `kn`, where `g` is the greatest common divisor of the integers `x1`, ..., `xn`, and `k1`, ..., `kn` are the integer coefficients such that

     g = (GCD x1 ... xn)
       = (+ (* k1 x1) ... (* kn xn))

### Floating Point

`EXPT` `(`EXPT` `base` `exponent`)` is not very precise if exponent has large absolute value.

`LOG` `(`LOG` `number` `base`)` signals an error if ``base` = 1`.

`PI` The value of `PI` is a `LONG-FLOAT` with the precision given by `(`ext:long-float-digits`)`. When this precision is changed, the value of `PI` is automatically recomputed. Therefore `PI` is a variable, not a constant.

### Float Decoding [CLHS]

`FLOAT-RADIX` always returns `2`.

`(`FLOAT-DIGITS` `number` `digits`)` coerces `number` (a real number) to a floating point number with at least `digits` mantissa digits. The following holds:

     (>= (FLOAT-DIGITS (FLOAT-DIGITS number digits)) digits)

### Boolean Operations [CLHS]

Boolean Operations

constant name: `boole-clr`

value: 0

constant name: `boole-set`

value: 15

constant name: `boole-1`

value: 10

constant name: `boole-2`

value: 12

constant name: `boole-c1`

value: 5

constant name: `boole-c2`

value: 3

constant name: `boole-and`

value: 8

constant name: `boole-ior`

value: 14

constant name: `boole-xor`

value: 6

constant name: `boole-eqv`

value: 9

constant name: `boole-nand`

value: 7

constant name: `boole-nor`

value: 1

constant name: `boole-andc1`

value: 4

constant name: `boole-andc2`

value: 2

constant name: `boole-orc1`

value: 13

constant name: `boole-orc2`

value: 11

### Fixnum Limits [CLHS]

Platform dependent

CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU
--- | --- | --- | ---
`MOST-POSITIVE-FIXNUM` | 224-1 = 16777215 | 232-1 = 4294967295
`MOST-NEGATIVE-FIXNUM` | -224 = -16777216 | -232 = -4294967296

### Float Limits [CLHS]

Together with `PI`, the other long float constants `LEAST-NEGATIVE-LONG-FLOAT` `LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT` `LEAST-POSITIVE-LONG-FLOAT` `LEAST-POSITIVE-NORMALIZED-LONG-FLOAT` `LONG-FLOAT-EPSILON` `LONG-FLOAT-NEGATIVE-EPSILON` `MOST-NEGATIVE-LONG-FLOAT` `MOST-POSITIVE-LONG-FLOAT` are recomputed whenever `(`ext:long-float-digits`)` is changed. They are variables, not constants.

### Condition `FLOATING-POINT-INVALID-OPERATION`

This condition is never signaled by CLISP.

### Condition `FLOATING-POINT-INEXACT`

This condition is never signaled by CLISP.

## Chapter 13. Characters [CLHS-13]

The characters are ordered according to a superset of the ASCII encoding.

Platform dependent: only in CLISP built with the compile-time flag UNICODE.

  More precisely, CLISP uses the 16-bit Unicode character set (ISO 10646, also known as UCS-2).

Platform dependent: DOS, OS/2 platforms only, and only in CLISP built without compile-time flag UNICODE.

  More precisely, CLISP uses the IBM PC character set (code page 437):

  the IBM PC character set (code page 437)

  | #x0 | #x1 | #x2 | #x3 | #x4 | #x5 | #x6 | #x7 | #x8 | #x9 | #xA | #xB | #xC | #xD | #xE | #xF
  --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
  #x00 | ** |  |  |  |  |  |  | ** | ** | ** | ** | ** | ** | ** | ¶ | §
  #x10 |  |  |  |  |  |  |  |  |  |  | ** | ** |  |  |  |
  #x20 |  | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | /
  #x30 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ?
  #x40 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O
  #x50 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _
  #x60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o
  #x70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |
  #x80 | Ç | ü | é | â | ä | à | å | ç | ê | ë | è | ï | î | ì | Ä | Å
  #x90 | É | æ | Æ | ô | ö | ò | û | ù | ÿ | Ö | Ü | ¢ | £ | ¥ | ₧ | ƒ
  #xA0 | á | í | ó | ú | ñ | Ñ | ª | º | ¿ | ⌐ | `NOT` | ½ | ¼ | ¡ | « | »
  #xB0 | ░ | ▒ | ▓ | │ | ┤ | ╡ | ╢ | ╖ | ╕ | ╣ | ║ | ╗ | ╝ | ╜ | ╛ | ┐
  #xC0 | └ | ┴ | ┬ | ├ | ─ | ┼ | ╞ | ╟ | ╚ | ╔ | ╩ | ╦ | ╠ | ═ | ╬ | ╧
  #xD0 | ╨ | ╤ | ╥ | ╙ | ╘ | ╒ | ╓ | ╛ | ╚ | ┘ | ┌ | █ | ▄ | ▌ | ▐ | ▀
  #xE0 | α | ß | Γ | `PI` | Σ | σ | µ | τ | Φ | Θ | Ω | δ | ∞ | φ | ∊ | ∩
  #xF0 | ≡ | ± | ≥ | ≤ | ⌠ | ⌡ | ÷ | ≍ | ° | ∙ | · | √ | ⁿ | ² | ■ |

  Here ** are control characters, not graphic characters. (The characters left blank here cannot be represented in this character set).

Platform dependent: UNIX (except NeXTstep), Win32, Amiga, Acorn platforms only, and only in CLISP built without compile-time flag UNICODE.

  More precisely, CLISP uses the ISO Latin-1 (ISO 8859-1) character set:

  the ISO Latin-1 (ISO 8859-1) character set

  | #x0 | #x1 | #x2 | #x3 | #x4 | #x5 | #x6 | #x7 | #x8 | #x9 | #xA | #xB | #xC | #xD | #xE | #xF
  --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
  #x00 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | **
  #x10 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | **
  #x20 |  | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | /
  #x30 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ?
  #x40 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O
  #x50 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _
  #x60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o
  #x70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |
  #x80 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
  #x90 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
  #xA0 |  | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | `NOT` |  | ® | ¯
  #xB0 | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | º | » | ¼ | ½ | ¾ | ¿
  #xC0 | À | Á | Â | Ã | Ä | Å | Æ | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï
  #xD0 | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß
  #xE0 | à | á | â | ã | ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï
  #xF0 | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ

  Here ** are control characters, not graphic characters. (The characters left blank here cannot be represented in this character set).

Platform dependent: NeXTstep platforms only, and only in CLISP built without compile-time flag UNICODE.

  More precisely, CLISP uses the NeXTstep character set:

  the NeXTstep character set

  | #x0 | #x1 | #x2 | #x3 | #x4 | #x5 | #x6 | #x7 | #x8 | #x9 | #xA | #xB | #xC | #xD | #xE | #xF
  --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
  #x00 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | **
  #x10 | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | ** | **
  #x20 |  | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | /
  #x30 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ?
  #x40 | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O
  #x50 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _
  #x60 | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o
  #x70 | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |
  #x80 |  | À | Á | Â | Ã | Ä | Å | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï
  #x90 | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | Ù | Ú | Û | Ü | Ý | Þ | µ | × | ÷
  #xA0 | © | ¡ | ¢ | £ | ⁄ | ¥ | ƒ | § | ¤ | ’ | “ | « | ‹ | › | ﬁ | ﬂ
  #xB0 | ® | – | † | ‡ | · | ¦ | ¶ | • | ‚ | „ | ” | » | … | ‰ | `NOT` | ¿
  #xC0 | ¹ | ˋ | ´ | ^ | ˜ | ¯ | ˘ | ˙ | ¨ | ² | ˚ | ¸ | ³ | ˝ | ˛ | ˇ
  #xD0 | — | ± | ¼ | ½ | ¾ | à | á | â | ã | ä | å | ç | è | é | ê | ë
  #xE0 | ì | Æ | í | ª | î | ï | ð | ñ | Ł | Ø | Œ | º | ò | ó | ô | õ
  #xF0 | ö | æ | ù | ú | û | ı | ü | ý | ł | ø | œ | ß | þ | ÿ |  |

  Here ** are control characters, not graphic characters. (The characters left blank here cannot be represented in this character set).

The following are standard characters:

character: #\Space

code: #x20

character: #\Newline

code: #x0A

The following are semi-standard characters:

character: #\Backspace

code: #x08

character: #\Tab

code: #x09

character: #\Linefeed

code: #x0A

character: #\Page

code: #x0C

character: #\Return

code: #x0D

Platform dependent: DOS, OS/2, Win32 platforms only.

character: #\Rubout

code: #x08

Platform dependent: UNIX, Amiga, Acorn platforms only.

character: #\Rubout

code: #x7F

#\Newline is the delimiter between lines.

Additional Named Characters

character: #\Null

code: #x00

character: #\Bell

code: #x07

character: #\Escape

code: #x1B

Additional syntax for characters with code from #x00 to #x1F:

character: #\^@

code: #x00

character: #\^A … #\^Z

code: #x01 … #x1A

character: #\^[

code: #x1B

character: #\^\

code: #x1C

character: #\^]

code: #x1D

character: #\^^

code: #x1E

character: #\^_

code: #x1F

See also the section Character I/O.

## Attributes

Characters do not have the [CLtL1] font and bits attributes. For backward compatibility, there is a class `sys::input-character` representing either a character with font and bits, or a keystroke. The following functions work with objects of types `CHARACTER` and `sys::input-character`. Note that `EQL` or `EQUAL` cannot be used to compare objects of type `sys::input-character`.

`ext:char-font-limit` = 16

  The system uses only font 0.

`ext:char-bits-limit` = 16

  The following bits are defined:

  key: `:control`

  value: `ext:char-control-bit`

  key: `:meta`

  value: `ext:char-meta-bit`

  key: `:super`

  value: `ext:char-super-bit`

  key: `:hyper`

  value: `ext:char-hyper-bit`

`(`ext:char-font` `object`)`

  returns the font of a character or `sys::input-character`.

`(`ext:char-bits` `object`)`

  returns the bits of a character or `sys::input-character`.

`(`ext:make-char` `char` [`bits` [`font`]])`

  returns a new `sys::input-character`, or `NIL` if such a character cannot be created.

`(`ext:char-bit` `object` `name`)`

  returns `T` if the named bit is set in `object`, else `NIL`.

`(`ext:set-char-bit` `object` `name` `newvalue`)`

  returns a new `sys::input-character` with the named bit set or unset, depending on the boolean `newvalue`.

Platform dependent: UNIX, DOS, OS/2, Win32, Acorn platforms only.

  The system itself uses this `sys::input-character` type only to mention special keys and Control/Alternate/Shift key status on return from `(`READ-CHAR` `ext:*keyboard-input*`)`.

## Character Scripts [CLHS-13.1.2.1]

The only defined character script is the type `CHARACTER` itself.

## Character Attributes [CLHS-13.1.3]

Characters have no implementation-defined attributes. All characters are simple characters.

## Graphic Characters [CLHS-13.1.4.1]

The graphic characters are those Unicode characters which are defined by the Unicode standard, excluding the ranges U0000 … U001F and U007F … U009F.

## Alphabetic Characters [CLHS-13.1.4.2]

The alphabetic characters are those Unicode characters which are defined as letters by the Unicode standard.

## Case of Implementation-Defined Characters [CLHS-13.1.4.3.4]

The characters with case are those Unicode characters `c`, for which the upper case mapping `uc` and the lower case mapping `lc` have the following properties:

- `uc` and `lc` are different

- `c` is one of `uc` and `lc`

- the upper case mapping of `uc` and of `lc` is `uc`

- the lower case mapping of `uc` and of `lc` is `lc`

The titlecase property of Unicode characters has no equivalent in Common Lisp.

## Numeric Characters [CLHS-13.1.4.4]

The numeric characters are those Unicode characters which are defined as digits by the Unicode standard.

## Ordering of Characters [CLHS-13.1.6]

The characters are ordered according to their Unicode code.

## Treatment of Newline during Input and Output [CLHS-13.1.8]

Newlines are written according to the stream's encoding, see the function `STREAM-EXTERNAL-FORMAT` and the description of encodings, in particular, line terminators. The default behavior is as follows:

Platform dependent: DOS, OS/2, Win32 platforms only.

  When writing to a file, #\Newline is converted to CR/LF. (This is the usual convention on DOS.) For example, #\Return+#\Newline is written as CR/CR/LF.

When reading from a file, CR/LF is converted to #\Newline (the usual convention on DOS), and CR not followed by LF is converted to #\Newline as well (the usual conversion on MacOS, also used by some programs on Win32).

## Character Encodings [CLHS-13.1.9]

The integer returned by `CHAR-INT` is the same as the character's code.

## Documentation of Implementation-Defined Scripts [CLHS-13.1.10]

See the description of encodings.

## The Characters Dictionary [CLHS-13.2]

`CHAR-CODE` takes values from 0 (inclusive) to `CHAR-CODE-LIMIT` (exclusive), i.e., the implementation supports exactly `CHAR-CODE-LIMIT` characters.

Platform dependent

binaries built | without UNICODE support | with UNICODE support
--- | --- | ---
`CHAR-CODE-LIMIT` | 28 = 256 | 216 = 65536

The types `ext:string-char` and `BASE-CHAR` are equivalent to `CHARACTER`.

The graphic characters have been described above.

The standard characters are #\Newline and the graphic characters with a code between 32 and 126 (inclusive).

The alphabetic characters are these characters:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
and the international alphabetic characters from the character set:
ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜßáíóúñÑªºãõØøÀÃÕ etc.

The functions `CHAR-EQUAL` `CHAR-NOT-EQUAL`, `CHAR-LESSP`, `CHAR-GREATERP`, `CHAR-NOT-GREATERP`, `CHAR-NOT-LESSP` ignore bits and font attributes of their arguments.

## Functions on characters

`(`ext:char-width` `char`)` returns the number of screen columns occupied by `char`. This is 0 for non-spacing characters (such as control characters and many combining characters), 2 for double-width East Asian characters, and 1 for all other characters. See also function `string-width`.

## platform-dependent characters

The characters that are not graphic chars and the space character have names:

Platform dependent: Amiga platforms only.

code: `(`CODE-CHAR` #x00)`

char: #\Null

code: `(`CODE-CHAR` #x01)`

char: #\Code1

code: `(`CODE-CHAR` #x02)`

char: #\Code2

code: `(`CODE-CHAR` #x03)`

char: #\Code3

code: `(`CODE-CHAR` #x04)`

char: #\Code4

code: `(`CODE-CHAR` #x05)`

char: #\Code5

code: `(`CODE-CHAR` #x06)`

char: #\Code6

code: `(`CODE-CHAR` #x07)`

char: #\Bell

: #\Bel

code: `(`CODE-CHAR` #x08)`

char: #\Backspace

: #\Bs

code: `(`CODE-CHAR` #x09)`

char: #\Tab

: #\Ht

code: `(`CODE-CHAR` #x0A)`

char: #\Newline

: #\Linefeed

: #\Lf

code: `(`CODE-CHAR` #x0B)`

char: #\Vt

code: `(`CODE-CHAR` #x0C)`

char: #\Page

: #\Ff

code: `(`CODE-CHAR` #x0D)`

char: #\Return

: #\Cr

code: `(`CODE-CHAR` #x0E)`

char: #\So

code: `(`CODE-CHAR` #x0F)`

char: #\Si

code: `(`CODE-CHAR` #x10)`

char: #\Code16

code: `(`CODE-CHAR` #x11)`

char: #\Code17

code: `(`CODE-CHAR` #x12)`

char: #\Code18

code: `(`CODE-CHAR` #x13)`

char: #\Code19

code: `(`CODE-CHAR` #x14)`

char: #\Code20

code: `(`CODE-CHAR` #x15)`

char: #\Code21

code: `(`CODE-CHAR` #x16)`

char: #\Code22

code: `(`CODE-CHAR` #x17)`

char: #\Code23

code: `(`CODE-CHAR` #x18)`

char: #\Code24

code: `(`CODE-CHAR` #x19)`

char: #\Code25

code: `(`CODE-CHAR` #x1A)`

char: #\Code26

code: `(`CODE-CHAR` #x1B)`

char: #\Escape

: #\Esc

code: `(`CODE-CHAR` #x1C)`

char: #\Code28

code: `(`CODE-CHAR` #x1D)`

char: #\Code29

code: `(`CODE-CHAR` #x1E)`

char: #\Code30

code: `(`CODE-CHAR` #x1F)`

char: #\Code31

code: `(`CODE-CHAR` #x20)`

char: #\Space

code: `(`CODE-CHAR` #x7F)`

char: #\Rubout

code: `(`CODE-CHAR` #x9B)`

char: #\Csi

Platform dependent: DOS, OS/2, Win32 platforms only.

code: `(`CODE-CHAR` #x00)`

char: #\Null

code: `(`CODE-CHAR` #x07)`

char: #\Bell

code: `(`CODE-CHAR` #x08)`

char: #\Backspace

: #\Rubout

code: `(`CODE-CHAR` #x09)`

char: #\Tab

code: `(`CODE-CHAR` #x0A)`

char: #\Newline

: #\Linefeed

code: `(`CODE-CHAR` #x0B)`

char: #\Code11

code: `(`CODE-CHAR` #x0C)`

char: #\Page

code: `(`CODE-CHAR` #x0D)`

char: #\Return

code: `(`CODE-CHAR` #x1A)`

char: #\Code26

code: `(`CODE-CHAR` #x1B)`

char: #\Escape

code: `(`CODE-CHAR` #x20)`

char: #\Space

Platform dependent: UNIX, Acorn, platforms only.

code: `(`CODE-CHAR` #x00)`

char: #\Null

: #\Nul

code: `(`CODE-CHAR` #x01)`

char: #\Soh

code: `(`CODE-CHAR` #x02)`

char: #\Stx

code: `(`CODE-CHAR` #x03)`

char: #\Etx

code: `(`CODE-CHAR` #x04)`

char: #\Eot

code: `(`CODE-CHAR` #x05)`

char: #\Enq

code: `(`CODE-CHAR` #x06)`

char: #\Ack

code: `(`CODE-CHAR` #x07)`

char: #\Bell

: #\Bel

code: `(`CODE-CHAR` #x08)`

char: #\Backspace

: #\Bs

code: `(`CODE-CHAR` #x09)`

char: #\Tab

: #\Ht

code: `(`CODE-CHAR` #x0A)`

char: #\Newline

: #\Nl

: #\Linefeed

code: `(`CODE-CHAR` #x0B)`

char: #\Vt

code: `(`CODE-CHAR` #x0C)`

char: #\Page

: #\Np

code: `(`CODE-CHAR` #x0D)`

char: #\Return

: #\Cr

code: `(`CODE-CHAR` #x0E)`

char: #\So

code: `(`CODE-CHAR` #x0F)`

char: #\Si

code: `(`CODE-CHAR` #x10)`

char: #\Dle

code: `(`CODE-CHAR` #x11)`

char: #\Dc1

code: `(`CODE-CHAR` #x12)`

char: #\Dc2

code: `(`CODE-CHAR` #x13)`

char: #\Dc3

code: `(`CODE-CHAR` #x14)`

char: #\Dc4

code: `(`CODE-CHAR` #x15)`

char: #\Nak

code: `(`CODE-CHAR` #x16)`

char: #\Syn

code: `(`CODE-CHAR` #x17)`

char: #\Etb

code: `(`CODE-CHAR` #x18)`

char: #\Can

code: `(`CODE-CHAR` #x19)`

char: #\Em

code: `(`CODE-CHAR` #x1A)`

char: #\Sub

code: `(`CODE-CHAR` #x1B)`

char: #\Escape

: #\Esc

code: `(`CODE-CHAR` #x1C)`

char: #\Fs

code: `(`CODE-CHAR` #x1D)`

char: #\Gs

code: `(`CODE-CHAR` #x1E)`

char: #\Rs

code: `(`CODE-CHAR` #x1F)`

char: #\Us

code: `(`CODE-CHAR` #x20)`

char: #\Space

: #\Sp

code: `(`CODE-CHAR` #x7F)`

char: #\Rubout

: #\Delete

: #\Del

## Obsolete Constants

obsolete constants

constant: `ext:char-control-bit`

value: 1

constant: `ext:char-meta-bit`

value: 2

constant: `ext:char-super-bit`

value: 4

constant: `ext:char-hyper-bit`

value: 8

## Chapter 14. Conses [CLHS-14]

## The Conses Dictionary [CLHS-14.2]

`SUBLIS`, `NSUBLIS` `SUBLIS` and `NSUBLIS` apply the `:key` argument to the nodes of the cons tree and not to the keys of the alist.

### Functions `MAPCAR`, `MAPCAN`, `MAPLIST`, `MAPCON`, ...

The function `ext:mapcap` is like `MAPCAN`, except that it concatenates the resulting lists with `APPEND` instead of `NCONC`:

`(`ext:mapcap` `function` `x1` ... `xn`)` == `(`APPLY` #'`APPEND` (`MAPCAR` `function` `x1` ... `xn`))`

(Actually a bit more efficient that this would be.)

The function `ext:maplap` is like `MAPCON`, except that it concatenates the resulting lists with `APPEND` instead of `NCONC`:

`(`ext:maplap` `function` `x1` ... `xn`)` == `(`APPLY` #'`APPEND` (`MAPLIST` `function` `x1` ... `xn`))`

(Actually a bit more efficient that this would be.)

## Chapter 15. Arrays [CLHS-15]

`MAKE-ARRAY` `MAKE-ARRAY` can return specialized arrays for the `ARRAY-ELEMENT-TYPE`s `(`UNSIGNED-BYTE` 2)`, `(`UNSIGNED-BYTE` 4)`, `(`UNSIGNED-BYTE` 8)`, `(`UNSIGNED-BYTE` 16)`, `(`UNSIGNED-BYTE` 32)` and of course `BIT` and `CHARACTER`.

## Array Elements [CLHS-15.1.1]

Platform dependent

CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU
--- | --- | --- | ---
`ARRAY-RANK-LIMIT` | 216 = 65536 | 232 = 4294967296
`ARRAY-DIMENSION-LIMIT` | 224 = 16777216 | 232 = 4294967296
`ARRAY-TOTAL-SIZE-LIMIT` | 224 = 16777216 | 232 = 4294967296

Note that these constants are not fixnums, contrary to the [ANSI CL standard] Issue ARRAY-DIMENSION-LIMIT-IMPLICATIONS:ALL-FIXNUM.

## The Arrays Dictionary [CLHS-15.2]

`ADJUST-ARRAY` for displaced arrays An array to which another array is displaced should not be shrunk (using `ADJUST-ARRAY`) in such a way that the other array points into void space. This is not checked at the time `ADJUST-ARRAY` is called!

## Chapter 16. Strings [CLHS-16]

String comparison is based on the function `CHAR<=`. Therefore diphthongs do not obey the usual national rules. Example: `o` < `oe` < `z` < `ö`.

## The Strings Dictionary [CLHS-16.2]

### Functions on strings

`(`ext:string-width` `string`)` returns the number of screen columns occupied by `string`. This is computed as the sum of all `ext:char-width`s of all of the `string`'s characters.

## Chapter 17. Sequences [CLHS-17]

## The Sequences Dictionary [CLHS-17.3.]

### Additional Macros

For iteration through a sequence, a macro `ext:doseq`, similar to `DOLIST`, may be used instead of `MAP`:

    (ext:doseq (variable seqform [resultform])
      {declaration}*
      {tag|statement}*)

`ext:doseq` forms are “iteration forms”.

### Functions `NREVERSE` & `NRECONC`

`NREVERSE` The result of `NREVERSE` is always `EQ` to the argument. `NREVERSE` on a `VECTOR` swaps pairs of elements. `NREVERSE` on a `LIST` swaps the first and the last element and reverses the list chaining between them.

`NRECONC` The result of `NRECONC` is `EQ` to the first argument unless it is `NIL`, in which case the result is `EQ` to the second argument.

### Functions `REMOVE` & `DELETE`

`REMOVE`, `REMOVE-IF`, `REMOVE-IF-NOT`, `REMOVE-DUPLICATES` return their argument unchanged, if no element has to be removed.

`DELETE`, `DELETE-IF`, `DELETE-IF-NOT`, `DELETE-DUPLICATES` destructively modify their argument: If the argument is a `LIST`, the `CDR` parts are modified. If the argument is a `VECTOR` with fill pointer, the fill pointer is lowered and the remaining elements are compacted below the new fill pointer.

Contrary to the [ANSI CL standard] issue 283 RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER, negative `:count` keyword arguments are not allowed unless you set `custom:*sequence-count-ansi*` to a non-`NIL` value, in hich case “using a negative integer value is functionally equivalent to using a value of zero”, as per the [ANSI CL standard] issue.

### Functions `SORT` & `STABLE-SORT`

`SORT` and `STABLE-SORT` have two additional keywords `:start` and `:end`:

    (SORT sequence predicate &KEY :key :start :end)
    (STABLE-SORT sequence predicate &KEY :key :start :end)

`SORT` and `STABLE-SORT` are identical. They implement the mergesort algorithm. Worst case complexity: `O(n*log(n))` comparisons, where `n` is the `LENGTH` of the subsequence bounded by the `:start` and `:end` arguments.

## Chapter 18. Hash Tables [CLHS-18]

## The Hash Tables Dictionary [CLHS-18.2.]

### Function `MAKE-HASH-TABLE`

`MAKE-HASH-TABLE` has an additional keyword `:initial-contents`:

    (MAKE-HASH-TABLE &KEY :test :initial-contents :size
                     :rehash-size :rehash-threshold)

The `:initial-contents` argument is an alist that is used to initialize the new hash table. The `:rehash-threshold` argument is ignored.

### Additional Macros

For iteration through a hash table, a macro `ext:dohash`, similar to `DOLIST`, can be used instead of `MAPHASH`:

    (ext:dohash (key-var value-var hash-table-form [resultform])
      {declaration}*
      {tag|statement}*)

`ext:dohash` forms are “iteration forms”.

## Chapter 19. Filenames [CLHS-19]

For most operations, pathnames denoting files and pathnames denoting directories cannot be used interchangeably.

Platform dependent: UNIX, Amiga platforms only.

  For example, `#p"FOO/BAR"` denotes the file `BAR` in the directory `FOO`, while `#p"FOO/BAR/"` denotes the subdirectory `BAR` of the directory `FOO`.

Platform dependent: DOS, OS/2, Win32 platforms only.

  For example, `#p"FOO\\BAR"` denotes the file `BAR` in the directory `FOO`, while `#p"FOO\\BAR\\"` denotes the subdirectory `BAR` of the directory `FOO`.

Platform dependent: Acorn platforms only.

  For example, `#p"FOO.BAR"` denotes the file `FOO` in the directory `BAR`, while `#p"FOO.BAR."` denotes the subdirectory `BAR` of the directory `FOO`.

This is especially important for the functions `directory`, `ext:dir`, `ext:cd`, `ext:make-dir`, `ext:delete-dir`.

The minimum filename syntax that may be used portably

pathname: `xxx`

meaning: for a file with name `xxx`

pathname: `xxx.yy`

meaning: for a file with name `xxx` and type `yy`

pathname: `.yy`

meaning: for a pathname with type `yy` and no name specified

Hereby `xxx` denotes 1 to 8 characters, and `yy` denotes 1 to 3 characters, each of which being either an alphanumeric character or the underscore #\_. Other properties of pathname syntax vary between operating systems.

## Pathname Components [CLHS-19.2.1]

When a pathname is to be fully specified (no wildcards), that means that no `:wild`, `:wild-inferiors` is allowed, no wildcard characters are allowed in the strings, and `name` `EQ` `NIL` may not be allowed either.

Platform dependent: Amiga platforms only.

  Pathname components

  `host`

    always `NIL`

  `device`

    `NIL` or a `SIMPLE-STRING`

  `directory`

    `(`startpoint` . `subdirs`)`

    element: `startpoint`

    values: `:relative` | `:absolute`

    element: `subdirs`

    values: `()` | `(`subdir` . `subdirs`)`

    element: `subdir`

    values: `:wild-inferiors`

    meaning: `**` or `...`, all subdirectories

    element: `subdir`

    values: `:parent`

    meaning: `/` instead of `subdir/`

    element: `subdir`

    values: `SIMPLE-STRING`, may contain wildcard characters `?` and `*`

  `name`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `type`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `version`

    always `NIL` (may also be specified as `:wild` or `:newest`)

  Constraint: `startpoint` = `:relative` only if `device` is `NIL`. If the device is specified, the pathname must be absolute!

  A filename from AMIGAOS is split into name and type according to the following rule:

  - if there is no `.` in the filename, then the `name` is everything, `type` is `NIL`;

  - if there is a `.`, then `name` is the part before and `type` the part after the last dot.

  Case is ignored in the strings on comparison. No case conversions are performed.

  filename notations

  : External notation:

  : `dev:sub1.typ/sub2.typ/name.typ`

  : using defaults:

  : `sub1.typ/sub2.typ/name.typ`

  : or

  : `name.typ`

  : or

  : `sub1.typ/**/sub3.typ/x*.lisp`

  : or similar.

  :

  Formal specification of the external notation

  ch ::==

    any character except ':','/' and '*','?'

  name ::==

    {ch}+

  device ::==

    [ <empty> | ':' | name ':' ]

    : empty

    : current device, relative to current directory

    : ':'

    : current device, absolute (relative to root for disks)

    : name ':'

    : specified device, absolute (relative to root for disks)

  subdir ::==

    [ <empty> | name ]

    : empty

    : parent directory

  pathname ::==

    device { subdir '/' }* name

  Examples

  String: `'c:foo'`

  Device: 'C'

  Directory: `device->foo`

  our pathname: `"c"` (`:absolute` `"foo"`)

  String: `'c:foo/'`

  Device: 'C'

  Directory: `device->foo`

  our pathname: `"c"` (`:absolute` `"foo"`)

  String: `'c:foo/bar'`

  Device: 'C'

  Directory: `device->foo->bar`

  our pathname: `"c"` (`:absolute` `"foo" "bar"`)

  String: `'c:/foo'`

  Device: 'C'

  Directory: `device->up->foo`

  our pathname: `"c"` (`:absolute` `:parent` `"foo"`)

  String: `'c:'`

  Device: 'C'

  Directory: `device`

  our pathname: `"c"` (`:absolute`)

  String: `:foo`

  Device: current

  Directory: `device->root->foo`

  our pathname: `NIL` (`:absolute` `"foo"`)

  String: `foo`

  Device: current

  Directory: `device->foo`

  our pathname: `NIL` (`:relative` `"foo"`)

  String: `'/foo'`

  Device: current

  Directory: `device->up->foo`

  our pathname: `NIL` (`:relative` `:parent` `"foo"`)

  String: `'//foo/bar'`

  Device: current

  Directory: `device->up->up->foo->bar`

  our pathname: `NIL` (`:relative` `:parent` `:parent` `"foo" "bar"`)

  String: `''`

  Device: current

  Directory: `device`

  our pathname: `NIL` (`:relative`)

  Appending a `'/'` to a path string that is non-empty and does not end with `':'` or `'/'` does not change its meaning. This `'/'` must be appended before another non-empty component can be appended. But appending a `'/'` to a path string that is empty or ends with `':'` or `'/'` means going up to the parent directory!

  We interpret any path string that is empty or ends with `':'` or `'/'` as pathname of a directory (with both `name` and `type` being `NIL`).

Platform dependent: UNIX platforms only.

  Pathname components

  `host`

    always `NIL`

  `device`

    always `NIL`

  `directory`

    `(`startpoint` . `subdirs`)`

    element: `startpoint`

    values: `:relative` | `:absolute`

    meaning:

    element: `subdirs`

    values: `()` | `(`subdir` . `subdirs`)`

    meaning:

    element: `subdir`

    values: `:wild-inferiors`

    meaning: `**` or `...`, all subdirectories

    element: `subdir`

    values: `SIMPLE-STRING`, may contain wildcard characters `?` and `*`

    meaning:

  `name`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `type`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `version`

    always `NIL` (may also be specified as `:wild` or `:newest`)

  A UNIX filename is split into name and type according to the following rule:

  - if there is no `'.'` in the filename, then the `name` is everything, `type` is `NIL`;

  - if there is a `'.'`, then `name` is the part before and `type` the part after the last dot.

  filename notations

  : External notation:

  : `server:sub1.typ/sub2.typ/name.typ`

  : using defaults:

  : `sub1.typ/sub2.typ/name.typ`

  : or

  : `name.typ`

  : or

  : `sub1.typ/**/sub3.typ/x*.lisp`

  : or similar.

  :

Platform dependent: OS/2 platforms only.

  Pathname components

  `host`

    always `NIL`

  `device`

    `NIL` or `:wild` or `A`|...|`Z`

  `directory`

    `(`startpoint` . `subdirs`)`

    element: `startpoint`

    values: `:relative` | `:absolute`

    meaning:

    element: `subdirs`

    values: `()` | `(`subdir` . `subdirs`)`

    meaning:

    element: `subdir`

    values: `:wild-inferiors`

    meaning: `**` or `...`, all subdirectories

    element: `subdir`

    values: `SIMPLE-STRING`, may contain wildcard characters `?` and `*`

    meaning:

  `name`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `type`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `version`

    always `NIL` (may also be specified as `:wild` or `:newest`)

  An OS/2 filename is split into name and type according to the following rule:

  - if there is no `'.'` in the filename, then the `name` is everything, `type` is `NIL`;

  - if there is a `'.'`, then `name` is the part before and `type` the part after the last dot.

  filename notations

  : External notation:

  : `A:\sub1.typ\sub2.typ\name.typ`

  : using defaults:

  : `\sub1.typ\sub2.typ\name.typ`

  : or

  : `name.typ`

  : or

  : `*:\sub1.typ\**\sub3.typ\x*.lisp`

  : or similar.

  :

  Instead of `'\'` one may use `'/'`, as usual for DOS calls.

Platform dependent: Win32 platforms only.

  Pathname components

  `host`

    `NIL` or `SIMPLE-STRING`, wildcard characters may occur but don't act as wildcards

  `device`

    `NIL` or `:wild` or `A`|...|`Z`

  `directory`

    `(`startpoint` . `subdirs`)`

    element: `startpoint`

    values: `:relative` | `:absolute`

    meaning:

    element: `subdirs`

    values: `()` | `(`subdir` . `subdirs`)`

    meaning:

    element: `subdir`

    values: `:wild-inferiors`

    meaning: `**` or `...`, all subdirectories

    element: `subdir`

    values: `SIMPLE-STRING`, may contain wildcard characters `?` and `*`

    meaning:

  `name`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `type`

    `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?` and `*` (may also be specified as `:wild`)

  `version`

    always `NIL` (may also be specified as `:wild` or `:newest`)

  If `host` is non-`NIL`, `device` must be `NIL`.

  A Win32 filename is split into name and type according to the following rule:

  - if there is no `'.'` in the filename, then the `name` is everything, `type` is `NIL`;

  - if there is a `'.'`, then `name` is the part before and `type` the part after the last dot.

  filename notations

  : External notation:

  : `A:\sub1.typ\sub2.typ\name.typ`

  : using defaults:

  : `\sub1.typ\sub2.typ\name.typ`

  : or

  : `name.typ`

  : or

  : `*:\sub1.typ\**\sub3.typ\x*.lisp`

  : or similar.

  :

  Instead of `'\'` one may use `'/'`, as usual for DOS calls.

  If `host` is non-`NIL` and the `directory`'s `startpoint` is not `:absolute`, `(`PARSE-NAMESTRING` (`NAMESTRING` `pathname`))` will not be the same as `pathname`.

Platform dependent: UNIX, Amiga, OS/2, Win32 platforms only.

  The wildcard characters: `*` matches any sequence of characters, `?` matches any one character.

Platform dependent: UNIX, Amiga, OS/2, Win32 platforms only.

  Due to the name/type splitting rule, there are pathnames that cannot result from `PARSE-NAMESTRING`. To get a pathname whose type contains a dot or whose name contains a dot and whose type is `NIL`, `MAKE-PATHNAME` must be used. Example: `(`MAKE-PATHNAME` :name ".profile")`.

Platform dependent: Acorn platforms only.

  RISC OS provides several file systems as standard (ADFS, IDEFS, NetFS, RamFS, NetPrint) and support for extra file systems (DOSFS, ResourceFS and DeviceFS).

  A module called FileSwitch is at the center of all file system operation in RISC OS. FileSwitch provides a common core of functions used by all file systems. It only provides the parts of these services that are device independent. The device dependent services that control the hardware are provided by separate modules, which are the actual file systems. FileSwitch keeps track of active file systems and switches between them as necessary.

  One of the file system modules that RISC OS provides is FileCore. It takes the normal calls that FileSwitch sends to a file system module, and converts them to a simpler set of calls to modules that control the hardware. Unlike FileSwitch it creates a fresh instantiation of itself for each module that it supports. Using FileCore to build file system modules imposes a more rigid structure on it, as more of the file system is predefined.

  As well as standard file systems, FileSwitch supports image file systems. These provide facilities for RISC OS to handle media in foreign formats, and to support `image files' (or partitions) in those formats. Rather than accessing the hardware directly they rely on standard RISC OS file systems to do so. DOSFS is an example of an image file system used to handle DOS format discs.

  Terminology

    A pathname may include a file system name, a special field, a media name (e.g., a disc name), directory name(s), and the name of the object itself; each of these parts of a pathname is known as an `element' of the pathname.

  Filenames

    Filename `elements' may be up to ten characters in length on FileCore-based file systems and on NetFS. These characters may be digits or letters. FileSwitch makes no distinction between upper and lower case, although file systems can do so. As a general rule, you should not use top-bit-set characters in filenames, although some file systems (such as FileCore-based ones) support them. Other characters may be used provided they do not have a special significance. Those that do are listed below:

    `.`

      Separates directory specifications, e.g., `$.fred`

    `:`

      Introduces a drive or disc specification, e.g., `:0`, `:bigdisc`. It also marks the end of a file system name, e.g., `adfs:`

    `*`

      Acts as a `wildcard' to match zero or more characters.

    `#`

      Acts as a `wildcard' to match any single character.

    `$`

      is the name of the root directory of the disc.

    `&`

      is the user root directory (URD)

    `@`

      is the currently selected directory (CSD)

    `^`

      is the `parent' directory

    `%`

      is the currently selected library (CSL)

    `\`

      is the previously selected directory (PSD)

  Directories

    The root directory, `$`, forms the top of the directory hierarchy of the media which contains the CSD. `$` does not have a parent directory, trying to access its parent will just access `$`. Each directory name is separated by a `.` character. For example:

    - `$.Documents.Memos`

    - `%.cc`

  File Systems

    Files may also be accessed on file systems other than the current one by prefixing the filename with a file system specification. A file system name may appear between `-` characters, or suffixed by a `:`, though the latter is advised since `-` can also be used to introduce a parameter on a command line, or as part of a file name. For example:

    - `-net-$.SystemMesg`

    - `adfs:%.aasm`

  Special Fields

    Special fields are used to supply more information to the file system than you can using standard path names; for example NetFS and NetPrint use them to specify server addresses or names. They are introduced by a `#` character; a variety of syntaxes are possible:

    - `net#MJHardy::disc1.mike`

    - `#MJHardy::disc1.mike`

    - `-net#MJHardy-:disc1.mike`

    - `-#MJHardy-:disc1.mike`

    The special fields here are all MJHardy, and give the name of the fileserver to use. Special fields may use any character except for control characters, double quote '"', solidus '|' and space. If a special field contains a hyphen you may only use the first two syntaxes given above.

  `File$Path` and `Run$Path`

    These two special variables control exactly where a file will be looked for, according to the operation being performed on it.

    name: File$Path

    purpose: for read operations

    name: Run$Path

    purpose: for execute operations

    The contents of each variable should expand to a list or prefixes, separated by commas. When a read operation is performed then the prefixes in `File$Path` are used in the order in which they are listed. The first object that matches is used, whether it be a file or directory. Similarly any execute operation uses the prefixes in Run$Path. These search paths are only used when the pathname does not contain an explicit file system reference, e.g., executing `adfs:file` will not use `Run$Path`.

  Other path variables

    You can set up other path variables and use them as pseudo file systems. For example if you typed:

    `*Set Source$Path adfs:$.src.,adfs:$.public.src.`
    , you could then refer to the pseudo file system as `Source:` or (less preferable) as `-Source-`. These path variables work in the same was as `File$Path` and `Run$Path`.

    NOTE: Path variables are not implemented in this version of CLISP. A workaround for this is to use "<Foo$Path>" instead of "Foo:" until they are made available.

  from Lisp-string notation to internal representation

    No swapping. `foo.lisp` means file type `lisp` and file name `foo`. This is pseudo-BNF:

    legal character ::==

      any ISO latin-1 graphic character ≥ ' ' except '.' ':' '*' '#' '$' '&' '@' '^' '%' '\' '?'

    extended legal character ::==

      any ISO latin-1 graphic character ≥ ' ' except ':' '"' '|'

    legal-wild char ::==

      legal char | '*' | '#' | '?'

    host ::==

      '-' { extended legal char except '-' }+ '-' | { extended legal char except '-' } { extended legal char }* ':' | empty

    device ::==

      ':' { legal char }+ '.' | empty

    directory ::==

      { '$' | '&' | '@' | '%' | '\' } '.' { subdirectory }* | { subdirectory }+ | empty

      : '$' ->

      : `:absolute` `:root`

      : '&' ->

      : `:absolute` `:home`

      : '@' ->

      : `:absolute` `:current`

      : '%' ->

      : `:absolute` `:library`

      : '\' ->

      : `:absolute` `:precious`

      : else

      : `:relative`

    subdirectory ::==

      { '^' | { legal-wild char }+ } '.'

      : '^' ->

      : `:parent`

    filename ::==

      { { legal-wild char }+ | empty }

    filetype ::==

      { '.' { legal-wild char }+ | empty }

    pathname ::==

      host device directory filename filetype

    Examples

    String: `-net-$.SystemMesg`

    Hostname: `net`

    Device: `NIL`

    Directory: `(`:absolute` `:root`)`

    Name: `SystemMesg`

    Type: `NIL`

    String: `net#MJHardy::disc1.mike`

    Hostname: `net#MJHardy`

    Device: `disc1`

    Directory: `(`:absolute` `:root`)`

    Name: `mike`

    Type: `NIL`

    String: `#MJHardy::disc1.mike`

    Hostname: `#MJHardy`

    Device: `disc1`

    Directory: `(`:absolute` `:root`)`

    Name: `mike`

    Type: `NIL`

    String: `-net#MJHardy-:disc1.mike`

    Hostname: `net#MJHardy`

    Device: `disc1`

    Directory: `(`:absolute` `:root`)`

    Name: `mike`

    Type: `NIL`

    String: `-#MJHardy-:disc1.mike`

    Hostname: `#MJHardy`

    Device: `disc1`

    Directory: `(`:absolute` `:root`)`

    Name: `mike`

    Type: `NIL`

    String: `@.foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:current`)`

    Name: `foo`

    Type: `NIL`

    String: `foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative`)`

    Name: `foo`

    Type: `NIL`

    String: `^.`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` `:parent`)`

    Name: `NIL`

    Type: `NIL`

    String: `@.^.`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:current` `:parent`)`

    Name: `NIL`

    Type: `NIL`

    String: `foo.bar`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative`)`

    Name: `foo`

    Type: `bar`

    String: `foo.bar.baz`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` "foo")`

    Name: `bar`

    Type: `baz`

    String: `foo.bar.`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` "foo" "bar")`

    Name: `NIL`

    Type: `NIL`

    String: `foo.@.`

    Hostname: illegal

    Device:

    Directory:

    Name:

    Type:

  From internal representation to RISCOS string

    with swapping only of name/type components.

    Hostname: `net`

    Device: `disc1`

    Directory: `(`:absolute` `:root`)`

    Name: `foo`

    Type: `NIL`

    RISCOS String: `net::disc1.$.foo`

    Hostname: `net#MJ`

    Device: `disc1`

    Directory: `(`:absolute` `:root` "foo")`

    Name: `bar`

    Type: `baz`

    RISCOS String: `net#MJ::disc1.$.foo.baz.bar`

    Hostname: `adfs`

    Device: `4`

    Directory: `(`:absolute` `:root` "foo" "bar")`

    Name: `NIL`

    Type: `NIL`

    RISCOS String: `adfs::4.$.foo.bar`

    Hostname: `NIL`

    Device: `disc1`

    Directory: `(`:absolute` `:root` "foo")`

    Name: `bar`

    Type: `NIL`

    RISCOS String: `:disc1.$.foo.bar`

    Hostname: `NIL`

    Device: `disc1`

    Directory: `(`:absolute` `:current`)`

    Name: `NIL`

    Type: `NIL`

    RISCOS String: illegal here

    Hostname: `NIL`

    Device: `disc1`

    Directory: `(`:relative`)`

    Name: `NIL`

    Type: `NIL`

    RISCOS String: `:disc1.`

    Hostname: `NIL`

    Device: `disc1`

    Directory: `NIL`

    Name: `NIL`

    Type: `NIL`

    RISCOS String: `:disc1.`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:root`)`

    Name: `foo`

    Type: `NIL`

    RISCOS String: `$.foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:current`)`

    Name: `foo`

    Type: `NIL`

    RISCOS String: `@.foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative`)`

    Name: `foo`

    Type: `bar`

    RISCOS String: `bar.foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` "foo")`

    Name: `bar`

    Type: `baz`

    RISCOS String: `foo.baz.bar`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:library`)`

    Name: `bar`

    Type: `NIL`

    RISCOS String: `%.bar`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:absolute` `:library` "foo")`

    Name: `bar`

    Type: `NIL`

    RISCOS String: `%.foo.bar`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative`)`

    Name: `foo`

    Type: `bar`

    RISCOS String: `bar.foo`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` "foo")`

    Name: `bar`

    Type: `NIL`

    RISCOS String: `foo.bar`

    Hostname: `NIL`

    Device: `NIL`

    Directory: `(`:relative` "foo")`

    Name: `NIL`

    Type: `bar`

    RISCOS String: illegal here

    That is, the RISCOS string is the flattening-concatenation of

          (append
            (if (null hostname) "" (append hostname ":"))
            (if (null device) "" (append ":" device "."))
            (case (pop directory)
              (:absolute (case (pop directory)
                                 (:root "$.")
                                 (:home "&.")
                                 (:current "@.")
                                 (:library "%.")
                                 (:previous "\\.")))
              (:relative ""))
            (mapcar (lambda (subdir) (append subdir ".")) directory)
            (if (null name)
                (if (null type) "" (error "type with name illegal here"))
                (if (null type)
                    name
                    (append type "." name))))

  internal representation

    Pathname components

    `host`

      `SIMPLE-STRING` or `NIL`

    `device`

      `SIMPLE-STRING` or `NIL`

    `directory`

      `(`Startpoint` . `Subdirs`)`

      element: `startpoint`

      values: `:relative` | `:absolute` `anchor`

      element: `anchor`

      values: `:root` | `:home` | `:current` | `:library` | `:precious`

      element: `Subdirs`

      values: `()` | `(`subdir` . `Subdirs`)`

      element: `subdir`

      values: `:parent`

      element: `subdir`

      values: `SIMPLE-STRING`, may contain wildcard characters `?`,`#` and `*`

    `name`

      `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?`,`#` and `*` (may also be specified as `:wild`)

    `type`

      `NIL` or `SIMPLE-STRING`, may contain wildcard characters `?`,`#` and `*` (may also be specified as `:wild`)

    `version`

      always `NIL` (may also be specified as `:wild` or `:newest`)

    Constraint: startpoint is not `:absolute` `:root` only if device is `NIL`. If the device is specified, the pathname must be `:absolute` `:root`.

    The wildcard characters: `'*'` matches any sequence of characters, `'#'` or `'?'` matches any one character.

    Due to the name/type swapping rule, there are pathnames that cannot result from `PARSE-NAMESTRING`. To get a pathname whose type is `NIL`, `MAKE-PATHNAME` must be used. Example: `(`MAKE-PATHNAME` :directory "!Clisp." :name "README")`.

## External notation.

External notation of pathnames (cf. `PARSE-NAMESTRING` and `NAMESTRING`), of course without spaces, [,],{,}:

Platform dependent: DOS platforms only.

  : [ [drivespec] : ]

  : a letter `*` | `A`|...|`Z`| `a`|...|`z`

  : { name [. type] \ }

  : each one a subdirectory, `\` may be replaced by `/`

  : [ name [. type] ]

  : filename with type (extension)

  Name and type may be character sequences of any `LENGTH` (consisting of alphanumeric characters and `-`, `_`). They are shortened to 8 (respectively 3) characters and converted to upper case. A single `*` is allowed for `:wild`.

Platform dependent: Amiga platforms only.

  see above.

Platform dependent: UNIX platforms only.

  : [ `/` ]

  : `/` denotes absolute pathnames

  : { `name` `/` }

  : each one a subdirectory

  : [ `name` [`.` `type`] ]

  : filename with type (extension)

  Name and type may be character sequences of any `LENGTH` (consisting of printing ASCII characters, except `/`).

Platform dependent: OS/2, Win32 platforms only.

  : [ [`drivespec`] : ]

  : a letter `*`| `a`|...|`z`| `A`|...|`Z`

  : { `name` [. `type`] \ }

  : each one a subdirectory, `\` may be replaced by `/`

  : [ `name` [. `type`] ]

  : filename with type (extension)

  Name and type may be character sequences of any `LENGTH` (consisting of printing ASCII characters, except `/`, `\`, `:`).

Platform dependent: Acorn platforms only.

  see above.

`NAMESTRING` has an optional flag argument: `(`NAMESTRING` `pathname` `T`)` returns an external notation suitable for passing to the operating system or other programs.

Platform dependent: DOS, OS/2, Amiga platforms only.

  The function `USER-HOMEDIR-PATHNAME` is not implemented.

Platform dependent: DOS, OS/2 platforms only.

  If you really need that function, you might define it like this:

      (defun user-homedir-pathname (&optional host)
        (declare (ignore host))
        (or (system::getenv "HOME") "\\"))

## Logical Pathnames [CLHS-19.3]

When the argument of the function `TRANSLATE-LOGICAL-PATHNAME` is a string, it is interpreted as a logical pathname string.

## The Filenames Dictionary [CLHS-19.4]

`PATHNAME` always returns a physical pathname.

`PATHNAME-MATCH-P` does not interpret missing components as wild.

`TRANSLATE-PATHNAME` has two additional keywords: `(`TRANSLATE-PATHNAME` `source` `from-wildname` `to-wildname` `&KEY` `:all` `:merge`)`

If `:all` is specified and non-`NIL`, a list of all resulting pathnames, corresponding to all matches of `(`PATHNAME-MATCH-P` `source` `from-wildname`)`, is returned. If `:merge` is specified and `NIL`, unspecified pieces of `to-pathname` are not replaced by corresponding pieces of `source`.

### Function `PARSE-NAMESTRING`

`(`PARSE-NAMESTRING` `string` `&OPTIONAL` `host` `defaults` `&KEY` `start` `end` `junk-allowed`)` returns a logical pathname only if `host` is a logical host or `host` is `NIL` and `defaults` is a `LOGICAL-PATHNAME`. To construct a logical pathname from a string, the function `LOGICAL-PATHNAME` can be used.

The ANSI-mandated behavior of recognizing logical pathnames when the `string` begins with some alphanumeric characters followed by a colon (#\:) is very confusing (cf. `"c:/autoexec.bat"`, `"home:.clisprc"` and `"prep:/pub/gnu"`) and therefore disabled by default. To enable the ANSI standard behavior, you should set `custom:*parse-namestring-ansi*` to non-`NIL`.

### Function `MERGE-PATHNAMES`

`(`MERGE-PATHNAMES` `pathname` [`default-pathname`])` returns a logical pathname only if `default-pathname` is a logical pathname. To construct a logical pathname from a string, the function `LOGICAL-PATHNAME` can be used.

When both `pathname` and `default-pathname` are relative pathnames, the behavior depends on `custom:*merge-pathnames-ansi*`: when it is `NIL`, then CLISP retains its traditional behavior: `(`MERGE-PATHNAMES` #p"x/" #p"y/")` evaluates to `#p"x/"`

Rationale: `MERGE-PATHNAMES` is used to specify default components for pathnames, so there is some analogy between `(`MERGE-PATHNAMES` a b)` and `(or a b)`. Obviously putting in the same default a second time should do the same as putting it in once: `(or a b b)` is the same as `(or a b)`, so `(`MERGE-PATHNAMES` (`MERGE-PATHNAMES` a b) b)` should be the same as `(`MERGE-PATHNAMES` a b)`.

(This question actually matters because in Common Lisp there is no distinction between “pathnames with defaults merged-in” and “pathnames with defaults not yet applied”.)

Now, `(`MERGE-PATHNAMES` (`MERGE-PATHNAMES` '#p"x/" '#p"y/") '#p"y/")` and `(`MERGE-PATHNAMES` '#p"x/" '#p"y/")` are `EQUAL` in CLISP (when `custom:*merge-pathnames-ansi*` is `NIL`), but not in implementations that strictly follow the [ANSI CL standard] spec. In fact, the above twice-default = once-default rule holds for all pathnames in CLISP.

When `custom:*merge-pathnames-ansi*` is non-`NIL`, the normal [ANSI CL standard] behavior is exhibited: `(`MERGE-PATHNAMES` #p"x/" #p"y/")` evaluates to `#p"y/x/"`

The rationale is that “merge” is merge and not or.

## Chapter 20. Files [CLHS-20]

## The Files Dictionary [CLHS-20.2]

`RENAME-FILE` `RENAME-FILE` always returns a non-logical pathname as its first value.

`PROBE-FILE` `PROBE-FILE` cannot be used to check whether a directory exists. Use the function `ext:probe-directory` or the function `DIRECTORY` for this purpose.

`FILE-AUTHOR` `FILE-AUTHOR` always returns `NIL`, because the operating systems CLISP is ported to do not store a file's author in the file system. Some operating systems, such as Unix, have the notion of a file's owner, and some other Common Lisp implementations return the user name of the file owner. CLISP does not do this, because owner and author are not the same; in particular, authorship is preserved by copying, while ownership is not.

`probe-directory` `(`ext:probe-directory` `pathname`)` tests whether `pathname` exists and is a directory. It will, unlike `PROBE-FILE` or `TRUENAME`, not signal an error if the parent directory of `pathname` does not exist.

### Function `DIRECTORY`

`(`DIRECTORY` `&OPTIONAL` `pathname` `&KEY` :full :circle)` can run in two modes:

- If `pathname` contains no name or type component, a list of all matching directories is produced.

- Otherwise a list of all matching files is returned. If the `:full` argument is non-`NIL`, this contains additional information: for each matching file you get a list of at least four elements `(`file-pathname` `file-truename` `file-write-date-as-decoded-time` `file-length`)`.

Platform dependent: UNIX platforms only.

  If the `:circle` argument is non-`NIL`, the function avoids endless loops that may result from symbolic links.

`ext:dir` `(`ext:dir` `&OPTIONAL` `pathname`)` is like `DIRECTORY`, but displays the pathnames instead of returning them. `(ext:dir)` shows the contents of the current directory.

`ext:cd`

Platform dependent: UNIX, Amiga platforms only.

  `(`ext:cd` [`pathname`])` manages the current directory.

Platform dependent: Acorn platforms only.

  `(`ext:cd` [`pathname`])` manages the current host, current device and the current directory.

Platform dependent: DOS, OS/2, Win32 platforms only.

  `(`ext:cd` [`pathname`])` manages the current device and the current directory.

`ext:cd` `(`ext:cd` `pathname`)` sets it, `(ext:cd)` returns it.

`ext:default-directory` `(`ext:default-directory`)` is equivalent to `(`ext:cd`)`. `(`SETF` (`ext:default-directory`) `pathname`)` is equivalent to `(`ext:cd` `pathname`)`, except for the return value.

`ext:make-dir` `(`ext:make-dir` `directory-pathname`)` creates a new subdirectory.

`ext:delete-dir` `(`ext:delete-dir` `directory-pathname`)` removes an (empty) subdirectory.

## Chapter 21. Streams [CLHS-21]

## Interactive Streams [CLHS-21.1.1.1.3]

Interactive streams are those whose next input might depend on a prompt one might output.

## terminal interaction.

GNU readline

Platform dependent: UNIX, DOS, OS/2 platforms only, and only in CLISP built without compile-time flag `NO_READLINE`.

  Input through `*TERMINAL-IO*` uses the GNU readline library. Arrow keys can be used to move within the input history. The Tab key completes the symbol's name that is being typed. See clreadline.html or clreadline.dvi for a complete description of the key bindings. The GNU readline library is not used if standard input and standard output do not both refer to the same terminal.

`ext:with-keyboard`

Platform dependent: UNIX, Amiga, Acorn, DOS, OS/2, Win32 platforms only.

  `*TERMINAL-IO*` is not the only stream that communicates directly with the user: During execution of the body of a `(`ext:with-keyboard` . `body`)` form, `ext:*keyboard-input*` is the stream that reads the keystrokes from the keyboard. It returns every keystroke in detail, as character or `sys::input-character` with the following bits:

  `:hyper`

    (Platform dependent: DOS, OS/2, Win32, Amiga platforms only.) if a non-standard key. These keys are: Function keys, cursor keypads, numeric keypad (Platform dependent: DOS, OS/2, Win32 platforms only). Function keys, cursor keypad (Platform dependent: Amiga platforms only).

  slot `key`

    the key name, for non-standard keys:

    Platform dependent: DOS, OS/2 platforms only.

      key: F1..F12

      value: `:F1`..`:F12`

      key: Insert

      value: `:Insert`

      key: Delete

      value: `:Delete`

      key: Home

      value: `:Home`

      key: End

      value: `:End`

      key: PgUp

      value: `:PgUp`

      key: PgDn

      value: `:PgDn`

      key: Arrow keys

      value: `:Left``:Right` `:Up``:Down`

    Platform dependent: UNIX, Win32 platforms only.

      key: F1..F12

      value: `:F1`..`:F12`

      key: Insert

      value: `:Insert`

      key: Delete

      value: `:Delete`

      key: Home

      value: `:Home`

      key: End

      value: `:End`

      key: Center

      value: `:Center`

      key: PgUp

      value: `:PgUp`

      key: PgDn

      value: `:PgDn`

      key: Arrow keys

      value: `:Left``:Right` `:Up``:Down`

    Platform dependent: Amiga platforms only.

      key: F1..F10

      value: `:F1`..`:F10`

      key: Help

      value: `:Help`

      key: Arrow keys

      value: `:Left``:Right` `:Up``:Down`

  slot `char`

    the ASCII code for standard keys

  `:super`

    (Platform dependent: DOS, OS/2, Win32, Amiga platforms only.) if pressed together with Shift key(s) and if the keystroke would have been an other without Shift.

  `:control`

    if pressed together with the Control key.

  `:meta`

    (Platform dependent: DOS, OS/2, Win32 platforms only.) if pressed together with the Alternate key.

  This keyboard input is not echoed on the screen. During execution of a `(`ext:with-keyboard` . `body`)` form, no input from `*TERMINAL-IO*` or any synonymous stream should be requested.

## The Streams Dictionary [CLHS-21.2.]

### Function `STREAM-ELEMENT-TYPE`

`STREAM-ELEMENT-TYPE` is `SETF`able. The `STREAM-ELEMENT-TYPE` of `STREAM`s created by the functions `OPEN`, `ext:make-pipe-input-stream`, `ext:make-pipe-output-stream`, `ext:make-pipe-io-stream`, `socket:socket-accept`, `socket:socket-connect` can be modified, if the old and the new `STREAM-ELEMENT-TYPE`s are either

- both equivalent to `CHARACTER` or `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`, or

- both equivalent to `(`UNSIGNED-BYTE` `n`)` or `(`SIGNED-BYTE` `n`)`, with the same `n`.

### Binary input, `READ-BYTE`, `ext:read-integer` & `ext:read-float`

The function `(`ext:read-integer` `stream` `element-type` `&OPTIONAL` `endianness` `eof-error-p` `eof-value`)` reads a multi-byte `INTEGER` from `stream`. `stream` should be a stream with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`. `element-type` should be a type equivalent to `(`UNSIGNED-BYTE` `n`)`, where `n` is a multiple of 8.

`(`ext:read-integer` `stream` `element-type`)` is like `(`READ-BYTE` `stream`)` if `stream`'s `STREAM-ELEMENT-TYPE` were set to `element-type`, except that `stream`'s `FILE-POSITION` will increase by `n`/8 instead of 1.

`endianness` can be `:little` or `:big`. The default is `:little`, which corresponds to the `READ-BYTE` behavior in CLISP.

Together with `(`SETF` `STREAM-ELEMENT-TYPE`)`, this function permits mixed character/binary input from a stream.

The function `(`ext:read-float` `stream` `element-type` `&OPTIONAL` `endianness` `eof-error-p` `eof-value`)` reads a floating-point number in IEEE binary representation from `stream`. `stream` should be a `STREAM` with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`. `element-type` should be a type equivalent to `SINGLE-FLOAT` or `DOUBLE-FLOAT`.

### Binary output, `WRITE-BYTE`, `ext:write-integer` & `ext:write-float`

The function `(`ext:write-integer` `integer` `stream` `element-type` `&OPTIONAL` `endianness`)` writes a multi-byte integer to `stream`. `stream` should be a `STREAM` with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`. `element-type` should be a type equivalent to `(`UNSIGNED-BYTE` `n`)`, where `n` is a multiple of 8.

`(`ext:write-integer` `integer` `stream` `element-type`)` is like `(`WRITE-BYTE` `integer` `stream`)` if `stream`'s `STREAM-ELEMENT-TYPE` were set to `element-type`, except that `stream`'s `FILE-POSITION` will increase by `n`/8 instead of 1.

Together with `(`SETF` `STREAM-ELEMENT-TYPE`)`, this function permits mixed character/binary output to a `STREAM`.

The function `(`ext:write-float` `float` `stream` `element-type` `&OPTIONAL` `endianness`)` writes a floating-point number in IEEE binary representation to `stream`. `stream` should be a `STREAM` with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`. `element-type` should be a type equivalent to `SINGLE-FLOAT` or `DOUBLE-FLOAT`.

### Function `READ-SEQUENCE`

In addition to `READ-SEQUENCE`, the following two functions are provided:

`ext:read-byte-sequence` performs multiple `READ-BYTE` operations:

  `(`ext:read-byte-sequence` `sequence` `stream` `&KEY` `:start` `:end`)` fills the subsequence of `sequence` specified by `:start` and `:end` with `INTEGER`s consecutively read from `stream`. It returns the index of the first element of `sequence` that was not updated (= `end` or < `end` if the `stream` reached its end).

  This function is especially efficient if `sequence` is a `(`VECTOR` (`UNSIGNED-BYTE` 8))` and `stream` is a file/pipe/socket stream with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`.

`ext:read-char-sequence` performs multiple `READ-CHAR` operations:

  `(`read-char-sequence` `sequence` `stream` `&KEY` `:start` `:end`)` fills the subsequence of `sequence` specified by `:start` and `:end` with characters consecutively read from `stream`. It returns the index of the first element of `sequence` that was not updated (= `end` or < `end` if the `stream` reached its end).

  This function is especially efficient if `sequence` is a `STRING` and `:stream` is a file/pipe/socket stream with `STREAM-ELEMENT-TYPE` `CHARACTER` or an input string stream.

### Function `WRITE-SEQUENCE`

In addition to `WRITE-SEQUENCE`, the following two functions are provided:

`ext:write-byte-sequence` performs multiple `WRITE-BYTE` operations:

  `(`ext:write-byte-sequence` `sequence` `:stream` `&KEY` `:start` `:end`)` outputs the `INTEGER`s of the subsequence of `sequence` specified by `:start` and `:end` to `:stream`. It returns `sequence`.

  This function is especially efficient if `sequence` is a `(`VECTOR` (`UNSIGNED-BYTE` 8))` and `:stream` is a file/pipe/socket `STREAM` with `STREAM-ELEMENT-TYPE` `(`UNSIGNED-BYTE` 8)`.

`ext:write-char-sequence` performs multiple `WRITE-CHAR` operations:

  `(`ext:write-char-sequence` `sequence` `:stream` `&KEY` `:start` `:end`)` outputs the characters of the subsequence of `sequence` specified by `:start` and `:end` to `:stream`. It returns `sequence`.

  This function is especially efficient if `sequence` is a `STRING` and `:stream` is a file/pipe/socket `STREAM` with `STREAM-ELEMENT-TYPE` `CHARACTER`.

### Function `FILE-POSITION`

Platform dependent: DOS, OS/2, Win32 platforms only.

  `FILE-POSITION` works on any buffered file stream. When a #\Newline is output to (respectively input from) a file stream, its file position is increased by 2 since #\Newline is encoded as CR/LF in the file.

### Function `OPEN`

`OPEN` cannot handle files of size ≥ 4 GB.

`OPEN` accepts three additional keywords: `:element-type`, `:external-format`, `:buffered`.

The acceptable values for the file/pipe/socket functions

`:element-type`

  types equivalent to `CHARACTER` or `(`UNSIGNED-BYTE` `n`)`, `(`SIGNED-BYTE` `n`)`; if the stream is to be unbuffered, `n` must be a multiple of 8.

`:external-format`

  encodings, (constant) symbols in the `CHARSET` package, strings (denoting iconv() based encodings), the symbol `:default`, and the line terminator keywords `:unix`, `:mac`, `:dos`. The default encoding is `custom:*default-file-encoding*`.

`:buffered`

  `NIL`, `T`, or `:default`.

  - for functions that create `socket-stream`s and pipes, `:default` is equivalent to `NIL`;

  - for functions that open files, `:default` means that buffered file streams will be returned for regular files and (on Unix) block-devices, and unbuffered file streams for special files.

### Function `CLOSE`

`CLOSE` ignores its `:abort` argument.

### Class `BROADCAST-STREAM`

`INPUT-STREAM-P` and `INTERACTIVE-STREAM-P` return false for broadcast streams.

## Chapter 22. Printer [CLHS-22]

## Multiple Possible Textual Representations [CLHS-22.1.1.1]

`custom:*print-closure*` An additional variable `custom:*print-closure*` controls whether compiled and interpreted functions (closures) are output in detailed form. If `custom:*print-closure*` is non-`NIL`, compiled closures are output in #Y syntax which the reader understands. `custom:*print-closure*` is initially set to `NIL`.

`custom:*print-rpars*` An additional variable `custom:*print-rpars*` controls the output of the right (closing) parentheses. If `custom:*print-rpars*` is non-`NIL`, closing parentheses which do not fit onto the same line as the the corresponding opening parenthesis are output just below their corresponding opening parenthesis, in the same column. `custom:*print-rpars*` is initially set to `NIL`.

`custom:*print-indent-lists*` An additional variable `custom:*print-indent-lists*` controls the indentation of lists that span more than one line. It specifies by how many characters items within the list will be indented relative to the beginning of the list. `custom:*print-indent-lists*` is initially set to `1`.

## Printing Other Vectors [CLHS-22.1.3.7]

When `*PRINT-READABLY*` is true, other vectors are written as follows: if the `ARRAY-ELEMENT-TYPE` is `T`, the syntax `#(`x0` ... `xn-1`)` is used. Otherwise, the syntax `#A(`element-type` `dimensions` `contents`)` is used.

## Printing Other Arrays [CLHS-22.1.3.8]

When `*PRINT-READABLY*` is true, other arrays are written as follows: if the `ARRAY-ELEMENT-TYPE` is `T`, the syntax `#`rank`A `contents`` is used. Otherwise, the syntax `#A(`element-type` `dimensions` `contents`)` is used.

## The Lisp Pretty Printer [CLHS-22.2]

The List Pretty Printer is not implemented yet.

## The Printer Dictionary [CLHS-22.4]

`WRITE` & `WRITE-TO-STRING` The functions `WRITE` and `WRITE-TO-STRING` have an additional keyword argument `:closure` which is used to bind `custom:*print-closure*`.

### Function `FORMAT`

The `FORMAT` instruction `~W` is similar to `~A` and `~S`, but avoids binding of `*PRINT-ESCAPE*`. `(`FORMAT` `:stream` "~W" `object`)` is equivalent to `(`WRITE` `object` :stream `:stream`)`.

The `FORMAT` instruction `~!` is similar to `~/`, but avoids putting a function name into a string. Thus, even if the function is not interned in the “COMMON-LISP-USER” package, you might not need to specify the package.

`(`FORMAT` `:stream` "~args!" `function` `object`)` is equivalent to `(`FUNCALL` `function` `:stream` `object` `colon-modifier-p` `atsign-modifier-p` `args`)`.

`FORMAT` `~R` and `FORMAT` `~:R` can output only integers in the range `|n| < `1066``. The output is in English, according to the American conventions, and these conventions are identical to the British conventions only in the range `|n| < `109``.

`FORMAT` `~:@C` does not output the character itself, only the instruction how to type the character.

For `FORMAT` `~E` and `FORMAT` `~G`, the value of `*READ-DEFAULT-FLOAT-FORMAT*` does not matter if `*PRINT-READABLY*` is true.

`FORMAT` `~T` can determine the current column of any built-in stream.

### pathnames

Pathnames are printed as follows: If `*PRINT-ESCAPE*` is `NIL`, only the namestring is printed; otherwise it is printed with `#P""` syntax, as per [ANSI CL standard] Issue PRINT-READABLY-BEHAVIOR:CLARIFY. But, if `*PRINT-READABLY*` is true, we are in trouble as `#P""` is ambiguous (which is verboten when `*PRINT-READABLY*` is true), while being mandated by the [ANSI CL standard]. Therefore, in this case, CLISP's behavior is determined by the value of `custom:*print-pathnames-ansi*`: when it is `NIL`, we print pathnames like this: `#-CLISP #P"" #+CLISP #S(PATHNAME ...)`. Otherwise, when the variable `custom:*print-pathnames-ansi*` is non-`NIL`, the `#P""` notation is used as per 1.5.1.4.1 Resolution of Apparent Conflicts in Exceptional Situations.

### Miscellaneous Issues

`*PRINT-CASE*` controls the output not only of symbols, but also of characters and some `#<...>` objects.

In the absence of `sys::write-float-decimal`, floating point numbers are output in radix 2. This function is defined in `floatpri.lisp` and is not available if you run CLISP without a memory image (which you should never do anyway!)

If `*PRINT-READABLY*` is true, `*READ-DEFAULT-FLOAT-FORMAT*` has no influence on the way floating point numbers are printed.

Platform dependent: UNIX, DOS, OS/2, Win32, Acorn platforms only.

  `*PRINT-PRETTY*` is initially `NIL` but set to `T` in `config.lsp`. This makes screen output prettier.

Platform dependent: Amiga platforms only.

  `*PRINT-PRETTY*` is initially `NIL` but set to `T` in `config.lsp`. This makes unbuffered screen output both much faster and prettier.

`*PRINT-ARRAY*` is initially set to `T`.

## Chapter 23. Reader [CLHS-23]

This is the list of objects whose external representation cannot be meaningfully read in:

unreadable objects

format: `#<`type` ...>`

meaning: all structures lacking a keyword constructor

format: `#<ARRAY `type` `dimensions`>`

meaning: all arrays except strings, if `*PRINT-ARRAY*` is `NIL`

format: `#<SYSTEM-FUNCTION `name`>`

meaning: built-in function written in C

format: `#<ADD-ON-SYSTEM-FUNCTION `name`>`

meaning: other function written in C

format: `#<SPECIAL-OPERATOR `name`>`

meaning: special operator handler

format: `#<COMPILED-CLOSURE `name`>`

meaning: compiled function, if `custom:*print-closure*` is `NIL`

format: `#<CLOSURE `name` ...>`

meaning: interpreted function

format: `#<FRAME-POINTER #x...>`

meaning: pointer to a stack frame

format: `#<DISABLED POINTER>`

meaning: frame pointer which has become invalid on exit from the corresponding `BLOCK` or `TAGBODY`

format: `#<...-STREAM ...>`

meaning: stream

format: `#<PACKAGE `name`>`

meaning: package

format: `#<HASH-TABLE #x...>`

meaning: hash table, if `*PRINT-ARRAY*` is `NIL`

format: `#<READTABLE #x...>`

meaning: readtable

format: `#<SYMBOL-MACRO `form`>`

meaning: `symbol-macro` handler

format: `#<FOREIGN-POINTER #x...>`

meaning: foreign pointer (Platform dependent: UNIX, Win32, Amiga platforms only.)

format: `#<FOREIGN-ADDRESS #x...>`

meaning: foreign address (Platform dependent: UNIX, Win32 platforms only.)

format: `#<FOREIGN-VARIABLE `name` #x...>`

meaning: foreign variable (Platform dependent: UNIX, Win32 platforms only.)

format: `#<FOREIGN-FUNCTION `name` #x...>`

meaning: foreign function (Platform dependent: UNIX, Win32 platforms only.)

format: `#<UNBOUND>`

meaning: "value" of a symbol without value, "value" of an unsupplied optional or keyword argument

format: `#<SPECIAL REFERENCE>`

meaning: environment marker for variables declared `SPECIAL`

format: `#<DOT>`

meaning: internal `READ` result for "."

format: `#<END OF FILE>`

meaning: internal `READ` result, when the end of file is reached

format: `#<READ-LABEL ...>`

meaning: intermediate `READ` result for `#n#`

format: `#<ADDRESS #x...>`

meaning: machine address, should not occur

format: `#<SYSTEM-POINTER #x...>`

meaning: should not occur

## characters

#\Code allows input of characters of arbitrary code: e.g., #\Code231 reads as the character `(`CODE-CHAR` 231.)`.

## Additional read dispatch macros

- #Y is used to read compiled functions and to set the current input stream's encoding.

- `#""` is used to read pathnames: `#"test.lisp"` is the value of `(`PATHNAME` "test.lisp")`

  Platform dependent: DOS, OS/2, Win32 platforms only.

    As in all strings, backslashes must be written twice here: `#"A:\\programs\\test.lisp"`

  Platform dependent: Acorn platforms only.

    As in all strings, backslashes must be written twice here: `#"\\.test.lisp"`

## Function `READTABLE-CASE`

When the value of `(`READTABLE-CASE` `readtable`)` is `:invert`, it applies to the package name and the symbol name of a symbol separately (not to the entire token at once). An alternative to the use of `READTABLE-CASE` is the use of the `:case-sensitive` option to `MAKE-PACKAGE`, `IN-PACKAGE` and `DEFPACKAGE`.

## Functions `LISTEN`, `READ-CHAR-NO-HANG`

`(`ext:read-char-will-hang-p` `stream`)`

  `ext:read-char-will-hang-p` queries the stream's input status. It returns `NIL` if `READ-CHAR` and `PEEK-CHAR` with a `peek-type` of `NIL` will return immediately. Otherwise it returns true. (In the latter case the standard `LISTEN` function would return `NIL`.)

  Note the difference with `(`NOT` (`LISTEN` `stream`))`: When the `end-of-stream` is reached, `LISTEN` returns `NIL`, whereas `ext:read-char-will-hang-p` returns `NIL`.

  Note also that `ext:read-char-will-hang-p` is not a good mean to test for `end-of-stream`: If `ext:read-char-will-hang-p` returns `T`, this does not mean that the `stream` will deliver more characters. It only means that it is not known at this moment whether the `stream` is already at `end-of-stream`, or will deliver more characters.

## Function `READ-BYTE`

`(`ext:read-byte-lookahead` `stream`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns `T` if `READ-BYTE` would return immediately with an `INTEGER` result. Returns `:eof` if the `end-of-stream` is already known to be reached. If `READ-BYTE`'s value is not available immediately, returns `NIL` instead of waiting.

`(`ext:read-byte-will-hang-p` `stream`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns `NIL` if `READ-BYTE` will return immediately. Otherwise it returns true.

`(`ext:read-byte-no-hang` `stream` `&OPTIONAL` `eof-error-p` `eof-value`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns an `INTEGER` or does `end-of-stream` handling, like `READ-BYTE`, if that would return immediately. If `READ-BYTE`'s value is not available immediately, returns `NIL` instead of waiting.

## Chapter 24. System Construction [CLHS-24]

## 24.2: The System Construction Dictionary

The compiler can be called not only by the functions `COMPILE`, `COMPILE-FILE` and `DISASSEMBLE`, but also by the declaration `(compile)`.

### Function `COMPILE-FILE`

`(`COMPILE-FILE` `input-file` `&KEY` :output-file :listing `:warnings` `:verbose` `:print`)` compiles a file to platform-independent bytecode.

`input-file`

  should be a pathname/string/symbol.

`:output-file`

  should be `NIL` or `T` or a pathname/string/symbol or an output-stream. The default is `T`.

`:listing`

  should be `NIL` or `T` or a pathname/string/symbol or an output-stream. The default is `NIL`.

`:warnings`

  specifies whether warnings should also appear on the screen.

`:verbose`

  specifies whether error messages should also appear on the screen.

`:print`

  specifies whether an indication which forms are being compiled should appear on the screen.

The variables `custom:*compile-warnings*`, `*COMPILE-VERBOSE*`, `*COMPILE-PRINT*` provide defaults for the `:warnings`, `:verbose`, `:print` keyword arguments, respectively. For each input file (default file type: `#p".lisp"`) the following files are generated:

File: output file

When: only if `:output-file` is not `NIL`

Default file type: `#p".fas"`

Contents: can be loaded using the `LOAD` function

File: auxiliary output file

When: only if `:output-file` is not `NIL`

Default file type: `#p".lib"`

Contents: used by `COMPILE-FILE` when compiling a `REQUIRE` form referring to the input file

File: listing file

When: only if `:listing` is not `NIL`

Default file type: `#p".lis"`

Contents: disassembly of the output file

File: C output file

When: only if `:output-file` is not `NIL`

Default file type: `#p".c"`

Contents: foreign function interface; this file is deleted if it is empty

### Function `COMPILE-FILE-PATHNAME`

The default for the `:output-file` argument is `T`, which means `#p".fas"`.

### Function `REQUIRE`

The function `REQUIRE` receives as optional argument either a pathname or a list of pathnames: files to be loaded if the required module is not already in memory.

### Function `LOAD`

`LOAD` has two additional keywords `:echo` and `:compiling`.

`(`LOAD` `filename` `&KEY` `:verbose` `:print` `:echo` `:if-does-not-exist` `:compiling`)`

`:verbose` `T`

  causes `LOAD` to emit a short message that a file is being loaded. The default is `*LOAD-VERBOSE*`, which is initially `T`.

`:print` `T`

  causes `LOAD` to print the value of each form. The default is `*LOAD-PRINT*`, which is initially `NIL`.

`:echo` `T`

  causes the input from the file to be echoed to `*STANDARD-OUTPUT*` (normally to the screen). Should there be an error in the file, you can see at one glance where it is. The default is `custom:*load-echo*`, which is initially `NIL`.

`:compiling` `T`

  causes each form read to be compiled on the fly. The compiled code is executed at once and - in contrast to `compile-file` - not written to a file. The default is `custom:*load-compiling*`, which is initially `NIL`.

The variable `custom:*load-paths*` contains a list of directories where program files are searched - additionally to the specified or current directory - by `LOAD`, `REQUIRE`, `COMPILE-FILE`.

### Variable `*FEATURES*`

The variable `*FEATURES*` initially contains the symbols

keyword: `:CLISP`

meaning: the name of this implementation

keyword: `:ANSI-CL`

meaning:

keyword: `:COMMON-LISP`

meaning:

keyword: `:INTERPRETER`

meaning:

keyword: `:COMPILER`

meaning:

keyword: `:SOCKETS`

meaning: see Socket Streams

keyword: `:GENERIC-STREAMS`

meaning: see Defining new kinds of Streams

keyword: `:SYSCALLS`

meaning: see System Calls

keyword: `:DIR-KEY`

meaning: see Directory Access

keyword: `:LOGICAL-PATHNAMES`

meaning:

keyword: `:FFI`

meaning: if a foreign function interface is supported (Platform dependent: many UNIX, Win32 platforms only)

keyword: `:GETTEXT`

meaning: if internationalization using the GNU gettext package is supported (Platform dependent: most UNIX platforms only)

keyword: `:UNICODE`

meaning: if Unicode (ISO 10646) characters are supported

keyword: `:LOOP`

meaning:

keyword: `:CLOS`

meaning:

keyword: `:AMIGA`

meaning: if `hardware` = Amiga and `operating system` = Exec/AmigaDOS

keyword: `:DOS`

meaning: if `hardware` = PC (clone) and `operating system` = DOS

keyword: `:OS/2`

meaning: if `hardware` = PC (clone) and `operating system` = OS/2

keyword: `:WIN32`

meaning: if `hardware` = PC (clone) and `operating system` = Win32 (Windows 95/98/NT)

keyword: `:PC386`

meaning: if `hardware` = PC (clone) with a 386/486/586/686 CPU

keyword: `:UNIX`

meaning: if `operating system` = Unix (yes, in this case the hardware is irrelevant!)

## Chapter 25. Environment [CLHS-25]

## Debugging Utilities [CLHS-25.1.2]

The debugger may be invoked through the functions `INVOKE-DEBUGGER`, `BREAK`, `SIGNAL`, `ERROR`, `CERROR`, `WARN`. The stepper is invoked through the macro `STEP` . Debugger and stepper execute subordinate read-eval-print loop (called "break loops") which are similar to the main read-eval-print loop except for the prompt and the set of available commands. Commands must be typed literally, without surrounding quotes or white space. Each command has a keyword abbreviation, indicated in the second column.

Commands common to the main loop, the debugger and the stepper

command: Help

abbreviation: :h

operation: prints a list of available commands

Commands common to the debugger and the stepper

command: Abort

abbreviation: :a

operation: abort to the next most recent read-eval-print loop

command: Unwind

abbreviation: :uw

operation: abort to the next most recent read-eval-print loop

The stack is organized into frames and other stack elements. Usually every invocation of an interpreted function and every evaluation of an interpreted form corresponds to one stack frame. Special forms such as `LET`, `LET*`, `UNWIND-PROTECT` and `CATCH` produce special kinds of stack frames.

In a break loop there is a current stack frame, which is initially the most recent stack frame but can be moved using the debugger commands Up and Down.

Evaluation of forms in a break loop occurs in the lexical environment of the current stack frame but in the dynamic environment of the debugger's caller. This means that to inspect or modify a lexical variable all you have to do is to move to the current stack frame just below the frame that corresponds to the form or the function call that binds that variable.

There is a current "stack mode" which defines in how much detail the stack is shown by the stack related debugger commands.

Commands common to the debugger and the stepper

command: Error

abbreviation: :e

operation: print the last error message.

command: Mode-1

abbreviation: :m1

operation: sets the current mode to 1: all the stack elements are considered. This mode is fine for debugging compiled functions.

command: Mode-2

abbreviation: :m2

operation: sets the current mode to 2: all the frames are considered.

command: Mode-3

abbreviation: :m3

operation: sets the current mode to 3: only lexical frames (frames that correspond to special forms that modify the lexical environment) are considered.

command: Mode-4

abbreviation: :m4

operation: sets the current mode to 4 (the default): only `EVAL` and `APPLY` frames are considered. Every evaluation of a form in the interpreter corresponds to an EVAL frame.

command: Mode-5

abbreviation: :m5

operation: sets the current mode to 5: only `APPLY` frames are considered. Every invocation of an interpreted function corresponds to one `APPLY` frame.

command: Where

abbreviation: :w

operation: shows the current stack frame.

command: Up

abbreviation: :u

operation: goes up one frame, i.e., to the caller if in mode-5

command: Down

abbreviation: :d

operation: does down one frame, i.e., to the callee if in mode-5

command: Top

abbreviation: :t

operation: goes to top frame, i.e., to the top-level form if in mode-4

command: Bottom

abbreviation: :b

operation: goes to bottom (most recent) frame, i.e., most probably to the form or function that caused the debugger to be entered.

command: Backtrace

abbreviation: :bt

operation: lists the stack in current mode, bottom frame first, top frame last.

command: Backtrace-1

abbreviation: :bt1

operation: lists the stack in mode 1.

command: Backtrace-2

abbreviation: :bt2

operation: lists the stack in mode 2.

command: Backtrace-3

abbreviation: :bt3

operation: lists the stack in mode 3.

command: Backtrace-4

abbreviation: :bt4

operation: lists the stack in mode 4.

command: Backtrace-5

abbreviation: :bt5

operation: lists the stack in mode 5.

command: Frame-limit

abbreviation: :fl

operation: set the frame-limit: this many frames will be printed in a backtrace at most.

command: Backtrace-l

abbreviation: :bl

operation: limit of frames to print will be prompted for.

If the current stack frame is an `EVAL` or `APPLY` frame, the following commands are available as well:

command: Break+

abbreviation: :br+

operation: sets a breakpoint in the current frame. When the corresponding form or function will be left, the debugger will be entered again, with the variable `*trace-values*` containing a list of its values.

command: Break-

abbreviation: :br-

operation: removes a breakpoint from the current frame.

command: Redo

abbreviation: :rd

operation: re-evaluates the corresponding form or function call. This command can be used to restart parts of a computation without aborting it entirely.

command: Return

abbreviation: :rt

operation: leaves the current frame. You will be prompted for the return values.

Commands specific to the debugger

command: Continue

abbreviation: :c

operation: continues evaluation of the program.

Commands specific to the stepper

command: Step

abbreviation: :s

operation: step into a form: evaluate this form in single step mode

command: Next

abbreviation: :n

operation: step over a form: evaluate this form at once

command: Over

abbreviation: :o

operation: step over this level: evaluate at once up to the next return

command: Continue

abbreviation: :c

operation: switch off single step mode, continue evaluation

The stepper is usually used like this: If some form returns a strange value or results in an error, call `(`STEP` `form`)` and navigate using the commands Step and Next until you reach the form you regard as responsible. If you are too fast (execute Next once and get the error), there is no way back; you have to restart the entire stepper session. If you are too slow (stepped into a function or a form which certainly is OK), a couple of Next commands or one Over command will help.

## The Environment Dictionary [CLHS-25.2]

### Function `DISASSEMBLE`

Platform dependent: UNIX platforms only.

  `DISASSEMBLE` can disassemble to machine code, provided that GNU gdb is present. In that case the argument may be a `system-function`, a `foreign-function`, a special operator indicator, a symbol denoting one of these, a number, or a string.

### Function `EXT:UNCOMPILE`

The function `ext:uncompile` does the converse of `COMPILE`: `(`ext:uncompile` `function`)` reverts an interpreted `function` (name), that has been entered or loaded in the same session and then compiled, back to its interpreted form.

### Function `DOCUMENTATION`

No on-line documentation is available for the system functions (yet). `DOCUMENTATION` still has the [CLtL1] implementation.

`ext:clhs` [Common Lisp HyperSpec] access is provided via `(`ext:clhs` `symbol` `&KEY` `:browser` `browser`)` function which uses your web browser. `browser` should be a valid keyword in the `custom:*browsers*` alist.

### Macro `TRACE`

`(`TRACE` `function` ...)` makes the functions `function`, ... traced. `function` should be either a symbol or a list `(`symbol` `&KEY` `:suppress-if` `:step-if` `:pre` `:post` `:pre-break-if` `:post-break-if` `:pre-print` `:post-print` `:print`)`, where

`:suppress-if` `form`

  no trace output as long as `form` is true

`:step-if` `form`

  invokes the stepper as soon as `form` is true

`:pre` `form`

  evaluates `form` before calling the function

`:post` `form`

  evaluates `form` after return from the function

`:pre-break-if` `form`

  goes into the break loop before calling the function if `form` is true

`:post-break-if` `form`

  goes into the break loop after return from the function if `form` is true

`:pre-print` `form`

  prints the values of `form` before calling the function

`:post-print` `form`

  prints the values of `form` after return from the function

`:print` `form`

  prints the values of `form` both before calling and after return from the function

In all these forms you can access the following variables:

`ext:*trace-function*`

  the function itself

`ext:*trace-args*`

  the arguments to the function

`ext:*trace-form*`

  the function/macro call as form

`ext:*trace-values*`

  after return from the function: the list of return values from the function call

and you can leave the function call with specified values by using `RETURN`.

`TRACE` and `UNTRACE` are also applicable to functions `(`SETF` `symbol`)` and to macros, but not to locally defined functions and macros.

### Function `INSPECT`

The function `INSPECT` takes a keyword argument `:frontend`, which specifies the way CLISP will interact with the user.

Available `:frontend`s for `INSPECT` in CLISP

`:tty`

  The interaction is conducted via the `*TERMINAL-IO*` stream. Please use the `:h` command to get the list of all available commands.

`:http`

  A window in your Web browser (specified by the `:browser` keyword argument) is opened and it is controlled by CLISP via a `socket-stream`, using the HTTP protocol. You should be able to use all the standard browser features.

  Since CLISP is not multitasking at this time, you will not be able to do anything else during an `INSPECT` session. Please click on the `quit` link to terminate the session.

  Please be aware though, that once you terminate an `INSPECT` session, all links in all `INSPECT` windows in your browser will become obsolete and using them in a new `INSPECT` session will result in unpredictable behavior.

### EXT:SPACE

The macro `ext:space` is like the macro `TIME`: `(`ext:space` `form`)` evaluates the `form`, and, as a side effect, outputs information about the memory allocations caused by this evaluation. It also prints everything printed by `time`.

### Function `ROOM`

The function `ROOM` returns two values: the number of bytes currently occupied by Lisp objects, and the number of bytes that can be allocated before the next regular garbage-collection occurs.

The function `ext:gc` starts a global garbage-collection and its return value has the same meaning as the second value of `ROOM`.

### Macro `TIME`

The timing data printed by the macro `TIME` includes: The real time (elapsed time), the run time (processor time for this process), the number of bytes allocated (use the `ext:space` macro for more detailed analysis), and the number of GCs performed, if any.

### Function `ED`

The function `ED` calls the external editor specified by the variable `custom:*editor*` (see `config.lsp`). If the argument is a function name which was defined in the current session (not loaded from a file), the program text to be edited is a pretty-printed version (without comments) of the text which was used to define the function.

### Clock Time

Platform dependent: Amiga, Acorn, DOS, OS/2 platforms only.

  The variable `custom:*default-time-zone*` contains the default time zone used by `ENCODE-UNIVERSAL-TIME` and `DECODE-UNIVERSAL-TIME`. It is initially set to -1 (which means 1 hour east of Greenwich, i.e., Mid European Time).

The timezone in a decoded time must not necessarily be an integer, but (as float or rational number) it should be a multiple of `1/3600`.

Platform dependent

platform: `INTERNAL-TIME-UNITS-PER-SECOND`

Acorn, DOS, OS/2: 100

Amiga: 50

UNIX: 1,000,000

Win32: 10,000,000

`GET-INTERNAL-RUN-TIME` returns the amount of run time consumed by the current CLISP process since its startup.

### Machine

Platform dependent: UNIX, Win32 platforms only.

  The functions `SHORT-SITE-NAME`, `LONG-SITE-NAME` should be defined in a site-specific `config.lsp` file.

Platform dependent: Amiga, Acorn, DOS, OS/2 platforms only.

  The functions `MACHINE-TYPE`, `MACHINE-VERSION`, `MACHINE-INSTANCE` and `SHORT-SITE-NAME`, `LONG-SITE-NAME` should be defined by every user in his site-specific `config.lsp` file.

### Functions `APROPOS` & `APROPOS-LIST`

The search performed by `APROPOS` and `APROPOS-LIST` is case-insensitive.

### Function `DRIBBLE`

If `DRIBBLE` is called with an argument, and dribbling is already enabled, a warning is printed, and the new dribbling request is ignored.

### Function `LISP-IMPLEMENTATION-VERSION`

`LISP-IMPLEMENTATION-VERSION` returns the numeric version (like `3.14`), and the release date (like `"1999-07-21"`). When running on the same machine on which CLISP was built, it appends the binary build and memory image dump date in universal time (like `3141592654`). When running on a different machine, it appends the `MACHINE-INSTANCE` of the machine on which it was built.

## Chapter 26. Glossary [CLHS-26]

No notes.

## Chapter 27. Appendix [CLHS-a]

No notes.

## Chapter 28. X3J13 Issue Index [CLHS-ic]

This is the list of ANSI CL issues and their current status in CLISP, i.e., whether CLISP supports code that makes use of the functionality specified by the vote.

&ENVIRONMENT-BINDING-ORDER:FIRST

  yes

ACCESS-ERROR-NAME

  yes

ADJUST-ARRAY-DISPLACEMENT

  yes

ADJUST-ARRAY-FILL-POINTER

  yes

ADJUST-ARRAY-NOT-ADJUSTABLE:IMPLICIT-COPY

  no

ALLOCATE-INSTANCE:ADD

  yes

ALLOW-LOCAL-INLINE:INLINE-NOTINLINE

  yes

ALLOW-OTHER-KEYS-NIL:PERMIT

  yes

AREF-1D

  yes

ARGUMENT-MISMATCH-ERROR-AGAIN:CONSISTENT

  yes

ARGUMENT-MISMATCH-ERROR-MOON:FIX

  yes

ARGUMENT-MISMATCH-ERROR:MORE-CLARIFICATIONS

  yes, except for argument list checking in `CALL-NEXT-METHOD` in compiled code (items 11,12)

ARGUMENTS-UNDERSPECIFIED:SPECIFY

  yes

ARRAY-DIMENSION-LIMIT-IMPLICATIONS:ALL-FIXNUM

  no

ARRAY-TYPE-ELEMENT-TYPE-SEMANTICS:UNIFY-UPGRADING

  yes for arrays, no for complex numbers

ASSERT-ERROR-TYPE:ERROR

  yes

ASSOC-RASSOC-IF-KEY

  yes

ASSOC-RASSOC-IF-KEY:YES

  yes

BOA-AUX-INITIALIZATION:ERROR-ON-READ

  yes

BREAK-ON-WARNINGS-OBSOLETE:REMOVE

  no

BROADCAST-STREAM-RETURN-VALUES:CLARIFY-MINIMALLY

  no

BUTLAST-NEGATIVE:SHOULD-SIGNAL

  yes

CHANGE-CLASS-INITARGS:PERMIT

  no

CHAR-NAME-CASE:X3J13-MAR-91

  yes

CHARACTER-LOOSE-ENDS:FIX

  yes

CHARACTER-PROPOSAL:2

  yes

CHARACTER-PROPOSAL:2-1-1

  yes

CHARACTER-PROPOSAL:2-1-2

  yes

CHARACTER-PROPOSAL:2-2-1

  yes

CHARACTER-PROPOSAL:2-3-1

  yes

CHARACTER-PROPOSAL:2-3-2

  yes

CHARACTER-PROPOSAL:2-3-3

  yes

CHARACTER-PROPOSAL:2-3-4

  yes

CHARACTER-PROPOSAL:2-3-5

  yes

CHARACTER-PROPOSAL:2-3-6

  yes

CHARACTER-PROPOSAL:2-4-1

  yes

CHARACTER-PROPOSAL:2-4-2

  yes

CHARACTER-PROPOSAL:2-4-3

  yes

CHARACTER-PROPOSAL:2-5-2

  yes

CHARACTER-PROPOSAL:2-5-6

  yes

CHARACTER-PROPOSAL:2-5-7

  yes

CHARACTER-PROPOSAL:2-6-1

  yes

CHARACTER-PROPOSAL:2-6-2

  yes

CHARACTER-PROPOSAL:2-6-3

  yes

CHARACTER-PROPOSAL:2-6-5

  yes

CHARACTER-VS-CHAR:LESS-INCONSISTENT-SHORT

  yes

CLASS-OBJECT-SPECIALIZER:AFFIRM

  yes

CLOS-CONDITIONS-AGAIN:ALLOW-SUBSET

  yes

CLOS-CONDITIONS:INTEGRATE

  yes

CLOS-ERROR-CHECKING-ORDER:NO-APPLICABLE-METHOD-FIRST

  yes

CLOS-MACRO-COMPILATION:MINIMAL

  yes

CLOSE-CONSTRUCTED-STREAM:ARGUMENT-STREAM-ONLY

  yes

CLOSED-STREAM-OPERATIONS:ALLOW-INQUIRY

  yes

COERCING-SETF-NAME-TO-FUNCTION:ALL-FUNCTION-NAMES

  yes

COLON-NUMBER

  yes

COMMON-FEATURES:SPECIFY

  yes

COMMON-TYPE:REMOVE

  yes, still present in package LISP

COMPILE-ARGUMENT-PROBLEMS-AGAIN:FIX

  yes

COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY

  yes

COMPILE-FILE-OUTPUT-FILE-DEFAULTS:INPUT-FILE

  yes

COMPILE-FILE-PACKAGE

  yes

COMPILE-FILE-PATHNAME-ARGUMENTS:MAKE-CONSISTENT

  yes

COMPILE-FILE-SYMBOL-HANDLING:NEW-REQUIRE-CONSISTENCY

  yes

COMPILED-FUNCTION-REQUIREMENTS:TIGHTEN

  yes

COMPILER-DIAGNOSTICS:USE-HANDLER

  no

COMPILER-LET-CONFUSION:ELIMINATE

  yes

COMPILER-VERBOSITY:LIKE-LOAD

  yes

COMPILER-WARNING-STREAM

  yes

COMPLEX-ATAN-BRANCH-CUT:TWEAK

  yes

COMPLEX-ATANH-BOGUS-FORMULA:TWEAK-MORE

  yes

COMPLEX-RATIONAL-RESULT:EXTEND

  yes

COMPUTE-APPLICABLE-METHODS:GENERIC

  yes

CONCATENATE-SEQUENCE:SIGNAL-ERROR

  yes

CONDITION-ACCESSORS-SETFABLE:NO

  yes

CONDITION-RESTARTS:BUGGY

  yes

CONDITION-RESTARTS:PERMIT-ASSOCIATION

  yes, except for (6)

CONDITION-SLOTS:HIDDEN

  yes

CONS-TYPE-SPECIFIER:ADD

  yes

CONSTANT-CIRCULAR-COMPILATION:YES

  yes

CONSTANT-COLLAPSING:GENERALIZE

  yes

CONSTANT-COMPILABLE-TYPES:SPECIFY

  yes

CONSTANT-FUNCTION-COMPILATION:NO

  no

CONSTANT-MODIFICATION:DISALLOW

  yes

CONSTANTP-DEFINITION:INTENTIONAL

  yes

CONSTANTP-ENVIRONMENT:ADD-ARG

  yes

CONTAGION-ON-NUMERICAL-COMPARISONS:TRANSITIVE

  yes

COPY-SYMBOL-COPY-PLIST:COPY-LIST

  yes

COPY-SYMBOL-PRINT-NAME:EQUAL

  yes

DATA-IO:ADD-SUPPORT

  yes for `*PRINT-READABLY*`, `*READ-EVAL*` and `WITH-STANDARD-IO-SYNTAX`, no for everything else

DATA-TYPES-HIERARCHY-UNDERSPECIFIED

  yes

DEBUGGER-HOOK-VS-BREAK:CLARIFY

  no

DECLARATION-SCOPE:NO-HOISTING

  no

DECLARE-ARRAY-TYPE-ELEMENT-REFERENCES:RESTRICTIVE

  yes

DECLARE-FUNCTION-AMBIGUITY:DELETE-FTYPE-ABBREVIATION

  yes

DECLARE-MACROS:FLUSH

  no

DECLARE-TYPE-FREE:LEXICAL

  yes

DECLS-AND-DOC

  ??

DECODE-UNIVERSAL-TIME-DAYLIGHT:LIKE-ENCODE

  yes

DEFCONSTANT-SPECIAL:NO

  yes

DEFGENERIC-DECLARE:ALLOW-MULTIPLE

  yes

DEFINE-COMPILER-MACRO:X3J13-NOV89

  no

DEFINE-CONDITION-SYNTAX:INCOMPATIBLY-MORE-LIKE-DEFCLASS+EMPHASIZE-READ-ONLY

  yes

DEFINE-METHOD-COMBINATION-BEHAVIOR:CLARIFY

  no

DEFINING-MACROS-NON-TOP-LEVEL:ALLOW

  no

DEFMACRO-BLOCK-SCOPE:EXCLUDES-BINDINGS

  yes

DEFMACRO-LAMBDA-LIST:TIGHTEN-DESCRIPTION

  yes

DEFMETHOD-DECLARATION-SCOPE:CORRESPONDS-TO-BINDINGS

  yes

DEFPACKAGE:ADDITION

  yes

DEFSTRUCT-CONSTRUCTOR-KEY-MIXTURE:ALLOW-KEY

  yes

DEFSTRUCT-CONSTRUCTOR-OPTIONS:EXPLICIT

  yes

DEFSTRUCT-CONSTRUCTOR-SLOT-VARIABLES:NOT-BOUND

  no (furthermore it gets hairy when applied to BOA constructors)

DEFSTRUCT-COPIER-ARGUMENT-TYPE:RESTRICT

  yes

DEFSTRUCT-COPIER:ARGUMENT-TYPE

  yes

DEFSTRUCT-DEFAULT-VALUE-EVALUATION:IFF-NEEDED

  yes

DEFSTRUCT-INCLUDE-DEFTYPE:EXPLICITLY-UNDEFINED

  yes

DEFSTRUCT-PRINT-FUNCTION-AGAIN:X3J13-MAR-93

  yes

DEFSTRUCT-PRINT-FUNCTION-INHERITANCE:YES

  yes

DEFSTRUCT-REDEFINITION:ERROR

  yes

DEFSTRUCT-SLOTS-CONSTRAINTS-NAME:DUPLICATES-ERROR

  yes

DEFSTRUCT-SLOTS-CONSTRAINTS-NUMBER

  yes

DEFTYPE-DESTRUCTURING:YES

  yes

DEFTYPE-KEY:ALLOW

  yes

DEFVAR-DOCUMENTATION:UNEVALUATED

  yes

DEFVAR-INIT-TIME:NOT-DELAYED

  yes

DEFVAR-INITIALIZATION:CONSERVATIVE

  yes

DEPRECATION-POSITION:LIMITED

  yes

DESCRIBE-INTERACTIVE:NO

  yes

DESCRIBE-UNDERSPECIFIED:DESCRIBE-OBJECT

  yes

DESTRUCTIVE-OPERATIONS:SPECIFY

  yes

DESTRUCTURING-BIND:NEW-MACRO

  yes

DISASSEMBLE-SIDE-EFFECT:DO-NOT-INSTALL

  yes

DISPLACED-ARRAY-PREDICATE:ADD

  yes

DO-SYMBOLS-BLOCK-SCOPE:ENTIRE-FORM

  yes

DO-SYMBOLS-DUPLICATES

  yes

DOCUMENTATION-FUNCTION-BUGS:FIX

  no

DOCUMENTATION-FUNCTION-TANGLED:REQUIRE-ARGUMENT

  no

DOTIMES-IGNORE:X3J13-MAR91

  yes

DOTTED-LIST-ARGUMENTS:CLARIFY

  yes

DOTTED-MACRO-FORMS:ALLOW

  yes

DRIBBLE-TECHNIQUE

  yes

DYNAMIC-EXTENT-FUNCTION:EXTEND

  yes

DYNAMIC-EXTENT:NEW-DECLARATION

  yes

EQUAL-STRUCTURE:MAYBE-STATUS-QUO

  no for `EQUALP` on hash tables, yes for everything else

ERROR-TERMINOLOGY-WARNING:MIGHT

  yes

EVAL-OTHER:SELF-EVALUATE

  yes

EVAL-TOP-LEVEL:LOAD-LIKE-COMPILE-FILE

  yes, except maybe if `LOAD` `:compiling` `T`

EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS

  no

EVAL-WHEN-OBSOLETE-KEYWORDS:X3J13-MAR-1993

  no

EVALHOOK-STEP-CONFUSION:FIX

  yes

EVALHOOK-STEP-CONFUSION:X3J13-NOV-89

  yes

EXIT-EXTENT-AND-CONDITION-SYSTEM:LIKE-DYNAMIC-BINDINGS

  yes

EXIT-EXTENT:MINIMAL

  yes, actually implement MEDIUM

EXPT-RATIO:P.211

  yes

EXTENSIONS-POSITION:DOCUMENTATION

  yes

EXTERNAL-FORMAT-FOR-EVERY-FILE-CONNECTION:MINIMUM

  no

EXTRA-RETURN-VALUES:NO

  yes

FILE-OPEN-ERROR:SIGNAL-FILE-ERROR

  no

FIXNUM-NON-PORTABLE:TIGHTEN-DEFINITION

  no

FLET-DECLARATIONS

  yes

FLET-DECLARATIONS:ALLOW

  yes

FLET-IMPLICIT-BLOCK:YES

  yes

FLOAT-UNDERFLOW:ADD-VARIABLES

  yes

FLOATING-POINT-CONDITION-NAMES:X3J13-NOV-89

  yes

FORMAT-ATSIGN-COLON

  yes

FORMAT-COLON-UPARROW-SCOPE

  yes

FORMAT-COMMA-INTERVAL

  yes

FORMAT-E-EXPONENT-SIGN:FORCE-SIGN

  yes

FORMAT-OP-C

  yes

FORMAT-PRETTY-PRINT:YES

  yes, except that `~F`, `~E`, `~G`, `~$` also bind `*PRINT-BASE*` to 10 and `*PRINT-RADIX*` to `NIL`

FORMAT-STRING-ARGUMENTS:SPECIFY

  yes

FUNCTION-CALL-EVALUATION-ORDER:MORE-UNSPECIFIED

  yes

FUNCTION-COMPOSITION:JAN89-X3J13

  yes

FUNCTION-DEFINITION:JAN89-X3J13

  yes

FUNCTION-NAME:LARGE

  yes

FUNCTION-TYPE

  yes

FUNCTION-TYPE-ARGUMENT-TYPE-SEMANTICS:RESTRICTIVE

  yes

FUNCTION-TYPE-KEY-NAME:SPECIFY-KEYWORD

  yes

FUNCTION-TYPE-REST-LIST-ELEMENT:USE-ACTUAL-ARGUMENT-TYPE

  yes

FUNCTION-TYPE:X3J13-MARCH-88

  yes

GENERALIZE-PRETTY-PRINTER:UNIFY

  no

GENERIC-FLET-POORLY-DESIGNED:DELETE

  yes

GENSYM-NAME-STICKINESS:LIKE-TEFLON

  yes

GENTEMP-BAD-IDEA:DEPRECATE

  yes

GET-MACRO-CHARACTER-READTABLE:NIL-STANDARD

  yes

GET-SETF-METHOD-ENVIRONMENT:ADD-ARG

  yes

HASH-TABLE-ACCESS:X3J13-MAR-89

  yes

HASH-TABLE-KEY-MODIFICATION:SPECIFY

  yes

HASH-TABLE-PACKAGE-GENERATORS:ADD-WITH-WRAPPER

  no

HASH-TABLE-REHASH-SIZE-INTEGER

  yes

HASH-TABLE-SIZE:INTENDED-ENTRIES

  yes

HASH-TABLE-TESTS:ADD-EQUALP

  yes

IEEE-ATAN-BRANCH-CUT:SPLIT

  yes

IGNORE-USE-TERMINOLOGY:VALUE-ONLY

  yes

IMPORT-SETF-SYMBOL-PACKAGE

  no

IN-PACKAGE-FUNCTIONALITY:MAR89-X3J13

  yes

IN-SYNTAX:MINIMAL

  yes

INITIALIZATION-FUNCTION-KEYWORD-CHECKING

  ??

ISO-COMPATIBILITY:ADD-SUBSTRATE

  yes

JUN90-TRIVIAL-ISSUES:11

  yes

JUN90-TRIVIAL-ISSUES:14

  yes

JUN90-TRIVIAL-ISSUES:24

  yes

JUN90-TRIVIAL-ISSUES:25

  yes

JUN90-TRIVIAL-ISSUES:27

  yes for `THE`, no for `APPLY` (spec not clear)

JUN90-TRIVIAL-ISSUES:3

  yes

JUN90-TRIVIAL-ISSUES:4

  yes

JUN90-TRIVIAL-ISSUES:5

  yes

JUN90-TRIVIAL-ISSUES:9

  yes

KEYWORD-ARGUMENT-NAME-PACKAGE:ANY

  yes

LAST-N

  yes

LCM-NO-ARGUMENTS:1

  yes

LEXICAL-CONSTRUCT-GLOBAL-DEFINITION:UNDEFINED

  yes

LISP-PACKAGE-NAME:COMMON-LISP

  yes

LISP-SYMBOL-REDEFINITION-AGAIN:MORE-FIXES

  yes

LISP-SYMBOL-REDEFINITION:MAR89-X3J13

  yes

LOAD-OBJECTS:MAKE-LOAD-FORM

  no

LOAD-TIME-EVAL:R**2-NEW-SPECIAL-FORM

  obsolete

LOAD-TIME-EVAL:R**3-NEW-SPECIAL-FORM

  yes, except for macro expansion at compile time

LOAD-TRUENAME:NEW-PATHNAME-VARIABLES

  yes

LOCALLY-TOP-LEVEL:SPECIAL-FORM

  yes

LOOP-AND-DISCREPANCY:NO-REITERATION

  yes

LOOP-FOR-AS-ON-TYPO:FIX-TYPO

  yes

LOOP-INITFORM-ENVIRONMENT:PARTIAL-INTERLEAVING-VAGUE

  no

LOOP-MISCELLANEOUS-REPAIRS:FIX

  yes

LOOP-NAMED-BLOCK-NIL:OVERRIDE

  yes

LOOP-PRESENT-SYMBOLS-TYPO:FLUSH-WRONG-WORDS

  yes

LOOP-SYNTAX-OVERHAUL:REPAIR

  yes

MACRO-AS-FUNCTION:DISALLOW

  yes

MACRO-DECLARATIONS:MAKE-EXPLICIT

  yes

MACRO-ENVIRONMENT-EXTENT:DYNAMIC

  yes

MACRO-FUNCTION-ENVIRONMENT

  obsolete

MACRO-FUNCTION-ENVIRONMENT:YES

  yes

MACRO-SUBFORMS-TOP-LEVEL-P:ADD-CONSTRAINTS

  no

MACROEXPAND-HOOK-DEFAULT:EXPLICITLY-VAGUE

  yes

MACROEXPAND-HOOK-INITIAL-VALUE:IMPLEMENTATION-DEPENDENT

  yes

MACROEXPAND-RETURN-VALUE:TRUE

  yes

MAKE-LOAD-FORM-CONFUSION:REWRITE

  no

MAKE-LOAD-FORM-SAVING-SLOTS:NO-INITFORMS

  no

MAKE-PACKAGE-USE-DEFAULT:IMPLEMENTATION-DEPENDENT

  yes

MAP-INTO:ADD-FUNCTION

  yes

MAPPING-DESTRUCTIVE-INTERACTION:EXPLICITLY-VAGUE

  yes

METACLASS-OF-SYSTEM-CLASS:UNSPECIFIED

  yes

METHOD-COMBINATION-ARGUMENTS:CLARIFY

  no

METHOD-INITFORM:FORBID-CALL-NEXT-METHOD

  no

MUFFLE-WARNING-CONDITION-ARGUMENT

  yes

MULTIPLE-VALUE-SETQ-ORDER:LIKE-SETF-OF-VALUES

  yes

MULTIPLE-VALUES-LIMIT-ON-VARIABLES:UNDEFINED

  yes

NINTERSECTION-DESTRUCTION

  yes

NINTERSECTION-DESTRUCTION:REVERT

  yes

NOT-AND-NULL-RETURN-VALUE:X3J13-MAR-93

  yes

NTH-VALUE:ADD

  yes

OPTIMIZE-DEBUG-INFO:NEW-QUALITY

  yes

PACKAGE-CLUTTER:REDUCE

  no

PACKAGE-DELETION:NEW-FUNCTION

  yes

PACKAGE-FUNCTION-CONSISTENCY:MORE-PERMISSIVE

  yes

PARSE-ERROR-STREAM:SPLIT-TYPES

  yes

PATHNAME-COMPONENT-CASE:KEYWORD-ARGUMENT

  yes

PATHNAME-COMPONENT-VALUE:SPECIFY

  no

PATHNAME-HOST-PARSING:RECOGNIZE-LOGICAL-HOST-NAMES

  no

PATHNAME-LOGICAL:ADD

  yes

PATHNAME-PRINT-READ:SHARPSIGN-P

  yes

PATHNAME-STREAM

  yes

PATHNAME-STREAM:FILES-OR-SYNONYM

  yes

PATHNAME-SUBDIRECTORY-LIST:NEW-REPRESENTATION

  no

PATHNAME-SYMBOL

  no

PATHNAME-SYNTAX-ERROR-TIME:EXPLICITLY-VAGUE

  yes

PATHNAME-UNSPECIFIC-COMPONENT:NEW-TOKEN

  no

PATHNAME-WILD:NEW-FUNCTIONS

  yes

PEEK-CHAR-READ-CHAR-ECHO:FIRST-READ-CHAR

  yes

PLIST-DUPLICATES:ALLOW

  yes

PRETTY-PRINT-INTERFACE

  no

PRINC-READABLY:X3J13-DEC-91

  yes

PRINT-CASE-BEHAVIOR:CLARIFY

  yes

PRINT-CASE-PRINT-ESCAPE-INTERACTION:VERTICAL-BAR-RULE-NO-UPCASE

  no

PRINT-CIRCLE-SHARED:RESPECT-PRINT-CIRCLE

  yes

PRINT-CIRCLE-STRUCTURE:USER-FUNCTIONS-WORK

  yes

PRINT-READABLY-BEHAVIOR:CLARIFY

  yes

PRINTER-WHITESPACE:JUST-ONE-SPACE

  yes

PROCLAIM-ETC-IN-COMPILE-FILE:NEW-MACRO

  yes

PUSH-EVALUATION-ORDER:FIRST-ITEM

  yes

PUSH-EVALUATION-ORDER:ITEM-FIRST

  yes

PUSHNEW-STORE-REQUIRED:UNSPECIFIED

  yes

QUOTE-SEMANTICS:NO-COPYING

  yes

RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER

  yes, when `custom:*sequence-count-ansi*` is non-`NIL`; otherwise negative `:count` values are not allowed.

RANGE-OF-START-AND-END-PARAMETERS:INTEGER-AND-INTEGER-NIL

  yes

READ-AND-WRITE-BYTES:NEW-FUNCTIONS

  yes

READ-CASE-SENSITIVITY:READTABLE-KEYWORDS

  yes

READ-MODIFY-WRITE-EVALUATION-ORDER:DELAYED-ACCESS-STORES

  no

READ-SUPPRESS-CONFUSING:GENERALIZE

  yes, except that `READ-DELIMITED-LIST` still constructs a list

READER-ERROR:NEW-TYPE

  yes

REAL-NUMBER-TYPE:X3J13-MAR-89

  yes

RECURSIVE-DEFTYPE:EXPLICITLY-VAGUE

  yes

REDUCE-ARGUMENT-EXTRACTION

  yes

REMF-DESTRUCTION-UNSPECIFIED:X3J13-MAR-89

  yes

REQUIRE-PATHNAME-DEFAULTS-AGAIN:X3J13-DEC-91

  yes

REQUIRE-PATHNAME-DEFAULTS-YET-AGAIN:RESTORE-ARGUMENT

  yes, except that `REQUIRE` wants a pathname, not a list of pathnames

REQUIRE-PATHNAME-DEFAULTS:ELIMINATE

  superseded by REQUIRE-PATHNAME-DEFAULTS-AGAIN:X3J13-DEC-91

REST-LIST-ALLOCATION:MAY-SHARE

  yes

RESULT-LISTS-SHARED:SPECIFY

  yes

RETURN-VALUES-UNSPECIFIED:SPECIFY

  yes

ROOM-DEFAULT-ARGUMENT:NEW-VALUE

  yes

SELF-MODIFYING-CODE:FORBID

  yes

SEQUENCE-TYPE-LENGTH:MUST-MATCH

  yes

SETF-APPLY-EXPANSION:IGNORE-EXPANDER

  no

SETF-FIND-CLASS:ALLOW-NIL

  no

SETF-FUNCTIONS-AGAIN:MINIMAL-CHANGES

  yes

SETF-GET-DEFAULT:EVALUATED-BUT-IGNORED

  yes

SETF-MACRO-EXPANSION:LAST

  yes

SETF-METHOD-VS-SETF-METHOD:RENAME-OLD-TERMS

  yes

SETF-MULTIPLE-STORE-VARIABLES:ALLOW

  yes

SETF-OF-APPLY:ONLY-AREF-AND-FRIENDS

  yes

SETF-OF-VALUES:ADD

  yes

SETF-SUB-METHODS:DELAYED-ACCESS-STORES

  yes

SHADOW-ALREADY-PRESENT

  yes

SHADOW-ALREADY-PRESENT:WORKS

  yes

SHARP-COMMA-CONFUSION:REMOVE

  no

SHARP-O-FOOBAR:CONSEQUENCES-UNDEFINED

  yes

SHARP-STAR-DELIMITER:NORMAL-DELIMITER

  yes

SHARPSIGN-PLUS-MINUS-PACKAGE:KEYWORD

  yes

SLOT-MISSING-VALUES:SPECIFY

  yes

SLOT-VALUE-METACLASSES:LESS-MINIMAL

  yes

SPECIAL-FORM-P-MISNOMER:RENAME

  yes

SPECIAL-TYPE-SHADOWING:CLARIFY

  yes

STANDARD-INPUT-INITIAL-BINDING:DEFINED-CONTRACTS

  yes

STANDARD-REPERTOIRE-GRATUITOUS:RENAME

  yes

STEP-ENVIRONMENT:CURRENT

  yes

STEP-MINIMAL:PERMIT-PROGN

  yes

STREAM-ACCESS:ADD-TYPES-ACCESSORS

  yes

STREAM-CAPABILITIES:INTERACTIVE-STREAM-P

  yes

STRING-COERCION:MAKE-CONSISTENT

  yes

STRING-OUTPUT-STREAM-BASHING:UNDEFINED

  yes

STRUCTURE-READ-PRINT-SYNTAX:KEYWORDS

  yes

SUBSEQ-OUT-OF-BOUNDS

  yes

SUBSEQ-OUT-OF-BOUNDS:IS-AN-ERROR

  yes

SUBSETTING-POSITION:NONE

  yes

SUBTYPEP-ENVIRONMENT:ADD-ARG

  no

SUBTYPEP-TOO-VAGUE:CLARIFY-MORE

  yes

SXHASH-DEFINITION:SIMILAR-FOR-SXHASH

  no

SYMBOL-MACROLET-DECLARE:ALLOW

  yes

SYMBOL-MACROLET-SEMANTICS:SPECIAL-FORM

  yes

SYMBOL-MACROLET-TYPE-DECLARATION:NO

  yes

SYMBOL-MACROS-AND-PROCLAIMED-SPECIALS:SIGNALS-AN-ERROR

  yes

SYMBOL-PRINT-ESCAPE-BEHAVIOR:CLARIFY

  yes

SYNTACTIC-ENVIRONMENT-ACCESS:RETRACTED-MAR91

  yes

TAGBODY-TAG-EXPANSION:NO

  yes

TAILP-NIL:T

  yes

TEST-NOT-IF-NOT:FLUSH-ALL

  yes, but no warning

THE-AMBIGUITY:FOR-DECLARATION

  yes

THE-VALUES:RETURN-NUMBER-RECEIVED

  no

TIME-ZONE-NON-INTEGER:ALLOW

  yes

TYPE-DECLARATION-ABBREVIATION:ALLOW-ALL

  no

TYPE-OF-AND-PREDEFINED-CLASSES:TYPE-OF-HANDLES-FLOATS

  yes

TYPE-OF-AND-PREDEFINED-CLASSES:UNIFY-AND-EXTEND

  yes, except for class `METHOD-COMBINATION`

TYPE-OF-UNDERCONSTRAINED:ADD-CONSTRAINTS

  yes

TYPE-SPECIFIER-ABBREVIATION:X3J13-JUN90-GUESS

  yes

UNDEFINED-VARIABLES-AND-FUNCTIONS:COMPROMISE

  yes

UNINITIALIZED-ELEMENTS:CONSEQUENCES-UNDEFINED

  yes, could add error checking

UNREAD-CHAR-AFTER-PEEK-CHAR:DONT-ALLOW

  yes

UNSOLICITED-MESSAGES:NOT-TO-SYSTEM-USER-STREAMS

  yes

VARIABLE-LIST-ASYMMETRY:SYMMETRIZE

  yes

WITH-ADDED-METHODS:DELETE

  yes

WITH-COMPILATION-UNIT:NEW-MACRO

  yes

WITH-OPEN-FILE-DOES-NOT-EXIST:STREAM-IS-NIL

  yes

WITH-OPEN-FILE-SETQ:EXPLICITLY-VAGUE

  yes

WITH-OPEN-FILE-STREAM-EXTENT:DYNAMIC-EXTENT

  yes

WITH-OUTPUT-TO-STRING-APPEND-STYLE:VECTOR-PUSH-EXTEND

  yes

WITH-STANDARD-IO-SYNTAX-READTABLE:X3J13-MAR-91

  yes

# The CLISP bytecode specification

## Last modified: 19 September 1998.

## Chapter 1. Introduction

The CLISP compiler compiles Common Lisp programs into instruction codes for a virtual processor. This bytecode is optimized for saving space in the most common cases of Common Lisp programs. The main advantages/drawbacks of this approach, compared to native code compilation, are:

- Bytecode compiled programs are a lot smaller than when compiled to native code. This results in better use of CPU caches, and in less virtual memory paging. Users perceive this as good responsiveness.

- Maximum execution speed (throughput in tight loops) is limited.

- Since no bytecode instructions are provided for "unsafe" operations (like unchecked array accesses, or "fast" `CAR`/`CDR`), programs run with all safety checks enabled even when compiled.

- Execution speed of a program can easily be understood by looking at the output of the `DISASSEMBLE` function. A rule of thumb is that every elementary instruction costs 1 time unit, whereas a function call costs 3 to 4 time units.

- Needing to do no type inference, the compiler is pretty straightforward and fast. As a consequence, the definition of CLOS generic functions, which needs to compile small pieces of generated code, is not perceived to be slow.

- The compiler is independent from the hardware CPU. Different backends, one for each hardware CPU, are not needed. As a consequence, the compiler is fairly small (and would have been easily maintainable if it were written in a less kludgy way...), and it is impossible for the compiler writer to introduce CPU dependent bugs.

## Chapter 2. The virtual machine

The bytecode can be thought of as being interpreted by a virtual processor. The engine which actually interprets the bytecode (the "implementation of the virtual machine") is actually a C function, but it could as well be a just-in-time compiler which translates a function's bytecode into hardware CPU instructions the first time said function is called.

The virtual machine is a stack machine with two stacks:

`STACK`

  a stack for Lisp objects and frames.

`SP`

  a stack for other data and pointers.

This two-stack architecture permits to save an unlimited number of Lisp objects on the `STACK` (needed for handling of Common Lisp multiple values), without consing. Also, in a world with a compacting no-ambiguous-roots garbage collector, `STACK` must only hold Lisp objects, and `SP` can hold all the other data belonging to a frame, which would not fit into `STACK` without tagging/untagging overhead.

The scope of `STACK` and `SP` is only valid for a given function invocation. Whereas the amount of `STACK` space needed for executing a function (excluding other function calls) is unlimited, the amount of `SP` space needed is known a priori, at compile time. When a function is called, no relation is specified between the caller's `STACK` and the callee's `STACK`, and between the caller's `SP` and the callee's `SP`. The bytecode is designed so that outgoing arguments on the caller's `STACK` can be shared by the caller's incoming arguments area (on the callee's `STACK`), but a virtual machine implementation may also copy outgoing arguments to incoming arguments instead of sharing them.

The virtual machine has a special data structure, `values`, containing the "top of stack", specially adapted to Common Lisp multiple values:

`mv_count`

  an unsigned integer.

`value1`

  the first value, a Lisp object. If ``mv_count`` = 0, this is `NIL`.

`mv_space`

  all values except the first one, an array of Lisp objects.

The contents of `values` is short-lived. It does not survive a function call, not even a garbage collection.

The interpretation of some bytecode instructions depends on a constant, `jmpbufsize`. This is a CPU-dependent number, the value of `system::*jmpbuf-size*`. In C, it is defined as `ceiling(sizeof(jmp_buf),sizeof(void*))`.

## Chapter 3. The structure of compiled functions

A compiled function consists of two objects: The function itself, containing the references to all Lisp objects needed for the bytecode, and a byte vector containing only immediate data, including the bytecode proper.

Typically, the byte vector is about twice as large as the function vector. The separation thus helps the garbage collector (since the byte vector does not need to be scanned for pointers).

A function looks like this (cf. the C type `Cclosure`):

name

  This is the name of the function, normally a symbol or a list of the form `(`SETF` `symbol`)`. It is used for printing the function and for error messages. This field is immutable.

`codevec`

  This is the byte vector. It is a `SIMPLE-BIT-VECTOR` (because that's the simplest type in CLISP which contains immediate data -- note that `(`SIMPLE-VECTOR` (`UNSIGNED-BYTE` 8))` is more complex than this). This field is immutable.

`consts`[]

  The remaining fields in the function object are references to other Lisp objects. These references are immutable, which is why they are called "constants". (The referenced Lisp objects can be mutable objects, such as conses or vectors, however.)

There is actually one exception to the immutability rule: When a generic function's dispatch code is installed, the `codevec` and `consts` fields are destructively modified.

Some of the `consts` can play special roles. A function looks like this, in more detail:

name

  see above

`codevec`

  see above

`venv-const`*

  At most one object, representing the closed-up variables, representing the variables of the lexical environment in which this function was defined. It is a `SIMPLE-VECTOR`, which looks like this: `#(`next` `value1` ... `valuen`)` where `value1`, ..., `valuen` are the values of the closed-up variables, and `next` is either `NIL` or a `SIMPLE-VECTOR` having the same structure.

`block-const`*

  Objects representing closed-up `BLOCK` tags, representing the `BLOCK` tags of the lexical environment in which this function was defined. Each is a `CONS` containing in the `CDR` part: either a frame pointer to the block frame, or `#<DISABLED>`. The `CAR` is the block's name, only for error message purposes.

`tagbody-const`*

  Objects representing closed-up `TAGBODY` tags, representing the `TAGBODY` tags of the lexical environment in which this function was defined. Each is a `CONS` containing in the `CDR` part: either a frame pointer to the `TAGBODY` frame, or `#<DISABLED>` if the `TAGBODY` has already been left. The `CAR` is a `SIMPLE-VECTOR` containing the names of the `TAGBODY` tags, only for the error message purposes.

`keyword-const`*

  If the function was defined with a lambda list containing `&KEY`, here come the symbols ("keywords"), in their correct order. They are used by the interpreter during function call.

`other-const`*

  Other objects needed by the function's bytecode.

If `venv-const`, `block-const`, `tagbody-const` are all absent, the function is called autonomous. This is the case if the function does not refer to lexical variables, blocks or tags defined in compile code outside of the function. In particular, it is the case if the function is defined in a null lexical environment.

If some `venv-const`, `block-const`, or `tagbody-const` are present, the function (a "closure") is created at runtime. The compiler only generates a prototype, containing `NIL` values instead of each `venv-const`, `block-const`, `tagbody-const`. At runtime, a function is created by copying this prototype and replacing the `NIL` values by the definitive ones.

The list `(`keyword-const`* `other-const`*)` normally does not contain duplicates, because the compiler removes duplicates when possible. (Duplicates can occur nevertheless, through the use of `LOAD-TIME-VALUE`.)

The `codevec` looks like this (cf. the C type `Codevec`):

`spdepth_1` (2 bytes)

  The 1st part of the maximal `SP` depth.

`spdepth_jmpbufsize` (2 bytes)

  The `jmpbufsize` part of the maximal `SP` depth. The maximal `SP` depth (precomputed by the compiler) is given by `spdepth_1 + spdepth_jmpbufsize * `jmpbufsize``.

`numreq` (2 bytes)

  Number of required parameters.

`numopt` (2 bytes)

  Number of optional parameters.

`flags` (1 byte)
  bit 0

    set if the function has an `&REST` parameter

  bit 7

    set if the function has `&KEY` parameters

  bit 6

    set if the function has `&ALLOW-OTHER-KEYS`

  bit 4

    set if the function is a generic function

  bit 3

    set if the function is a generic function and its effective method shall be returned (instead of being executed)

`signature` (1 byte)

  An abbreviation code depending on `numreq`, `numopt`, `flags`. It is used for speeding up the function call.

`numkey` (2 bytes, only if the function has `&KEY`)

  The number of `&KEY` parameters.

`keyconsts` (2 bytes, only if the function has `&KEY`)

  The offset of the `keyword-const` in the function.

`byte`* (any number of bytes)

  The bytecode instructions.

## Chapter 4. The general structure of the instructions

All instructions consist of one byte, denoting the opcode, and some number of operands.

The conversion from a byte (in the range 0..255) to the opcode is performed by lookup in the table contained in the file `bytecode.d`.

There are the following types of operands, denoted by different letters:

`k`, `n`, `m`, `l`

  A (nonnegative) numeric operand. The next byte is read. If its bit 7 is zero, then the bits 6..0 give the value (7 bits). If its bit 7 is one, then the bits 6..0 and the subsequent byte together form the value (15 bits).

`b`

  A (nonnegative) 1-byte operand. The next byte is read and is the value.

`label`

  A label operand. A signed numeric operand is read: The next byte is read. If its bit 7 is zero, then the bits 6..0 give the value (7 bits, sign-extended). If its bit 7 is one, then the bits 6..0 and the subsequent byte together form the value (15 bits, sign-extended). If the latter 15-bit result is zero, then four more bytes are read and put together (32 bits, sign-extended). Finally, the bytecode pointer for the target is computed as the current bytecode pointer (pointing after the operand just read), plus the signed numeric operand.

## Chapter 5. The instruction set

## Instructions for constants

Instructions for constants

mnemonic | description | semantics
--- | --- | ---
`(`NIL`)` | Load `NIL` into values. | `value1` := `NIL`, `mv_count` := 1
`(PUSH-NIL `n`)` | Push `n` `NIL`s into the `STACK`. | `n` times do: *--`STACK` := `NIL`, values undefined
`(`T`)` | Load `T` into values. | `value1` := `T`, `mv_count` := 1
`(CONST `n`)` | Load the function's `n`th constant into values. | `value1` := `consts`[`n`], `mv_count` := 1

## Instructions for lexical variables

Instructions for lexical variables

mnemonic | description | semantics
--- | --- | ---
`(LOAD `n`)` | Load a directly accessible local variable into values. | `value1` := *(`STACK`+`n`), `mv_count` := 1
`(LOADI `k1` `k2` `n`)` | Load an indirectly accessible local variable into values. | `k` := `k1` + `jmpbufsize` * `k2`, `value1` := *(*(`SP`+`k`)+ `n`), `mv_count` := 1
`(LOADC `n` `m`)` | Load a closed-up variable, defined in the same function and directly accessible, into values. | `value1` := `SVREF`(*(`STACK`+`n`),1+`m`), `mv_count` := 1
`(LOADV `k` `m`)` | Load a closed-up variable, defined in an outer function, into values. | `v` := `venv-const`, `m` times do: `v` := `SVREF`(`v`,0), `value1` := `SVREF`(`v`,`m`), `mv_count` := 1
`(LOADIC `k1` `k2` `n` `m`)` | Load a closed-up variable, defined in the same function and indirectly accessible, into values. | `k` := `k1` + `jmpbufsize` * `k2`, `value1` := `SVREF`(*(*(`SP`+`k`)+`n`),1+`m`), `mv_count` := 1
`(STORE `n`)` | Store values into a directly accessible local variable. | *(`STACK`+`n`) := `value1`, `mv_count` := 1
`(STOREI `k1` `k2` `n`)` | Store values into an indirectly accessible local variable. | `k` := `k1` + `jmpbufsize` * `k2`, *(*(`SP`+`k`)+ `n`) := `value1`, `mv_count` := 1
`(STOREC `n` `m`)` | Store values into a closed-up variable, defined in the same function and directly accessible. | `SVREF`(*(`STACK`+`n`),1+m) := `value1`, `mv_count` := 1
`(STOREV `k` `m`)` | Store values into a closed-up variable, defined in an outer function. | `v` := `venv-const`, `m` times do: `v` := `SVREF`(`v`,0), `SVREF`(`v`,`m`) := `value1`, `mv_count` := 1
`(STOREIC `k1` `k2` `n` `m`)` | Store values into a closed-up variable, defined in the same function and indirectly accessible. | `k` := `k1` + `jmpbufsize` * `k2`, `SVREF`(*(*(`SP`+`k`)+`n`),1+`m`) := `value1`, `mv_count` := 1

## Instructions for dynamic variables

Instructions for dynamic variables

mnemonic | description | semantics
--- | --- | ---
`(GETVALUE `n`)` | Load a symbol's value into values. | `value1` := symbol-value(`consts`[`n`]), `mv_count` := 1
`(SETVALUE `n`)` | Store values into a symbol's value. | symbol-value(`consts`[`n`]) := `value1`, `mv_count` := 1
`(BIND `n`)` | Bind a symbol dynamically. | Bind the value of the symbol `consts`[`n`] to `value1`, implicitly `STACK` -= 3, values undefined
`(UNBIND1)` | Dissolve one binding frame. | Unbind the binding frame `STACK` is pointing to, implicitly `STACK` += 3
`(UNBIND `n`)` | Dissolve `n` binding frames. | `n` times do: Unbind the binding frame `STACK` is pointing to, thereby incrementing `STACK` Thus, `STACK` += 1+2*`n`
`(PROGV)` | Bind a set of symbols dynamically to a set of values. | `symbols` := *`STACK`++, *--`SP` := `STACK`, build a single binding frame binding the symbols in `symbols` to the values in `value1`, values undefined

## Instructions for stack operations

Instructions for stack operations

mnemonic | description | semantics
--- | --- | ---
`(PUSH)` | Push one object onto the `STACK`. | *--`STACK` := `value1`, values undefined
`(POP)` | Pop one object from the `STACK`, into values. | `value1` := *`STACK`++, `mv_count` := 1
`(SKIP `n`)` | Restore a previous `STACK` pointer. Remove `n` objects from the `STACK`. | `STACK` := `STACK` + `n`
`(SKIPI `k1` `k2` `n`)` | Restore a previous `STACK` pointer. Remove an unknown number of objects from the `STACK`. | `k` := `k1` + `jmpbufsize` * `k2`, `STACK` := *(`SP`+`k`), `SP` := `SP`+`k`+1
`(SKIPSP `k1` `k2`)` | Restore a previous `SP` pointer. | `k` := `k1` + `jmpbufsize` * `k2`, `SP` := `SP`+`k`

## Instructions for control flow, jumps

Instructions for control flow, jumps

mnemonic | description | semantics
--- | --- | ---
`(SKIP&RET `n`)` | Clean up the `STACK`, and return from the function. | `STACK` := `STACK`+`n`, return from the function, returning values.
`(SKIP&RETGF `n`)` | Clean up the `STACK`, and return from the generic function. | If bit 3 is set in the function's `flags`, then `STACK` := `STACK`+`n`, `mv_count` := 1, and return from the function. Otherwise: if the current function has no `&REST` argument, then `STACK` := `STACK`+`n`-`numreq`, apply `value1` to the `numreq` arguments still on the `STACK`, and return from the function. Else `STACK` := `STACK`+`n`-`numreq`-1, apply `value1` to the `numreq` arguments and the `&REST` argument, all still on the `STACK`, and return from the function.
`(JMP `label`)` | Jump to `label`. | PC := `label`.
`(JMPIF `label`)` | Jump to `label`, if `value1` is true. | If `value1` is not `NIL`, PC := `label`.
`(JMPIFNOT `label`)` | Jump to `label`, if `value1` is false. | If `value1` is `NIL`, PC := `label`.
`(JMPIF1 `label`)` | Jump to `label` and forget secondary values, if `value1` is true. | If `value1` is not `NIL`, `mv_count` := 1, PC := `label`.
`(JMPIFNOT1 `label`)` | Jump to `label` and forget secondary values, if `value1` is false. | If `value1` is `NIL`, `mv_count` := 1, PC := `label`.
`(JMPIFATOM `label`)` | Jump to `label`, if `value1` is not a cons. | If `value1` is not a cons, PC := `label`. values undefined
`(JMPIFCONSP `label`)` | Jump to `label`, if `value1` is a cons. | If `value1` is a cons, PC := `label`. values undefined
`(JMPIFEQ `label`)` | Jump to `label`, if `value1` is `EQ` to the top-of-stack. | If eq(`value1`,*`STACK`++), PC := `label`. values undefined
`(JMPIFNOTEQ `label`)` | Jump to `label`, if `value1` is not `EQ` to the top-of-stack. | If not eq(`value1`,*`STACK`++), PC := `label`. values undefined
`(JMPIFEQTO `n` `label`)` | Jump to `label`, if the top-of-stack is `EQ` to a constant. | If eq(*`STACK`++,`consts`[`n`]), PC := `label`. values undefined
`(JMPIFNOTEQTO `n` `label`)` | Jump to `label`, if the top-of-stack is not `EQ` to a constant. | If not eq(*`STACK`++,`consts`[`n`]), PC := `label`. values undefined
`(JMPHASH `n` `label`)` | Table-driven jump, depending on `value1`. | Lookup `value1` in the hash table `consts`[`n`]. (The hash table's test is either `EQ` or `EQL`.) If found, the hash table value is a signed `FIXNUM`, jump to it: PC := PC + value. Else jump to `label`. values undefined
`(JMPHASHV `n` `label`)` | Table-driven jump, depending on `value1`, inside a generic function. | Lookup `value1` in the hash table `SVREF`(`consts`[0],`n`). (The hash table's test is either `EQ` or `EQL`.) If found, the hash table value is a signed `FIXNUM`, jump to it: PC := PC + value. Else jump to `label`. values undefined
`(JSR `label`)` | Subroutine call. | *--`STACK` := function. Then start interpreting the bytecode at `label`, with values undefined. When a `(RET)` is encountered, program execution is resumed at the instruction after `(JSR `label`)`.
`(JMPTAIL `m` `n` `label`)` | Tail subroutine call. | `n` >= `m`. The `STACK` frame of size `n` is reduced to size `m`: {*(`STACK`+`n`-`m`), ..., *(`STACK`+`n`-1)} := {*`STACK`, ..., *(`STACK`+`m`-1)}. `STACK` += n-m. *--`STACK` := function. Then jump to `label`, with values undefined.

## Instructions for lexical environment, creation of closures

Instructions for lexical environment, creation of closures

mnemonic | description | semantics
--- | --- | ---
`(VENV)` | Load the `venv-const` into values. | `value1` := `consts`[0], `mv_count` := 1.
`(MAKE-VECTOR1&PUSH `n`)` | Create a simple-vector used for closed-up variables. | `v` := new simple-vector of size `n`+1. `SVREF`(`v`,0) := `value1`. *--`STACK` := `v`. values undefined
`(COPY-CLOSURE `m` `n`)` | Create a closure by copying the prototype and filling in the lexical environment. | `f` := copy-function(`consts`[`m`]). For `i`=0,..,`n`-1: `f`_`consts`[i] := *(`STACK`+`n`-1-`i`). `STACK` += `n`. `value1` := `f`, `mv_count` := 1

## Instructions for function calls

Instructions for function calls

mnemonic | description | semantics
--- | --- | ---
`(CALL `k` `n`)` | Calls a constant function with `k` arguments. | The function `consts`[`n`] is called with the arguments *(`STACK`+`k`-1), ..., *(`STACK`+0). `STACK` += `k`. The returned values go into values.
`(CALL0 `n`)` | Calls a constant function with 0 arguments. | The function `consts`[`n`] is called with 0 arguments. The returned values go into values.
`(CALL1 `n`)` | Calls a constant function with 1 argument. | The function `consts`[`n`] is called with one argument *`STACK`. `STACK` += 1. The returned values go into values.
`(CALL2 `n`)` | Calls a constant function with 2 arguments. | The function `consts`[`n`] is called with two arguments *(`STACK`+1) and *(`STACK`+0). `STACK` += 2. The returned values go into values.
`(CALLS1 `b`)` | Calls a system function with no `&REST`. | Calls the system function FUNTAB[`b`]. The right number of arguments is already on the `STACK` (including `#<UNBOUND>`s in place of absent `&OPTIONAL` or `&KEY` parameters). The arguments are removed from the `STACK`. The returned values go into values.
`(CALLS2 `b`)` | Calls a system function with no `&REST`. | Calls the system function FUNTAB[256+`b`]. The right number of arguments is already on the `STACK` (including `#<UNBOUND>`s in place of absent `&OPTIONAL` or `&KEY` parameters). The arguments are removed from the `STACK`. The returned values go into values.
`(CALLSR `m` `b`)` | Calls a system function with `&REST`. | Calls the system function FUNTABR[`b`]. The minimum number of arguments is already on the `STACK`, and `m` additional arguments as well. The arguments are removed from the `STACK`. The returned values go into values.
`(CALLC)` | Calls a computed compiled function with no `&KEY`. | Calls the compiled function `value1`. The right number of arguments is already on the `STACK` (including `#<UNBOUND>`s in place of absent `&OPTIONAL` parameters). The arguments are removed from the `STACK`. The returned values go into values.
`(CALLCKEY)` | Calls a computed compiled function with `&KEY`. | Calls the compiled function `value1`. The right number of arguments is already on the `STACK` (including `#<UNBOUND>`s in place of absent `&OPTIONAL` or `&KEY` parameters). The arguments are removed from the `STACK`. The returned values go into values.
`(FUNCALL `n`)` | Calls a computed function. | Calls the function *(`STACK`+`n`) with the arguments *(`STACK`+`n`-1), ..., *(`STACK`+0). `STACK` += `n`+1. The returned values go into values.
`(APPLY `n`)` | Calls a computed function with an unknown number of arguments. | Calls the function *(`STACK`+`n`) with the arguments *(`STACK`+`n`-1), ..., *(`STACK`+0) and a list of additional arguments `value1`. `STACK` += `n`+1. The returned values go into values.

## Instructions for optional and keyword parameters

Instructions for optional and keyword parameters

mnemonic | description | semantics
--- | --- | ---
`(PUSH-UNBOUND `n`)` | Push `n``#<UNBOUND>`s into the `STACK`. | `n` times do: *--`STACK` := `#<UNBOUND>`. values undefined
`(UNLIST `n` `m`)` | Destructure a proper list. | 0 ≤ `m` ≤ `n`. `n` times do: *--`STACK` := `CAR`(`value1`), `value1` := `CDR`(`value1`). During the last `m` iterations, the list `value1` may already have reached its end; in this case, *--`STACK` := `#<UNBOUND>`. At the end, `value1` must be `NIL`. values undefined
`(UNLIST* `n` `m`)` | Destructure a proper or dotted list. | 0 ≤ `m` ≤ `n`, `n` > 0. `n` times do: *--`STACK` := `CAR`(`value1`), `value1` := `CDR`(`value1`). During the last `m` iterations, the list `value1` may already have reached its end; in this case, *--`STACK` := `#<UNBOUND>`. At the end, after `n` `CDR`s, *--`STACK` := `value1`. values undefined
`(JMPIFBOUNDP `n` `label`)` | Jump to `label`, if a local variable is not unbound. | If *(`STACK`+`n`) is not `#<UNBOUND>`, `value1` := *(`STACK`+`n`), `mv_count` := 1, PC := `label`. Else: values undefined.
`(BOUNDP `n`)` | Load `T` or `NIL` into values, depending on whether a local variable is bound. | If *(`STACK`+`n`) is not `#<UNBOUND>`, `value1` := `T`, `mv_count` := 1. Else: `value1` := `NIL`, `mv_count` := 1.
`(UNBOUND->NIL `n`)` | If a local variable is unbound, assign a default value `NIL` to it. | If *(`STACK`+`n`) is `#<UNBOUND>`, *(`STACK`+`n`) := `NIL`.

## Instructions for multiple values

Instructions for multiple values

mnemonic | description | semantics
--- | --- | ---
`(VALUES0)` | Load no values into values. | `value1` := `NIL`, `mv_count` := 0
`(VALUES1)` | Forget secondary values. | `mv_count` := 1
`(`STACK`-TO-MV `n`)` | Pop the first `n` objects from `STACK` into values. | Load values(*(`STACK`+`n`-1),...,*(`STACK`+0)) into values. `STACK` += `n`.
`(MV-TO-`STACK`)` | Save values on `STACK`. | Push the `mv_count` values onto the `STACK` (in order: `value1` comes first). `STACK` -= `mv_count`. values undefined
`(NV-TO-`STACK` `n`)` | Save `n` values on `STACK`. | Push the first `n` values onto the `STACK` (in order: `value1` comes first). `STACK` -= `n`. values undefined
`(MV-TO-LIST)` | Convert multiple values into a list. | `value1` := list of values, `mv_count` := 1
`(LIST-TO-MV)` | Convert a list into multiple values. | Call the function `VALUES-LIST` with `value1` as argument. The returned values go into values.
`(MVCALLP)` | Start a `MULTIPLE-VALUE-CALL` invocation. | *--`SP` := `STACK`. *--`STACK` := `value1`.
`(MVCALL)` | Finish a `MULTIPLE-VALUE-CALL` invocation. | newSTACK := *`SP`++. Call the function *(newSTACK-1), passing it *(newSTACK-2), ..., *(`STACK`+0) as arguments. `STACK` := newSTACK. The returned values go into values.

## Instructions for `BLOCK` and `RETURN-FROM`

Instructions for `BLOCK` and `RETURN-FROM`

mnemonic | description | semantics
--- | --- | ---
`(BLOCK-OPEN `n` `label`)` | Create a `BLOCK` frame. | Create a `BLOCK` frame, `STACK` -= 3, `SP` -= 2+`jmpbufsize`. The topmost (third) object in the block frame is `CONS`(`consts`[`n`],frame-pointer) (its `block-cons`). Upon a `RETURN-FROM` to this frame, execution will continue at `label`.
`(BLOCK-CLOSE)` | Dissolve a `BLOCK` frame. | Dissolve the `BLOCK` frame at `STACK`, `STACK` += 3, `SP` += 2+`jmpbufsize`. Mark the `block-cons` as invalid.
`(RETURN-FROM `n`)` | Leave a `BLOCK` whose `block-cons` is given. | `block-cons` := `consts`[`n`]. If `CDR`(`block-cons`) = `#<DISABLED>`, signal an error. Else `CDR`(`block-cons`) is a frame-pointer. Unwind the stack up to this frame, pass it values.
`(RETURN-FROM-I `k1` `k2` `n`)` | Leave a `BLOCK` whose `block-cons` is indirectly accessible. | `k` := `k1` + `jmpbufsize` * `k2`, `block-cons` := *(*(`SP`+`k`)+`n`). If `CDR`(`block-cons`) = `#<DISABLED>`, signal an error. Else `CDR`(`block-cons`) is a frame-pointer. Unwind the stack up to this frame, pass it values.

## Instructions for `TAGBODY` and `GO`

Instructions for `TAGBODY` and `GO`

mnemonic | description | semantics
--- | --- | ---
`(TAGBODY-OPEN `n` `label1` ... `labelm`)` | Create a tagbody frame. | Fetch `consts`[`n`], this is a `SIMPLE-VECTOR` with `m` elements, then decode `m` label operands. Create a `TAGBODY` frame, `STACK` -= 3+`m`, `SP` -= 1+`jmpbufsize`. The third object in the tagbody frame is `CONS`(`consts`[`n`],frame-pointer) (the `tagbody-cons`) Upon a `GO` to tag `label` of this frame, execution will continue at `labell`. values undefined
`(TAGBODY-CLOSE-NIL)` | Dissolve a tagbody frame, and load `NIL` into values. | Dissolve the tagbody frame at `STACK`, `STACK` += 3+`m`, `SP` += 1+`jmpbufsize`. Mark the `tagbody-cons` as invalid. `value1` := `NIL`, `mv_count` := 1.
`(TAGBODY-CLOSE)` | Dissolve a tagbody frame. | Dissolve the tagbody frame at `STACK`, `STACK` += 3+`m`, `SP` += 1+`jmpbufsize`. Mark the `tagbody-cons` as invalid.
`(GO `n` `label`)` | Jump into a tagbody whose `tagbody-cons` is given. | `tagbody-cons` := `consts`[`n`]. If `CDR`(`tagbody-cons`) = `#<DISABLED>`, signal an error. Else `CDR`(`tagbody-cons`) is a frame-pointer. Unwind the stack up to this frame, pass it the number `label`.
`(GO-I `k1` `k2` `n` `label`)` | Jump into a tagbody whose `tagbody-cons` is indirectly accessible. | `k` := `k1` + `jmpbufsize` * `k2`, `tagbody-cons` := *(*(`SP`+`k`)+`n`). If `CDR`(`tagbody-cons`) = `#<DISABLED>`, signal an error. Else `CDR`(`tagbody-cons`) is a frame-pointer. Unwind the stack up to this frame, pass it the number `label`.

## Instructions for `CATCH` and `THROW`

Instructions for `CATCH` and `THROW`

mnemonic | description | semantics
--- | --- | ---
`(CATCH-OPEN `label`)` | Create a `CATCH` frame. | Create a `CATCH` frame, with `value1` as tag. `STACK` -= 3, `SP` -= 2+`jmpbufsize`. Upon a `THROW` to this tag execution continues at `label`.
`(CATCH-CLOSE)` | Dissolve a `CATCH` frame. | Dissolve the `CATCH` frame at `STACK`. `STACK` += 3, `SP` += 2+`jmpbufsize`.
`(THROW)` | Non-local exit to a `CATCH` frame. | `tag` := *`STACK`++. Search the innermost `CATCH` frame with tag `tag` on the `STACK`, unwind the stack up to it, pass it values.

## Instructions for `UNWIND-PROTECT`

Instructions for `UNWIND-PROTECT`

mnemonic | description | semantics
--- | --- | ---
`(UNWIND-PROTECT-OPEN `label`)` | Create an `UNWIND-PROTECT` frame. | Create an `UNWIND-PROTECT` frame. `STACK` -= 2, `SP` -= 2+`jmpbufsize`. When the stack will be unwound by a non-local exit, values will be saved on `STACK`, and execution will be transferred to `label`.
`(UNWIND-PROTECT-NORMAL-EXIT)` | Dissolve an `UNWIND-PROTECT` frame, and start the cleanup code. | Dissolve the `UNWIND-PROTECT` frame at `STACK`. `STACK` += 2, `SP` += 2+`jmpbufsize`. *--`SP` := 0, *--`SP` := 0, *--`SP` := `STACK`. Save the values on the `STACK`, `STACK` -= `mv_count`.
`(UNWIND-PROTECT-CLOSE)` | Terminate the cleanup code. | newSTACK := *`SP`++. Load values(*(newSTACK-1), ..., *(`STACK`+0)) into values. `STACK` := newSTACK. SPword1 := *`SP`++, SPword2 := *`SP`++. Continue depending on SPword1 and SPword2. If both are 0, simply continue execution. If SPword2 is 0 but SPword1 is nonzero, interpret it as a label and jump to it.
`(UNWIND-PROTECT-CLEANUP)` | Dissolve an `UNWIND-PROTECT` frame, and execute the cleanup code like a subroutine call. | Dissolve the `UNWIND-PROTECT` frame at `STACK`, get `label` out of the frame. `STACK` += 2, `SP` += 2+`jmpbufsize`. *--`SP` := 0, *--`SP` := PC, *--`SP` := `STACK`. Save the values on the `STACK`, `STACK` -= `mv_count`. PC := `label`.

## Instructions for `HANDLER-BIND`

Instructions for `HANDLER-BIND`

mnemonic | description | semantics
--- | --- | ---
`(HANDLER-OPEN `n`)` | Create a handler frame. | Create a handler frame, using `consts`[`n`] which contains the condition types, the corresponding labels and the current `SP` depth (= function entry `SP` - current `SP`).
`(HANDLER-BEGIN&PUSH)` | Start a handler. | Restore the same `SP` state as after the HANDLER-OPEN. `value1` := the condition that was passed to the handler, `mv_count` := 1. *--`STACK` := `value1`.

## Instructions for some inlined functions

Instructions for some inlined functions

mnemonic | description | semantics
--- | --- | ---
`(NOT)` | Inlined call to NOT. | `value1` := not(`value1`), `mv_count` := 1.
`(EQ)` | Inlined call to EQ. | `value1` := eq(*`STACK`++,`value1`), `mv_count` := 1.
`(CAR)` | Inlined call to `CAR`. | `value1` := `CAR`(`value1`), `mv_count` := 1.
`(CDR)` | Inlined call to `CDR`. | `value1` := `CDR`(`value1`), `mv_count` := 1.
`(CONS)` | Inlined call to `CONS`. | `value1` := cons(*`STACK`++,`value1`), `mv_count` := 1.
`(SYMBOL-FUNCTION)` | Inlined call to `SYMBOL-FUNCTION`. | `value1` := `SYMBOL-FUNCTION`(`value1`), `mv_count` := 1.
`(SVREF)` | Inlined call to `SVREF`. | `value1` := `SVREF`(*`STACK`++,`value1`), `mv_count` := 1.
`(SVSET)` | Inlined call to SYSTEM::SVSTORE. | `arg1` := *(`STACK`+1), `arg2` := *(`STACK`+0), `STACK` += 2. `SVREF`(`arg2`,`value1`) := `arg1`. `value1` := `arg1`, `mv_count` := 1.
`(LIST `n`)` | Inlined call to `LIST`. | `value1` := `LIST`(*(`STACK`+`n`-1),...,*(`STACK`+0)), `mv_count` := 1, `STACK` += `n`.
`(LIST* `n`)` | Inlined call to `LIST*`. | `value1` := `LIST*`(*(`STACK`+`n`-1),..., *(`STACK`+0),`value1`), `mv_count` := 1, `STACK` += `n`.

## Combined instructions

The most frequent short sequences of instructions have an equivalent combined instruction. They are only present for space and speed optimization. The only exception is `FUNCALL&SKIP&RETGF`, which is needed for generic functions.

Combined instructions

mnemonic | equivalent
--- | ---
`(NIL&PUSH)` | `(NIL) (PUSH)`
`(T&PUSH)` | `(T) (PUSH)`
`(CONST&PUSH `n`)` | `(CONST `n`) (PUSH)`
`(LOAD&PUSH `n`)` | `(LOAD `n`) (PUSH)`
`(LOADI&PUSH `k1` `k2` `n`)` | `(LOADI `k1` `k2` `n`) (PUSH)`
`(LOADC&PUSH `n` `m`)` | `(LOADC `n` `m`) (PUSH)`
`(LOADV&PUSH `k` `m`)` | `(LOADV `k` `m`) (PUSH)`
`(POP&STORE `n`)` | `(POP) (STORE `n`)`
`(GETVALUE&PUSH `n`)` | `(GETVALUE `n`) (PUSH)`
`(JSR&PUSH `label`)` | `(JSR `label`) (PUSH)`
`(COPY-CLOSURE&PUSH `m` `n`)` | `(COPY-CLOSURE `m` `n`) (PUSH)`
`(CALL&PUSH `k` `n`)` | `(CALL `k` `n`) (PUSH)`
`(CALL1&PUSH `n`)` | `(CALL1 `n`) (PUSH)`
`(CALL2&PUSH `n`)` | `(CALL2 `n`) (PUSH)`
`(CALLS1&PUSH `b`)` | `(CALLS1 `b`) (PUSH)`
`(CALLS2&PUSH `b`)` | `(CALLS2 `b`) (PUSH)`
`(CALLSR&PUSH `m` `n`)` | `(CALLSR `m` `n`) (PUSH)`
`(CALLC&PUSH)` | `(CALLC) (PUSH)`
`(CALLCKEY&PUSH)` | `(CALLCKEY) (PUSH)`
`(FUNCALL&PUSH `n`)` | `(FUNCALL `n`) (PUSH)`
`(APPLY&PUSH `n`)` | `(APPLY `n`) (PUSH)`
`(CAR&PUSH)` | `(CAR) (PUSH)`
`(CDR&PUSH)` | `(CDR) (PUSH)`
`(CONS&PUSH)` | `(CONS) (PUSH)`
`(LIST&PUSH `n`)` | `(LIST `n`) (PUSH)`
`(LIST*&PUSH `n`)` | `(LIST* `n`) (PUSH)`
`(NIL&STORE `n`)` | `(NIL) (STORE `n`)`
`(T&STORE `n`)` | `(T) (STORE `n`)`
`(LOAD&STOREC `k` `n` `m`)` | `(LOAD `k`) (STOREC `n` `m`)`
`(CALLS1&STORE `b` `k`)` | `(CALLS1 `b`) (STORE `k`)`
`(CALLS2&STORE `b` `k`)` | `(CALLS2 `b`) (STORE `k`)`
`(CALLSR&STORE `m` `n` `k`)` | `(CALLSR `m` `n`) (STORE `k`)`
`(LOAD&CDR&STORE `n`)` | `(LOAD `n`) (CDR) (STORE `n`)`
`(LOAD&CONS&STORE `n`)` | `(LOAD `n`+1) (CONS) (STORE `n`)`
`(LOAD&INC&STORE `n`)` | `(LOAD `n`) (CALL1 #'1+) (STORE `n`)`
`(LOAD&DEC&STORE `n`)` | `(LOAD `n`) (CALL1 #'1-) (STORE `n`)`
`(LOAD&CAR&STORE `m` `n`)` | `(LOAD `m`) (CAR) (STORE `n`)`
`(CALL1&JMPIF `n` `label`)` | `(CALL1 `n`) (JMPIF `label`)`
`(CALL1&JMPIFNOT `n` `label`)` | `(CALL1 `n`) (JMPIFNOT `label`)`
`(CALL2&JMPIF `n` `label`)` | `(CALL2 `n`) (JMPIF `label`)`
`(CALL2&JMPIFNOT `n` `label`)` | `(CALL2 `n`) (JMPIFNOT `label`)`
`(CALLS1&JMPIF `b` `label`)` | `(CALLS1 `b`) (JMPIF `label`)`
`(CALLS1&JMPIFNOT `b` `label`)` | `(CALLS1 `b`) (JMPIFNOT `label`)`
`(CALLS2&JMPIF `b` `label`)` | `(CALLS2 `b`) (JMPIF `label`)`
`(CALLS2&JMPIFNOT `b` `label`)` | `(CALLS2 `b`) (JMPIFNOT `label`)`
`(CALLSR&JMPIF `m` `n` `label`)` | `(CALLSR `m` `n`) (JMPIF `label`)`
`(CALLSR&JMPIFNOT `m` `n` `label`)` | `(CALLSR `m` `n`) (JMPIFNOT `label`)`
`(LOAD&JMPIF `n` `label`)` | `(LOAD `n`) (JMPIF `label`)`
`(LOAD&JMPIFNOT `n` `label`)` | `(LOAD `n`) (JMPIFNOT `label`)`
`(LOAD&CAR&PUSH `n`)` | `(LOAD `n`) (CAR) (PUSH)`
`(LOAD&CDR&PUSH `n`)` | `(LOAD `n`) (CDR) (PUSH)`
`(LOAD&INC&PUSH `n`)` | `(LOAD `n`) (CALL1 #'1+) (PUSH)`
`(LOAD&DEC&PUSH `n`)` | `(LOAD `n`) (CALL1 #'1-) (PUSH)`
`(CONST&SYMBOL-FUNCTION `n`)` | `(CONST `n`) (SYMBOL-FUNCTION)`
`(CONST&SYMBOL-FUNCTION&PUSH `n`)` | `(CONST `n`) (SYMBOL-FUNCTION) (PUSH)`
`(CONST&SYMBOL-FUNCTION&STORE `n` `k`)` | `(CONST `n`) (SYMBOL-FUNCTION) (STORE `k`)`
`(APPLY&SKIP&RET `n` `k`)` | `(APPLY `n`) (SKIP&RET `k`)`
`(FUNCALL&SKIP&RETGF `n` `k`)` | `(FUNCALL `n`) (SKIP&RETGF `k`)`

## Shortcut instructions

There are special one-byte instructions (without explicit operands) for the following frequent instructions:

Shortcut instructions

mnemonic | operand range
--- | ---
`(LOAD `n`)` | 0 ≤ `n` < 15
`(LOAD&PUSH `n`)` | 0 ≤ `n` < 25
`(CONST `n`)` | 0 ≤ `n` < 21
`(CONST&PUSH `n`)` | 0 ≤ `n` < 30
`(STORE `n`)` | 0 ≤ `n` < 8

# Extensions

## Chapter 1. Extensions-1: Platform independent Extensions

## Extensions-1.1. Saving an Image

The function `(`ext:saveinitmem` `&OPTIONAL` (`filename` "lispinit.mem") `&KEY` :quiet :init-function)` saves the running CLISP's memory to a file. If the `:quiet` argument is not `NIL`, the startup banner and the good-bye message will be suppressed. The `:init-function` argument specifies a function that will be executed at startup of the saved image. The starting package of the new image is the one in which you were when you invoked `ext:saveinitmem`.

## Extensions-1.2. Quitting Lisp

The functions `(`ext:exit` [`errorp`])`, `(`ext:quit` [`errorp`])` and `(`ext:bye` [`errorp`])` - all synonymous - terminate CLISP. If `errorp` is non-`NIL`, CLISP aborts with error status, i.e., the environment is informed that the CLISP session did not succeed.

## Extensions-1.3. The Language

The language CLISP uses to communicate with the user can be either `ENGLISH` or `DEUTSCH` (i.e., German) or `FRANCAIS` (i.e., French) or `ESPAÑOL` (i.e., Spanish). More languages can be defined through the macro `i18n:deflanguage`: `(`i18n:deflanguage` `lang`)`. For such an additional language to take effect, you must install the corresponding message catalog, or translate the messages yourself, using GNU gettext and Emacs po-mode.

The macros `ENGLISH`, `DEUTSCH`, `FRANCAIS` produce strings that depends on the language: `(ENGLISH `english-string` DEUTSCH `deutsch-string` FRANCAIS `francais-string`)` - and all permutations of this - evaluates all of `english-string`, `deutsch-string`, `francais-string` in no particular order and returns the evaluation result corresponding to the user language, be it among these three or not.

This works only for strings. For arbitrary language-dependent Lisp objects, you define one through the macro `i18n:definternational`: `(`i18n:definternational` `symbol` `&OPTIONAL` (`default-language` `T`))` and add language-dependent values through the macro `i18n:deflocalized`: `(`i18n:deflocalized` `symbol` `language` `value-form`)`

(One such form for each language. Languages without an assigned value will be treated like the default-language.) You can then access the localized value by calling `i18n:localized`: `(`i18n:localized` `symbol` `&OPTIONAL` `language`)`

## Extensions-1.4. Encodings

### Introduction

An encoding describes the correspondence between `CHARACTER`s and raw bytes during input/output via `STREAM`s with `STREAM-ELEMENT-TYPE` `CHARACTER`.

An encoding is an object composed of the following facets:

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

- A line terminator mode. This denotes the way newline characters are represented.

### Character Sets

Platform dependent: Only in CLISP built without compile-time flag UNICODE.

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

Platform dependent: Only in CLISP built with compile-time flag UNICODE.

  The following character sets are supported, as values of the corresponding (constant) symbol in the “CHARSET” package:

  - `UCS-2` = `UNICODE-16` = `UNICODE-16-BIG-ENDIAN`, the 16-bit Unicode character set. Every character is represented as two bytes.

  - `UNICODE-16-LITTLE-ENDIAN`

  - `UCS-4` = `UNICODE-32` = `UNICODE-32-BIG-ENDIAN`, the 32-bit Unicode character set. Every character is represented as four bytes. Note that CLISP understands only those characters which are already contained in the 16-bit Unicode character set.

  - `UNICODE-32-LITTLE-ENDIAN`

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

  - `UTF-16`, the 16-bit Unicode character set. Every character is represented as two bytes.

  - `UTF-7`, the 16-bit Unicode character set. This is a stateful 7-bit encoding. Not all ASCII characters represent themselves.

  - `JAVA`, the 16-bit Unicode character set. ASCII characters represent themselves and need one byte per character. All other characters are represented by `\u`nnnn`` sequences (`nnnn` a hexadecimal number) and need 6 bytes per character. While this encoding is very comfortable for editing Unicode files using only ASCII aware tools and editors, it cannot faithfully represent all Unicode text. Only text which does not contain `\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).

  - `ISO-8859-1`, an extension of the ASCII character set, suitable for the Afrikaans, Albanian, Basque, Breton, Catalan, Cornish, Danish, Dutch, English, Faeroese, Finnish, French, Frisian, Galician, German, Greenlandic, Icelandic, Irish, Italian, Latin, Luxemburgish, Norwegian, Portuguese, Raeto-Romanic, Scottish, Spanish, and Swedish languages.

  - `ISO-8859-2`, an extension of the ASCII character set, suitable for the Croatian, Czech, German, Hungarian, Polish, Slovak, Slovenian, and Sorbian languages.

  - `ISO-8859-3`, an extension of the ASCII character set, suitable for the Esperanto and Maltese languages.

  - `ISO-8859-4`, an extension of the ASCII character set, suitable for the Estonian, Latvian, Lithuanian and Sami (Lappish) languages.

  - `ISO-8859-5`, an extension of the ASCII character set, suitable for the Bulgarian, Byelorussian, Macedonian, Russian, Serbian, and Ukrainian languages.

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

  - `ISO-8859-7`, an extension of the ASCII character set, suitable for the Greek language.

  - `ISO-8859-8`, an extension of the ASCII character set, suitable for the Hebrew language (without punctuation).

  - `ISO-8859-9`, an extension of the ASCII character set, suitable for the Turkish language.

  - `ISO-8859-10`, an extension of the ASCII character set, suitable for the Estonian, Icelandic, Inuit (Greenlandic), Latvian, Lithuanian, and Sami (Lappish) languages.

  - `ISO-8859-13`, an extension of the ASCII character set, suitable for the Estonian, Latvian, Lithuanian, Polish and Sami (Lappish) languages.

  - `ISO-8859-14`, an extension of the ASCII character set, suitable for Irish Gaelic, Manx Gaelic, Scottish Gaelic, and Welsh languages.

  - `ISO-8859-15`, an extension of the ASCII character set, suitable for the ISO-8859-1 languages, with improvements for French, Finnish and the Euro.

  - `ISO-8859-16` an extension of the ASCII character set, suitable for the Rumanian language.

  - `KOI8-R`, an extension of the ASCII character set, a popular character set for the Russian language.

  - `KOI8-U`, an extension of the ASCII character set, a popular character set for the Ukrainian language.

  - `KOI8-RU`, an extension of the ASCII character set, suitable for Russian (this is the standard Russian encoding on the Internet)

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

  - `MAC-ARABIC`, a platform specific extension of the ASCII character set.

  - `MAC-CENTRAL-EUROPE`, a platform specific extension of the ASCII character set.

  - `MAC-CROATIAN`, a platform specific extension of the ASCII character set.

  - `MAC-CYRILLIC`, a platform specific extension of the ASCII character set.

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

  - `MAC-GREEK`, a platform specific extension of the ASCII character set.

  - `MAC-HEBREW`, a platform specific extension of the ASCII character set.

  - `MAC-ICELAND`, a platform specific extension of the ASCII character set.

  - `MAC-ROMAN` = `MACINTOSH`, a platform specific extension of the ASCII character set.

  - `MAC-ROMANIA`, a platform specific extension of the ASCII character set.

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

  - `MAC-THAI`, a platform specific extension of the ASCII character set.

  - `MAC-TURKISH`, a platform specific extension of the ASCII character set.

  - `MAC-UKRAINE`, a platform specific extension of the ASCII character set.

  - `CP437`, a DOS oldie, a platform specific extension of the ASCII character set.

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

  - `CP737`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Greek language.

  - `CP775`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for some Baltic languages.

  - `CP850`, a DOS oldie, a platform specific extension of the ASCII character set.

  - `CP852`, a DOS oldie, a platform specific extension of the ASCII character set.

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

  - `CP855`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Russian language.

  - `CP857`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Turkish language.

  - `CP860`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Portuguese language.

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

  - `CP861`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Icelandic language.

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

  - `CP862`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Hebrew language.

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

  - `CP863`, a DOS oldie, a platform specific extension of the ASCII character set.

  - `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, a platform specific extension of the ASCII character set, meant to be suitable for some Nordic languages.

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

  - `CP866`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Russian language.

  - `CP869`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Greek language.

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

  - `CP874`, a DOS oldie, a platform specific extension of the ASCII character set, meant to be suitable for the Thai language.

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

  - `WINDOWS-1250` = `CP1250`, a platform specific extension of the ASCII character set, heavily incompatible with ISO-8859-2.

  - `WINDOWS-1251` = `CP1251`, a platform specific extension of the ASCII character set, 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`, a platform specific extension of the ASCII character set, 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`, a platform specific extension of the ASCII character set, gratuitously incompatible with ISO-8859-8, suitable for the Hebrew language.

  - `WINDOWS-1256` = `CP1256`, a platform specific extension of the ASCII character set, meant to be suitable for the Arabic language.

  - `WINDOWS-1257` = `CP1257`, a platform specific extension of the ASCII character set.

  - `WINDOWS-1258` = `CP1258`, a platform specific extension of the ASCII character set.

  - `HP-ROMAN8`, a platform specific extension of the ASCII character set.

  - `NEXTSTEP`, a platform specific extension of the ASCII character set.

  - `EUC-JP`, a multibyte character set for the Japanese language.

  - `SHIFT-JIS`, a multibyte character set for the Japanese language.

  - `CP932`, a Microsoft variant of `SHIFT-JIS`.

  - `ISO-2022-JP`, a stateful 7-bit multibyte character set for the Japanese language.

  - `ISO-2022-JP-2`, a stateful 7-bit multibyte character set for the Japanese language.

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

  - `EUC-CN`, a multibyte character set for simplified Chinese.

  - `HZ`, a stateful 7-bit multibyte character set for simplified Chinese.

  - `GBK`, a multibyte character set for Chinese,

  - `CP936`, a Microsoft variant of `GBK`.

  - `GB18030`, a multibyte character set for Chinese,

  - `EUC-TW`, a multibyte character set for traditional Chinese.

  - `BIG5`, a multibyte character set for traditional Chinese.

  - `CP950`, a Microsoft variant of `BIG5`.

  - `BIG5HKSCS`, a multibyte character set for traditional Chinese.

  - `ISO-2022-CN`, a stateful 7-bit multibyte character set for Chinese.

  - `ISO-2022-CN-EXT`, a stateful 7-bit multibyte character set for Chinese.

  - `EUC-KR`, a multibyte character set for Korean.

  - `CP949`, a Microsoft variant of `EUC-KR`.

  - `ISO-2022-KR`, a stateful 7-bit multibyte character set for Korean.

  - `ARMSCII-8`, an extension of the ASCII character set, suitable for Armenian.

  - `GEORGIAN-ACADEMY`, an extension of the ASCII character set, suitable for Georgian.

  - `GEORGIAN-PS`, an extension of the ASCII character set, suitable for Georgian.

  - `TIS-620`, an extension of the ASCII character set, suitable for Thai.

  - `MULELAO-1`, an extension of the ASCII character set, suitable for Laotian.

  - `CP1133`, an extension of the ASCII character set, suitable for Laotian.

  - `VISCII`, an extension of the ASCII character set, suitable for Vietnamese.

  - `TCVN`, an extension of the ASCII character set, suitable for Vietnamese.

  CLISP comes with it own implementation of `iconv()`, so the following is more or less obsolete now. (Platform dependent: Only on UNIX systems having the C library function iconv()).

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

    These encodings are not assigned to global variables, since there is no portable way to get the list of all character sets supported by `iconv()`.

    On Linux and GNU systems, you get this list by calling the program iconv: iconv --list. GNU glibc-2.1 supports in particular, among others:

    - `EUC-JP` and `SHIFT-JIS`, for the Japanese language,

    - `EUC-CN`, `EUC-TW`, `BIG5` and `GB`, for the Chinese language,

    - `EUC-KR` and `ISO-2022-KR`, for the Korean language.

    HP-UX systems support in particular, among others:

    - `eucJP` and `sjis`, for the Japanese language,

    - `eucTW`, `big5` and `chinese-gb`, for the Chinese language,

    - `eucKR`, for the Korean language.

    AIX 4.2 systems support in particular, among others:

    - `IBM-eucJP`, for the Japanese language,

    - `IBM-eucTW`, for the Chinese language,

    - `IBM-eucKR`, for the Korean language.

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

    On IRIX systems, you can forget about iconv-based encodings as well, because all the interesting possible encodings are already built-in.

    On OSF/1 systems, iconv-based encodings are not usable at all.

    When an encoding is available as a built-in (see the list above) and through iconv(), the built-in is preferred, because it is more efficient and available across platforms.

### Line Terminators

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

keyword: `:unix`

newline representation: Newline is represented by the ASCII LF character (U000A).

keyword: `:mac`

newline representation: Newline is represented by the ASCII CR character (U000D).

keyword: `:dos`

newline representation: Newline is represented by ASCII CR followed by ASCII LF.

Windows programs typically use the `:dos` line terminator, sometimes they also accept `:unix` line terminators or produce `:mac` 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, CR and CR/LF, you have to resort to binary input (function `READ-BYTE`).

See also 13.1.8 Treatment of Newline during Input and Output.

### ext:make-encoding

The function `(`ext:make-encoding` `&KEY` :charset :line-terminator :input-error-action :output-error-action)` returns an encoding. The `:charset` argument may be an encoding, a string, or `:default`. The possible values for the `:line-terminator` argument are the keywords `:unix`, `:mac`, `:dos`.

The `:input-error-action` specifies what happens when an invalid byte sequence is encountered while converting bytes to characters. Its value can be `:error`, `:ignore` or a character to be used instead. The Unicode character #\uFFFD is typically used to indicate an error in the input sequence.

The `:output-error-action` specifies what happens when an invalid character is encountered while converting characters to bytes. Its value can be `:error`, `:ignore`, a byte to be used instead, or a character to be used instead. The Unicode character #\uFFFD can be used here only if it is encodable in the character set.

Encodings are types. As such, they represent the set of characters encodable in the character set. In this context, the way characters are translated into raw bytes is ignored, and the line terminator mode is ignored as well. `TYPEP` and `SUBTYPEP` can be used on encodings.

Besides every file/pipe/socket stream containing an encoding, the following `symbol-macro` places contain global encodings:

`custom:*default-file-encoding*` is the encoding used for new file/pipe/socket streams, when no `:external-format` argument was specified.

Platform dependent: Only in CLISP built with compile-time flag UNICODE.
  `custom:*pathname-encoding*`

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

  `custom:*terminal-encoding*`

    is the encoding used for communication with the terminal, in particular by `*TERMINAL-IO*`.

  `custom:*misc-encoding*`

    is the encoding used for access to environment variables, command line options, and the like. Its line terminator mode is ignored.

### 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` `&KEY` `:start` `:end`)`

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

`(`ext:convert-string-to-bytes` `string` `encoding` `&KEY` `:start` `:end`)`

  converts the subsequence of `string` from `start` to `end` to a vector of `(`UNSIGNED-BYTE` 8)`, according to the given `encoding`, 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 `gray:fundamental-stream` 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 STREAM-DEFINITION-BY-USER:GENERIC-FUNCTIONS proposal by David N. Gray and is supported by most Common Lisp implementations currently in use. The `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 STREAM-DEFINITION-BY-USER:GENERIC-FUNCTIONS 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” and re-exported from “EXT”.

Defined classes

`gray:fundamental-stream`

  This is a superclass of all user-defined streams. It is a subclass of `STREAM` and of `STANDARD-OBJECT`. Its metaclass is `STANDARD-CLASS`.

`gray:fundamental-input-stream`

  This is a superclass of all user-defined input streams. It is a subclass of `gray:fundamental-stream`. 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 `gray:fundamental-input-stream`.

`gray:fundamental-output-stream`

  This is a superclass of all user-defined output streams. It is a subclass of `gray:fundamental-stream`. 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 `gray:fundamental-output-stream`.

`gray:fundamental-character-stream`

  This is a superclass of all user-defined streams whose `STREAM-ELEMENT-TYPE` is `CHARACTER`. It is a subclass of `gray:fundamental-stream`. It defines a method on `STREAM-ELEMENT-TYPE` that returns `CHARACTER`.

`gray:fundamental-binary-stream`

  This is a superclass of all user-defined streams whose `STREAM-ELEMENT-TYPE` is a subtype of `INTEGER`. It is a subclass of `gray:fundamental-stream`. When you define a subclass of `gray:fundamental-binary-stream`, you have to provide a method on `STREAM-ELEMENT-TYPE`.

`gray:fundamental-character-input-stream`

  This is a convenience class inheriting from both `gray:fundamental-character-stream` and `gray:fundamental-input-stream`.

`gray:fundamental-character-output-stream`

  This is a convenience class inheriting from both `gray:fundamental-character-stream` and `gray:fundamental-output-stream`.

`gray:fundamental-binary-input-stream`

  This is a convenience class inheriting from both `gray:fundamental-binary-stream` and `gray:fundamental-input-stream`.

`gray:fundamental-binary-output-stream`

  This is a convenience class inheriting from both `gray:fundamental-binary-stream` and `gray:fundamental-output-stream`.

general generic functions defined on streams

`(`STREAM-ELEMENT-TYPE` `stream`)`

  Returns the stream's element type, normally a subtype of `CHARACTER` or `INTEGER`.

  The method for `gray:fundamental-character-stream` returns `CHARACTER`.

`((`SETF` `STREAM-ELEMENT-TYPE`) `new-element-type` `stream`)`

  Changes the stream's element type.

  The default method signals an error.

  This function is a CLISP extension.

`(`CLOSE` `stream` `&KEY` `:abort`)`

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

  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

`(`gray:stream-read-char` `stream`)`

  If a character was pushed back using `gray:stream-unread-char`, returns and consumes it. Otherwise returns and consumes the next character from the stream. Returns `:eof` if the `end-of-stream` is reached.

  You must define a method for this function.

`(`gray:stream-unread-char` `stream` `char`)`

  Pushes `char`, which must be the last character read from the `stream`, back onto the front of the `stream`.

  You must define a method for this function.

`(`stream-read-char-no-hang` `stream`)`

  Returns a character or `:eof`, like `gray:stream-read-char`, if that would return immediately. If `gray:stream-read-char`'s value is not available immediately, returns `NIL` instead of waiting.

  The default method simply calls `gray:stream-read-char`; this is sufficient for streams whose `gray:stream-read-char` method never blocks.

`(`gray:stream-peek-char` `stream`)`

  If a character was pushed back using `gray:stream-unread-char`, returns it. Otherwise returns the next character from the stream, avoiding any side effects `gray:stream-read-char` would do. Returns `:eof` if the `end-of-stream` is reached.

  The default method calls `gray:stream-read-char` and `gray:stream-unread-char`; this is sufficient for streams whose `gray:stream-read-char` method has no side-effects.

`(`gray:stream-listen` `stream`)`

  If a character was pushed back using `gray:stream-unread-char`, returns it. Otherwise returns the next character from the stream, if already available. If no character is available immediately, or if `end-of-stream` is reached, returns `NIL`.

  The default method calls `gray:stream-read-char-no-hang` and `gray:stream-unread-char`; this is sufficient for streams whose `gray:stream-read-char` method has no side-effects.

`(`gray:stream-read-char-will-hang-p` `stream`)`

  Returns `NIL` if `gray:stream-read-char` will return immediately. Otherwise it returns true.

  The default method calls `gray:stream-read-char-no-hang` and `gray:stream-unread-char`; this is sufficient for streams whose `gray:stream-read-char` method has no side-effects.

  This function is a CLISP extension.

`(`gray:stream-read-char-sequence` `stream` `sequence` `&OPTIONAL` [`start` [`end`]])`

  Fills the subsequence of `sequence` specified by `:start` and `:end` with characters consecutively read from `stream`. Returns the index of the first element of `sequence` that was not updated (= `end` or < `end` if the stream reached its end).

  `sequence` is an array of characters, i.e. a string. `start` is a nonnegative integer and default to 0. `end` is a nonnegative integer or `NIL` and defaults to `NIL`, which stands for `(`LENGTH` `sequence`)`.

  The default method repeatedly calls `gray:stream-read-char`; this is always sufficient if speed does not matter.

  This function is a CLISP extension.

`(`gray:stream-read-line` `stream`)`

  Reads a line of characters, and return two values: the line (a string, without the terminating #\Newline character), and a boolean value which is true if the line was terminated by `end-of-stream` instead of #\Newline.

  The default method repeatedly calls `gray:stream-read-char`; this is always sufficient.

`(`gray:stream-clear-input` `stream`)`

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

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

generic functions for character output

`(`gray:stream-write-char` `stream` `char`)`

  Writes `char`.

  You must define a method for this function.

`(`gray:stream-line-column` `stream`)`

  Returns the column number where the next character would be written (0 stands for the first column), or `NIL` if that is not meaningful for this stream.

  You must define a method for this function.

`(`gray:stream-start-line-p` `stream`)`

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

  The default method calls `gray:stream-line-column` and compares its result with 0; this is sufficient for streams whose `gray:stream-line-column` never returns `NIL`.

`(`gray:stream-write-char-sequence` `stream` `sequence` `&OPTIONAL` [`start` [`end`]])`

  Outputs the subsequence of `sequence` specified by `:start` and `:end` to `stream`.

  `sequence` is an array of characters, i.e. a string. `start` is a nonnegative integer and default to 0. `end` is a nonnegative integer or `NIL` and defaults to `NIL`, which stands for `(`LENGTH` `sequence`)`.

  The default method repeatedly calls `gray:stream-write-char`; this is always sufficient if speed does not matter.

  This function is a CLISP extension.

`(`gray:stream-write-string` `stream` `string` `&OPTIONAL` [`start` [`end`]])`

  Outputs the subsequence of `string` specified by `:start` and `:end` to `stream`. Returns `string`.

  `string` is a string. `start` is a nonnegative integer and default to 0. `end` is a nonnegative integer or `NIL` and defaults to `NIL`, which stands for `(`LENGTH` `string`)`.

  The default method calls `gray:stream-write-char-sequence`; this is always sufficient.

`(`gray:stream-terpri` `stream`)`

  Outputs a #\Newline character.

  The default method calls `gray:stream-write-char`; this is always sufficient.

`(`gray:stream-fresh-line` `stream`)`

  Possibly outputs a #\Newline 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 #\Newline 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`)`

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

  The default method does nothing.

`(`gray:stream-force-output` `stream`)`

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

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

  The default method does nothing.

`(`gray:stream-advance-to-column` `stream` `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

`(`gray:stream-read-byte` `stream`)`

  Returns and consumes the next integer from the stream. Returns `:eof` if the `end-of-stream` is reached.

  You must define a method for this function.

`(`stream-read-byte-lookahead` `stream`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns `T` if `gray:stream-read-byte` would return immediately with an `INTEGER` result. Returns `:eof` if the `end-of-stream` is already known to be reached. If `gray:stream-read-byte`'s value is not available immediately, returns `NIL` instead of waiting.

  You must define a method for this function.

`(`stream-read-byte-will-hang-p` `stream`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns `NIL` if `gray:stream-read-byte` will return immediately. Otherwise it returns true.

  The default method calls `gray:stream-read-byte-lookahead`; this is always sufficient.

`(`stream-read-byte-no-hang` `stream`)`

  To be called only if `stream`'s `STREAM-ELEMENT-TYPE` is `(`UNSIGNED-BYTE` 8)` or `(`SIGNED-BYTE` 8)`. Returns an `INTEGER` or `:eof`, like `gray:stream-read-byte`, if that would return immediately. If `gray:stream-read-byte`'s value is not available immediately, returns `NIL` instead of waiting.

  The default method calls `gray:stream-read-byte` if `gray:stream-read-byte-lookahead` returns true; this is always sufficient.

`(`gray:stream-read-byte-sequence` `stream` `sequence` `&OPTIONAL` [`start` [`end`]])`

  Fills the subsequence of `sequence` specified by `:start` and `:end` with integers consecutively read from `stream`. Returns the index of the first element of `sequence` that was not updated (= `end` or < `end` if the stream reached its end).

  `sequence` is an array of integers. `start` is a nonnegative integer and default to 0. `end` is a nonnegative integer or `NIL` and defaults to `NIL`, which stands for `(`LENGTH` `sequence`)`.

  The default method repeatedly calls `gray:stream-read-byte`; this is always sufficient if speed does not matter.

  This function is a CLISP extension.

generic functions for binary output

`(`gray:stream-write-byte` `stream` `integer`)`

  Writes `integer`.

  You must define a method for this function.

`(`gray:stream-write-byte-sequence` `stream` `sequence` `&OPTIONAL` [`start` [`end`]])`

  Outputs the subsequence of `sequence` specified by `:start` and `:end` to `stream`

  `sequence` is an array of integers. `start` is a nonnegative integer and default to 0. `end` is a nonnegative integer or `NIL` and defaults to `NIL`, which stands for `(`LENGTH` `sequence`)`.

  The default method repeatedly calls `gray:stream-write-byte`; this is always sufficient if speed does not matter.

  This function is a CLISP extension.

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

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

  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 Common Lisp 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` `char`)`

  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` `start` `length`)`

  Writes the subsequence of `string` starting from `start` of length `length`. 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 garbage-collected.

`(`ext:make-weak-pointer` `value`)`

  returns a fresh weak pointer referring to `value`.

`(`ext:weak-pointer-p` `object`)`

  returns true if the `object` 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 garbage-collected, else `NIL` and `NIL`.

## Extensions-1.7. Finalization

Calling `(`ext:finalize` `object` `function`)` has the effect that when the specified object is being garbage-collected, `(`FUNCALL` `function` `object`)` will be executed.

Calling `(`ext:finalize` `object` `function` `guardian`)` has a similar effect, but only as long as the "guardian" has not been garbage-collected: When `object` is being garbage-collected, `(`FUNCALL` `function` `object` `guardian`)` will be executed. If the guardian is garbage-collected before `object` is, nothing happens.

Note: The time when “the `object` is being garbage-collected” is not defined deterministically. (Actually, it might possibly never occur.) It denotes a moment at which no references to `object` exist from other Lisp objects. When the `function` is called, `object` (and possibly `guardian`) enter the "arena of live Lisp objects" again.

No finalization request will be executed more than once.

## Extensions-1.8. The Prompt

The variable `custom:*prompt*` controls the appearance of the prompt. When its value is a function, it is called and its value is printed with `PRINC`. Otherwise, the value itself is printed with `PRINC`. The default value of `custom:*prompt*` prints `"package[nn]> "` where `package` is the shortest (nick)name of the current package `*PACKAGE*` if it is the same as it was in the beginning or if it does not contain symbol `T` (it is assumed that in the latter case you would want to keep in mind that your current package is something weird); and `nn` is the ordinal number of the current prompt (hopefully, it will remain finite). To help you in constructing your own fancy prompts, two functions are provided: `ext:prompt-new-package`, returning `*PACKAGE*` or `NIL` if the current package is the same as it was initially; and `ext:package-short-name` taking one argument, a package, and returning its shortest name or nickname. Also, a 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 image).

## Extensions-1.9. Maximum ANSI CL compliance

A few [ANSI CL standard] features are turned off by default, because they would hurt in every-day use. They can be switched on, all at once by setting the `symbol-macro` `custom:*ansi*` to `T`, or they can be switched on individually. Setting `custom:*ansi*` to `T` implies the following:

- Setting `custom:*print-pathnames-ansi*` to `T` for [ANSI CL standard] compliant `PATHNAME` printing.

- Setting `custom:*coerce-fixnum-char-ansi*` to `T` so that `FIXNUM`s cannot be `COERCE`d to `CHARACTER`s (because a `FIXNUM` is not a character designator in [ANSI CL standard].)

- Setting `custom:*sequence-count-ansi*` to `T` so that negative `:count` keyword parameter is equivalent to 0 as per the RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER [ANSI CL standard] Issue 283.

- Setting `custom:*merge-pathnames-ansi*` to `T`.

- Setting `custom:*parse-namestring-ansi*` to `T`.

- Setting `custom:*floating-point-contagion-ansi*` to `T`.

Please note that if you run CLISP with the `-a` switch or set the `symbol-macro` `custom:*ansi*` to `T` and save image, then all subsequent invocations of CLISP with this image will be as if with `-a` (regardless whether you actually supply the `-a` switch). You can always set the `symbol-macro` `custom:*ansi*` to `NIL`, reversing the above settings, i.e.,

- Setting `custom:*print-pathnames-ansi*` to `NIL` for readable `PATHNAME` printing.

- Setting `custom:*coerce-fixnum-char-ansi*` to `NIL` so that `FIXNUM`s can be `COERCE`d to `CHARACTER`s (via `CODE-CHAR`).

- Setting `custom:*sequence-count-ansi*` to `NIL` to signal an error on negative `:count` keyword parameter, contrary to the RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER [ANSI CL standard] Issue 283.

- Setting `custom:*merge-pathnames-ansi*` to `NIL`.

- Setting `custom:*parse-namestring-ansi*` to `NIL`.

- Setting `custom:*floating-point-contagion-ansi*` to `NIL`.

## Extensions-1.10. Additional Fancy Macros

If you uncomment the `(`LOAD` "macros3")` line in the file `init.lisp` before doing make, or load the file `macros3.lisp`into a running CLISP, you gain access to the following macros:

`ext:ethe` `(`ext:ethe` `value-type` `form`)` enforces a type check in both interpreted and compiled code.

`ext:letf` & `ext:letf*` These macros are similar to `LET` and `LET*`, 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* ((#:g1 l) (#:g2 (first #:g1)))
       (UNWIND-PROTECT (PROGN (SETF (first #:g1) 7) ...)
          (SETF (first #:g1) #:g2)))

`ext:with-collect` Similar to the `LOOP`'s `collect` instruction, except that it is more "Lispy" in appearance and can appear arbitrarily deep. It defines local macros (with `MACROLET`) which collect objects given to it in lists, which are then returned as multiple values. E.g.,

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

You might want to add a `(`LOAD` "macros3")` statement to your `.clisprc` file if you do not want to dump your own image.

## Extensions-1.11. Customizing CLISP behavior.

The user-customizable variables are located in the package “CUSTOM” and thus can be listed using `(`APROPOS` "" "CUSTOM")`

## Chapter 2. Extensions-2: Platform specific Extensions

## Extensions-2.1. Random Screen Access

## Platform dependent: UNIX, Amiga, DOS, OS/2 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*` should not be used for input or output during this time. (Use `ext:with-keyboard` and `ext:*keyboard-input*` instead.)

`(`screen:with-window` . `body`)`

  binds `screen:*window*` to a window stream and executes `body`. The stream is guaranteed to be closed when the body is left. During its execution, `*TERMINAL-IO*` should not be used, as above.

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

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

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

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

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

  sets the position of the cursor in the window.

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

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

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

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

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

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

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

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

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

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

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

  switches highlighted output on.

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

  switches highlighted output off.

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

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

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

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

## Extensions-2.2. External Modules

## Platform dependent: UNIX platforms only.

CLISP has a facility for adding external modules (written in C, 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 environment variable `CLISP_LINKKIT`.

clisp-link operates on CLISP linking sets and on module sets.

A linking set is a directory containing:

`makevars`

  some /bin/sh commands, setting the variables

  `CC`

    the C compiler

  `CFLAGS`

    flags for the C compiler, when compiling

  `CLFLAGS`

    flags for the C compiler, when linking

  `LIBS`

    libraries to use when linking

  `X_LIBS`

    additional X window system libraries to use

  `RANLIB`

    the ranlib command

  `FILES`

    the list of files needed when linking

`modules.h`

  the list of modules contained in this linking set

`modules.o`

  the compiled list of modules contained in this linking set

all the `FILES`

  listed in `makevars`

`lisp.run`

  the executable

`lispinit.mem`

  the memory image

To run a CLISP contained in some linking set `dir`, call `dir`/lisp.run -M `dir`/lispinit.mem

A module set is a directory containing:

link.sh

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

and any other files

  needed by link.sh

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

`NEW_FILES`

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

`NEW_LIBS`

  the space-separated list of files or C compiler switches that need to be passed to the C compiler when linking the lisp.run belonging to a new linking set.

`NEW_MODULES`

  the space-separated list of the module names belonging to the module set. Normally, every `.c` file in the module set defines a module of its own. The module name is derived from the file name.

`TO_LOAD`

  the space-separated list of Lisp files to load before building the `lispinit.mem` belonging to a new linking set.

`TO_PRELOAD` (optional)

  the space-separated list of Lisp files to load into an intermediate `lispinit.mem` file, before building the `lispinit.mem` belonging to a new linking set. This variable is usually used for defining Lisp packages which must be present when the new `.c` files are initialized.

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

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

The command clisp-link run `source-dir` `module-dir` ... runs the linking set 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 linking set will be created and deleted afterwards. Note that dynamic loading does not work on all operating systems, and that `--with-dynamic-modules` precludes some efficiency optimizations which are on by default.

### Example

To link in the FFI bindings for the Linux operating system, the following steps are needed. (Step 1 and step 2 need not be executed in this order.)

1. Create a new module set:

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

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

       NEW_LIBS="$file_list"

   with

       NEW_LIBS="$file_list -lm"

   Modify the newly created `linux/link.sh` to load `linux.fas` before saving the memory 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 linking set:

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

4. Run and try it:

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

### Modules included in the distribution.

The following modules come with the distribution of CLISP:

bindings

  Call the operating system functions from CLISP. The following platforms are supported:

  - AmigaOS

  - Linux/libc5

  - Linux/libc6

CLX

  Call Xlib functions from CLISP. Two implementations are supplied:

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

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

postgresql632, postgresql642

  Access PostgreSQL from CLISP.

queens

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

regexp

  The POSIX Regular Expressions matching, compiling, executing.

  The following code computes the number of people who use a particular shell:

      (use-package :regexp)
      (sexp ((h (make-hash-table :test #'equal :size 10)) (n 0))
        (with-open-file (f "/etc/passwd")
          (with-loop-split (s f ":")
            (let ((sh (seventh s)))
              (if (gethash sh h)
                  (incf (gethash sh h))
                  (setf (gethash sh h) 1)))))
        (with-hash-table-iterator (i h)
          (loop (multiple-value-bind (r k v) (i)
                  (unless r (return))
                  (format t "[~d] ~s~30t== ~5:d~%" (incf n) k v)))))

  The same is done by the following Perl:

      #!/usr/local/bin/perl -w

      use diagnostics;
      use strict;

      my $IN = $ARGV[0];
      open(INF,"< $IN") || die "$0: cannot read file [$IN]: $!\n;";
      my %hash;
      while (<INF>) {
        chop;
        my @all = split($ARGV[1]);
        my $shell = ($#all >= 6 ? $all[6] : "");
        if ($hash{$shell}) { $hash{$shell} ++; }
        else { $hash{$shell} = 1; }
      }
      my $ii = 0;
      for my $kk (keys(%hash)) {
        print "[",++$ii,"] \"",$kk,"\"  --  ",$hash{$kk},"\n";
      }

wildcard

  Shell globbing

## Extensions-2.3. The Foreign Function Call Facility

## Platform dependent: many UNIX, Win32 platforms only.

A foreign function description is written as a Lisp file, and when compiled it produces a `.c` file which is then compiled by the C compiler and may be linked together with `lisp.a`.

All symbols relating to the foreign function interface are exported from the package FFI. To use them, `(`USE-PACKAGE` "FFI")`.

Special FFI forms may appear anywhere in the Lisp file.

### Overview

These are the special FFI forms. We have taken a pragmatic approach: the only foreign languages we support for now are C and ANSI C.

special FFI forms; `name` is any Lisp symbol; `c-name` is a string.

`(`def-c-type` `name` `c-type`)`

  This form makes `name` a shortcut for `c-type`. Note that `c-type` may already refer to name. Forward declarations of types are not possible, however.

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

  `option` ::==:

  :

  : `(:name `c-name`)`

  `option` ::==:

  : |

  : `(:type `c-type`)`

  `option` ::==:

  : |

  : `(:read-only `boolean`)`

  `option` ::==:

  : |

  : `(:alloc `allocation`)`

  This form defines a foreign variable. `name` is the Lisp name, a regular Lisp symbol.

  The `:name` option specifies the name, as seen from C, as a string. If not specified, it is derived from the print name of the Lisp name.

  The `:type` option specifies the variable's foreign type.

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

  The `:alloc` option can be either `:none` or `:malloc-free` and defaults to `:none`. If it is `:malloc-free`, 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`, `SETQ` assumes that the pointers point to good storage (not `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 `NULL` pointer...) and deprecated.

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

  `option` ::==:

  :

  : `(:name `c-name`)`

  `option` ::==:

  : `(:arguments {(`arg-name` `c-type` [`param-mode` [`allocation`]])}*)` |

  `option` ::==:

  : |

  : `(:return-type `c-type` [`allocation`])`

  `option` ::==:

  : |

  : `(:language `language`)`

  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`` is redirected to call the C function `c-name`. The `language` is either `:C` (denotes K&R C) or `:STDC` (denotes ANSI C) or `:stdc-stdcall` (denotes ANSI C with stdcall calling convention). It specifies whether the C function has been compiled by a K&R C compiler or by an ANSI C compiler, and possibly the calling convention.

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

  `option` ::==:

  : `(:name `c-name`)` |

  `option` ::==:

  :

  : `(:arguments {(`arg-name` `c-type` [`param-mode` [`allocation`]])}*)`

  `option` ::==:

  : |

  : `(:return-type `c-type` [`allocation`])`

  `option` ::==:

  : |

  : `(:language `language`)`

  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 function call to the C function `c-name` is redirected to call the Lisp function `#'`name``. The `language` is either `:c` (denotes K&R C) or `:stdc` (denotes ANSI C) or `:stdc-stdcall` (denotes ANSI C with stdcall calling convention). It specifies whether the calling code has been compiled by a K&R C compiler or by an ANSI C compiler, and possibly the calling convention.

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

  This is equivalent to `def-call-out` with `:language` `:stdc`.

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

  This is equivalent to `def-call-in` with `:language` `:stdc`.

`(`def-c-struct` `name` (`ident` `c-type`)*)`

  This form defines `name` to be both a `STRUCTURE-CLASS` and a foreign C type with the given slots.

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

  This form defines `ident`s as constants, similarly to the C declaration enum { `ident` [= `value`], ... };

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

  This form outputs the string `(`FORMAT` `NIL` `format-string` {`argument`}*)` to the C output file. This is a rarely needed low-level facility.

`(`element` `c-place` `index1` ... `indexn`)`

  Array element: If `c-place` is of foreign type `(c-array `c-type` `dim1` ... `dimn`)` and 0 ≤ `index1` < `dim1`, ..., 0 ≤ `indexn` < `dimn`, this will be the place corresponding to `(`AREF` `c-place` `index1` ... `indexn`)` or ``c-place`[`index1`]...[`indexn`]`. It is a place of type `c-type`. If `c-place` is of foreign type `(c-array-max `c-type` `dim`)` and 0 ≤ `index` < `dim`, this will be the place corresponding to `(`AREF` `c-place` `index`)` or ``c-place`[`index`]`. It is a place of type `c-type`.

`(`deref` `c-place`)`

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

`(`slot` `c-place` `slot-name`)`

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

`(`cast` `c-place` `c-type`)`

  Type change: A place denoting the same memory locations as the original `c-place`, but of type `c-type`.

`(`typeof` `c-place`)`

  returns the `c-type` corresponding to the `c-place`.

`(`sizeof` `c-type`)`, `(`sizeof` `c-place`)`

  The first form returns the size and alignment of a C type `c-type`, measured in bytes.

  The second form returns the size and alignment of the C type of `c-place`, measured in bytes.

`(`bitsizeof` `c-type`)`, `(`bitsizeof` `c-place`)`

  The first form returns the size and alignment of the C type `c-type`, measured in bits.

  The second form returns the size and alignment of the C type of `c-place`, measured in bits.

`(`validp` `foreign-entity`)`

  This predicate returns `NIL` if the `foreign-entity` (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 `foreign-entity` can be used within the current Lisp process.

### (Foreign) C types

Foreign C types are used in the FFI. They are not regular Common Lisp types or CLOS classes.

A `c-type` is either a predefined C type or the name of a type defined by `def-c-type`.

the predefined C types (`c-type`)

`simple-c-type`

  the simple C types

  Lisp name: `NIL`

  Lisp equivalent: `NIL`

  C equivalent: void

  ILU equivalent:

  Comment: as a result type only

  Lisp name: `BOOLEAN`

  Lisp equivalent: `BOOLEAN`

  C equivalent: int

  ILU equivalent: BOOLEAN

  Lisp name: `CHARACTER`

  Lisp equivalent: `CHARACTER`

  C equivalent: char

  ILU equivalent: SHORT CHARACTER

  Lisp name: char

  Lisp equivalent: `INTEGER`

  C equivalent: signed char

  Lisp name: uchar

  Lisp equivalent: `INTEGER`

  C equivalent: unsigned char

  Lisp name: short

  Lisp equivalent: `INTEGER`

  C equivalent: short

  Lisp name: ushort

  Lisp equivalent: `INTEGER`

  C equivalent: unsigned short

  Lisp name: int

  Lisp equivalent: `INTEGER`

  C equivalent: int

  Lisp name: uint

  Lisp equivalent: `INTEGER`

  C equivalent: unsigned int

  Lisp name: long

  Lisp equivalent: `INTEGER`

  C equivalent: long

  Lisp name: ulong

  Lisp equivalent: `INTEGER`

  C equivalent: unsigned long

  Lisp name: uint8

  Lisp equivalent: `(`UNSIGNED-BYTE` 8)`

  C equivalent: uint8

  ILU equivalent: BYTE

  Lisp name: sint8

  Lisp equivalent: `(`SIGNED-BYTE` 8)`

  C equivalent: sint8

  Lisp name: uint16

  Lisp equivalent: `(`UNSIGNED-BYTE` 16)`

  C equivalent: uint16

  ILU equivalent: SHORT CARDINAL

  Lisp name: sint16

  Lisp equivalent: `(`SIGNED-BYTE` 16)`

  C equivalent: sint16

  ILU equivalent: SHORT INTEGER

  Lisp name: uint32

  Lisp equivalent: `(`UNSIGNED-BYTE` 32)`

  C equivalent: uint32

  ILU equivalent: CARDINAL

  Lisp name: sint32

  Lisp equivalent: `(`SIGNED-BYTE` 32)`

  C equivalent: sint32

  ILU equivalent: INTEGER

  Lisp name: uint64

  Lisp equivalent: `(`UNSIGNED-BYTE` 64)`

  C equivalent: uint64

  ILU equivalent: LONG CARDINAL

  Comment: does not work on all platforms

  Lisp name: sint64

  Lisp equivalent: `(`SIGNED-BYTE` 64)`

  C equivalent: sint64

  ILU equivalent: LONG INTEGER

  Comment: does not work on all platforms

  Lisp name: `SINGLE-FLOAT`

  Lisp equivalent: `SINGLE-FLOAT`

  C equivalent: float

  Lisp name: `DOUBLE-FLOAT`

  Lisp equivalent: `DOUBLE-FLOAT`

  C equivalent: double

c-pointer

  This type corresponds to what C calls void*, an opaque pointer.

c-string

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

`(c-struct `class` (`ident1` `c-type1`) ... (`identn` `c-typen`))`

  This type is equivalent to what C calls struct { `c-type1` `ident1`; ...; `c-typen` `identn`; }. Its Lisp equivalent is: if `class` is `VECTOR`, a `SIMPLE-VECTOR`; if `class` is `LIST`, a list; if `class` is a symbol naming a structure or CLOS class, an instance of this class, with slots of names `ident1`, ... ,`identn`.

`(c-union (`ident1` `c-type1`) ... (`identn` `c-typen`))`

  This type is equivalent to what C calls union { `c-type1` `ident1`; ...; `c-typen` `identn`; }. Conversion to and from Lisp assumes that a value is to be viewed as being of `c-type1`.

`(c-array `c-type` `dim1` ... `dimn`)`

  This type is equivalent to what C calls `c-type` [`dim1`] ... [`dimn`]. Note that when an array is passed as an argument to a function in C, it is actually passed as a pointer; you therefore have to write `(c-ptr (c-array ...))` for this argument's type.

`(c-array-max `c-type` `maxdimension`)`

  This type is equivalent to what C calls `c-type` [`maxdimension`], an array containing up to `maxdimension` elements. The array is zero-terminated if it contains less than `maxdimension` elements. Conversion from Lisp of an array with more than `maxdimension` elements silently ignores the superfluous elements.

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

  This type designates a C function that can be called according to the given prototype `(`r-c-type` (*) (`a-c-type1`, ...))`. The `language` is either `:c` (denotes K&R C) or `:stdc` (denotes ANSI C) or `:stdc-stdcall` (denotes ANSI C with stdcall calling convention). It specifies whether the C function has been compiled by a K&R C compiler or by an ANSI C compiler, and possibly the calling convention. Conversion between C functions and Lisp functions is transparent.

`(c-ptr `c-type`)`

  This type is equivalent to what C calls `c-type` *: a pointer to a single item of the given `c-type`.

`(c-ptr-null `c-type`)`

  This type is also equivalent to what C calls `c-type` *: a pointer to a single item of the given `c-type`, with the exception that C `NULL` corresponds to Lisp `NIL`.

`(c-array-ptr `c-type`)`

  This type is equivalent to what C calls `c-type` (*)[]: a pointer to a zero-terminated array of items of the given `c-type`.

### 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` the form `(`EQL` `x` `x`)` is not necessarily true, since every time `x` is evaluated its foreign value is converted to a freshly created Lisp value. Foreign variables are defined using `def-c-var`.

### Operations on foreign places

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

### Foreign functions

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

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

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

### Argument and result passing conventions

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

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

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

`allocation`: `:none`

meaning: no storage is allocated.

`allocation`: `:alloca`

meaning: allocation of storage on the stack, which has dynamic extent.

`allocation`: `:malloc-free`

meaning: storage will be allocated via `malloc()` and freed via `free()`.

If no `allocation` is specified, the default `allocation` is `:none` for most types, but `:alloca` for c-string and c-ptr and c-ptr-null and c-array-ptr and for `:out` arguments. [Subject to change!] The `:malloc-free` 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:
    If `allocation` is `:malloc-free`:

      Lisp allocates the storage using malloc() and never deallocates it. The C function is supposed to call free() when done with it.

    If `allocation` is `:alloca`:

      Lisp allocates the storage on the stack, with dynamic extent. It is freed when the C function returns.

    If `allocation` is `:none`:

      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 to Lisp:
    If `allocation` is `:malloc-free`:

      Lisp calls free() on it when done.

    If `allocation` is `:none`:

      Lisp does nothing.

For call-in functions:
  For arguments passed from C to Lisp:
    If `allocation` is `:malloc-free`:

      Lisp calls free() on it when done.

    If `allocation` is `:alloca` or `:none`:

      Lisp does nothing.

  For results passed from Lisp to C:
    If `allocation` is `:malloc-free`:

      Lisp allocates the storage using malloc() and never deallocates it. The C function is supposed to call free() when done with it.

    If `allocation` is `:none`:

      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.

A function parameter's `param-mode` may be

`:in` (means: read-only):

  The caller passes information to the callee.

`:out` (means: write-only):

  The callee passes information back to the caller on return. When viewed as a Lisp function, there is no Lisp argument corresponding to this, instead it means an additional return value.

`:in-out` (means: read-write):

  Information is passed from the caller to the callee and then back to the caller. When viewed as a Lisp function, the `:out` value is returned as an additional multiple value.

The default is `:in`.

[Currently, only `:in` is fully implemented. `:out` works only with `allocation` = `:alloca`.]

Platform dependent: Amiga platforms only.

  `allocation` may not be `:malloc-free` 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 compiler supports it. Most C compilers do it right, but some C compilers (such as gcc on hppa) have problems with this.

Platform dependent: only in CLISP built with compile-time flag UNICODE.

  A `symbol-macro` place `custom:*foreign-encoding*` contains the encoding for characters and strings passed through the FFI. Its value must be a 1:1 encoding, i.e., an encoding in which every character is represented by one byte.

### Examples

Simple declarations and access

The C 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 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 systems, `stdlib.h` contains the declarations:

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

This translates to

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

Sample call from within Lisp:

    > (div 20 3)
    #S(DIV :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 (i,s,r,a)
        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:

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

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.

call-in

To sort an array of double-floats using the Lisp function `sort` instead of the C 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`:

    (use-package "FFI")
    (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.
    $ cd ..
    $ base/lisp.run -M base/lispinit.mem -c sort2.lisp sorttest.lisp
    $ clisp-link add-module-set sort base base+sort
    $ base+sort/lisp.run -M base+sort/lispinit.mem -i sort2 sorttest
    > (sort10 10 '#(0.501d0 0.528d0 0.615d0 0.550d0 0.711d0
                    0.523d0 0.585d0 0.670d0 0.271d0 0.063d0))
    #(0.063d0 0.271d0 0.501d0 0.523d0 0.528d0 0.55d0 0.585d0 0.615d0 0.67d0 0.711d0)
    $ rm -r base+sort

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

## Platform dependent: Amiga platforms only.

Another Foreign Function Interface All symbols relating to the simple foreign function interface are exported from the package “AFFI”. To use them, `(`USE-PACKAGE` "AFFI")`.

### Design issues

AFFI was designed to be small in size but powerful enough to use most library functions. Lisp files may be compiled to `.fas` files without the need to load function definition files at run-time and without external C or linker support. Memory images can be created, provided that the function libraries are opened at run-time.

Therefore, AFFI supports only primitive C types (integers 8, 16 and 32 bits wide, signed or unsigned, pointers) and defines no new types or classes. Foreign functions are not first-class objects (you can define a lambda yourself), name spaces are separate.

The AFFI does no tracking of resources. Use `ext:finalize`.

### Overview

These are the AFFI forms:

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

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

`(open-library `base-symbol`)`

`(clos-library `base-symbol`)`

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

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

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

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

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

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

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

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

`(nzero-pointer-p `value`)`

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 level. This symbol is created in the package “AFFI”. 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 “KEYWORD” 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” 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` or `UNSIGNED-BYTE` `VECTOR` into memory.

`nzero-pointer-p` tests for non-`NULL` pointers in all recognized representations (`NULL`, `UNSIGNED-BYTE` and `foreign-pointer`).

### Foreign Libraries

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

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

CLISP will not close libraries for you at program exit. [A previous version did so but now AFFI is a module and there are no module exit functions.] Programmers, watch `affi::*libraries-alist*`.

### (Foreign) C types

The following foreign C types are used in AFFI. They are not regular Common Lisp types or CLOS classes.

foreign C types used in AFFI

AFFI name: `NIL`

Lisp equivalent: `NIL`

C equivalent: void

Comment: as a result type for functions only

AFFI name: 4

Lisp equivalent: `(`UNSIGNED-BYTE` 32)`

C equivalent: unsigned long

Comment:

AFFI name: 2

Lisp equivalent: `(`UNSIGNED-BYTE` 16)`

C equivalent: unsigned short

Comment:

AFFI name: 1

Lisp equivalent: `(`UNSIGNED-BYTE` 8)`

C equivalent: unsigned char

Comment:

AFFI name: -4

Lisp equivalent: `(`SIGNED-BYTE` 32)`

C equivalent: long

Comment:

AFFI name: -2

Lisp equivalent: `(`SIGNED-BYTE` 16)`

C equivalent: short

Comment:

AFFI name: -1

Lisp equivalent: `(`SIGNED-BYTE` 8)`

C equivalent: signed char

Comment:

AFFI name: 0

Lisp equivalent: `BOOLEAN`

C equivalent: BOOL

Comment: as a result type for functions only

AFFI name: *

Lisp equivalent: opaque

C equivalent: void*

Comment:

AFFI name: `:external`

Lisp equivalent: opaque

C equivalent: void*

Comment:

AFFI name: `STRING`

Lisp equivalent: `STRING` or `VECTOR`

C equivalent: char*

Comment:

AFFI name: `:io`

Lisp equivalent: `STRING` or `VECTOR`

C equivalent: char*

Comment:

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

Platform dependent: Only in CLISP built with compile-time flag UNICODE.

  A `symbol-macro` place `custom:*foreign-encoding*` contains the encoding for characters and strings passed through the FFI. Its value must be a 1:1 encoding, i.e., an encoding in which every character is represented by one byte.

To meet the design goals, predefined types and objects were used. As such, pointers were represented as integers. Now that there is the `foreign-pointer` type, both representations may be used on input. The pointer type should be therefore considered as opaque. Use `nzero-pointer-p` for 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.

`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 type `0` is only acceptable as a function result type and yields either `T` or `NIL`. The difference between `*` and `:external` is the following: `*` uses integers, `:external` uses `foreign-pointer` as function result-type (except from `NIL` for a NULL pointer) and refuses objects of type `STRING` or `UNSIGNED-BYTE` `VECTOR` as input. Thus `:external` provides some security on the input and the ability to use `ext:finalize` for resource-tracking on the output side.

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

`option` ::==

  :

  : `(:offset `library-offset`)`

  : |

  : `(:arguments {(`arg-name` `AFFI-type` `register`)}*)`

  : |

  : `(:return-type `AFFI-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

`(mem-read `address` `type` `offset`)` can read 8, 16 and 32 bit signed or unsigned integers (AFFI types -4, -2, -1, 1, 2, 4), a pointer (*), a NUL-terminated string (string) or, if the type argument is of type `STRING` or `UNSIGNED-BYTE` `VECTOR`, it can fill this vector. `:external` is not an acceptable type as no object can be created by using `mem-read`.

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

`(mem-write-vector `address` `vector` [`offset`])` can write memory from the given vector (of type string or unsigned byte vector).

### Function Definition Files

`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 `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`, `string` or `:external` 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 `declare-library-base` and `require-library-functions` and not using `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 `ext: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 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 integers and foreign-pointers, no symbols. 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

    (use-package "AFFI")

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

    (use-package "AFFI")

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

    (use-package "AFFI")

    (sexp-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)
    (sexp-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 NUL-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` `&KEY` :string :result :token :io :host)`

  -> `(RC `&OPTIONAL` `result`)`, or `NIL` on failure

`(rexx-run-command `command` `&KEY` :string :token)`

  -> `T`, or `NIL` on failure

`(rexx-send-command `command` `&KEY` :string :result :token :io :host)`

  -> `arexx-msg-handle`, or `NIL` on failure

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

  -> `(RC `&OPTIONAL` `result`)`, or `NIL` on failure

`(rexx-loop)`

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

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

`(`socket:socket-server` `&OPTIONAL` [`port-or-socket`])`

  This function creates a socket, binds a port to the socket, and then listens for connect attempts. The server exists to watch for client connect attempts. The optional argument is either a port (positive `FIXNUM`) or a `socket-stream` (from whose peer the connections will be made).

`(`socket:socket-server-close` `socket-server`)`

  Closes down the server socket.

`(`socket:socket-server-port` `socket-server`)`

  Returns the port which was bound using `socket:socket-server`.

`(`socket:socket-wait` `socket-server` `&OPTIONAL` [`seconds` [`microseconds`]])`

  Given time argument(s), waits for (possibly zero) fixed duration for a connect on the socket-server. Without an argument, `socket:socket-wait` blocks indefinitely.

`(`socket:socket-accept` `socket-server` `&KEY` `:element-type` `:external-format` `:buffered`)`

  Creates the server-side two-way stream for the connection.

`(`socket:socket-connect` `port` `&OPTIONAL` [`host`] `&KEY` `:element-type` `:external-format` `:buffered`)`

  Attempts to create a client-side two-way `socket-stream`. Blocks until the server accepts the connections.

`(`socket:socket-status` `socket-stream-or-list` `&OPTIONAL` [`seconds` [`microseconds`]])`

  Checks whether it is possible to read from or write to a `socket-stream` without blocking. This is similar to `LISTEN`, which checks only one stream and only for input.

  `socket-stream-or-list` is an open `socket-stream` (one symbol is returned) or a list of streams (a list of symbols, one for each stream, is returned).

  The optional arguments specify the timeout. `NIL` means wait forever, 0 means poll. Note that this function never waits for input or output to arrive, only for information on input or output presense (so that `READ-CHAR` or `WRITE-CHAR` will not block) to become available.

  For each `socket-stream` this function returns

  Return values of `socket:socket-status`

  `NIL`

    when no information is available or no operation is possible

  `:error`

    when an i/o operation will cause an error

  `:input`

    when you can only read from the stream

  `:output`

    when you can only write to the stream

  `:io`

    when you can both read from and write to the stream

`(`socket:socket-stream-host` `socket-stream`)`, `(`socket:socket-stream-port` `socket-stream`)`

  These two functions return information about the `socket-stream`. For a server, `socket:socket-stream-host` returns `NIL`.

`(`socket:socket-service-port` `&OPTIONAL` `service-name` (`protocol` "tcp"))`

  A convenience function for looking up a port given the service name. It returns the servent struct as multiple values (name, list of aliases, port, protocol) for the given `service-name` and `protocol`, or all services as the list of vectors of `LENGTH` 4, if `service-name` is not given or is `:default` or `NIL`.

`(`socket:socket-stream-peer` `socket-stream`)`

  Given a stream, this function returns the name of the host on the opposite side of the connection and its port number; the server-side can use this to see who connected.

`(`socket:socket-stream-local` `socket-stream`)`

  The dual to `socket:socket-stream-peer` - same information, host name and port number, but for the local host. The difference from `socket:socket-stream-host` and `socket:socket-stream-port` is that this function asks the OS (and thus returns the correct trusted values) while the other two are just accessors to the internal data structure, and basically return the arguments given to the function which created the `socket-stream`.

## Extensions-2.7. System Calls

When CLISP is configured with an option `--with-export-syscalls`, some system calls are available from lisp, in package “POSIX”.

`(`posix:resolve-host-ipaddr` `&OPTIONAL` `host`)`

  Returns the hostent struct (name, list of aliases, list of IP addresses as dotted quads (for IPv4) or coloned octets (for IPv6), address type - IPv4 or IPv6). When `host` is omitted or `:default`, return the data for the current host. When `host` is given and is `NIL`, all the host database is returned as a list (this would be the contents of the `/etc/hosts` file on a UNIX system or `${windir}/system32/etc/hosts` on a Win32 system).

`(`posix:file-stat` `pathname` `&OPTIONAL` `link-p`)`

  Return the stat struct. `pathname` can be a `STREAM`, a `PATHNAME`, a `STRING` or a `NUMBER` (on a UNIX system, meaning file descriptor). The first slot of the struct returned is the string or the number on which `stat(2)`/`fstat(2)`/`lstat(2)` was called. The other 13 slots are numbers, members of the stat struct: device, inode, protection, number of hard links, owner's UID, owner's GID, device type, total size (bytes), blocksize for filesystem I/O, number of blocks allocated, atime, mtime, ctime (as the number of seconds since 1900-01-01). If the system does not support a particular field (e.g., Win32 does not have hard links), `NIL` (or the default, like 1 for the number of hard links for Win32 or DOS) is returned.

  [UNIX systems only at this time, patches are welcome.]

`(`posix:user-data` `&OPTIONAL` `user`)`>

  Return the passwd struct (name, encoded password, UID, GID, full name, home directory, shell). When `user` is `NIL`, return all users. When `user` is `:default` or not supplied, return the information about the current user. If the system does not support a particular field (e.g., Win32 does not have a concept of a shell), `NIL` (or the default, like `c:\command.com` for DOS) is returned.

  [UNIX systems only at this time, patches are welcome.]

`(`posix:sysinfo`)`

  Return a struct describing the OS, derived from `uname(2)` and `sysconf(3)`.

`(`posix:resource-usage-limits`)`

  Return 3 structs describing the resources usage and limits, derived from `getrlimit(2)` and `getrusage(3)`.

`(`posix:erf` `real`)` `(`posix:erfc` `real`)` `(`posix:j0` `real`)` `(`posix:j1` `real`)` `(`posix:jn` `integer` `real`)` `(`posix:y0` `real`)` `(`posix:y1` `real`)` `(`posix:yn` `integer` `real`)` `(`posix:gamma` `real`)` `(`posix:lgamma` `real`)`

  Compute the error functions, Bessel functions and Gamma. These functions are required by the POSIX standard and should be available in libm.so. Please note that these functions do not provide lisp-style error handling and precision, and do all the computations at the double float level.

  [UNIX systems only at this time, patches are welcome.]

## Extensions-2.8. Quickstarting delivery with CLISP

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

UNIX

  CLISP can act as a script interpreter.

Desktop environments such as KDE, GNOME, or Windows.

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

Linux with `CONFIG_BINFMT_MISC=y`

  Associate the extensions `fas` and `lsp` 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 `fas` files can be concatenated (using `Join`) into one file.

These three techniques apply to a single `lsp` or `fas` file. If your application is made up of several `lsp` or `fas` files, you can simply concatenate them (using `cat`(1)) into one file; the techniques then apply to that concatenated file.

Platform dependent: UNIX platforms only.

  On Unix, a text file (`fas` or `lsp`) can be made executable by adding a first line of the form

      #!interpreter [interpreter-args]

  and using chmod(1) to make the script executable. CLISP can be used as a script interpreter under the following circumstances:

  - The `interpreter` 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 `interpreter` must be a real executable, not a script. Unfortunately, in the binary distributions of CLISP on Solaris, `clisp` is a shell script because a C compiler cannot be assumed to be installed on this platform. If you do have a C compiler installed, build CLISP from the source yourself; make install will install clisp 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 `interpreter`. 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 `interpreter` and `interpreter-args` must still be a normal space!) CLISP will split the `interpreter-args` at hard spaces and at normal spaces.

  The script should contain Lisp forms, except in the #! line. The file is normally loaded, through the function `LOAD`. Before it is loaded, the variable `ext:*args*` is bound to a list of strings, representing the arguments given to the Lisp script. `*STANDARD-INPUT*` and `*STANDARD-OUTPUT*` are bound, as usual, to the Unix standard input and output. `*ERROR-OUTPUT*` is bound to the Unix error output. Continuable errors will be turned to warnings. Non-continuable errors and Ctrl-C interrupts will terminate the execution of the Lisp script with error status. If you wish the script's contents to be compiled during loading, add `-C` to the `interpreter-args`.

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

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

  The problem with this approach is that the return values of each form will be printed to the standard output. Another problem is that no user input will be available.

Platform dependent: Win32 platforms only.

  There are two different ways to make CLISP "executables" for Windows platforms.

  - Associate the `mem` extension with c:\clisp\lisp.exe -m 10M -M %s -N c:\clisp\locale.

  - Associate the `fas` extension with c:\clisp\lisp.exe -m 10M -M c:\clisp\lispinit.mem -N c:\clisp\locale -i %s. Alternatively, you may want to have a function `main` in your files and associate the `fas` extension with c:\clisp\lisp.exe -m 10M -M c:\clisp\lispinit.mem -N c:\clisp\locale -i %s -x (main).

  Then clicking on the compiled lisp file (with `fas` extension) will load the file (thus executing all the code in the file), while the clicking on a CLISP memory image (with `mem` extension) will start clisp with the given memory image.

Platform dependent: Linux platforms only.

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

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

  Then you can do the following:

      bash$ cat << EOF > hello.lisp
      (print "hello, world!")
      EOF
      bash$ clisp -c hello.lisp

      Compiling file hello.lisp ...

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

      "hello, world!"
      bash$

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

Platform dependent: Amiga platforms only.

  Using a Workbench project file, the memory images, 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 memory 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 `fas` suffix) will load the image and the file (thus executing all the code in the file), while clicking on the CLISP's memory image (with `mem` suffix) with start clisp with the given memory image.

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

## Extensions-2.9. Application delivery with CLISP

Some ways of packaging CLISP programs are discussed in the section Quickstarting delivery with CLISP.

CLISP is Free Software, covered by the GNU GPL, with special terms governing the distribution of applications that run in CLISP. The precise terms can be found in the `COPYRIGHT` file contained in the source and binary distributions of CLISP. Here is an informal clarification what these terms mean in practice. Please refer to the said `COPYRIGHT` file when in doubt.

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

CLISP extensions, i.e. programs which need to access non-portable CLISP internal symbols (in the packages SYSTEM, COMPILER, CLOS, FFI, ...), 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 of `.fas` files can be distributed without restrictions coming from CLISP.

- Programs distributed as CLISP memory images can be distributed only if accompanied with the non-CLISP `.fas` files which make up the memory image, and a `Makefile` for rebuilding the memory image.

- If you need to distribute a modified CLISP executable (for example, incorporating additional modules written in C), you must distribute its full source under GNU GPL. If you are not satisfied with this, you can instead put the additional modules into a separate (non-CLISP) program, with which your Lisp program will communicate via `socket-stream`s.

## Extensions-2.10. Shell, Pipes and Printing

### Shell

Platform dependent: UNIX, Acorn, DOS, OS/2, platforms only.

  `(`ext:execute` `programfile` `arg1` `arg2` ...)` executes an external program. Its name is `programfile`. It is given the strings `arg1`, `arg2`, ... as arguments.

Platform dependent: Amiga platforms only.

  `(`ext:execute` `command`)` executes a given `command` using the operating system's shell.

Platform dependent: UNIX, Amiga, Acorn, DOS, OS/2, Win32 platforms only.

  `(`ext:shell` [`command`])` calls the operating system's shell. `(`ext:shell`)` calls the shell for interactive use. `(`ext:shell` `command`)` calls the shell only for execution of the one given `command`.

Platform dependent: UNIX, OS/2, Win32 platforms only.

  The functions `ext:run-shell-command` and `ext:run-program` are the general interface to `ext:shell` and the above:

  `(`ext:run-shell-command` `command` `:input` `:output` `:if-output-exists`)` runs a shell command.

  `(`ext:run-program` `program` `:arguments` `:input` `:output` `:if-output-exists`)` runs an external program.

  `command`

    the shell command.

    Platform dependent: UNIX platforms only.

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

  `program`

    the program. The directories listed in the `PATH` environment variable will be searched for it.

  `:arguments`

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

  `:input`

    where the program's input is to come from: either `:terminal` (the standard input) or `:stream` (a Lisp stream to be created) or a pathname (an input file) or `NIL` (no input at all).

  `:output`

    where the program's output is to be sent to: either `:terminal` (the standard output) or `:stream` (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` file already exists. The possible values are `:overwrite`, `:append`, `:error`, with the same meaning as for `OPEN`.

  If `:stream` was specified for `:input` or `:output`, a Lisp stream is returned. If `:stream` was specified for `:input` and `:output`, three Lisp streams are returned, as for the function `ext:make-pipe-io-stream`. This use of `ext:run-program` can cause deadlocks, see `ext:make-pipe-io-stream`.

### Pipes

Platform dependent: UNIX, OS/2, Win32 platforms only.
  `(`ext:make-pipe-input-stream` `command` `&KEY` `:element-type` `:external-format` `:buffered`)`

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

  `(`ext:make-pipe-output-stream` `command` `&KEY` `:element-type` `:external-format` `:buffered`)`

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

  `(`ext:make-pipe-io-stream` `command` `&KEY` `:element-type` `:external-format` `:buffered`)`

    returns three values. The first value is a bidirectional stream that will simultaneously pass its output as input to the execution of the given operating system command and supply the output from this command as input. The second and third value will be the input stream and the output stream that make up the I/O stream, respectively. Note that they must be closed individually.

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

    A deadlock occurs if the command and your program either both try to read from each other at the same time or both try to write to each other at the same time. To avoid deadlocks, it is recommended that you fix a protocol between the command and your program and avoid any hidden buffering: use `READ-CHAR`, `READ-CHAR-NO-HANG`, `LISTEN` instead of `READ-LINE` and `READ` on the input side, and complete every output operation by a `FINISH-OUTPUT`. The same cautions must apply to the called command as well.

### Printing

The macro `ext:with-output-to-printer`:

    (ext:with-output-to-printer (variable [:external-format])
      {declaration}*
      {form}*)

binds the variable `variable` to an output stream that sends its output to the printer.

## Extensions-2.11. Directory Access

When CLISP is configured with an option `--with-dir-key`, some directory access is available from lisp, in package “LDAP”. 3 types of directory keys may exist, depending on the compilation environment.

valid directory key types

:win32

  Win32 registry access

:gnome

  Gnome-config access

:ldap

  LDAP interface via OpenLDAP.

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

`(`ldap:dir-key-open` `dkey` `path` `&KEY` (`:direction` `:input`) `:if-does-not-exist``

  Open the directory key under `dkey`, which should be either an open directory key or a valid directory key type. The meaning of the `:direction` and `:if-does-not-exist` keyword arguments is the same as for `OPEN`.

`(`ldap:dir-key-close` `dkey`)`

  Close the directory key. The preferred way is to use the `ldap:with-dir-key-open` macro.

`(`ldap:with-dir-key-open` (`variable` `dkey` `path` `&REST` `options`) `&BODY` `body`)`

  Open the directory key (by calling `ldap:dir-key-open` on `dkey`, `path` and `options`), bind it to `variable`, execute `body`, then close it with `ldap:dir-key-close`.

`(`ldap:dir-key-type` `dkey`)`

  Return the type of the directory key

`(`ldap:dir-key-path` `dkey`)`

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

`(`ldap:dir-key-direction` `dkey`)`

  One of `:input`, `:output` and `:io`, indicating the permitted operation on this key and its derivatives.

`(`ldap:dir-key-closed-p` `dkey`)`

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

`(`ldap:dir-key-subkey-delete` `dkey` `subkey`)` `(`ldap:dir-key-value-delete` `dkey` `attribute`)`

  Delete the specified subkey or attribute.

`(`ldap:dir-key-subkey` `dkey`)` `(`ldap:dir-key-attributes` `dkey`)`

  Return the list of the subkeys or attributes.

`(`ldap:dir-key-value` `dkey` `attribute` `&OPTIONAL` `default`)`

  Return the value of the specified attribute, similar to `GETHASH` and `SETF`able just like `GETHASH`.

`(`ldap:dir-key-info` `dkey`)`

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

`(`with-dir-key-search` (`key-iter` `atribute-iter` `dkey` `path` `&KEY` `:scope`) `&BODY` `body`)`

  This is the main way to iterate over the subtree under the key `dkey`+`path`.

  `key-iter` is a non-`NIL` symbol and is bound via `MACROLET` to a macro, each call of which returns the next subkey.

  `atribute-iter` is a symbol and is bound, when non-`NIL`, to a macro, each call of which returns two values - the next attribute and its value.

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

  `:self`

    iterate over the key itself

  `:level`

    iterate over the children of the key

  `:tree`

    iterate over the subtree

  `with-dir-key-search` is used to implement `dir-key-values`, `dir-key-childred` and `dir-key-dump-tree` in `dirkey.lisp`.

## Extensions-2.12. Other

Platform dependent: Amiga platforms only.

  To have `*DEBUG-IO*` and `*ERROR-OUTPUT*` point to separate console windows (thus keeping your standard console window clean from error messages) you can use

        (SETQ *ERROR-OUTPUT*
          (SETQ *DEBUG-IO*
            (OPEN "CON:0/0/500/300/CLISP-Debugger/AUTO/CLOSE"
                    :direction :io)))

  at startup.

## References

### Books

[CLtL1] Guy L. Steele, Jr.. 1984. 465. 0-201-10088-6. Digital Press. Common Lisp: the Language (1st Edition).

[CLtL2] Guy L. Steele, Jr.. 1990. 1032. 0-201-10088-6. Digital Press. Common Lisp: the Language (2nd Edition).

### ANSI standard documents

[ANSI CL] 1994. ANSI Common Lisp standard X3.226-1994 - Information Technology - Programming Language - Common Lisp.

[CLHS] Common Lisp HyperSpec.