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".
Table of Contents
These notes discuss the CLISP implementation of Common Lisp by
and
<honorific>Dr</honorific>
<firstname>Bruno</firstname> <surname>Haible</surname>
<haible@clisp.cons.org>
Louisenstraße 103
Bad Homburg
D-61348 Germany
http://clisp.cons.org/~haible
The current maintainers are
<honorific>Dr</honorific>
<firstname>Michael</firstname> <surname>Stoll</surname>
<stoll@math.uni-duesseldorf.de>
Westerwaldweg 22
Remagen-Oberwinter
D-53424 Germany
http://www.math.uni-duesseldorf.de/home/stoll
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].
Table of Contents
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.
Safety settings are ignored; therefore where the standard uses the phrase “should signal an error”, an error is signaled.
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 missing from the “COMMON-LISP” package:
Table of Contents
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.
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.
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.
Table of Contents
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).
lisp:the-environment As in Scheme, the macro (lisp:the-environment) returns the current lexical environment. This works only in interpreted code and is not compilable!
(lisp:eval-env form &OPTIONAL env) evaluates a form in a given lexical environment, just if the form had been part of the program text that environment came from.
The declarations (TYPE type var ...), (FTYPE type fun ...), (OPTIMIZE (quality value) ...) are ignored by the interpreter and the compiler.
The ANSI CL declaration (OPTIMIZE (debug ...)) is legal.
The ANSI CL declaration (IGNORABLE var ...) affects the variable binding for the variable var. The compiler will not warn about the variable, regardless whether it is used or not.
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 lisp:ethe macro.
The initial value of an &AUX variable in a boa lambda list is the value of the corresponding slot's initial form.
(PROCLAIM '(SPECIAL var)) 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.
Table of Contents
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 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.
(lisp:type-expand-1 typespec) If typespec is a user-defined type, lisp: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.
(lisp:type-expand typespec) This is similar to (lisp: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 lisp:type-expand-1, indicating whether the original typespec was a user-definedtype.
The possible results of TYPE-OF are:
FIXNUM, BIGNUM, RATIONAL, SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT, COMPLEX
(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)
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)
The CLOS symbols are exported 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").
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 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 CONSes and NUMBERs, due to the performance concerns.
DOCUMENTATION still has the [CLtL1] implementation.
Among those classes listed in Figure 4-8, only the following are instances of BUILT-IN-CLASS:
DEFCLASS supports the :metaclass option. Possible values are STANDARD-CLASS (the default) and STRUCTURE-CLASS (which creates structure classes, like DEFSTRUCT does).
Redefining classes is not supported. The function UPDATE-INSTANCE-FOR-REDEFINED-CLASS is not implemented.
Table of Contents
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, rather efficient.
DESTRUCTURING-BIND does not perform full error checking.
COMPILED-FUNCTION-P returns T on built-in functions written in C, compiled functions and special operator handlers. Therefore COMPILED-FUNCTION is not a subtype of FUNCTION.
EQ compares characters and fixnums as EQL does. No unnecessary copies are made of characters and numbers. Nevertheless, one should use EQL as it is more portable across CL implementations.
(let ((x y)) (eq x x)) always returns T, regardless of y.
(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.
Additional places:
(SETF (FUNCALL #'symbol ...) object) and (SETF (FUNCALL 'symbol ...) object) are equivalent to (SETF (symbol ...) object).
(SETF (GET-DISPATCH-MACRO-CHARACTER ...) ...) calls SET-DISPATCH-MACRO-CHARACTER.
(SETF (lisp:long-float-digits) digits) sets the default mantissa length of long floats to digits bits.
(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), (lisp:get-setf-method form &OPTIONAL env), and (lisp:get-setf-method-multiple-value form &OPTIONAL env) receive as optional argument the environment necessary for macro expansions. In DEFINE-SETF-EXPANDER and lisp: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, lisp:get-setf-method and lisp: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 lisp:letf and lisp:letf* macros.
(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.
The macro DEFINE-SYMBOL-MACRO establishes symbol-macros with global scope (as opposed to symbol-macros defined with SYMBOL-MACROLET, which have local scope): (DEFINE-SYMBOL-MACRO symbol expansion).
The function lisp:symbol-macro-expand tests for a symbol-macro: If symbol is defined as a symbol-macro, (lisp: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.
LAMBDA-LIST-KEYWORDS (&OPTIONAL &REST &KEY &ALLOW-OTHER-KEYS &AUX &BODY &WHOLE &ENVIRONMENT)
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 |
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))))
No notes.
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.
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 to 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*, lisp:*print-closure*, lisp:*print-rpars*, lisp:*print-indent-lists*
The :inherit option is exactly like :include except that it does not create new accessors for the inherited slots.
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.
lisp:muffle-cerrors The macro (lisp:muffle-cerrors {form}*) executes the forms. When a continuable error occurs, no message is printed. Instead, the CONTINUE restart is invoked.
lisp:appease-cerrors The macro (lisp:appease-cerrors {form}*) executes the forms. When a continuable error occurs, the error is printed as a warning and the CONTINUE restart is invoked.
lisp:exit-on-error The macro (lisp:exit-on-error {form}*) executes the forms. When a non-continuable error or a Ctrl-C interrupt occurs, the error is printed and CLISP terminates with error status.
lisp:with-restarts The macro lisp: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. (lisp:with-restarts ({restart-clause}*) {form}*) is therefore equivalent to (RESTART-CASE (PROGN {form}*) {restart-clause}*).
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.
SIGNAL The default condition type for conditions created by SIGNAL is SIMPLE-CONDITION, not SIMPLE-ERROR.
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}*)
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.
WARN The default condition type for conditions created by WARN is SIMPLE-WARNING, not SIMPLE-ERROR.
No notes.
Table of Contents
The standard ANSI CL packages
“COMMON-LISP” with the nickname CL;
“COMMON-LISP-USER” with the nickname CL-USER and
are implemented. The package “COMMON-LISP” exports only those symbols from the [ANSI CL standard] that are actually implemented.
The “COMMON-LISP-USER” package uses only the “COMMON-LISP” package.
The following additional packages exist:
Implementation-Defined Packages
exports all symbols needed for a CLtL1/CltL2 environment, excluding CLOS.
exports all CLOS specific symbols needed for a CLtL1/CltL2 environment.
is the default user's package for a CLtL1/CltL2 environment.
has the nicknames SYS and COMPILER, and has no exported symbols. It defines many system internals.
defines and exports some character sets, for use with make-encoding and as :external-format argument.
implements the foreign function interface. Some platforms only.
defines an API for random screen access. Some platforms only.
All pre-existing packages except USER and COMMON-LISP-USER belong to the implementation, in the sense that doing side-effects on them or on their symbols causes undefined behavior.
For MAKE-PACKAGE, the default value of the :use argument is ("COMMON-LISP"). For lisp:make-package, the default value of the :use argument is ("LISP" "CLOS").
MAKE-PACKAGE and lisp:in-package accept 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.
Table of Contents
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.
When a mathematical function may return an exact (rational) or inexact (floating-point) result, it always returns the exact result.
There are four floating point types: SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT and LONG-FLOAT:
Table 12.1. 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 (lisp:long-float-digits). It can be set by (SETF (lisp:long-float-digits) nnn), where nnn is a positive integer. E.g., (SETF (lisp:long-float-digits) 3322) sets the default precision of long floats to 1000 decimal digits.
The floating point contagion is controlled by the variable lisp:*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.
See it pragmatically: save what you can and let others worry about the rest.
CL 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.
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 CLISP's 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 CL 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.
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 lisp:*warn-on-floating-point-contagion* is for), but one should not be penalized for this too harshly.
When lisp:*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!)
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.
Do not suggest accuracy of a result by giving it a precision that is greater than its accuracy.
(- (+ 1.7 PI) PI) should not return 1.700000726342836417234L0, it should return 1.7f0 (or 1.700001f0 if there were rounding errors).
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.
lisp:*warn-on-floating-point-contagion* If the variable lisp:*warn-on-floating-point-contagion* is non-NIL, a warning is emitted for every coercion involving different floating-point types.
lisp:*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 lisp:*default-float-format*.
lisp:without-floating-point-underflow The macro (without-floating-point-underflow {form}*) executes the forms, 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 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).
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).
lisp:! (lisp:! n) returns the factorial of n, n a nonnegative integer.
lisp:exquo (lisp: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 /.)
lisp:xgcd (lisp:xgcd x1 ... xn) returns the values g, c1, ..., cn, where g is the greatest common divisor of the integers x1, ..., xn, and c1, ..., cn are the integer coefficients such that
g = (GCD x1 ... xn) = (+ (* c1 x1) ... (* cn xn))
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 (lisp:long-float-digits). When this precision is changed, the value of PI is automatically recomputed. Therefore PI is a variable, not a constant.
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
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
Table 12.2. 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 |
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 (lisp:long-float-digits) is changed. They are variables, not constants.
Table of Contents
The characters are ordered according to a superset of the ASCII encoding.
More precisely, CLISP uses the IBM PC character set (code page 437):
Table 13.1. 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 | ≡ | ± | ≥ | ≤ | ⌠ | ⌡ | ÷ | ≍ | ° | ∙ | · | √ | ⁿ | ² | ■ |
More precisely, CLISP uses the ISO Latin-1 (ISO 8859-1) character set:
Table 13.2. 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 | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
More precisely, CLISP uses the NeXTstep character set:
Table 13.3. 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 | © | ¡ | ¢ | £ | ⁄ | ¥ | ƒ | § | ¤ | ’ | “ | « | ‹ | › | fi | fl |
#xB0 | ® | – | † | ‡ | · | ¦ | ¶ | • | ‚ | „ | ” | » | … | ‰ | NOT | ¿ |
#xC0 | ¹ | ˋ | ´ | ^ | ˜ | ¯ | ˘ | ˙ | ¨ | ² | ˚ | ¸ | ³ | ˝ | ˛ | ˇ |
#xD0 | — | ± | ¼ | ½ | ¾ | à | á | â | ã | ä | å | ç | è | é | ê | ë |
#xE0 | ì | Æ | í | ª | î | ï | ð | ñ | Ł | Ø | Œ | º | ò | ó | ô | õ |
#xF0 | ö | æ | ù | ú | û | ı | ü | ý | ł | ø | œ | ß | þ | ÿ |
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.
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 can not be used to compare objects of type sys::input-character.
The system uses only font 0.
The following bits are defined:
key: :control
value: lisp:char-control-bit
key: :meta
value: lisp:char-meta-bit
key: :super
value: lisp:char-super-bit
key: :hyper
value: lisp:char-hyper-bit
returns the font of a character or sys::input-character.
returns the bits of a character or sys::input-character.
returns a new sys::input-character, or NIL if such a character cannot be created.
returns a new sys::input-character with the named bit set or unset, depending on the boolean newvalue.
The graphic characters are those Unicode characters which are defined by the Unicode standard, excluding the ranges U0000 … U001F and U007F … U009F.
The alphabetic characters are those Unicode characters which are defined as letters by the Unicode standard.
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:
The titlecase property of Unicode characters has no equivalent in Common Lisp.
The numeric characters are those Unicode characters which are defined as digits by the Unicode standard.
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:
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).
CHAR-CODE takes values from 0 (inclusive) to CHAR-CODE-LIMIT (exclusive), i.e., the implementation supports exactly CHAR-CODE-LIMIT characters.
Table 13.4. Platform dependent
binaries built | withoutUNICODE support | withUNICODE support |
---|---|---|
CHAR-CODE-LIMIT | 28 = 256 | 216 = 65536 |
The types lisp: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:
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.
(lisp:char-width character) returns the number of screen columns occupied by character. 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.
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
Table of Contents
SUBLIS, NSUBLIS SUBLIS and NSUBLIS apply the :key argument to the nodes of the cons tree and not to the keys of the alist.
The constant lisp:mapcap is like MAPCAN, except that it concatenates the resulting lists with APPEND instead of NCONC:
(lisp:mapcap fun x1 ... xn) == (apply #'APPEND (MAPCAR fun x1 ... xn))
(Actually a bit more efficient that this would be.)
The function lisp:maplap is like MAPCON, except that it concatenates the resulting lists with APPEND instead of NCONC:
(lisp:maplap fun x1 ... xn) == (apply #'APPEND (MAPLIST fun x1 ... xn))
(Actually a bit more efficient that this would be.)
Table of Contents
MAKE-ARRAY MAKE-ARRAY can return specialized arrays for the element types (UNSIGNED-BYTE 2), (UNSIGNED-BYTE 4), (UNSIGNED-BYTE 8), (UNSIGNED-BYTE 16), (UNSIGNED-BYTE 32) and of course BIT and CHARACTER.
Table 15.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 Issue ARRAY-DIMENSION-LIMIT-IMPLICATIONS:ALL-FIXNUM.
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!
Table of Contents
String comparison is based on the function CHAR<=. Therefore diphthongs do not obey the usual national rules. Example: o < oe < z < ö.
Functions on strings (lisp:string-width string) returns the number of screen columns occupied by string. This is computed as the sum of all char-widths of all of the string's characters.
Table of Contents
For iteration through a sequence, a macro lisp:doseq, similar to DOLIST, may be used instead of MAP:
(lisp:doseq (var seqform [resultform]) {declaration}* {tag|statement}*)
lisp:doseq forms are “iteration forms”.
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.
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 issue 283 RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER, negative :count keyword arguments are not allowed unless you set lisp:*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 issue.
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.
Table of Contents
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.
For iteration through a hash table, a macro lisp:dohash, similar to DOLIST, can be used instead of MAPHASH:
(lisp:dohash (key-var value-var hash-table-form [resultform]) {declaration}* {tag|statement}*)
lisp:dohash forms are “iteration forms”.
Table of Contents
For most operations, pathnames denoting files and pathnames denoting directories can not be used interchangeably.
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.
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.
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, lisp:dir, lisp:cd, lisp:make-dir, lisp: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.
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.
Pathname components
always NIL
NIL or a SIMPLE-STRING
(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 *
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
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*.lsp
: or similar.
:
Formal specification of the external notation
any character except ':','/' and '*','?'
{ch}+
: empty
: current device, relative to current directory
: ':'
: current device, absolute (relative to root for disks)
: name ':'
: specified device, absolute (relative to root for disks)
: empty
: parent directory
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).
Pathname components
always NIL
always NIL
(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:
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
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*.lsp
: or similar.
:
Pathname components
always NIL
NIL or :wild or A|...|Z
(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:
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
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*.lsp
: or similar.
:
Instead of '\' one may use '/', as usual for DOS calls.
Pathname components
NIL or SIMPLE-STRING, wildcard characters may occur but don't act as wildcards
NIL or :wild or A|...|Z
(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:
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
NIL or SIMPLE-STRING, may contain wildcard characters ? and * (may also be specified as :wild)
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*.lsp
: 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.
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").
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.
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.
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)
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:
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:
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:
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.
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.
You can set up other path variables and use them as pseudo file systems. For example if you typed:
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.
No swapping. foo.lsp means file type lsp and file name foo. This is pseudo-BNF:
any ISO latin-1 graphic character ≥ ' ' except '.' ':' '*' '#' '$' '&' '@' '^' '%' '\' '?'
any ISO latin-1 graphic character ≥ ' ' except ':' '"' '|'
legal char | '*' | '#' | '?'
'-' { extended legal char except '-' }+ '-' | { extended legal char except '-' } { extended legal char }* ':' | empty
':' { legal char }+ '.' | empty
{ '$' | '&' | '@' | '%' | '\' } '.' { subdirectory }* | { subdirectory }+ | empty
: '$' ->
: :absolute :root
: '&' ->
: :absolute :home
: '@' ->
: :absolute :current
: '%' ->
: :absolute :library
: '\' ->
: :absolute :precious
: else
: :relative
{ '^' | { legal-wild char }+ } '.'
: '^' ->
: :parent
{ { legal-wild char }+ | empty }
{ '.' { legal-wild char }+ | empty }
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:
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))))
Pathname components
SIMPLE-STRING or NIL
SIMPLE-STRING or NIL
(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 *
NIL or SIMPLE-STRING, may contain wildcard characters ?,# and * (may also be specified as :wild)
NIL or SIMPLE-STRING, may contain wildcard characters ?,# and * (may also be specified as :wild)
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 of pathnames (cf. PARSE-NAMESTRING and NAMESTRING), of course without spaces, [,],{,}:
: [ [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.
see above.
: [ / ]
: / 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 /).
: [ [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 /, \, :).
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.
The function USER-HOMEDIR-PATHNAME is not implemented.
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") "\\"))
When the argument of the function TRANSLATE-LOGICAL-PATHNAME is a string, it is interpreted as a logical pathname string.
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.
This function seems to be buggy at this time. Sorry.
(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 lisp:*parse-namestring-ansi* to non-NIL.
(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 lisp:*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 lisp:*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 lisp:*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.
Table of Contents
RENAME-FILE RENAME-FILE always returns a non-logical pathname as its first value.
PROBE-FILE PROBE-FILE can not be used to check whether a directory exists. Use the function lisp: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 (lisp: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.
(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).
lisp:dir (lisp:dir &OPTIONAL pathname) is like DIRECTORY, but displays the pathnames instead of returning them. (lisp:dir) shows the contents of the current directory.
lisp:cd
(lisp:cd [pathname]) manages the current directory.
(lisp:cd [pathname]) manages the current host, current device and the current directory.
(lisp:cd [pathname]) manages the current device and the current directory.
lisp:cd (lisp:cd pathname) sets it, (lisp:cd) returns it.
lisp:default-directory (lisp:default-directory) is equivalent to (lisp:cd). (SETF (lisp:default-directory) pathname) is equivalent to (lisp:cd pathname), except for the return value.
lisp:make-dir (lisp:make-dir directory-pathname) creates a new subdirectory.
lisp:delete-dir (lisp:delete-dir directory-pathname) removes an (empty) subdirectory.
Table of Contents
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.
*TERMINAL-IO* is not the only stream that communicates directly with the user: During execution of the body of a (lisp:with-keyboard . body) form, lisp:*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:
(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).
the key name, for non-standard keys:
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
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
key: F1..F10
value: :F1..:F10
key: Help
value: :Help
key: Arrow keys
value: :Left:Right :Up:Down
the ASCII code for standard keys
(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.
if pressed together with the Control key.
(Platform dependent: DOS, OS/2, Win32 platforms only.) if pressed together with the Alternate key.
STREAM-ELEMENT-TYPE is SETFable. The element type of streams created by the functions OPEN, lisp:make-pipe-input-stream, lisp:make-pipe-output-stream, lisp:make-pipe-io-stream, lisp:socket-accept, lisp:socket-connect can be modified, if the old and the new element type 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.
The function (lisp: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 element-type (UNSIGNED-BYTE 8). element-type should be a type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.
(lisp:read-integer stream element-type) is like (READ-BYTE stream) if stream's 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 (lisp: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 element-type (UNSIGNED-BYTE 8). element-type should be a type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
The function (lisp:write-integer integer stream element-type &OPTIONAL endianness) writes a multi-byte integer to stream. stream should be a stream with element-type (UNSIGNED-BYTE 8). element-type should be a type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.
(lisp:write-integer integer stream element-type) is like (WRITE-BYTE integer stream) if stream's 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 (lisp: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 element-type (UNSIGNED-BYTE 8). element-type should be a type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
In addition to READ-SEQUENCE, the following two functions are provided:
(lisp:read-byte-sequence sequence stream &KEY :start :end) fills the subsequence of sequence specified by :start and :end with integers 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 element type (UNSIGNED-BYTE 8).
(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 element type CHARACTER or an input string stream.
In addition to WRITE-SEQUENCE, the following two functions are provided:
(lisp:write-byte-sequence sequence stream &KEY :start :end) outputs the integers 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 element type (UNSIGNED-BYTE 8).
(lisp: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 element type CHARACTER.
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.
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
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.
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 lisp:*default-file-encoding*.
for functions that create socket-streams 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.
Table of Contents
An additional variable lisp:*print-closure* controls whether compiled and interpreted functions (closures) are output in detailed form. If lisp:*print-closure* is non-NIL, compiled closures are output in #Y syntax which the reader understands. lisp:*print-closure* is initially set to NIL.
An additional variable lisp:*print-rpars* controls the output of the right (closing) parentheses. If lisp:*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. lisp:*print-rpars* is initially set to NIL.
An additional variable lisp:*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. lisp:*print-indent-lists* is initially set to 1.
When *PRINT-READABLY* is true, other vectors are written as follows: if the element-type is T, the syntax #(x0 ... xn-1) is used. Otherwise, the syntax #A(element-type dimensions contents) is used.
When *PRINT-READABLY* is true, other arrays are written as follows: if the element-type is T, the syntax #rankA contents is used. Otherwise, the syntax #A(element-type dimensions contents) is used.
WRITE & WRITE-TO-STRING The functions WRITE and WRITE-TO-STRING have an additional keyword :closure that can be used to bind lisp:*print-closure*.
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 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 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, we print it like this: #-CLISP #P"" #+CLISP #S(PATHNAME ...)
When the variable lisp:*print-pathnames-ansi* is NIL, otherwise the #P"" notation is used as per 1.5.1.4.1 Resolution of Apparent Conflicts in Exceptional Situations.
*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.lsp and is not available if you run CLISP without a memory image.
If *PRINT-READABLY* is true, *READ-DEFAULT-FLOAT-FORMAT* has no influence on the way floating point numbers are printed.
*PRINT-PRETTY* is initially NIL but set to T in config.lsp. This makes screen output prettier.
*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.
Table of Contents
This is the list of objects whose external representation can not 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 lisp:*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
#\ allows inputting characters of arbitrary code: e.g., #\Code231 yields the character (CODE-CHAR 231.).
#Y is used to read compiled functions and to set the current input stream's encoding.
#"" is used to read pathnames: #"test.lsp" is the value of (PATHNAME "test.lsp")
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.
lisp: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 lisp:read-char-will-hang-p returns NIL.
Note also that lisp:read-char-will-hang-p is not a good mean to test for end-of-stream: If lisp: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.
To be called only if stream's 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.
To be called only if stream's element-type is (unsigned-byte 8) or (signed-byte 8). Returns NIL if READ-BYTE will return immediately. Otherwise it returns true.
To be called only if stream's 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.
Table of Contents
The compiler can be called not only by the functions COMPILE, COMPILE-FILE and DISASSEMBLE, but also by the declaration (compile).
(COMPILE-FILE input-file &KEY :output-file :listing :warnings :verbose :print) compiles a file to platform-independent bytecode.
should be a pathname/string/symbol.
should be NIL or T or a pathname/string/symbol or an output-stream. The default is T.
should be NIL or T or a pathname/string/symbol or an output-stream. The default is NIL.
specifies whether warnings should also appear on the screen.
specifies whether error messages should also appear on the screen.
specifies whether an indication which forms are being compiled should appear on the screen.
The variables lisp:*compile-warnings*, *COMPILE-VERBOSE*, *COMPILE-PRINT* provide defaults for the :warnings, :verbose, :print keyword arguments, respectively. For each input file (default file type: #p".lsp") 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
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.
LOAD has two additional keywords :echo and :compiling.
(LOAD filename &KEY :verbose :print :echo :if-does-not-exist :compiling)
causes LOAD to emit a short message that a file is being loaded. The default is *LOAD-VERBOSE*, which is initially T.
causes LOAD to print the value of each form. The default is *LOAD-PRINT*, which is initially NIL.
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 lisp:*load-echo*, which is initially NIL.
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 lisp:*load-compiling*, which is initially NIL.
The variable lisp:*load-paths* contains a list of directories where program files are searched - additionally to the specified or current directory - by LOAD, REQUIRE, COMPILE-FILE.
The variable *FEATURES* initially contains the symbols
keyword: :CLISP
meaning: the name of this implementation
keyword: :ANSI-CL
meaning: if invoked with the -a command line option.
keyword: :COMMON-LISP
meaning:
keyword: :CLTL2
meaning:
keyword: :INTERPRETER
meaning:
keyword: :COMPILER
meaning:
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!)
Table of Contents
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.
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.
The function lisp:uncompile does the converse of COMPILE: (lisp:uncompile function-name) reverts an interpreted function that has been entered or loaded in the same session and then compiled back to its interpreted form.
No on-line documentation is available for the system functions (yet). DOCUMENTATION still has the CLtL1 implementation.
lisp:clhs [Common Lisp HyperSpec] access is provided via (lisp:clhs symbol &KEY browser) function which uses your web browser. browser should be a valid keyword in the lisp:*browsers* alist.
(TRACE fun ...) makes the functions fun, ... traced. fun 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
no trace output as long as form is true
invokes the stepper as soon as form is true
evaluates form before calling the function
evaluates form after return from the function
goes into the break loop before calling the function if form is true
goes into the break loop after return from the function if form is true
prints the values of form before calling the function
prints the values of form after return from the function
prints the values of form both before calling and after return from the function
In all these forms you can access the following variables:
TRACE and UNTRACE are also applicable to functions (SETF symbol) and to macros, but not to locally defined functions and macros.
The function INSPECT takes a keyword argument :frontend, which specifies the way CLISP will interact with the user.
Available :frontends for INSPECT in CLISP
The interaction is conducted via the *TERMINAL-IO* stream. Please use the :h command to get the list of all available commands.
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.
The macro lisp:space is like the macro TIME: (lisp: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.
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 lisp:gc starts a global garbage-collection and its return value has the same meaning as the second value of ROOM.
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 lisp:space macro for more detailed analysis), and the number of GCs performed, if any.
The function ED calls the external editor specified by the variable lisp:*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.
The variable lisp:*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
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.
The functions SHORT-SITE-NAME, LONG-SITE-NAME should be defined in a site-specific config.lsp file.
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.
If DRIBBLE is called with an argument, and dribbling is already enabled, a warning is printed, and the new dribbling request is ignored.
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.
No notes.
No notes.
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.
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
yes
yes, except for argument list checking in CALL-NEXT-METHOD in compiled code (items 11,12)
yes
no
yes for arrays, no for complex numbers
yes
yes
yes
yes
no
no
yes
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes, still present in package LISP
yes
yes
yes
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes, except for (6)
yes
yes
yes
yes
yes
no
yes
yes
no
yes
yes
yes
yes for *PRINT-READABLY*, *READ-EVAL* and WITH-STANDARD-IO-SYNTAX, no for everything else
yes
no
no
yes
yes
no
yes
??
yes
yes
yes
no
yes
no
no
yes
yes
yes
yes
yes
yes
no (furthermore it gets hairy when applied to BOA constructors)
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
no
no
yes
yes
yes
yes
yes
yes
no for EQUALP on hash tables, yes for everything else
yes
yes
yes, except maybe if LOAD :compiling T
no
no
yes
yes
yes
yes, actually implement MEDIUM
yes
yes
no
yes
no
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes, except that ~F, ~E, ~G, ~$ also bind *PRINT-BASE* to 10 and *PRINT-RADIX* to NIL
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
no
yes
yes
??
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
no
obsolete
yes, except for macro expansion at compile time
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
yes
yes
obsolete
yes
no
yes
yes
yes
no
no
yes
yes
yes
yes
no
no
yes
yes
yes
yes
yes
yes
yes
yes
no
yes
yes
yes
yes
no
no
yes
yes
yes
yes
no
no
yes
no
yes
yes
yes
no
yes
yes
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes, when lisp:*sequence-count-ansi* is non-NIL; otherwise negative :count values are not allowed.
yes
yes
yes
no
yes, except that READ-DELIMITED-LIST still constructs a list
yes
yes
yes
yes
yes
yes
yes, except that REQUIRE wants a pathname, not a list of pathnames
superseded by REQUIRE-PATHNAME-DEFAULTS-AGAIN:X3J13-DEC-91
yes
yes
yes
yes
yes
yes
no
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
no
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
no
yes
no
yes
yes
yes
yes
yes
yes
yes
yes
yes, but no warning
yes
no
yes
no
yes
yes, except for class METHOD-COMBINATION
yes
yes
yes
yes, could add error checking
yes
yes
yes
yes
yes
yes
yes
yes
yes
yes
Table of Contents
The function (lisp: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 lisp:saveinitmem.
The functions (lisp:exit [errorp]), (lisp:quit [errorp]) and (lisp: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.
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 lisp:deflanguage: (lisp: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 lisp:definternational: (lisp:definternational symbol &OPTIONAL (default-language T)) and add language-dependent values through the macro lisp:deflocalized: (lisp: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 lisp:localized: (lisp:localized symbol &OPTIONAL language)
An encoding describes the correspondence between characters and raw bytes during input/output via streams with 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.
Only one character set is understood: the platform's native (8-bit) character set. See Chapter 13.
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 \unnnn 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.
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:
HP-UX systems support in particular, among others:
AIX 4.2 systems support in particular, among others:
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.
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.
The function (lisp: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:
lisp:*default-file-encoding* is the encoding used for new file/pipe/socket streams, when no :external-format argument was specified.
is the encoding used for pathnames in the file system. Normally, this is a 1:1 encoding. Its line terminator mode is ignored.
is the encoding used for communication with the terminal, in particular by *TERMINAL-IO*.
is the encoding used for access to environment variables, command line options, and the like. Its line terminator mode is ignored.
Encodings can also be used to convert directly between strings and their corresponding byte vector representation according to that encoding.
converts the subsequence of byte-vector from start to end to a string, according to the given encoding, and returns the resulting string.
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.
Two mechanisms are supported for creating new streams with user-defined behavior:
You can create a new subclass of lisp: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 lisp: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 lisp:make-generic-stream.
The fundamental-stream API is based on a 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.
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 “LISP”.
Defined classes
This is a superclass of all user-defined streams. It is a subclass of STREAM and of STANDARD-OBJECT. Its metaclass is STANDARD-CLASS.
This is a superclass of all user-defined input streams. It is a subclass of lisp: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 lisp:fundamental-input-stream.
This is a superclass of all user-defined output streams. It is a subclass of lisp: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 lisp:fundamental-output-stream.
This is a superclass of all user-defined streams whose element-type is CHARACTER. It is a subclass of lisp:fundamental-stream. It defines a method on STREAM-ELEMENT-TYPE that returns CHARACTER.
This is a superclass of all user-defined streams whose element-type is a subtype of INTEGER. It is a subclass of lisp:fundamental-stream. When you define a subclass of lisp:fundamental-binary-stream, you have to provide a method on STREAM-ELEMENT-TYPE.
This is a convenience class inheriting from both lisp:fundamental-character-stream and lisp:fundamental-input-stream.
This is a convenience class inheriting from both lisp:fundamental-character-stream and lisp:fundamental-output-stream.
This is a convenience class inheriting from both lisp:fundamental-binary-stream and lisp:fundamental-input-stream.
This is a convenience class inheriting from both lisp:fundamental-binary-stream and lisp:fundamental-output-stream.
general generic functions defined on streams
Returns the stream's element type, normally a subtype of CHARACTER or INTEGER.
The method for lisp:fundamental-character-stream returns CHARACTER.
Changes the stream's element type.
The default method signals an error.
This function is a CLISP extension.
Closes the stream and flushes any associated buffers.
When you define a primary method on this function, do not forget to CALL-NEXT-METHOD.
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
If a character was pushed back using lisp: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.
Pushes character, 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.
Returns a character or :eof, like lisp:stream-read-char, if that would return immediately. If lisp:stream-read-char's value is not available immediately, returns NIL instead of waiting.
The default method simply calls lisp:stream-read-char; this is sufficient for streams whose lisp:stream-read-char method never blocks.
If a character was pushed back using lisp:stream-unread-char, returns it. Otherwise returns the next character from the stream, avoiding any side effects lisp:stream-read-char would do. Returns :eof if the end-of-stream is reached.
The default method calls lisp:stream-read-char and lisp:stream-unread-char; this is sufficient for streams whose lisp:stream-read-char method has no side-effects.
If a character was pushed back using lisp: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 lisp:stream-read-char-no-hang and lisp:stream-unread-char; this is sufficient for streams whose lisp:stream-read-char method has no side-effects.
Returns NIL if lisp:stream-read-char will return immediately. Otherwise it returns true.
The default method calls lisp:stream-read-char-no-hang and lisp:stream-unread-char; this is sufficient for streams whose lisp:stream-read-char method has no side-effects.
This function is a CLISP extension.
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 lisp:stream-read-char; this is always sufficient if speed does not matter.
This function is a CLISP extension.
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 lisp:stream-read-char; this is always sufficient.
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
Writes character.
You must define a method for this function.
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.
Returns true if the next character would be written at the start of a new line.
The default method calls lisp:stream-line-column and compares its result with 0; this is sufficient for streams whose lisp:stream-line-column never returns NIL.
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 lisp:stream-write-char; this is always sufficient if speed does not matter.
This function is a CLISP extension.
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 lisp:stream-write-char-sequence; this is always sufficient.
Outputs a #\Newline character.
The default method calls lisp:stream-write-char; this is always sufficient.
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 lisp:stream-start-line-p and then lisp:stream-terpri if necessary; this is always sufficient.
Ensures that any buffered output has reached its destination, and then returns.
The default method does nothing.
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.
Attempts to discard any buffered output which has not yet reached its destination.
The default method does nothing.
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
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.
To be called only if stream's element-type is (unsigned-byte 8) or (signed-byte 8). Returns T if lisp:stream-read-byte would return immediately with an integer result. Returns :eof if the end-of-stream is already known to be reached. If lisp:stream-read-byte's value is not available immediately, returns NIL instead of waiting.
You must define a method for this function.
To be called only if stream's element-type is (unsigned-byte 8) or (signed-byte 8). Returns NIL if lisp:stream-read-byte will return immediately. Otherwise it returns true.
The default method calls lisp:stream-read-byte-lookahead; this is always sufficient.
To be called only if stream's element-type is (unsigned-byte 8) or (signed-byte 8). Returns an integer or :eof, like lisp:stream-read-byte, if that would return immediately. If lisp:stream-read-byte's value is not available immediately, returns NIL instead of waiting.
The default method calls lisp:stream-read-byte if lisp:stream-read-byte-lookahead returns true; this is always sufficient.
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 lisp:stream-read-byte; this is always sufficient if speed does not matter.
This function is a CLISP extension.
generic functions for binary output
Writes integer.
You must define a method for this function.
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 lisp:stream-write-byte; this is always sufficient if speed does not matter.
This function is a CLISP extension.
This interface is CLISP specific and now obsolete. Please use the Gray streams interface instead.
Generic streams are user programmable streams. The programmer interface:
returns a generic 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 lisp:make-generic-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 lisp:generic-stream-xyz corresponds to the Common Lisp function xyz. They all take a controller and some number of arguments.
Returns and consumes the next character, NIL at end of file. Takes one argument, the controller object.
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.
Returns and consumes the next integer, NIL at end of file. Takes one argument, the controller object.
This generic function is used to query the stream's input status. It returns NIL if lisp:generic-stream-read-char and lisp:generic-stream-peek-char will certainly return immediately. Otherwise it returns true.
The first argument is the controller object. The second argument is the character to be written.
The first argument is the controller object. The second argument is the integer to be written.
Writes the subsequence of string starting from start of length len. The first argument is the controller object.
Take one argument, the controller object.
A weak pointer is an object holding a reference to a given object, without keeping the latter from being garbage-collected.
returns a fresh weak pointer referring to value.
returns true if the object is of type weak-pointer.
returns two values: The original value and T, if the value has not yet been garbage-collected, else NIL and NIL.
Calling (lisp:finalize object function) has the effect that when the specified object is being garbage-collected, (FUNCALL function object) will be executed.
Calling (lisp: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.
The variable sys::*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 sys::*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: sys::prompt-new-package, returning *PACKAGE* or NIL if the current package is the same as it was initially; and sys::package-short-name taking one argument, a package, and returning its shortest name or nickname. Also, a variable sys::*command-index* contains the current prompt number, it is your responsibility to increment it (this variable is bound to 0 before saving the image).
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 lisp:*ansi* to T, or they can be switched on individually. Setting lisp:*ansi* to T implies the following:
Setting lisp:*print-pathnames-ansi* to T for [ANSI CL standard] compliant PATHNAME printing.
Setting lisp:*coerce-fixnum-char-ansi* to T so that FIXNUMs cannot be COERCEd to CHARACTERs (because a FIXNUM is not a character designator in [ANSI CL standard].)
Setting lisp:*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 lisp:*merge-pathnames-ansi* to T.
Setting lisp:*parse-namestring-ansi* to T.
Setting lisp:*floating-point-contagion-ansi* to T.
Adding :ansi-cl to *FEATURES*.
Please note that if you run CLISP with the -a switch or set the symbol-macro lisp:*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 lisp:*ansi* to NIL, reversing the above settings, i.e.,
Setting lisp:*print-pathnames-ansi* to NIL for readable PATHNAME printing.
Setting lisp:*coerce-fixnum-char-ansi* to NIL so that FIXNUMs can be COERCEd to CHARACTERs (via CODE-CHAR).
Setting lisp:*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 lisp:*merge-pathnames-ansi* to NIL.
Setting lisp:*parse-namestring-ansi* to NIL.
Setting lisp:*floating-point-contagion-ansi* to NIL.
Deleting :ansi-cl from *FEATURES*.
If you uncomment the (LOAD "macros3") line in the file init.lsp before doing make, or load the file macros3.lspinto a running CLISP, you gain access to the following macros:
lisp:ethe (lisp:ethe value-type form) enforces a type check in both interpreted and compiled code.
lisp:letf & lisp: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)))
lisp: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.,
(lisp: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.
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 lisp:with-keyboard and lisp:*keyboard-input* instead.)
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.
returns the window's size, as two values: height (= ymax+1) and width (= xmax+1).
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).
sets the position of the cursor in the window.
clears the window's contents and puts the cursor in the upper left corner.
clears the window's contents from the cursor position to the end of window.
clears the window's contents from the cursor position to the end of line.
removes the cursor's line, moves the lines below it up by one line and clears the window's last line.
inserts a line at the cursor's line, moving the lines below it down by one line.
switches highlighted output on.
switches highlighted output off.
makes the cursor visible, a cursor block in most implementations.
makes the cursor invisible, in implementations where this is possible.
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:
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:
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:
Note that in link.sh the module set directory is referred to as $modulename/.
the space-separated list of files that belong to the module set and will belong to every new linking set.
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.
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.
the space-separated list of Lisp files to load before building the lispinit.mem belonging to a new linking set.
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.
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.)
$ clisp-link create-module-set linux /somewhere/bindings/linux.cModify 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'
Compile linux.lsp, creating linux.c:
$ clisp -c /somewhere/bindings/linux.lsp
$ clisp-link add-module-set linux base base+linux
$ base+linux/lisp.run -M base+linux/lispinit.mem > (linux::stat "/tmp")
The following modules come with the distribution of CLISP:
Call the operating system functions from CLISP. The following platforms are supported:
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.
Access PostgreSQL from CLISP.
Compute the number of solutions to the n-queens problem on a n*n checkboard.
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"; }
Shell globbing
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.
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.
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.
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.
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.
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.
This is equivalent to def-call-out with :language :stdc.
This is equivalent to def-call-in with :language :stdc.
This form defines name to be both a defstruct structure type and a foreign C type with the given slots.
This form defines idents as constants, similarly to the C declaration enum { ident [= value], ... };
This form outputs the string (FORMAT NIL format-string {argument}*) to the C output file. This is a rarely needed low-level facility.
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.
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.
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.
Type change: A place denoting the same memory locations as the original c-place, but of type c-type.
returns the c-type corresponding to the 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.
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.
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 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)
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
This type corresponds to what C calls void*, an opaque pointer.
This type corresponds to what C calls char*, a zero-terminated string. Its Lisp equivalent is a string, without the trailing zero character.
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.
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.
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.
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.
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.
This type is equivalent to what C calls c-type *: a pointer to a single item of the given 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.
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 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.
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 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.
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.
Lisp allocates the storage using malloc() and never deallocates it. The C function is supposed to call free() when done with it.
Lisp allocates the storage on the stack, with dynamic extent. It is freed when the C function returns.
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.
Lisp calls free() on it when done.
Lisp does nothing.
Lisp calls free() on it when done.
Lisp does nothing.
Lisp allocates the storage using malloc() and never deallocates it. The C function is supposed to call free() when done with it.
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
The caller passes information to the callee.
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.
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.]
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.
A symbol-macro place lisp:*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.
Example 29.1. 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].acorresponds to
(declare (type foo f)) (foo-a (aref (foo-b f) 7)) or (slot-value (aref (slot-value f 'b) 7) 'a)
Example 29.2. 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)))
Example 29.3. 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)
Example 29.4. 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.lsp (do not call it cfun.lsp - 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.lsp $ 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.
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.lsp:
(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.lsp:
(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.lsp sorttest.lsp $ 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
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").
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 lisp:finalize.
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).
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*.
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.
A symbol-macro place lisp:*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 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 lisp:finalize for resource-tracking on the output side.
(declare-library-function name library-name {option}*)
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.
(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).
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.lsp 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).
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 lisp:finalize to free resources for you, as CLISP does not call finalizers when it exits, use UNWIND-PROTECT.
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.lsp) 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!
Example 29.6. 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.
(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)
Example 29.8. 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)))
Example 29.9. 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)))
CLISP comes with a small yet extensible and powerful ARexx interface.
tells you the name of the CLISP ARexx port. The default extension for CLISP ARexx scripts is cl.
-> arexx-msg-handle, or NIL on failure
-> 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.
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).
Closes down the server socket.
Returns the port which was bound using lisp:socket-server.
Given time argument(s), waits for (possibly zero) fixed duration for a connect on the socket-server. Without an argument, lisp:socket-wait blocks indefinitely.
Creates the server-side two-way stream for the connection.
Attempts to create a client-side two-way socket-stream. Blocks until the server accepts the connections.
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 lisp:socket-status
when no information is available or no operation is possible
when an i/o operation will cause an error
when you can only read from the stream
when you can only write to the stream
when you can both read from and write to the stream
These two functions return information about the socket-stream. For a server, lisp:socket-stream-host returns NIL.
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.
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.
The dual to lisp:socket-stream-peer - same information, host name and port number, but for the local host. The difference from lisp:socket-stream-host and lisp: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.
When CLISP is configured with an option --with-export-syscalls, some system calls are available from lisp, in package “POSIX”.
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).
Return the stat struct. file 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.]
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.]
Return a struct describing the OS, derived from uname(2) and sysconf(3).
Return 3 structs describing the resources usage and limits, derived from getrlimit(2) and getrusage(3).
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.]
This section describes four ways to turn CLISP programs into executable programs, which can be started as quickly as executables written in other languages.
CLISP can act as a script interpreter.
Files created with CLISP can be associated with the CLISP executables so that clicking on them would make CLISP execute the appropriate code.
Associate the extensions fas and lsp with CLISP; then you can make the files executable and run them from the command line.
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.
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:
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 lisp:*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.
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.
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::lsp::/usr/bin/clisp:" >> /proc/sys/fs/binfmt_misc/register
Then you can do the following:
bash$ cat << EOF > hello.lsp (print "hello, world!") EOF bash$ clisp -c hello.lsp Compiling file /home/sds/hello.lsp ... Compilation of file /home/sds/hello.lsp 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.
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.
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.
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-streams.
(lisp:execute programfile arg1 arg2 ...) executes an external program. Its name is programfile. It is given the strings arg1, arg2, ... as arguments.
(lisp:execute command) executes a given command using the operating system's shell.
(lisp:shell [command]) calls the operating system's shell. (lisp:shell) calls the shell for interactive use. (lisp:shell command) calls the shell only for execution of the one given command.
The functions lisp:run-shell-command and lisp:run-program are the general interface to lisp:shell and the above:
(lisp:run-shell-command command :input :output :if-output-exists) runs a shell command.
(lisp:run-program program :arguments :input :output :if-output-exists) runs an external program.
the shell command.
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).
the program. The directories listed in the PATH environment variable will be searched for it.
a list of arguments (strings) that are given to the program.
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).
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).
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 lisp:make-pipe-io-stream. This use of lisp:run-program can cause deadlocks, see lisp:make-pipe-io-stream.
returns an input stream that will supply the output from the execution of the given operating system command.
returns an output stream that will pass its output as input to the execution of the given operating system command.
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.
The macro lisp:with-output-to-printer:
(lisp:with-output-to-printer (var [:external-format]) {declaration}* {form}*)binds the variable var to an output stream that sends its output to the printer.
When CLISP is configured with an option --with-dir-key, some directory access is available from lisp, in package “LISP”. 3 types of directory keys may exist, depending on the compilation environment.
valid directory key types
The following functions and macros are exported (please note that these features are experimental and the API may be modified in the future).
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.
Close the directory key. The preferred way is to use the lisp:with-dir-key-open macro.
Open the directory key (by calling lisp:dir-key-open on dkey, path and options), bind it to var, execute body, then close it with lisp:dir-key-close.
Return the type of the directory key
Return the path of this directory key, which is the path argument of lisp:dir-key-open if dkey was a type or the concatenation of the path argument and the lisp:dir-key-path of dkey.
One of :input, :output and :io, indicating the permitted operation on this key and its derivatives.
Check whether the key has been closed. It is not an error to close a closed key.
Delete the specified subkey or attribute.
Return the list of the subkeys or attributes.
Return the value of the specified attribute, similar to GETHASH and SETFable just like GETHASH.
Return some information about the directory key. This is highly platform-dependent and will probably be removed or replaced or modified in the future.
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
with-dir-key-search is used to implement dir-key-values, dir-key-childred and dir-key-dump-tree in dirkey.lisp.
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.
[CLtL2] 1990. 1032. 0-201-10088-6. Digital Press. Common Lisp: the Language (2nd Edition).
[ANSI CL] 1994. ANSI Common Lisp standard X3.226-1994 - Information Technology - Programming Language - Common Lisp.
[CLHS] Common Lisp HyperSpec.