
Copyright © 1992-2002 by Bruno Haible
Copyright © 1998-2002 by Sam Steingold
These notes are covered by the GNU GFDL:
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (GFDL), Version 1.1 or any later version published by the Free Software Foundation (FSF); with no Invariant Sections, with Front-Cover Text being this section, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License."
These notes discuss the CLISP implementation of Common Lisp by
and
Dr Bruno Haible
Louisenstraße 103
Bad Homburg
D-61348 Germany
http://www.haible.de/bruno/
The current maintainers are
Dr Michael Stoll
Westerwaldweg 22
Remagen-Oberwinter
D-53424 Germany
http://www.math.uni-duesseldorf.de/~stoll/
and
Dr Bruno Haible
Dr Sam Steingold
http://www.podval.org/~sds/
This implementation is mostly conforming to the [ANSI CL standard] available on-line as the [Common Lisp HyperSpec] (but the printed ANSI document remains the authoritative source of information). [ANSI CL standard] supersedes the earlier specifications [CLtL1] and [CLtL2].
The first part of these notes is indexed in parallel to the [Common Lisp HyperSpec] and documents the differences between the CLISP implementation of Common Lisp and the [ANSI CL standard].
The second part documents the CLISP garbage-collection (for developers only) and the bytecodes generated by the compiler (i.e., what is printed by DISASSEMBLE).
The third part documents the CLISP extensions.
The final delimiter of an interactive stream: On UNIX, the user has to type Control-D at the beginning of a line. On DOS or Win32, the user has to type Control-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.
The 11 symbols missing from the "COMMON-LISP" package (out of 978 specified by the [ANSI CL standard]):
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.
Reader macros are also defined for the following:
Table 2-1. Additional reader macros
| Macro | Meaning |
|---|---|
| #, | load-time evaluation |
| #Y | function objects and file EXT:ENCODINGs |
| #"" | pathname |
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).
Compiler macros are expanded in the compiled code only, and ignored by the interpreter.
The declarations (TYPE type variable ...), (FTYPE type function ...), (OPTIMIZE (quality value) ...) are ignored by the interpreter and the compiler.
The [ANSI CL standard] declaration (OPTIMIZE (debug ...)) is legal.
The [ANSI CL standard] declaration (IGNORABLE variable ...) affects the variable binding for the variable variable. The compiler will not warn about the variable, regardless whether it is used or not.
The declaration (compile) has the effect that the current form is compiled prior to execution. Examples:
(LOCALLY (DECLARE (compile)) form) |
(LET ((x 0)) (FLET ((inc () (DECLARE (compile)) (INCF x)) (dec () (DECF x))) (VALUES #'inc #'dec))) |
The type assertion (THE value-type form) enforces a type check in interpreted code. No type check is done in compiled code. See also the EXT:ETHE macro.
The initial value of an &AUX variable in a boa lambda list is the value of the corresponding slot's initial form.
(PROCLAIM '(SPECIAL variable)) declarations may not be undone. The same holds for DEFVAR, DEFPARAMETER and DEFCONSTANT declarations.
It is an error if a DEFCONSTANT variable is bound at the moment the DEFCONSTANT is executed, but DEFCONSTANT does not check this.
Constants may not be bound dynamically or lexically.
EVAL-WHEN also accepts the situations (NOT EVAL) and (NOT COMPILE).
Note that the situations LOAD and COMPILE are deprecated by the spec, and they are not equivalent to the new standard situations :LOAD-TOPLEVEL and :COMPILE-TOPLEVEL.
The general form of the COMPLEX type specifier is (COMPLEX type-of-real-part type-of-imaginary-part). The type specifier (COMPLEX type) is equivalent to (COMPLEX type type).
The [ANSI CL standard] type specifier (REAL low high) denotes the real numbers between low and high.
DEFTYPE lambda lists are subject to destructuring (nested lambda lists are allowed, as in DEFMACRO) and may contain a &WHOLE marker, but not an &ENVIRONMENT marker.
Function (EXT:TYPE-EXPAND typespec &OPTIONAL once-p). If typespec is a user-defined type, this will expand it recursively until it is no longer a user-defined type (unless once-p is supplied and non-NIL). Two values are returned - the expansion and an indicator (T or NIL) of whether the original typespec was a user-defined type.
The possible results of TYPE-OF
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, EXT:ENCODING, FFI:FOREIGN-POINTER, foreign-address, foreign-variable, foreign-function
EXT: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". "COMMON-LISP" uses (as in USE-PACKAGE) "CLOS" and EXT:RE-EXPORTs all its exported symbols. Since the default :USE argument to MAKE-PACKAGE is "COMMON-LISP", the CLOS symbols are normally visible in all user-defined 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 the following:
(DEFPACKAGE "CL-NO-CLOS" (:use "CL")) (DO-EXTERNAL-SYMBOLS (symbol "COMMON-LISP") (SHADOW symbol "CL-NO-CLOS")) (DO-SYMBOLS (symbol "CL-NO-CLOS") (EXPORT symbol "CL-NO-CLOS")) (IN-PACKAGE "CL-NO-CLOS") (LOAD "pcl") ; or whatever (DEFPACKAGE "MY-USER" (:use "CL-NO-CLOS")) (IN-PACKAGE "MY-USER") ;; your code which uses PCL goes here |
Macro DEFCLASS. It is required that the superclasses of a class be defined before the DEFCLASS form for the class is evaluated.
DEFCLASS supports the option :METACLASS STRUCTURE-CLASS. This option is necessary in order to define a subclass of a DEFSTRUCT-defined structure type using DEFCLASS instead of DEFSTRUCT.
When CALL-NEXT-METHOD is called with arguments, the rule that the ordered set of applicable methods must be the same as for the original arguments is enforced by the implementation only in interpreted code.
There is a generic function CLOS:NO-PRIMARY-METHOD (similar to NO-APPLICABLE-METHOD) which is called when a generic function of the class STANDARD-GENERIC-FUNCTION is invoked and no primary method on that generic function is applicable.
clos:generic-flet and clos:generic-labels are implemented as macros, not as special operators. They are not imported into the packages "COMMON-LISP-USER" and "COMMON-LISP" because of the [ANSI CL standard] issue GENERIC-FLET-POORLY-DESIGNED:DELETE.
The function ENSURE-GENERIC-FUNCTION is not implemented.
ADD-METHOD can put methods into other generic functions than the one the method came from.
PRINT-OBJECT is only called on objects of type STANDARD-OBJECT and STRUCTURE-OBJECT. It is not called on other objects, like 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.
FIXNUM is not a character designator in [ANSI CL standard], although CODE-CHAR provides an obvious venue to COERCE a FIXNUM to a CHARACTER. When CUSTOM:*COERCE-FIXNUM-CHAR-ANSI* is NIL, CLISP COERCEs FIXNUMs to CHARACTERs via CODE-CHAR. When CUSTOM:*COERCE-FIXNUM-CHAR-ANSI* is non-NIL, FIXNUMs cannot be COERCEd to CHARACTERs.
Macro DESTRUCTURING-BIND. does not perform full error checking.
PROG1, PROG2, AND, OR, PSETQ, WHEN, UNLESS, COND, CASE, MULTIPLE-VALUE-LIST, MULTIPLE-VALUE-BIND, MULTIPLE-VALUE-SETQ. are implemented as special operators and, as such, are rather efficient.
This macro allows specifying the test for CASE, e.g.,
(fcase string= (subseq foo 0 (position #\Space foo))
("first" 1)
(("second" "two") 2)
(("true" "yes") t)
(otherwise nil))
|
(let ((var (subseq foo 0 (position #\Space foo))))
(cond ((string= var "first") 1)
((or (string= var "second") (string= var "two")) 2)
((or (string= var "true") (string= var "yes")) t)
(t nil)))
|
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 Common Lisp 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 (EXT: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), (EXT:GET-SETF-METHOD form &OPTIONAL env), and (EXT:GET-SETF-METHOD-MULTIPLE-VALUE form &OPTIONAL env) receive as optional argument env the environment necessary for macro expansions. In DEFINE-SETF-EXPANDER and EXT:DEFINE-SETF-METHOD lambda lists, one can specify &ENVIRONMENT and a variable, which will be bound to the environment. This environment should be passed to all calls of GET-SETF-EXPANSION, EXT:GET-SETF-METHOD and EXT:GET-SETF-METHOD-MULTIPLE-VALUE. If this is done, even local macros will be interpreted as places correctly.
Attempts to modify read-only data will signal an error. Program text and quoted constants loaded from files are considered read-only data. This check is only performed for strings, not for conses, other kinds of arrays, and user-defined data types.
(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 EXT:SYMBOL-MACRO-EXPAND tests for a SYMBOL-MACRO: If symbol is defined as a SYMBOL-MACRO, (EXT:SYMBOL-MACRO-EXPAND symbol) returns two values, T and the expansion, otherwise it returns NIL.
Calling BOUNDP on a symbol defined as a SYMBOL-MACRO returns T.
Calling SYMBOL-VALUE on a symbol defined as a SYMBOL-MACRO returns the value of the expansion. Calling SET on a symbol defined as a SYMBOL-MACRO calls SETF on the expansion.
Calling MAKUNBOUND on a symbol defined as a SYMBOL-MACRO removes the SYMBOL-MACRO definition.
Constant LAMBDA-LIST-KEYWORDS. (&OPTIONAL &REST &KEY &ALLOW-OTHER-KEYS &AUX &BODY &WHOLE &ENVIRONMENT)
Table 5-1. Function call limits (platform dependent)
| CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU |
|---|---|---|---|
| CALL-ARGUMENTS-LIMIT | 216=65536 | 232=4294967296 | |
| MULTIPLE-VALUES-LIMIT | 27=128 | ||
| LAMBDA-PARAMETERS-LIMIT | 216=65536 | 232=4294967296 | |
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))))
|
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 be respected. This is managed by the system. (But the print-circle mechanism handles only those objects that are (direct or indirect) components of structure.)
The value of *PRINT-LEVEL* is respected by WRITE, PRIN1, PRINC, PRINT, PPRINT, FORMAT instructions ~A, ~S, ~W, and FORMAT instructions ~R, ~D, ~B, ~O, ~X, ~F, ~E, ~G, ~$ with not-numerical arguments. Therefore the print-level mechanism works automatically if only these functions are used for outputting objects and if they are not called on objects with nesting level > 1. (The print-level mechanism does not recognize how many parentheses you have output. It only counts how many times it was called recursively.)
The value of *PRINT-LENGTH* must be respected, especially if you are outputting an arbitrary number of components.
The value of *PRINT-READABLY* must be respected. Remember that the values of *PRINT-ESCAPE*, *PRINT-LEVEL*, *PRINT-LENGTH* are ignored if *PRINT-READABLY* is true. The value of *PRINT-READABLY* is respected by PRINT-UNREADABLE-OBJECT, WRITE, PRIN1, PRINC, PRINT, PPRINT, FORMAT instructions ~A, ~S, ~W, and FORMAT instructions ~R, ~D, ~B, ~O, ~X, ~F, ~E, ~G, ~$ with not-numerical arguments. Therefore *PRINT-READABLY* will be respected automatically if only these functions are used for printing objects.
You need not worry about the values of *PRINT-BASE*, *PRINT-RADIX*, *PRINT-CASE*, *PRINT-GENSYM*, *PRINT-ARRAY*, CUSTOM:*PRINT-CLOSURE*, CUSTOM:*PRINT-RPARS*, CUSTOM:*PRINT-INDENT-LISTS*.
The :INHERIT option is exactly like :INCLUDE except that it does not create new accessors for the inherited slots.
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.
Macro EXT:MUFFLE-CERRORS. The macro (EXT:MUFFLE-CERRORS {form}*) executes the forms. When a continuable error occurs, no message is printed. Instead, the CONTINUE restart is invoked.
Macro EXT:APPEASE-CERRORS. The macro (EXT:APPEASE-CERRORS {form}*) executes the forms. When a continuable error occurs, the error is printed as a warning and the CONTINUE restart is invoked.
Macro EXT:EXIT-ON-ERROR. The macro (EXT:EXIT-ON-ERROR {form}*) executes the forms. When a non-continuable error or a Control-C interrupt occurs, the error is printed and CLISP terminates with an error status.
Macro EXT:WITH-RESTARTS. The macro EXT:WITH-RESTARTS is like RESTART-CASE, except that the forms are specified after the restart clauses instead of before them, and the restarts created are not implicitly associated to any condition. (EXT:WITH-RESTARTS ({restart-clause}*) {form}*) is therefore equivalent to (RESTART-CASE (PROGN {form}*) {restart-clause}*).
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.
Macro 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
Macro (RESTART-CASE form {restart-clause}*)
(restart-name arglist
{keyword-value}* {form}*) |
(restart-name {keyword-value}*
arglist {form}*)
|
Function 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.
The [ANSI CL standard] packages present in CLISP
with the nicknames "CL" and "LISP"
with the nicknames "CL-USER" and "USER"
with the nickname ""
The package "COMMON-LISP" EXPORTs only those symbols from the [ANSI CL standard] that are actually implemented.
Function EXT:PACKAGE-LOCK. Packages can be "locked". When a package is locked, attempts to change its symbol table or redefine functions which its symbols name result in a continuable error (continuing overrides locking for this operation). Function (EXT:PACKAGE-LOCK package) returns the generalized boolean indicating whether the package is locked. A package (or list thereof) can be locked using (SETF (EXT:PACKAGE-LOCK package-or-list) T). CLISP locks its system packages (specified in the variable CUSTOM:*SYSTEM-PACKAGE-LIST*).
Macro EXT:WITHOUT-PACKAGE-LOCK. If you want to evaluate some forms with certain packages unlocked, you can use EXT:WITHOUT-PACKAGE-LOCK:
(without-package-lock ("LISP" "EXT" "CLOS")
(defun restart () ...))
|
(without-package-lock ("LISP") (trace read-line))
|
Discussion - see also the USENET posting by Steven M. Haflich. This should prevent you from accidentally hosing yourself with
(defstruct instance ...) |
The "COMMON-LISP-USER" package uses the "COMMON-LISP" and "EXT" packages.
The following additional packages exist:
Implementation-Defined Packages
EXPORTs all CLOS-specific symbols, including some additional symbols.
has the nicknames "SYS" and "COMPILER", and has no EXPORTed symbols. It defines many system internals.
is the umbrella package for all extensions: it imports and EXT:RE-EXPORTs all the external symbols in all CLISP extensions, so a simple (USE-PACKAGE "EXT") is enough to make all the extensions available in the current package. This package uses packages (in addition to "COMMON-LISP"): "LDAP" "POSIX" "SOCKET" "GSTREAM" "GRAY" "I18N" "CUSTOM".
defines and EXPORTs some character sets, for use with EXT: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 "COMMON-LISP-USER" belong to the implementation, in the sense that the programs that do not follow Section 11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs cause undefined behavior.
For MAKE-PACKAGE, the default value of the :USE argument is ("COMMON-LISP").
MAKE-PACKAGE accepts a keyword argument :CASE-SENSITIVE. Similarly, DEFPACKAGE accepts an option :CASE-SENSITIVE. When its value is non-NIL, the package will be case sensitive, i.e., the reader will not case-convert symbol names before looking them up or creating them in this package. The package names are still subject to (READTABLE-CASE *READTABLE*), though.
The function (EXT:RE-EXPORT FROM-PACK TO-PACK) re-exports all external symbols from FROM-PACK also from TO-PACK, provided it already uses FROM-PACK; and signals an error otherwise.
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.
Byte specifiers are objects of built-in type BYTE, not INTEGERs.
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 754 |
| DOUBLE-FLOAT | 1 bit | 52+1 bits | 11 bits | IEEE 754 |
| LONG-FLOAT | 1 bit | >=64 bits | 32 bits | variable length |
The single and double float formats are those of the IEEE 754 "Standard for Binary Floating-Point Arithmetic", except that CLISP does not support features like ±0, ±inf, NaN, gradual underflow, etc. (Common Lisp does not make use of these features.) This is why *FEATURES* does not contain the :IEEE-FLOATING-POINT keyword.
Arbitrary Precision Floats. Long floats have variable mantissa length, which is a multiple of 16 (or 32, depending on the word size of the processor). The default length used when long floats are read is given by the place (EXT:LONG-FLOAT-DIGITS). It can be set by (SETF (EXT:LONG-FLOAT-DIGITS) n), where n is a positive integer. E.g., (SETF (EXT:LONG-FLOAT-DIGITS) 3322) sets the default precision of long floats to about 1000 decimal digits.
The floating point contagion is controlled by the variable CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*. When it is non-NIL, contagion is done as per the [ANSI CL standard]: SHORT-FLOAT → SINGLE-FLOAT → DOUBLE-FLOAT → LONG-FLOAT.
See it pragmatically: save what you can and let others worry about the rest.
Common Lisp knows the number's precision, not accuracy, so preserving the precision can be accomplished reliably, while anything relating to the accuracy is just a speculation - only the user (programmer) knows what it is in each case.
A computer 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) returns 3.25, while traditional CLISP would return 3.3. The implied random variables are: 3.25±0.005 and 3.3±0.05. Note that the traditional CLISP way does lie about the mean: the mean is 3.25 and nothing else, while the standard way could be lying about the deviation (accuracy): if the implied accuracy of 1.5 (0.05) is its actual accuracy, then the accuracy of the result cannot be smaller that that. Therefore, since Common Lisp has no way of knowing the actual accuracy, [ANSI CL standard] (and all the other standard engineering programming languages, like C, FORTRAN etc) decides that keeping the accuracy correct is the business of the programmer, while the language should preserve what it can - the precision.
Rounding errors accumulate, and if a computation is conducted with insufficient precision, an outright incorrect result can be returned. (E.g., E(x2) - E(x)2 can be negative!) The user should not mix floats of different precision (that's what CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION* is for), but one should not be penalized for this too harshly.
When CUSTOM:*FLOATING-POINT-CONTAGION-ANSI* is NIL, the traditional CLISP method is used, namely the result of an arithmetic operation whose arguments are of different float types is rounded to the float format of the shortest (least precise) of the arguments: RATIONAL → LONG-FLOAT → DOUBLE-FLOAT → SINGLE-FLOAT → SHORT-FLOAT (in contrast to 12.1.4.4 Rule of Float Precision Contagion!)
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.
Variable CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*. If the variable CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION* is non-NIL, a warning is emitted for every coercion involving different floating-point types.
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).
Function UPGRADED-COMPLEX-PART-TYPE. When the argument is not a recognizable subtype or REAL, UPGRADED-COMPLEX-PART-TYPE signals an ERROR, otherwise it returns REAL, since a COMPLEX number in CLISP can always have REALPART and IMAGPART of any type.
Variable CUSTOM:*DEFAULT-FLOAT-FORMAT*. When rational numbers are to be converted to floats (due to FLOAT, COERCE, SQRT or a transcendental function), the result type is given by the variable CUSTOM:*DEFAULT-FLOAT-FORMAT*.
Macro EXT:WITHOUT-FLOATING-POINT-UNDERFLOW. The macro (EXT: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.
Function EXT:! (EXT:! n) returns the factorial of n, n being a nonnegative INTEGER.
Function EXT:EXQUO. (EXT:EXQUO x y) returns the integer quotient x/y of two integers x,y, and signals an error when the quotient is not integer. (This is more efficient than /.)
Function EXT:XGCD. (EXT:XGCD x1 ... xn) returns the values l, k1, ..., kn, where l is the greatest common divisor of the integers x1, ..., xn, and k1, ..., kn are the integer coefficients such that
l = (GCD x1 ... xn) = (+ (* k1 x1) ... (* kn xn)) |
Constant PI. The value of PI is a LONG-FLOAT with the precision given by (EXT:LONG-FLOAT-DIGITS). When this precision is changed, the value of PI is automatically recomputed. Therefore PI is a variable, not a constant.
FLOAT-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 always evaluates to T:
(>= (FLOAT-DIGITS (FLOAT-DIGITS number digits)) digits) |
Table 12-3. Fixnum limits (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 (EXT:LONG-FLOAT-DIGITS) is SETFed. They are variables, not constants.
The characters are ordered according to a superset of the ASCII character set.
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 | ö | æ | ù | ú | û | ı | ü | ý | ł | ø | œ | ß | þ | ÿ |
Table 13-4. Standard characters:
| character | code |
|---|---|
| #\Space | #x20 |
| #\Newline | #x0A |
Table 13-5. Semi-standard characters:
| character | code |
|---|---|
| #\Backspace | #x08 |
| #\Tab | #x09 |
| #\Linefeed | #x0A |
| #\Page | #x0C |
| #\Return | #x0D |
#\Newline is the line terminator.
Table 13-6. Additional Named Characters
| character | code |
|---|---|
| #\Null | #x00 |
| #\Bell | #x07 |
| #\Escape | #x1B |
Table 13-7. Additional syntax for characters with code from #x00 to #x1F:
| character | code |
|---|---|
| #\^@ | #x00 |
| #\^A … #\^Z | #x01 … #x1A |
| #\^[ | #x1B |
| #\^\ | #x1C |
| #\^] | #x1D |
| #\^^ | #x1E |
| #\^_ | #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 cannot be used to compare objects of type SYS::INPUT-CHARACTER.
The system uses only font 0.
Table 13-8. Character bits
| key | value |
|---|---|
| :CONTROL | EXT:CHAR-CONTROL-BIT |
| :META | EXT:CHAR-META-BIT |
| :SUPER | EXT:CHAR-SUPER-BIT |
| :HYPER | EXT: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 system itself uses this SYS::INPUT-CHARACTER type only to mention special keys and Control/Alternate/Shift key status on return from (READ-CHAR EXT:*KEYBOARD-INPUT*).
The only defined character script is the type CHARACTER itself.
Characters have no implementation-defined attributes. All characters are simple characters.
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:
uc and lc are different
c is one of uc and lc
the upper case mapping of uc and of lc is uc
the lower case mapping of uc and of lc is lc
The titlecase property of UNICODE characters has no equivalent in Common Lisp.
The numeric characters are those UNICODE characters which are defined as digits by the UNICODE standard.
The characters are ordered according to their UNICODE code.
Newlines are written according to the stream's EXT:ENCODING, see the function STREAM-EXTERNAL-FORMAT and the description of EXT: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).
The integer returned by CHAR-INT is the same as the character's code.
See the description of EXT:ENCODINGs.
CHAR-CODE takes values from 0 (inclusive) to CHAR-CODE-LIMIT (exclusive), i.e., the implementation supports exactly CHAR-CODE-LIMIT characters.
Table 13-9. Number of characters (platform dependent)
| binaries built | without UNICODE support | with UNICODE support |
|---|---|---|
| CHAR-CODE-LIMIT | 28 = 256 | 17 * 216 = 1114112 |
The types ext:string-char and BASE-CHAR are equivalent to CHARACTER.
The graphic characters have been described above.
The standard characters are #\Newline and the graphic characters with a code between 32 and 126 (inclusive).
The alphabetic characters are these characters:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜßáíóúñѪºãõØøÀÃÕ etc.
The functions CHAR-EQUAL CHAR-NOT-EQUAL, CHAR-LESSP, CHAR-GREATERP, CHAR-NOT-GREATERP, CHAR-NOT-LESSP ignore bits and font attributes of their arguments.
Function (EXT:CHAR-WIDTH char). returns the number of screen columns occupied by char. This is 0 for non-spacing characters (such as control characters and many combining characters), 2 for double-width East Asian characters, and 1 for all other characters. See also function EXT:STRING-WIDTH.
The characters that are not graphic chars and the space character have names:
Table 13-10. Platform dependent characters: Amiga platforms only.
| code | char | ||
|---|---|---|---|
| (CODE-CHAR #x00) | #\Null | ||
| (CODE-CHAR #x01) | #\Code1 | ||
| (CODE-CHAR #x02) | #\Code2 | ||
| (CODE-CHAR #x03) | #\Code3 | ||
| (CODE-CHAR #x04) | #\Code4 | ||
| (CODE-CHAR #x05) | #\Code5 | ||
| (CODE-CHAR #x06) | #\Code6 | ||
| (CODE-CHAR #x07) | #\Bell | #\Bel | |
| (CODE-CHAR #x08) | #\Backspace | #\Bs | |
| (CODE-CHAR #x09) | #\Tab | #\Ht | |
| (CODE-CHAR #x0A) | #\Newline | #\Linefeed | #\Lf |
| (CODE-CHAR #x0B) | #\Vt | ||
| (CODE-CHAR #x0C) | #\Page | #\Ff | |
| (CODE-CHAR #x0D) | #\Return | #\Cr | |
| (CODE-CHAR #x0E) | #\So | ||
| (CODE-CHAR #x0F) | #\Si | ||
| (CODE-CHAR #x10) | #\Code16 | ||
| (CODE-CHAR #x11) | #\Code17 | ||
| (CODE-CHAR #x12) | #\Code18 | ||
| (CODE-CHAR #x13) | #\Code19 | ||
| (CODE-CHAR #x14) | #\Code20 | ||
| (CODE-CHAR #x15) | #\Code21 | ||
| (CODE-CHAR #x16) | #\Code22 | ||
| (CODE-CHAR #x17) | #\Code23 | ||
| (CODE-CHAR #x18) | #\Code24 | ||
| (CODE-CHAR #x19) | #\Code25 | ||
| (CODE-CHAR #x1A) | #\Code26 | ||
| (CODE-CHAR #x1B) | #\Escape | #\Esc | |
| (CODE-CHAR #x1C) | #\Code28 | ||
| (CODE-CHAR #x1D) | #\Code29 | ||
| (CODE-CHAR #x1E) | #\Code30 | ||
| (CODE-CHAR #x1F) | #\Code31 | ||
| (CODE-CHAR #x20) | #\Space | ||
| (CODE-CHAR #x7F) | #\Rubout | ||
| (CODE-CHAR #x9B) | #\Csi |
Table 13-11. Platform dependent characters: DOS, OS/2, Win32 platforms only.
| code | char | |
|---|---|---|
| (CODE-CHAR #x00) | #\Null | |
| (CODE-CHAR #x07) | #\Bell | |
| (CODE-CHAR #x08) | #\Backspace | #\Rubout |
| (CODE-CHAR #x09) | #\Tab | |
| (CODE-CHAR #x0A) | #\Newline | #\Linefeed |
| (CODE-CHAR #x0B) | #\Code11 | |
| (CODE-CHAR #x0C) | #\Page | |
| (CODE-CHAR #x0D) | #\Return | |
| (CODE-CHAR #x1A) | #\Code26 | |
| (CODE-CHAR #x1B) | #\Escape | |
| (CODE-CHAR #x20) | #\Space |
Table 13-12. Platform dependent characters: UNIX, Acorn platforms only.
| code | char | ||
|---|---|---|---|
| (CODE-CHAR #x00) | #\Null | #\Nul | |
| (CODE-CHAR #x01) | #\Soh | ||
| (CODE-CHAR #x02) | #\Stx | ||
| (CODE-CHAR #x03) | #\Etx | ||
| (CODE-CHAR #x04) | #\Eot | ||
| (CODE-CHAR #x05) | #\Enq | ||
| (CODE-CHAR #x06) | #\Ack | ||
| (CODE-CHAR #x07) | #\Bell | #\Bel | |
| (CODE-CHAR #x08) | #\Backspace | #\Bs | |
| (CODE-CHAR #x09) | #\Tab | #\Ht | |
| (CODE-CHAR #x0A) | #\Newline | #\Nl | #\Linefeed |
| (CODE-CHAR #x0B) | #\Vt | ||
| (CODE-CHAR #x0C) | #\Page | #\Np | |
| (CODE-CHAR #x0D) | #\Return | #\Cr | |
| (CODE-CHAR #x0E) | #\So | ||
| (CODE-CHAR #x0F) | #\Si | ||
| (CODE-CHAR #x10) | #\Dle | ||
| (CODE-CHAR #x11) | #\Dc1 | ||
| (CODE-CHAR #x12) | #\Dc2 | ||
| (CODE-CHAR #x13) | #\Dc3 | ||
| (CODE-CHAR #x14) | #\Dc4 | ||
| (CODE-CHAR #x15) | #\Nak | ||
| (CODE-CHAR #x16) | #\Syn | ||
| (CODE-CHAR #x17) | #\Etb | ||
| (CODE-CHAR #x18) | #\Can | ||
| (CODE-CHAR #x19) | #\Em | ||
| (CODE-CHAR #x1A) | #\Sub | ||
| (CODE-CHAR #x1B) | #\Escape | #\Esc | |
| (CODE-CHAR #x1C) | #\Fs | ||
| (CODE-CHAR #x1D) | #\Gs | ||
| (CODE-CHAR #x1E) | #\Rs | ||
| (CODE-CHAR #x1F) | #\Us | ||
| (CODE-CHAR #x20) | #\Space | #\Sp | |
| (CODE-CHAR #x7F) | #\Rubout | #\Delete | #\Del |
The function EXT:MAPCAP is like MAPCAN, except that it concatenates the resulting lists with APPEND instead of NCONC:
(EXT:MAPCAP function x1 ... xn) == (APPLY #'APPEND (MAPCAR function x1 ... xn))
(Actually a bit more efficient that this would have been.)
The function EXT:MAPLAP is like MAPCON, except that it concatenates the resulting lists with APPEND instead of NCONC:
(EXT:MAPLAP function x1 ... xn) == (APPLY #'APPEND (MAPLIST function x1 ... xn))
(Actually a bit more efficient that this would have been.)
Function MAKE-ARRAY. MAKE-ARRAY can return specialized arrays for the ARRAY-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. Array limits (platform dependent)
| CPU type | 16-bit CPU | 32-bit CPU | 64-bit CPU |
|---|---|---|---|
| ARRAY-RANK-LIMIT | 216 = 65536 | 232 = 4294967296 | |
| ARRAY-DIMENSION-LIMIT | 224 = 16777216 | 232 = 4294967296 | |
| ARRAY-TOTAL-SIZE-LIMIT | 224 = 16777216 | 232 = 4294967296 | |
Note that these constants are not fixnums, contrary to the [ANSI CL standard] Issue ARRAY-DIMENSION-LIMIT-IMPLICATIONS:ALL-FIXNUM.
Function 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!
String comparison is based on the function CHAR<=. Therefore diphthongs do not obey the usual national rules. Example: o < oe < z < ö.
Function EXT:STRING-WIDTH. (EXT:STRING-WIDTH string) returns the number of screen columns occupied by string. This is computed as the sum of all EXT:CHAR-WIDTHs of all of the string's characters.
For iteration through a sequence, a macro EXT:DOSEQ, similar to DOLIST, may be used instead of MAP:
(EXT:DOSEQ (variable seqform [resultform]) {declaration}* {tag|form}*) |
EXT:DOSEQ forms are "iteration forms".
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.
Variable CUSTOM:*SEQUENCE-COUNT-ANSI*. Contrary to the [ANSI CL standard] issue 283 RANGE-OF-COUNT-KEYWORD:NIL-OR-INTEGER, negative :COUNT keyword arguments are not allowed unless you set CUSTOM:*SEQUENCE-COUNT-ANSI* to a non-NIL value, in which case "using a negative integer value is functionally equivalent to using a value of zero", as per the [ANSI CL standard] 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.
MAKE-HASH-TABLE supports additional keywords :initial-contents and :weak:
(MAKE-HASH-TABLE &KEY :test :initial-contents :size :rehash-size :rehash-threshold :weak) |
The :initial-contents argument is an alist that is used to initialize the new hash table. The :rehash-threshold argument is ignored.
The boolean :weak argument defaults to NIL and specifies whether the HASH-TABLE is weak: the key is not considered accessible for the garbage-collection purposes, i.e., if it is only accessible in the weak HASH-TABLE, it is garbage-collected and removed from the weak HASH-TABLE.
The SETFable predicate EXT:HASH-TABLE-WEAK-P checks whether the HASH-TABLE is weak.
Just like EXT:WEAK-POINTERs, weak HASH-TABLEs cannot be printed readably.
For iteration through a hash table, a macro EXT:DOHASH similar to DOLIST, can be used instead of MAPHASH:
(EXT:DOHASH (key-var value-var hash-table-form [resultform]) {declaration}* {tag|form}*) |
EXT:DOHASH forms are "iteration forms".
For most operations, pathnames denoting files and pathnames denoting directories cannot be used interchangeably.
For example, #P"foo/bar" denotes the file #P"bar" in the directory #P"foo", while #P"foo/bar/" denotes the subdirectory #P"bar" of the directory #P"foo".
For example, #P"foo\\bar" denotes the file #P"bar" in the directory #P"foo", while #P"foo\\bar\\" denotes the subdirectory #P"bar" of the directory #P"foo".
For example, #P"foo.bar" denotes the file #P"foo" in the directory #P"bar", while #P"foo.bar." denotes the subdirectory #P"bar" of the directory #P"foo".
User variable CUSTOM:*DEVICE-PREFIX* controls translation between Cygwin pathnames (e.g., #P"/cygdrive/c/gnu/clisp/") and native Win32 pathnames (e.g., #P"C:\\gnu\\clisp\\") When it is set to NIL, no translations occur and the Cygwin port will not understand the native paths and the native Win32 port will not understand the Cygwin paths. When its value is a string, it is used by PARSE-NAMESTRING to translate into the appropriate platform-specific representation, so that on Cygwin, (PARSE-NAMESTRING "c:/gnu/clisp/") returns #P"/cygdrive/c/gnu/clisp/", while on Win32 (PARSE-NAMESTRING "/cygdrive/c/gnu/clisp/") returns #P"C:/gnu/clisp/". The initial value is "cygdrive", you should edit #P"config.lisp" to change it.
This is especially important for the directory-handling functions.
Table 19-1. The minimum filename syntax that may be used portably
| pathname | meaning |
|---|---|
| "xxx" | for a file with name xxx |
| "xxx.yy" | for a file with name xxx and type yy |
| ".yy" | 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
Table 19-2. Directory = (startpoint . subdirs)
| element | values | meaning |
|---|---|---|
| startpoint | :RELATIVE | :ABSOLUTE | |
| subdirs | () | (subdir . subdirs) | |
| subdir | :WILD-INFERIORS | ** or ..., all subdirectories |
| subdir | SIMPLE-STRING, may contain wildcard characters "?" and "*" (may also be specified as :WILD) | |
| subdir | :PARENT | "/" instead of "subdir/" |
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!
An Amiga filename is split into name and type.
Case is ignored in the strings on comparison. No case conversions are performed.
Table 19-3. filename notations
| External notation: | "dev:sub1.typ/sub2.typ/name.typ" |
| using defaults: | "sub1.typ/sub2.typ/name.typ" |
| or | "name.typ" |
| or | "sub1.typ/**/sub3.typ/x*.lisp" |
| or similar. |
Formal specification of the external notation
any character except ':','/' and '*','?'
{ch}+
[ <empty> | ':' | name ':' ]
Table 19-4.
| 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> | name ]
Table 19-5.
| empty | parent directory |
device { subdir '/' }* name
Table 19-6. Examples
| String | Device | Directory | our pathname |
|---|---|---|---|
| "c:foo" | 'C' | "device->foo" | "c" (:ABSOLUTE #P"foo") |
| "c:foo/" | 'C' | "device->foo" | "c" (:ABSOLUTE #P"foo") |
| "c:foo/bar" | 'C' | "device->foo->bar" | "c" (:ABSOLUTE #P"foo" #P"bar") |
| "c:/foo" | 'C' | "device->up->foo" | "c" (:ABSOLUTE :PARENT #P"foo") |
| "c:" | 'C' | "device" | "c" (:ABSOLUTE) |
| ":foo" | current | "device->root->foo" | NIL (:ABSOLUTE #P"foo") |
| #P"foo" | current | "device->foo" | NIL (:RELATIVE #P"foo") |
| "/foo" | current | "device->up->foo" | NIL (:RELATIVE :PARENT #P"foo") |
| "//foo/bar" | current | "device->up->up->foo->bar" | NIL (:RELATIVE :PARENT :PARENT #P"foo" #P"bar") |
| "\" | current | "device" | 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
Table 19-7. Directory = (startpoint . subdirs)
| element | values | meaning |
|---|---|---|
| startpoint | :RELATIVE | :ABSOLUTE | |
| subdirs | () | (subdir . subdirs) | |
| subdir | :WILD-INFERIORS | ** or ..., all subdirectories |
| subdir | 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)
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.
Table 19-8. filename notations
| External notation: | "server:sub1.typ/sub2.typ/name.typ" |
| using defaults: | "sub1.typ/sub2.typ/name.typ" |
| or | "name.typ" |
| or | "sub1.typ/**/sub3.typ/x*.lisp" |
| or similar. |
Pathname components
always NIL
NIL or :WILD or A|...|Z
Table 19-9. Directory = (startpoint . subdirs)
| element | values | meaning |
|---|---|---|
| startpoint | :RELATIVE | :ABSOLUTE | |
| subdirs | () | (subdir . subdirs) | |
| subdir | :WILD-INFERIORS | ** or ..., all subdirectories |
| subdir | 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)
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.
Table 19-10. filename notations
| External notation: | "A:\sub1.typ\sub2.typ\name.typ" |
| using defaults: | "\sub1.typ\sub2.typ\name.typ" |
| or | "name.typ" |
| or | "*:\sub1.typ\**\sub3.typ\x*.lisp" |
| or similar. |
Instead of "\" one may use "/", as usual for DOS calls.
Pathname components
NIL or SIMPLE-STRING, wildcard characters may occur but do not act as wildcards
NIL or :WILD or A|...|Z
Table 19-11. Directory = (startpoint . subdirs)
| element | values | meaning |
|---|---|---|
| startpoint | :RELATIVE | :ABSOLUTE | |
| subdirs | () | (subdir . subdirs) | |
| subdir | :WILD-INFERIORS | ** or ..., all subdirectories |
| subdir | 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)
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.
Table 19-12. filename notations
| External notation: | "A:\sub1.typ\sub2.typ\name.typ" |
| using defaults: | "\sub1.typ\sub2.typ\name.typ" |
| or | "name.typ" |
| or | "*:\sub1.typ\**\sub3.typ\x*.lisp" |
| or similar. |
Instead of "\" one may use "/", as usual for DOS calls.
If host is non-NIL and the directory's startpoint is not :ABSOLUTE, (PARSE-NAMESTRING (NAMESTRING pathname)) will not be the same as pathname.
Name/type namestring split. A 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. if the only "." is the first character, then
the behavior depends on the value of the user variable
CUSTOM:*PARSE-NAMESTRING-DOT-FILE*
which can be either
Due to this 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 "foo.bar").
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:
"$.Documents.Memos"
"%.cc"
Files may also be accessed on file systems other than the current one by prefixing the filename with a file system specification. A file system name may appear between "-" characters, or suffixed by a ":", though the latter is advised since "-" can also be used to introduce a parameter on a command line, or as part of a file name. For example:
"-net-$.SystemMesg"
"adfs:%.aasm"
Special fields are used to supply more information to the file system than you can using standard path names; for example NetFS and NetPrint use them to specify server addresses or names. They are introduced by a "#" character; a variety of syntaxes are possible:
"net#MJHardy::disc1.mike"
"#MJHardy::disc1.mike"
"-net#MJHardy-:disc1.mike"
"-#MJHardy-:disc1.mike"
The special fields here are all MJHardy, and give the name of the fileserver to use. Special fields may use any character except for control characters, double quote '"', solidus '|' and space. If a special field contains a hyphen you may only use the first two syntaxes given above.
These two special variables control exactly where a file will be looked for, according to the operation being performed on it.
Table 19-13.
| name | purpose |
|---|---|
| File$Path | for read operations |
| Run$Path | 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:
*Set Source$Path adfs:$.src.,adfs:$.public.src.
, you could then refer to the pseudo file system as "Source:" or (less preferable) as "-Source-". These path variables work in the same was as "File$Path" and "Run$Path".NOTE: Path variables are not implemented in this version of CLISP. A workaround for this is to use "<Foo$Path>" instead of "Foo:" until they are made available.
No swapping. #P"foo.lisp" means file type #P".lisp" and file name #P"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
Table 19-14.
| '$' -> | :ABSOLUTE :ROOT |
| '&' -> | :ABSOLUTE :HOME |
| '@' -> | :ABSOLUTE :CURRENT |
| '%' -> | :ABSOLUTE :LIBRARY |
| '\' -> | :ABSOLUTE :PRECIOUS |
| else | :RELATIVE |
{ '^' | { legal-wild char }+ } '.'
Table 19-15.
| '^' -> | :PARENT |
{ { legal-wild char }+ | empty }
{ '.' { legal-wild char }+ | empty }
host device directory filename filetype
Table 19-16. Examples
| String | Hostname | Device | Directory | Name | Type |
|---|---|---|---|---|---|
| "-net-$.SystemMesg" | "net" | NIL | (:ABSOLUTE :ROOT) | "SystemMesg" | NIL |
| "net#MJHardy::disc1.mike" | "net#MJHardy" | "disc1" | (:ABSOLUTE :ROOT) | "mike" | NIL |
| "#MJHardy::disc1.mike" | "#MJHardy" | "disc1" | (:ABSOLUTE :ROOT) | "mike" | NIL |
| "-net#MJHardy-:disc1.mike" | "net#MJHardy" | "disc1" | (:ABSOLUTE :ROOT) | "mike" | NIL |
| "-#MJHardy-:disc1.mike" | "#MJHardy" | "disc1" | (:ABSOLUTE :ROOT) | "mike" | NIL |
| "@.foo" | NIL | NIL | (:ABSOLUTE :CURRENT) | #P"foo" | NIL |
| #P"foo" | NIL | NIL | (:RELATIVE) | #P"foo" | NIL |
| "^." | NIL | NIL | (:RELATIVE :PARENT) | NIL | NIL |
| "@.^." | NIL | NIL | (:ABSOLUTE :CURRENT :PARENT) | NIL | NIL |
| "foo.bar" | NIL | NIL | (:RELATIVE) | #P"foo" | #P"bar" |
| "foo.bar.baz" | NIL | NIL | (:RELATIVE #P"foo") | #P"bar" | "baz" |
| "foo.bar." | NIL | NIL | (:RELATIVE #P"foo" #P"bar") | NIL | NIL |
| "foo.@." | illegal |
with swapping only of name/type components.
Table 19-17.
| Hostname | Device | Directory | Name | Type | RISCOS String |
|---|---|---|---|---|---|
| "net" | "disc1" | (:ABSOLUTE :ROOT) | #P"foo" | NIL | "net::disc1.$.foo" |
| "net#MJ" | "disc1" | (:ABSOLUTE :ROOT #P"foo") | #P"bar" | "baz" | "net#MJ::disc1.$.foo.baz.bar" |
| "adfs" | "4" | (:ABSOLUTE :ROOT #P"foo" #P"bar") | NIL | NIL | "adfs::4.$.foo.bar" |
| NIL | "disc1" | (:ABSOLUTE :ROOT #P"foo") | #P"bar" | NIL | ":disc1.$.foo.bar" |
| NIL | "disc1" | (:ABSOLUTE :CURRENT) | NIL | NIL | illegal here |
| NIL | "disc1" | (:RELATIVE) | NIL | NIL | ":disc1." |
| NIL | "disc1" | NIL | NIL | NIL | ":disc1." |
| NIL | NIL | (:ABSOLUTE :ROOT) | #P"foo" | NIL | "$.foo" |
| NIL | NIL | (:ABSOLUTE :CURRENT) | #P"foo" | NIL | "@.foo" |
| NIL | NIL | (:RELATIVE) | #P"foo" | #P"bar" | "bar.foo" |
| NIL | NIL | (:RELATIVE #P"foo") | #P"bar" | "baz" | "foo.baz.bar" |
| NIL | NIL | (:ABSOLUTE :LIBRARY) | #P"bar" | NIL | "%.bar" |
| NIL | NIL | (:ABSOLUTE :LIBRARY #P"foo") | #P"bar" | NIL | "%.foo.bar" |
| NIL | NIL | (:RELATIVE) | #P"foo" | #P"bar" | "bar.foo" |
| NIL | NIL | (:RELATIVE #P"foo") | #P"bar" | NIL | "foo.bar" |
| NIL | NIL | (:RELATIVE #P"foo") | NIL | #P"bar" | 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
NIL or a SIMPLE-STRING
NIL or a SIMPLE-STRING
Table 19-18. Directory = (startpoint . subdirs)
| element | values |
|---|---|
| startpoint | :RELATIVE | :ABSOLUTE anchor |
| anchor | :ROOT | :HOME | :CURRENT | :LIBRARY | :PRECIOUS |
| subdirs | () | (subdir . subdirs) |
| subdir | :PARENT |
| subdir | SIMPLE-STRING, may contain wildcard characters "?", "#" and "*" |
SIMPLE-STRING or NIL, 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, [,],{,}:
Table 19-19.
| [ [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.
Table 19-20.
| [ "/" ] | "/" 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 "/").
Table 19-21.
| [ [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 (EXT:GETENV "HOME") "\\")) |
When the argument of the function TRANSLATE-LOGICAL-PATHNAME is a string, it is interpreted as a logical pathname string.
Pathname Designators. When CUSTOM:*PARSE-NAMESTRING-ANSI* is NIL, SYMBOL is also treated as a pathname designator, namely its SYMBOL-NAME is converted to the operating system's preferred pathname case.
Function PATHNAME-MATCH-P. 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.
(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 CL standard] behavior of recognizing logical pathnames when the string begins with some alphanumeric characters followed by a colon (#\:) can be very confusing (cf. "c:/autoexec.bat", "home:.clisprc" and "prep:/pub/gnu") and therefore is disabled by default. To enable the [ANSI CL standard] behavior, you should set CUSTOM:*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 CUSTOM:*MERGE-PATHNAMES-ANSI*: when it is NIL, then CLISP retains its traditional behavior: (MERGE-PATHNAMES #P"x/" #P"y/") evaluates to #P"x/"
Rationale: MERGE-PATHNAMES is used to specify default components for pathnames, so there is some analogy between (MERGE-PATHNAMES a b) and (or a b). Obviously putting in the same default a second time should do the same as putting it in once: (or a b b) is the same as (or a b), so (MERGE-PATHNAMES (MERGE-PATHNAMES a b) b) should be the same as (MERGE-PATHNAMES a b).
(This question actually matters because in Common Lisp there is no distinction between "pathnames with defaults merged-in" and "pathnames with defaults not yet applied".)
Now, (MERGE-PATHNAMES (MERGE-PATHNAMES #P"x/" #P"y/") #P"y/") and (MERGE-PATHNAMES #P"x/" #P"y/") are EQUAL in CLISP (when CUSTOM:*MERGE-PATHNAMES-ANSI* is NIL), but not in implementations that strictly follow the [ANSI CL standard] spec. In fact, the above twice-default = once-default rule holds for all pathnames in CLISP.
Reversely, when CUSTOM:*MERGE-PATHNAMES-ANSI* is non-NIL, the normal [ANSI CL standard] behavior is exhibited: (MERGE-PATHNAMES #P"x/" #P"y/") evaluates to #P"y/x/".
Rationale: "merge" is merge and not or.
When the host argument to LOAD-LOGICAL-PATHNAME-TRANSLATIONS is not a defined logical host yet, we proceed as follows:
If both environment variables LOGICAL_HOST_host_FROM and LOGICAL_HOST_host_TO exist, then their values define the map of the host.
If the environment variable LOGICAL_HOST_host exists, its value is read from, and the result is passed to (SETF LOGICAL-PATHNAME-TRANSLATIONS).
Variable CUSTOM:*LOAD-LOGICAL-PATHNAME-TRANSLATIONS-DATABASE* is consulted. Its value should be a list of files and/or directories, which are searched for in the CUSTOM:*LOAD-PATHS*, just like for LOAD. When the element is a file, it is READ from, Allegro CL-style, odd objects being host names and even object being their LOGICAL-PATHNAME-TRANSLATIONS. When the element is a directory, a file, named host or host.host, in that directory, is READ from once, CMUCL-style, the object read being the LOGICAL-PATHNAME-TRANSLATIONS of the host.
Function RENAME-FILE. RENAME-FILE always returns a non-logical pathname as its first value.
Function PROBE-FILE. PROBE-FILE cannot be used to check whether a directory exists. Use the function EXT:PROBE-DIRECTORY or the function DIRECTORY for this purpose.
Function 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.
Function EXT:PROBE-DIRECTORY. (EXT:PROBE-DIRECTORY pathname) tests whether pathname exists and is a directory. It will, unlike PROBE-FILE or TRUENAME, not signal an error if the parent directory of pathname does not exist.
(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. E.g., (DIRECTORY "/etc/*/") lists all subdirectories in the directory #P"/etc/".
Otherwise a list of all matching files is returned. E.g., (DIRECTORY "/etc/*") lists all regular files in the directory #P"/etc/". If the :full argument is non-NIL, additional information is returned: 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).
Function EXT:DIR. (EXT:DIR &OPTIONAL pathname) is like DIRECTORY, but displays the pathnames instead of returning them. (EXT:DIR) shows the contents of the current directory.
Function EXT:CD. (EXT:CD pathname) sets it,
(EXT:CD) returns it.
(EXT:CD [pathname])
manages the current directory. (EXT:CD [pathname])
manages the current host, current device and the current directory.
(EXT:CD [pathname])
manages the current device and the current directory.
Function EXT:DEFAULT-DIRECTORY. (EXT:DEFAULT-DIRECTORY) is equivalent to (EXT:CD). (SETF (EXT:DEFAULT-DIRECTORY) pathname) is equivalent to (EXT:CD pathname), except for the return value.
Function EXT:MAKE-DIR. (EXT:MAKE-DIR directory-pathname) creates a new subdirectory.
Function EXT:DELETE-DIR. (EXT:DELETE-DIR directory-pathname) removes an (empty) subdirectory.
Interactive streams are those whose next input might depend on a prompt one might output.
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 name or PATHNAME that is being typed. See readline user manual for general details and CLISP manual for CLISP-specific extensions. The GNU readline library is not used if standard input and standard output do not both refer to the same terminal.
Macro EXT:WITH-KEYBOARD
*TERMINAL-IO* is not the only stream that communicates directly with the user: During execution of the body of a (EXT:WITH-KEYBOARD . body) form, EXT:*KEYBOARD-INPUT* is the stream that reads the keystrokes from the keyboard. It returns every keystroke in detail, as CHARACTER or SYS::INPUT-CHARACTER with the following bits:
(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:
Table 21-1.
| key | value |
|---|---|
| F1..F12 | :F1..:F12 |
| Insert | :Insert |
| Delete | :Delete |
| Home | :Home |
| End | :End |
| PgUp | :PgUp |
| PgDn | :PgDn |
| Arrow keys | :Left:Right :Up:Down |
Table 21-2.
| key | value |
|---|---|
| F1..F12 | :F1..:F12 |
| Insert | :Insert |
| Delete | :Delete |
| Home | :Home |
| End | :End |
| Center | :Center |
| PgUp | :PgUp |
| PgDn | :PgDn |
| Arrow keys | :Left:Right :Up:Down |
Table 21-3.
| key | value |
|---|---|
| F1..F10 | :F1..:F10 |
| Help | :Help |
| Arrow keys | :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.
See also Random Screen Access.
STREAM-ELEMENT-TYPE is SETFable. The STREAM-ELEMENT-TYPE of STREAMs created by the functions OPEN, EXT:MAKE-PIPE-INPUT-STREAM EXT:MAKE-PIPE-OUTPUT-STREAM, EXT:MAKE-PIPE-IO-STREAM, SOCKET:SOCKET-ACCEPT, SOCKET:SOCKET-CONNECT can be modified, if the old and the new STREAM-ELEMENT-TYPEs 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.
Note that you cannot change STREAM-ELEMENT-TYPE for some built-in streams, such as terminal streams (which is normally the value of *TERMINAL-IO*).
The function (EXT:READ-INTEGER stream element-type &OPTIONAL ENDIANNESS eof-error-p eof-value) reads a multi-byte INTEGER from stream. stream should be a stream with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.
(EXT:READ-INTEGER stream element-type) is like (READ-BYTE stream) if stream's STREAM-ELEMENT-TYPE were set to element-type, except that stream's FILE-POSITION will increase by n/8 instead of 1.
Together with (SETF STREAM-ELEMENT-TYPE), this function permits mixed character/binary input from a stream.
The function (EXT:READ-FLOAT stream element-type &OPTIONAL ENDIANNESS eof-error-p eof-value) reads a floating-point number in IEEE 754 binary representation from stream. stream should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
Endianness. ENDIANNESS can be :LITTLE or :BIG. The default is :LITTLE, which corresponds to the READ-BYTE behavior in CLISP.
The function (EXT:WRITE-INTEGER integer stream element-type &OPTIONAL ENDIANNESS) writes a multi-byte integer to stream. stream should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to (UNSIGNED-BYTE n), where n is a multiple of 8.
(EXT:WRITE-INTEGER integer stream element-type) is like (WRITE-BYTE integer stream) if stream's STREAM-ELEMENT-TYPE were set to element-type, except that stream's FILE-POSITION will increase by n/8 instead of 1.
Together with (SETF STREAM-ELEMENT-TYPE), this function permits mixed character/binary output to a STREAM.
The function (EXT:WRITE-FLOAT float stream element-type &OPTIONAL ENDIANNESS) writes a floating-point number in IEEE 754 binary representation to stream. stream should be a STREAM with STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8). element-type should be type equivalent to SINGLE-FLOAT or DOUBLE-FLOAT.
In addition to READ-SEQUENCE, the following two functions are provided:
(EXT: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 STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8).
(EXT:READ-CHAR-SEQUENCE sequence stream &KEY :START :END) fills the subsequence of sequence specified by :START and :END with characters consecutively read from stream. It returns the index of the first element of sequence that was not updated (= end or < end if the stream reached its end).
This function is especially efficient if sequence is a STRING and :STREAM is a file/pipe/socket stream with STREAM-ELEMENT-TYPE CHARACTER or an input string stream.
In addition to WRITE-SEQUENCE, the following two functions are provided:
(EXT: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 STREAM-ELEMENT-TYPE (UNSIGNED-BYTE 8).
(EXT:WRITE-CHAR-SEQUENCE sequence :STREAM &KEY :START :END) outputs the characters of the subsequence of sequence specified by :START and :END to :STREAM. It returns sequence.
This function is especially efficient if sequence is a STRING and :STREAM is a file/pipe/socket STREAM with STREAM-ELEMENT-TYPE CHARACTER.
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.
If n is not a multiple of 8, CLISP will use the specified number of bits for i/o, and write the file length (as a number of n-bit bytes) in the preamble.
This is done to ensure the input/output consistency. Suppose you open a file with :ELEMENT-TYPE of (UNSIGNED-BYTE 3) and write 7 bytes (i.e., 21 bit) there. The underlying OS can do input/output only in whole 8-bit bytes. Thus the OS will report the size of the file as 3 (8-bit) bytes. Without the preamble CLISP will have no way to know how many 3-bit bytes to read from this file - 6, 7 or 8.
EXT:ENCODINGs, (constant) SYMBOLs in the "CHARSET" package, STRINGs (denoting iconv-based encodings), the symbol :DEFAULT, and the line terminator keywords :UNIX, :MAC, :DOS. The default encoding is CUSTOM:*DEFAULT-FILE-ENCODING*.
for functions that create SOCKET: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.
CLOSE ignores its :ABORT argument.
GET-OUTPUT-STREAM-STRING returns the same value after CLOSE as it would before it.
INPUT-STREAM-P and INTERACTIVE-STREAM-P return false for broadcast streams.
Variable CUSTOM:*PRINT-CLOSURE*. An additional variable CUSTOM:*PRINT-CLOSURE* controls whether compiled and interpreted functions (closures) are output in detailed form. If CUSTOM:*PRINT-CLOSURE* is non-NIL, compiled closures are output in #Y syntax which the reader understands. CUSTOM:*PRINT-CLOSURE* is initially set to NIL.
Variable CUSTOM:*PRINT-RPARS*. An additional variable CUSTOM:*PRINT-RPARS* controls the output of the right (closing) parentheses. If CUSTOM:*PRINT-RPARS* is non-NIL, closing parentheses which do not fit onto the same line as the the corresponding opening parenthesis are output just below their corresponding opening parenthesis, in the same column. CUSTOM:*PRINT-RPARS* is initially set to NIL.
Variable CUSTOM:*PRINT-INDENT-LISTS*. An additional variable CUSTOM:*PRINT-INDENT-LISTS* controls the indentation of lists that span more than one line. It specifies by how many characters items within the list will be indented relative to the beginning of the list. CUSTOM:*PRINT-INDENT-LISTS* is initially set to 1.
Variable CUSTOM:*PPRINT-FIRST-NEWLINE*. An additional variable CUSTOM:*PPRINT-FIRST-NEWLINE* controls pretty-printing of multi-line objects. When CUSTOM:*PPRINT-FIRST-NEWLINE* is non-NIL, and the current line already has some characters on it, and the next object will be printed on several lines, and it does not start with a #\Newline, then a #\Newline is printed before the object. CUSTOM:*PPRINT-FIRST-NEWLINE* has no effect if *PRINT-PRETTY* is NIL. CUSTOM:*PPRINT-FIRST-NEWLINE* is initially set to T.
When *PRINT-READABLY* is true, other vectors are written as follows: if the ARRAY-ELEMENT-TYPE is T, the syntax #(x0 ... xn-1) is used. Otherwise, the syntax #A(element-type dimensions contents) is used.
When *PRINT-READABLY* is true, other arrays are written as follows: if the ARRAY-ELEMENT-TYPE is T, the syntax #rankA contents is used. Otherwise, the syntax #A(element-type dimensions contents) is used.
The Lisp Pretty Printer implementation is not perfect yet. PPRINT-LOGICAL-BLOCK does not respect *PRINT-LINES*.
A pprint dispatch table is a CONS of a symbol *PRINT-PPRINT-DISPATCH* an alist which maps types into priorities and print functions. Their use is strongly discouraged because of the performance issues: when *PRINT-PPRINT-DISPATCH* is non-trivial and *PRINT-PRETTY* is non-NIL, printing of every object requires a lookup in the table, which entails many calls to TYPEP (which cannot be made fast enough).
Functions WRITE & WRITE-TO-STRING. The functions WRITE and WRITE-TO-STRING have an additional keyword argument :closure which is used to bind CUSTOM:*PRINT-CLOSURE*.
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 standard] Issue PRINT-READABLY-BEHAVIOR:CLARIFY. But, if *PRINT-READABLY* is true, we are in trouble as #P"" is ambiguous (which is verboten when *PRINT-READABLY* is true), while being mandated by the [ANSI CL standard]. Therefore, in this case, CLISP's behavior is determined by the value of CUSTOM:*PRINT-PATHNAMES-ANSI*: when it is NIL, we print pathnames like this: #-CLISP #P"" #+CLISP #S(PATHNAME ...). Otherwise, when the variable CUSTOM:*PRINT-PATHNAMES-ANSI* is non-NIL, the #P"" notation is used as per 1.5.1.4.1 Resolution of Apparent Conflicts in Exceptional Situations.
*PRINT-CASE* controls the output not only of symbols, but also of characters and some #<...> objects.
In the absence of sys::write-float-decimal, floating point numbers are output in radix 2. This function is defined in "floatpri.lisp" and is not available if you run CLISP without a memory image (which you should never do anyway!)
If *PRINT-READABLY* is true, *READ-DEFAULT-FLOAT-FORMAT* has no influence on the way floating point numbers are printed.
*PRINT-PRETTY* is initially NIL but set to T in #P"config.lisp". This makes screen output prettier.
*PRINT-PRETTY* is initially NIL but set to T in #P"config.lisp". This makes unbuffered screen output both much faster and prettier.
*PRINT-ARRAY* is initially set to T.
This is the list of objects whose external representation cannot be meaningfully read in:
Table 23-1. unreadable objects
| format | meaning |
|---|---|
| #<type ...> | all structures lacking a keyword constructor |
| #<ARRAY type dimensions> | all arrays except strings, if *PRINT-ARRAY* is NIL |
| #<SYSTEM-FUNCTION name> | built-in function written in C |
| #<ADD-ON-SYSTEM-FUNCTION name> | other function written in C |
| #<SPECIAL-OPERATOR name> | special operator handler |
| #<COMPILED-CLOSURE name> | compiled function, if CUSTOM:*PRINT-CLOSURE* is NIL |
| #<CLOSURE name ...> | interpreted function |
| #<FRAME-POINTER #x...> | pointer to a stack frame |
| #<DISABLED POINTER> | frame pointer which has become invalid on exit from the corresponding BLOCK or TAGBODY |
| #<...-STREAM ...> | stream |
| #<PACKAGE name> | package |
| #<HASH-TABLE #x...> | hash table, if *PRINT-ARRAY* is NIL |
| #<READTABLE #x...> | readtable |
| #<SYMBOL-MACRO form> | SYMBOL-MACRO handler |
| #<FOREIGN-POINTER #x...> | foreign pointer (Platform dependent: UNIX, Win32, Amiga platforms only.) |
| #<FOREIGN-ADDRESS #x...> | foreign address (Platform dependent: UNIX, Win32 platforms only.) |
| #<FOREIGN-VARIABLE name #x...> | foreign variable (Platform dependent: UNIX, Win32 platforms only.) |
| #<FOREIGN-FUNCTION name #x...> | foreign function (Platform dependent: UNIX, Win32 platforms only.) |
| #<UNBOUND> | "value" of a symbol without value, "value" of an unsupplied optional or keyword argument |
| #<SPECIAL REFERENCE> | environment marker for variables declared SPECIAL |
| #<DOT> | internal READ result for "." |
| #<END OF FILE> | internal READ result, when the end of file is reached |
| #<READ-LABEL ...> | intermediate READ result for #n# |
| #<ADDRESS #x...> | machine address, should not occur |
| #<SYSTEM-POINTER #x...> | should not occur |
#\Code allows input of characters of arbitrary code: e.g., #\Code231 reads as the character (CODE-CHAR 231.).
#Y is used to read compiled functions and to set the current input stream's EXT:ENCODING.
#"" is used to read pathnames: #"test.lisp" is the value of (PATHNAME "test.lisp")
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.
EXT:READ-CHAR-WILL-HANG-P queries the stream's input status. It returns NIL if READ-CHAR and PEEK-CHAR with a peek-type of NIL will return immediately. Otherwise it returns T. (In the latter case the standard LISTEN function would return NIL.)
Note the difference with (NOT (LISTEN stream)): When the end-of-stream is reached, LISTEN returns NIL, whereas EXT:READ-CHAR-WILL-HANG-P returns NIL.
Note also that EXT:READ-CHAR-WILL-HANG-P is not a good mean to test for end-of-stream: If EXT:READ-CHAR-WILL-HANG-P returns T, this does not mean that the stream will deliver more characters. It only means that it is not known at this moment whether the stream is already at end-of-stream, or will deliver more characters.
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns T if READ-BYTE would return immediately with an INTEGER result. Returns :EOF if the end-of-stream is already known to be reached. If READ-BYTE's value is not available immediately, returns NIL instead of waiting.
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns NIL if READ-BYTE will return immediately. Otherwise it returns true.
To be called only if stream's STREAM-ELEMENT-TYPE is (UNSIGNED-BYTE 8) or (SIGNED-BYTE 8). Returns an INTEGER or does end-of-stream handling, like READ-BYTE, if that would return immediately. If READ-BYTE's value is not available immediately, returns NIL instead of waiting.
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 CUSTOM:*COMPILE-WARNINGS*, *COMPILE-VERBOSE*, *COMPILE-PRINT* provide defaults for the :WARNINGS, :VERBOSE, :PRINT keyword arguments, respectively. For each input file (default file type: #P".lisp") the following files are generated:
Table 24-1.
| File | When | Default file type | Contents |
|---|---|---|---|
| output file | only if :OUTPUT-FILE is not NIL | #P".fas" | can be loaded using the LOAD function |
| auxiliary output file | only if :OUTPUT-FILE is not NIL | #P".lib" | used by COMPILE-FILE when compiling a REQUIRE form referring to the input file |
| listing file | only if :LISTING is not NIL | #P".lis" | disassembly of the output file |
| C output file | only if :OUTPUT-FILE is not NIL | #P".c" | foreign function interface; this file is deleted if it is empty |
The default for the :OUTPUT-FILE argument is T, which means #P".fas".
The function REQUIRE receives as the optional argument either a pathname or a list of pathnames: files to be loaded if the required module is not already loaded.
At compile time, (REQUIRE #P"foo") forms are treated specially: CUSTOM:*LOAD-PATHS* is searched for #P"foo.lisp" and #P"foo.lib". If the latest such file is a #P".lisp", it is compiled; otherwise the #P".lib" is loaded. The #P".lib" is a "header" file which contains the constant, variable, inline and macro definitions necessary for compilation of the files that REQUIRE this file, but not the function definitions and calls that are not necessary for that. Thus it is not necessary to either enclose REQUIRE forms in EVAL-WHEN or to load the required files in the makefiles: if you have two files, #P"foo.lisp" and #P"bar.lisp", and the latter requires the former, you can write in your #P"Makefile":
all: foo.fas bar.fas
foo.fas: foo.lisp
clisp -c foo
bar.fas: bar.lisp foo.fas
clisp -c bar
|
bar.fas: bar.lisp foo.fas
clisp -i foo -c bar
|
LOAD has three additional keywords :ECHO, :COMPILING, and :EXTRA-FILE-TYPES.
(LOAD filename &KEY :VERBOSE :PRINT :ECHO :IF-DOES-NOT-EXIST :COMPILING :EXTRA-FILE-TYPES)
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 CUSTOM:*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 CUSTOM:*LOAD-COMPILING*, which is initially NIL.
Specifies the additional file types considered for loading, in addition to CUSTOM:*SOURCE-FILE-TYPES* (which is initially ("lisp" "lsp" "cl")) and CUSTOM:*COMPILED-FILE-TYPES* (which is initially ("fas")).
When filename does not spefify a unique file (e.g., filename is #P"foo" and both #P"foo.lisp" and #P"foo.fas" are found in the CUSTOM:*LOAD-PATHS*), then the newest file is loaded.
Variable CUSTOM:*LOAD-PATHS*. The variable CUSTOM:*LOAD-PATHS* contains a list of directories where the files are looked for - in addition to the specified or current directory - by LOAD, REQUIRE, COMPILE-FILE and LOAD-LOGICAL-PATHNAME-TRANSLATIONS.
The variable *FEATURES* initially contains the symbols
Table 24-2.
| keyword | meaning |
|---|---|
| :CLISP | the name of this implementation |
| :ANSI-CL | |
| :COMMON-LISP | |
| :INTERPRETER | |
| :COMPILER | |
| :SOCKETS | see SOCKET:SOCKET-STREAMs |
| :GENERIC-STREAMS | see Defining new kinds of Streams |
| :SYSCALLS | see System Calls |
| :DIR-KEY | see Directory Access |
| :LOGICAL-PATHNAMES | |
| :FFI | if a foreign function interface (see "FFI") is supported (Platform dependent: many UNIX, Win32 platforms only) |
| :GETTEXT | if internationalization (see "I18N") using the GNU gettext package is supported (Platform dependent: most UNIX platforms only) |
| :UNICODE | if Unicode (ISO 10646) characters are supported (see "CHARSET") |
| :LOOP | |
| :CLOS | |
| :AMIGA | if hardware = Amiga and operating system = Exec/AmigaDOS |
| :DOS | if hardware = PC (clone) and operating system = DOS |
| :OS/2 | if hardware = PC (clone) and operating system = OS/2 |
| :WIN32 | if hardware = PC (clone) and operating system = Win32 (Windows 95/98/NT/Me/2000/XP) |
| :PC386 | if hardware = PC (clone) with a 386/486/586/686 CPU |
| :UNIX | if operating system = Unix (in this case the hardware is irrelevant!) |
| :CYGWIN | if CLISP is using the Cygwin UNIX compatibility layer on top of Win32 (in that case :UNIX is also present) |
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.
Table 25-1. Commands common to the main loop, the debugger and the stepper
| command | abbreviation | operation |
|---|---|---|
| Help | :h | prints a list of available commands |
Table 25-2. Commands common to the debugger and the stepper
| command | abbreviation | operation |
|---|---|---|
| Abort | :a | abort to the next most recent read-eval-print loop |
| Unwind | :uw | abort to the next most recent read-eval-print loop |
| Quit | :q | quit to the top 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.
Table 25-3. Commands common to the debugger and the stepper
| command | abbreviation | operation |
|---|---|---|
| Error | :e | print the last error message. |
| Mode-1 | :m1 | sets the current mode to 1: all the stack elements are considered. This mode works fine for debugging compiled functions. |
| Mode-2 | :m2 | sets the current mode to 2: all the frames are considered. |
| Mode-3 | :m3 | sets the current mode to 3: only lexical frames (frames that correspond to special forms that modify the lexical environment) are considered. |
| Mode-4 | :m4 | 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. |
| Mode-5 | :m5 | sets the current mode to 5: only APPLY frames are considered. Every invocation of an interpreted function corresponds to one APPLY frame. |
| Where | :w | shows the current stack frame. |
| Up | :u | goes up one frame, i.e., to the caller if in mode-5 |
| Down | :d | does down one frame, i.e., to the callee if in mode-5 |
| Top | :t | goes to top frame, i.e., to the top-level form if in mode-4 |
| Bottom | :b |