doc: cosmetic improvements
Consistent formatting and capitalization, clickable links to functions defined in other parts of the manual, better looking css for html output. Some small errors and typos have been corrected as well.
This commit is contained in:
parent
b85d628955
commit
c530793d2b
47 changed files with 1726 additions and 1667 deletions
|
|
@ -16,7 +16,7 @@ ecl.info.gz: $(FILES)
|
|||
gzip < ecl.info > ecl.info.gz
|
||||
|
||||
html/index.html: $(FILES)
|
||||
$(MAKEINFO) --html --css-include=ecl.css --split=chapter manual.txi
|
||||
$(MAKEINFO) --html --css-include=ecl.css --split=section manual.txi
|
||||
rm -rf html
|
||||
mv ecl html
|
||||
cp -r figures html
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ system. Call to @code{eval} invokes the bytecode compiler and then the
|
|||
bytecode interpreter.
|
||||
|
||||
@itemize
|
||||
@item @code{src/c/compiler.d} - bytecode compiler
|
||||
@item @code{src/c/interpreter.d} - bytecode interpreter
|
||||
@item @code{src/c/interpreter.d} - bytecode disassembler
|
||||
@item @file{src/c/compiler.d} - bytecode compiler
|
||||
@item @file{src/c/interpreter.d} - bytecode interpreter
|
||||
@item @file{src/c/disassembler.d} - bytecode disassembler
|
||||
@end itemize
|
||||
|
||||
Structure @code{ecl_bytecodes} has the following fields:
|
||||
|
|
@ -30,7 +30,7 @@ Moreover if bytecompiled function is a closure then its structure is
|
|||
@itemize
|
||||
@item @code{code} - closure function (@code{ecl_bytecodes})
|
||||
@item @code{lex} - closure lexical environment
|
||||
@item @code{entry} - closure entry address (function _ecl_bclosure_dispatch_vararg)
|
||||
@item @code{entry} - closure entry address (function @code{_ecl_bclosure_dispatch_vararg})
|
||||
@end itemize
|
||||
|
||||
@subsection Bytecode compiler
|
||||
|
|
@ -39,6 +39,6 @@ Moreover if bytecompiled function is a closure then its structure is
|
|||
|
||||
@subsection Bytecode disassembler
|
||||
|
||||
@defun{si:bc-split} {@var{function}}
|
||||
@defun si:bc-split function
|
||||
Returns five values: lex, bytecodes, data and name.
|
||||
@end defun
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ The C function @code{L1add1} implements the Lisp function @code{add1}. This rela
|
|||
@subsection Implementation of Compiled Closures
|
||||
The ECL compiler takes two passes before it invokes the C compiler. The major role of the first pass is to detect function closures and to detect, for each function closure, those lexical objects (i.e., lexical variable, local function definitions, tags, and block-names) to be enclosed within the closure. This check must be done before the C code generation in the second pass, because lexical objects to be enclosed in function closures are treated in a different way from those not enclosed.
|
||||
|
||||
Ordinarily, lexical variables in a compiled function @var{f} are allocated on the C stack. However, if a lexical variable is to be enclosed in function closures, it is allocated on a list, called the "environment list", which is local to @var{f}. In addition, a local variable is created which points to the lexical variable's location (within the environment list), so that the variable may be accessed through an indirection rather than by list traversal.
|
||||
Ordinarily, lexical variables in a compiled function @code{f} are allocated on the C stack. However, if a lexical variable is to be enclosed in function closures, it is allocated on a list, called the "environment list", which is local to @code{f}. In addition, a local variable is created which points to the lexical variable's location (within the environment list), so that the variable may be accessed through an indirection rather than by list traversal.
|
||||
|
||||
The environment list is a pushdown list: It is empty when @var{f} is called. An element is pushed on the environment list when a variable to be enclosed in closures is bound, and is popped when the binding is no more in effect. That is, at any moment during execution of @var{f}, the environment list contains those lexical variables whose binding is still in effect and which should be enclosed in closures. When a compiled closure is created during execution of @var{f}, the compiled code for the closure is coupled with the environment list at that moment to form the compiled closure.
|
||||
The environment list is a pushdown list: It is empty when @code{f} is called. An element is pushed on the environment list when a variable to be enclosed in closures is bound, and is popped when the binding is no more in effect. That is, at any moment during execution of @code{f}, the environment list contains those lexical variables whose binding is still in effect and which should be enclosed in closures. When a compiled closure is created during execution of @code{f}, the compiled code for the closure is coupled with the environment list at that moment to form the compiled closure.
|
||||
|
||||
Later, when the compiled closure is invoked, a pointer is set up to each lexical variable in the environment list, so that each object may be referenced through a memory indirection.
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ Declarations, especially type and function declarations, increase the efficiency
|
|||
@end lisp
|
||||
|
||||
|
||||
The compiler generates the following C code (Note that the tail-recursive call of @code{TAK} was replaced by iteration):
|
||||
The compiler generates the following C code (Note that the tail-recursive call of @code{tak} was replaced by iteration):
|
||||
@example
|
||||
@verbatim
|
||||
/* function definition for TAK */
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ Function return:
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
Return function expands into a lexical block @verb{|{}|}, so if it's
|
||||
used inside IF/ELSE, then it should be enclosed, even if we
|
||||
use sole @verb{|@(return);|}, because ";" will be treated as the next
|
||||
Return function expands into a lexical block @code{@{@}}, so if it's
|
||||
used inside @code{if/else}, then it should be enclosed, even if we
|
||||
use sole @code{@@(return);}, because ";" will be treated as the next
|
||||
instruction.
|
||||
|
||||
Symbols:
|
||||
|
|
@ -79,7 +79,7 @@ Symbols:
|
|||
@end example
|
||||
|
||||
Expands into a C statement, whole value is the given symbol
|
||||
from symbols_list.h
|
||||
from @file{symbols_list.h}
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -87,6 +87,6 @@ from symbols_list.h
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
Expands into a C statement, whole value is a fixnum
|
||||
corresponding to the index in the builtin symbols table of the
|
||||
given symbol from symbols_list.h. Used for handling type errors.
|
||||
Expands into a C statement, whole value is a fixnum corresponding to the
|
||||
index in the builtin symbols table of the given symbol from
|
||||
@file{symbols_list.h}. Used for handling type errors.
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ need to know about all these conventions. There is a preprocessor
|
|||
(@pxref{Defun preprocessor}) that takes care of the details, by using a
|
||||
lisp representation of the statements that output values, and of the
|
||||
function definitions. For instance, the actual source code for
|
||||
@code{cl_last} in @code{src/c/list.d} is
|
||||
@code{cl_last} in @file{src/c/list.d} is
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -107,7 +107,7 @@ Note that this list is different from what the Common Lisp standard
|
|||
calls a lexical environment, which is the content of a
|
||||
@code{&environment} parameter to @code{defmacro}. For the differences
|
||||
between this two environments see the comments in
|
||||
@code{src/c/compiler.d} and @code{src/c/interpreter.d}.
|
||||
@file{src/c/compiler.d} and @file{src/c/interpreter.d}.
|
||||
|
||||
@node The interpreter stack
|
||||
@subsection The interpreter stack
|
||||
|
|
@ -115,7 +115,7 @@ between this two environments see the comments in
|
|||
The bytecodes interpreter uses a stack of its own to save and restore
|
||||
values from intermediate calculations. This Forth-like data stack is
|
||||
also used in other parts of the C kernel for various purposes, such as
|
||||
saving compiled code, keeping arguments to @code{FORMAT}, etc.
|
||||
saving compiled code, keeping arguments to @code{format}, etc.
|
||||
|
||||
However, one of the most important roles of the Interpreter Stack is
|
||||
to keep a log of the functions which are called during the execution
|
||||
|
|
@ -130,7 +130,7 @@ lisp objects on the stack:
|
|||
|
||||
The first item is the object which is funcalled. It can be a bytecodes
|
||||
object, a compiled function or a generic function. In the last two
|
||||
cases the lexical environment is just @code{NIL}. In the first case,
|
||||
cases the lexical environment is just @code{nil}. In the first case,
|
||||
the second item on the stack is the lexical environment on which the
|
||||
code is executed. Each of these records are popped out of the stack
|
||||
after function invocation.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
If you want to extend, fix or simply customize ECL for your own needs,
|
||||
you should understand how the implementation works.
|
||||
|
||||
@cppindex cl_lispunion
|
||||
@cppdef cl_lispunion
|
||||
@deftp @cind{} cl_lispunion { cons big ratio SF DF longfloat gencomplex csfloat cdfloat clfloat symbol pack hash array vector base_string string stream random readtable pathname bytecodes bclosure cfun cfunfixed cclosure d instance process queue lock rwlock condition_variable semaphore barrier mailbox cblock foreign frame weak sse }
|
||||
|
||||
Union containing all first-class ECL types.
|
||||
|
|
@ -92,7 +92,7 @@ comments in the source code):
|
|||
*/
|
||||
@end verbatim
|
||||
|
||||
@cppindex cl_object
|
||||
@cppdef cl_object
|
||||
@deftp @cind{} cl_object
|
||||
This is the type of a lisp object. For your C/C++ program, a cl_object
|
||||
can be either a fixnum, a character, or a pointer to a union of
|
||||
|
|
@ -131,63 +131,63 @@ how to use the different fields of a @code{cl_object} pointer.
|
|||
Enumeration type which distinguishes the different types of lisp
|
||||
objects. The most important values are:
|
||||
|
||||
@cppindex t_start
|
||||
@cppindex t_list
|
||||
@cppindex t_character
|
||||
@cppindex t_fixnum
|
||||
@cppindex t_bignum
|
||||
@cppindex t_ratio
|
||||
@c @cppindex t_shortfloat
|
||||
@cppindex t_singlefloat
|
||||
@cppdef t_start
|
||||
@cppdef t_list
|
||||
@cppdef t_character
|
||||
@cppdef t_fixnum
|
||||
@cppdef t_bignum
|
||||
@cppdef t_ratio
|
||||
@c @cppdef t_shortfloat
|
||||
@cppdef t_singlefloat
|
||||
@c #ifdef ECL_LONG_FLOAT
|
||||
@cppindex t_longfloat
|
||||
@cppdef t_longfloat
|
||||
@c #endif
|
||||
@cppindex t_complex
|
||||
@cppdef t_complex
|
||||
@c #ifdef ECL_COMPLEX_FLOAT
|
||||
@cppindex t_csfloat
|
||||
@cppindex t_cdfloat
|
||||
@cppindex t_clfloat
|
||||
@cppdef t_csfloat
|
||||
@cppdef t_cdfloat
|
||||
@cppdef t_clfloat
|
||||
@c #endif
|
||||
@cppindex t_symbol
|
||||
@cppindex t_package
|
||||
@cppindex t_hashtable
|
||||
@cppindex t_array
|
||||
@cppindex t_vector
|
||||
@cppdef t_symbol
|
||||
@cppdef t_package
|
||||
@cppdef t_hashtable
|
||||
@cppdef t_array
|
||||
@cppdef t_vector
|
||||
@c #ifdef ECL_UNICODE
|
||||
@cppindex t_string
|
||||
@cppdef t_string
|
||||
@c #endif
|
||||
@cppindex t_base_string
|
||||
@cppindex t_bitvector
|
||||
@cppindex t_stream
|
||||
@cppindex t_random
|
||||
@cppindex t_readtable
|
||||
@cppindex t_pathname
|
||||
@cppindex t_bytecodes
|
||||
@cppindex t_bclosure
|
||||
@cppindex t_cfun
|
||||
@cppindex t_cfunfixed
|
||||
@cppindex t_cclosure
|
||||
@cppindex t_instance
|
||||
@cppindex t_structure = t_instance
|
||||
@cppdef t_base_string
|
||||
@cppdef t_bitvector
|
||||
@cppdef t_stream
|
||||
@cppdef t_random
|
||||
@cppdef t_readtable
|
||||
@cppdef t_pathname
|
||||
@cppdef t_bytecodes
|
||||
@cppdef t_bclosure
|
||||
@cppdef t_cfun
|
||||
@cppdef t_cfunfixed
|
||||
@cppdef t_cclosure
|
||||
@cppdef t_instance
|
||||
@cppdef t_structure = t_instance
|
||||
@c #ifdef ECL_THREADS
|
||||
@cppindex t_process
|
||||
@cppindex t_lock
|
||||
@cppindex t_rwlock
|
||||
@cppindex t_condition_variable
|
||||
@cppindex t_semaphore
|
||||
@cppindex t_barrier
|
||||
@cppindex t_mailbox
|
||||
@cppdef t_process
|
||||
@cppdef t_lock
|
||||
@cppdef t_rwlock
|
||||
@cppdef t_condition_variable
|
||||
@cppdef t_semaphore
|
||||
@cppdef t_barrier
|
||||
@cppdef t_mailbox
|
||||
@c #endif
|
||||
@cppindex t_codeblock
|
||||
@cppindex t_foreign
|
||||
@cppindex t_frame
|
||||
@cppindex t_weak_pointer
|
||||
@cppdef t_codeblock
|
||||
@cppdef t_foreign
|
||||
@cppdef t_frame
|
||||
@cppdef t_weak_pointer
|
||||
@c #ifdef ECL_SSE2
|
||||
@cppindex t_sse_pack
|
||||
@cppdef t_sse_pack
|
||||
@c #endif
|
||||
@cppindex t_end
|
||||
@cppindex t_other
|
||||
@cppindex t_contiguous – contiguous block
|
||||
@cppdef t_end
|
||||
@cppdef t_other
|
||||
@cppdef t_contiguous – contiguous block
|
||||
|
||||
@code{t_cons} @code{t_fixnum}, @code{t_character}, @code{t_bignum},
|
||||
@code{t_ratio}, @code{t_singlefloat}, @code{t_doublefloat},
|
||||
|
|
@ -198,39 +198,39 @@ objects. The most important values are:
|
|||
@code{t_instance}, @code{t_foreign} and @code{t_thread}.
|
||||
@end deftp
|
||||
|
||||
@cppindex ecl_t_of
|
||||
@cppdef ecl_t_of
|
||||
@deftypefun cl_type ecl_t_of (cl_object x)
|
||||
If @var{x} is a valid lisp object, @code{ecl_t_of(x)} returns an integer
|
||||
denoting the type that lisp object. That integer is one of the values of
|
||||
the enumeration type @code{cl_type}.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ECL_CHARACTERP
|
||||
@cppindex ECL_BASE_CHAR_P
|
||||
@cppindex ECL_BASE_CHAR_CODE_P
|
||||
@cppindex ECL_NUMBER_TYPE_P
|
||||
@cppindex ECL_COMPLEXP
|
||||
@cppindex ECL_REAL_TYPE_P
|
||||
@cppindex ECL_FIXNUMP
|
||||
@cppindex ECL_BIGNUMP
|
||||
@cppindex ECL_SINGLE_FLOAT_P
|
||||
@cppindex ECL_DOUBLE_FLOAT_P
|
||||
@cppindex ECL_LONG_FLOAT_P
|
||||
@cppindex ECL_CONSP
|
||||
@cppindex ECL_LISTP
|
||||
@cppindex ECL_ATOM
|
||||
@cppindex ECL_SYMBOLP
|
||||
@cppindex ECL_ARRAYP
|
||||
@cppindex ECL_VECTORP
|
||||
@cppindex ECL_BIT_VECTOR_P
|
||||
@cppindex ECL_STRINGP
|
||||
@cppindex ECL_HASH_TABLE_P
|
||||
@cppindex ECL_RANDOM_STATE_P
|
||||
@cppindex ECL_PACKAGEP
|
||||
@cppindex ECL_PATHNAMEP
|
||||
@cppindex ECL_READTABLEP
|
||||
@cppindex ECL_FOREIGN_DATA_P
|
||||
@cppindex ECL_SSE_PACK_P
|
||||
@cppdef ECL_CHARACTERP
|
||||
@cppdef ECL_BASE_CHAR_P
|
||||
@cppdef ECL_BASE_CHAR_CODE_P
|
||||
@cppdef ECL_NUMBER_TYPE_P
|
||||
@cppdef ECL_COMPLEXP
|
||||
@cppdef ECL_REAL_TYPE_P
|
||||
@cppdef ECL_FIXNUMP
|
||||
@cppdef ECL_BIGNUMP
|
||||
@cppdef ECL_SINGLE_FLOAT_P
|
||||
@cppdef ECL_DOUBLE_FLOAT_P
|
||||
@cppdef ECL_LONG_FLOAT_P
|
||||
@cppdef ECL_CONSP
|
||||
@cppdef ECL_LISTP
|
||||
@cppdef ECL_ATOM
|
||||
@cppdef ECL_SYMBOLP
|
||||
@cppdef ECL_ARRAYP
|
||||
@cppdef ECL_VECTORP
|
||||
@cppdef ECL_BIT_VECTOR_P
|
||||
@cppdef ECL_STRINGP
|
||||
@cppdef ECL_HASH_TABLE_P
|
||||
@cppdef ECL_RANDOM_STATE_P
|
||||
@cppdef ECL_PACKAGEP
|
||||
@cppdef ECL_PATHNAMEP
|
||||
@cppdef ECL_READTABLEP
|
||||
@cppdef ECL_FOREIGN_DATA_P
|
||||
@cppdef ECL_SSE_PACK_P
|
||||
|
||||
@deftypefun bool ECL_CHARACTERP (cl_object o)
|
||||
@deftypefunx bool ECL_BASE_CHAR_P (cl_object o)
|
||||
|
|
@ -264,7 +264,7 @@ type. These checks have been optimized, and are preferred over several
|
|||
calls to @code{ecl_t_of}.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ECL_IMMEDIATE
|
||||
@cppdef ECL_IMMEDIATE
|
||||
@deftypefun bool ECL_IMMEDIATE (cl_object o)
|
||||
Tells whether @var{x} is an immediate datatype.
|
||||
@end deftypefun
|
||||
|
|
@ -285,24 +285,24 @@ the functionality in the lisp environment. In those cases you need to
|
|||
The first way makes use of a C or Lisp string to construct an
|
||||
object. The two functions you need to know are the following ones.
|
||||
|
||||
@cppindex c_string_to_object
|
||||
@cppindex ecl_read_from_cstring
|
||||
@cppindex si_string_to_object
|
||||
@cppdef c_string_to_object
|
||||
@cppdef ecl_read_from_cstring
|
||||
@cppdef si_string_to_object
|
||||
@defun si::string-to-object string &optional (err-value nil)
|
||||
@end defun
|
||||
@deftypefun cl_object si_string_to_object (cl_narg narg, cl_object str, ...)
|
||||
@deftypefunx cl_object ecl_read_from_cstring (const char *s)
|
||||
@code{ecl_read_from_cstring} builds a lisp object from a C string
|
||||
@coderef{ecl_read_from_cstring} builds a lisp object from a C string
|
||||
which contains a suitable representation of a lisp
|
||||
object. @code{si_string_to_object} performs the same task, but uses a
|
||||
object. @coderef{si_string_to_object} performs the same task, but uses a
|
||||
lisp string, and therefore it is less useful.
|
||||
|
||||
@itemize @bullet
|
||||
@item @strong{DEPRECATED} @code{c_string_to_object} – equivalent to @code{ecl_read_from_cstring}
|
||||
@item @strong{DEPRECATED} @coderef{c_string_to_object} – equivalent to @coderef{ecl_read_from_cstring}
|
||||
@end itemize
|
||||
|
||||
@subsubheading Example
|
||||
@exindex @code{ecl_read_from_cstring} constructing Lisp objects in C
|
||||
@exindex @coderef{ecl_read_from_cstring} constructing Lisp objects in C
|
||||
|
||||
Using a C string
|
||||
@example
|
||||
|
|
@ -320,7 +320,7 @@ cl_object array2 = si_string_to_object(string);
|
|||
Common-Lisp distinguishes two types of integer types: @code{bignum}s and
|
||||
@code{fixnum}s. A fixnum is a small integer, which ideally occupies only
|
||||
a word of memory and which is between the values
|
||||
@code{MOST-NEGATIVE-FIXNUM} and @code{MOST-POSITIVE-FIXNUM}. A
|
||||
@coderef{MOST-NEGATIVE-FIXNUM} and @coderef{MOST-POSITIVE-FIXNUM}. A
|
||||
@code{bignum} is any integer which is not a @code{fixnum} and it is only
|
||||
constrained by the amount of memory available to represent it.
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ your C extensions are portable. All other integers are stored as
|
|||
amount of memory and the GNU Multiprecision Library is required to
|
||||
create, manipulate and calculate with them.
|
||||
|
||||
@cppindex cl_fixnum
|
||||
@cppdef cl_fixnum
|
||||
@deftp @cind{} cl_fixnum
|
||||
This is a C signed integer type capable of holding a whole @code{fixnum}
|
||||
without any loss of precision. The opposite is not true, and you may
|
||||
|
|
@ -341,28 +341,28 @@ create a @code{cl_fixnum} which exceeds the limits of a fixnum and
|
|||
should be stored as a @code{bignum}.
|
||||
@end deftp
|
||||
|
||||
@cppindex cl_index
|
||||
@cppdef cl_index
|
||||
@deftp @cind{} cl_index
|
||||
This is a C unsigned integer type capable of holding a non-negative
|
||||
@code{fixnum} without loss of precision. Typically, a @code{cl_index} is
|
||||
used as an index into an array, or into a proper list, etc.
|
||||
@end deftp
|
||||
|
||||
@cppindex MOST_NEGATIVE_FIXNUM
|
||||
@cppindex MOST_POSITIVE_FIXNUM
|
||||
@lspindex MOST-NEGATIVE-FIXNUM
|
||||
@lspindex MOST-POSITIVE-FIXNUM
|
||||
@cppdef MOST_NEGATIVE_FIXNUM
|
||||
@cppdef MOST_POSITIVE_FIXNUM
|
||||
@lspdef MOST-NEGATIVE-FIXNUM
|
||||
@lspdef MOST-POSITIVE-FIXNUM
|
||||
@defvr {Constant} MOST_NEGATIVE_FIXNUM
|
||||
@defvrx {Constant} MOST_POSITIVE_FIXNUM
|
||||
These constants mark the limits of a @code{fixnum}.
|
||||
@end defvr
|
||||
|
||||
@cppindex ecl_fixnum_lower
|
||||
@cppindex ecl_fixnum_greater
|
||||
@cppindex ecl_fixnum_leq
|
||||
@cppindex ecl_fixnum_geq
|
||||
@cppindex ecl_fixnum_plusp
|
||||
@cppindex ecl_fixnum_minusp
|
||||
@cppdef ecl_fixnum_lower
|
||||
@cppdef ecl_fixnum_greater
|
||||
@cppdef ecl_fixnum_leq
|
||||
@cppdef ecl_fixnum_geq
|
||||
@cppdef ecl_fixnum_plusp
|
||||
@cppdef ecl_fixnum_minusp
|
||||
@deftypefun bool ecl_fixnum_lower (cl_fixnum a, cl_fixnum b)
|
||||
@deftypefunx bool ecl_fixnum_greater (cl_fixnum a, cl_fixnum b)
|
||||
@deftypefunx bool ecl_fixnum_leq (cl_fixnum a, cl_fixnum b)
|
||||
|
|
@ -389,12 +389,14 @@ integer). These functions do @strong{not} check their arguments.
|
|||
|
||||
@cppindex cl_fixnum
|
||||
@cppindex cl_index
|
||||
@cppdef fixint
|
||||
@cppdef fixnint
|
||||
@deftypefun cl_fixnum fixint (cl_object o)
|
||||
@deftypefunx cl_index fixnint (cl_object o)
|
||||
Safe conversion of a lisp @code{fixnum} to a C integer of the
|
||||
appropriate size. Signals an error if @var{o} is not of fixnum type.
|
||||
|
||||
@code{fixnint} additionally ensure that @var{o} is not negative.
|
||||
@coderef{fixnint} additionally ensure that @var{o} is not negative.
|
||||
@end deftypefun
|
||||
|
||||
@subheading Characters
|
||||
|
|
@ -411,9 +413,9 @@ the other is used when ECL is built with a configure option
|
|||
@deftp @cind{} ecl_character
|
||||
Immediate type @code{t_character}. If ECL built with Unicode support,
|
||||
then may be either base or extended character, which may be
|
||||
distinguished with the predicate @code{ECL_BASE_CHAR_P}.
|
||||
distinguished with the predicate @coderef{ECL_BASE_CHAR_P}.
|
||||
|
||||
Additionally we have @code{ecl_base_char} for base strings, which is an
|
||||
Additionally we have @coderef{ecl_base_char} for base strings, which is an
|
||||
equivalent to the ordinary char.
|
||||
|
||||
@subsubheading Example
|
||||
|
|
@ -444,11 +446,11 @@ Each character is assigned an integer code which ranges from 0 to
|
|||
@deftypefunx ecl_character ECL_CHAR_CODE (cl_object o)
|
||||
@deftypefunx ecl_character ecl_char_code (cl_object o)
|
||||
@deftypefunx ecl_base_char ecl_base_char_code (cl_object o)
|
||||
@code{ECL_CHAR_CODE}, @code{ecl_char_code} and @code{ecl_base_char_code}
|
||||
return the integer code associated to a lisp
|
||||
character. @code{ecl_char_code} and @code{ecl_base_char_code} perform a
|
||||
safe conversion, while @code{ECL_CHAR_CODE} doesn't check its
|
||||
argument.
|
||||
@code{ECL_CHAR_CODE}, @code{ecl_char_code} and
|
||||
@code{ecl_base_char_code} return the integer code associated to a
|
||||
lisp character. @code{ecl_char_code} and @code{ecl_base_char_code}
|
||||
perform a safe conversion, while @code{ECL_CHAR_CODE} doesn't check
|
||||
its argument.
|
||||
|
||||
@code{ECL_CODE_CHAR} returns the lisp character associated to an integer
|
||||
code. It does not check its arguments.
|
||||
|
|
@ -459,21 +461,21 @@ code. It does not check its arguments.
|
|||
@end itemize
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_char_eq
|
||||
@cppindex ecl_char_equal
|
||||
@cppdef ecl_char_eq
|
||||
@cppdef ecl_char_equal
|
||||
@deftypefun bool ecl_char_eq (cl_object x, cl_object y)
|
||||
@deftypefunx bool ecl_char_equal (cl_object x, cl_object y)
|
||||
Compare two characters for equality. char_eq take case into account and
|
||||
char_equal ignores it.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_char_cmp
|
||||
@cppindex ecl_char_compare
|
||||
@cppdef ecl_char_cmp
|
||||
@cppdef ecl_char_compare
|
||||
@deftypefun int ecl_char_cmp (cl_object x, cl_object y)
|
||||
@deftypefunx int ecl_char_compare (cl_object x, cl_object y)
|
||||
Compare the relative order of two characters. @code{char_cmp} takes care
|
||||
of case and @code{char_compare} converts all characters to uppercase
|
||||
before comparing them.
|
||||
Compare the relative order of two characters. @coderef{ecl_char_cmp}
|
||||
takes care of case and @coderef{ecl_char_compare} converts all
|
||||
characters to uppercase before comparing them.
|
||||
@end deftypefun
|
||||
|
||||
@subheading Arrays
|
||||
|
|
@ -484,8 +486,8 @@ with a pointer to the region of memory which contains the actual
|
|||
data. The cell of an array datatype varies depending on whether it is a
|
||||
vector, a bit-vector, a multidimensional array or a string.
|
||||
|
||||
@cppindex ECL_ADJUSTABLE_ARRAY_P
|
||||
@cppindex ECL_ARRAY_HAS_FILL_POINTER_P
|
||||
@cppdef ECL_ADJUSTABLE_ARRAY_P
|
||||
@cppdef ECL_ARRAY_HAS_FILL_POINTER_P
|
||||
@deftypefun bool ECL_ADJUSTABLE_ARRAY_P (cl_object x)
|
||||
@deftypefunx bool ECL_ARRAY_HAS_FILL_POINTER_P (cl_object x)
|
||||
All arrays (arrays, strings and bit-vectors) may be tested for being
|
||||
|
|
@ -493,7 +495,7 @@ adjustable and whenever they have a fill pointer with this two
|
|||
macros. They don't check the type of their arguments.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_vector
|
||||
@cppdef ecl_vector
|
||||
@deftp @cind{} ecl_vector
|
||||
If @code{x} contains a vector, you can access the following fields:
|
||||
|
||||
|
|
@ -501,8 +503,8 @@ If @code{x} contains a vector, you can access the following fields:
|
|||
@item x->vector.elttype
|
||||
The type of the elements of the vector.
|
||||
@item x->vector.displaced
|
||||
List storing the vectors that x is displaced from and that x displaces
|
||||
to.
|
||||
List storing the vectors that @code{x} is displaced from and that x
|
||||
displaces to.
|
||||
@item x->vector.dim
|
||||
The maximum number of elements.
|
||||
@item x->vector.fillp
|
||||
|
|
@ -513,7 +515,7 @@ pointer depending on @var{x->vector.elttype}.
|
|||
@end table
|
||||
@end deftp
|
||||
|
||||
@cppindex ecl_array
|
||||
@cppdef ecl_array
|
||||
@deftp @cind{} ecl_array
|
||||
If @code{x} contains a multidimensional array, you can access the
|
||||
following fields:
|
||||
|
|
@ -524,8 +526,8 @@ The type of the elements of the array.
|
|||
@item x->array.rank
|
||||
The number of array dimensions.
|
||||
@item x->array.displaced
|
||||
List storing the arrays that x is displaced from and that x displaces
|
||||
to.
|
||||
List storing the arrays that @code{x} is displaced from and that x
|
||||
displaces to.
|
||||
@item x->array.dim
|
||||
The maximum number of elements.
|
||||
@item x->array.dims[]
|
||||
|
|
@ -549,13 +551,13 @@ value of @code{x->array.elttype} or @code{x->vector.elttype}. We list
|
|||
some of those types together with the C constant that denotes that type:
|
||||
|
||||
@table @var
|
||||
@item T
|
||||
@item t
|
||||
@code{ecl_aet_object}
|
||||
@item SINGLE-FLOAT
|
||||
@item single-float
|
||||
@code{ecl_aet_sf}
|
||||
@item DOUBLE-FLOAT
|
||||
@item double-float
|
||||
@code{ecl_aet_df}
|
||||
@item LONG-FLOAT
|
||||
@item long-float
|
||||
@code{ecl_aet_lf}
|
||||
@item (COMPLEX SINGLE-FLOAT)
|
||||
@code{ecl_aet_csf}
|
||||
|
|
@ -639,8 +641,8 @@ zero terminated C string. Thus, if a string has n characters, ECL will
|
|||
reserve n+1 bytes for the base-string. This allows us to pass the
|
||||
base-string self pointer to any C routine.
|
||||
|
||||
@cppindex ecl_string
|
||||
@cppindex ecl_base_string
|
||||
@cppdef ecl_string
|
||||
@cppdef ecl_base_string
|
||||
@deftp @cind{} ecl_string
|
||||
@deftpx @cind{} ecl_base_string
|
||||
If @code{x} is a lisp object of type string or a base-string, we can
|
||||
|
|
@ -655,8 +657,8 @@ Pointer to the characters (appropriately @code{ecl_character}'s and @code{ecl_ba
|
|||
@end table
|
||||
@end deftp
|
||||
|
||||
@cppindex ECL_EXTENDED_STRING_P
|
||||
@cppindex ECL_BASE_STRING_P
|
||||
@cppdef ECL_EXTENDED_STRING_P
|
||||
@cppdef ECL_BASE_STRING_P
|
||||
@deftypefun bool ECL_EXTENDED_STRING_P (cl_object object)
|
||||
@deftypefunx bool ECL_BASE_STRING_P (cl_object object)
|
||||
|
||||
|
|
@ -684,11 +686,11 @@ separate package @var{GRAY}. We may redefine functions in the
|
|||
@var{COMMON-LISP} package with a function @code{redefine-cl-functions}
|
||||
at run-time.
|
||||
|
||||
@cppindex ecl_file_pos
|
||||
@cppdef ecl_file_pos
|
||||
@deftp @cind{} ecl_file_ops write_* read_* unread_* peek_* listen clear_input clear_output finish_output force_output input_p output_p interactive_p element_type length get_position set_position column close
|
||||
@end deftp
|
||||
|
||||
@cppindex ecl_stream
|
||||
@cppdef ecl_stream
|
||||
@deftp @cind{} ecl_stream
|
||||
@table @code
|
||||
@item ecl_smmode mode
|
||||
|
|
@ -730,12 +732,12 @@ Character table, flags, etc
|
|||
@end table
|
||||
@end deftp
|
||||
|
||||
@cppindex ECL_ANSI_STREAM_P
|
||||
@cppdef ECL_ANSI_STREAM_P
|
||||
@deftypefun bool ECL_ANSI_STREAM_P (cl_object o)
|
||||
Predicate determining if @code{o} is a first-class stream object.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ECL_ANSI_STREAM_TYPE_P
|
||||
@cppdef ECL_ANSI_STREAM_TYPE_P
|
||||
@deftypefun bool ECL_ANSI_STREAM_TYPE_P (cl_object o, ecl_smmode m)
|
||||
Predicate determining if @code{o} is a first-class stream object of
|
||||
type @code{m}.
|
||||
|
|
@ -747,11 +749,11 @@ Structures and instances share the same datatype @code{t_instance} (
|
|||
with a few exceptions. Structure implementation details are the file
|
||||
@code{src/c/structure.d}.
|
||||
|
||||
@cppindex ECL_STRUCT_TYPE
|
||||
@cppindex ECL_STRUCT_SLOTS
|
||||
@cppindex ECL_STRUCT_LENGTH
|
||||
@cppindex ECL_STRUCT_SLOT
|
||||
@cppindex ECL_STRUCT_NAME
|
||||
@cppdef ECL_STRUCT_TYPE
|
||||
@cppdef ECL_STRUCT_SLOTS
|
||||
@cppdef ECL_STRUCT_LENGTH
|
||||
@cppdef ECL_STRUCT_SLOT
|
||||
@cppdef ECL_STRUCT_NAME
|
||||
@deftypefun cl_object ECL_STRUCT_TYPE (cl_object x)
|
||||
@deftypefunx cl_object ECL_STRUCT_SLOTS (cl_object x)
|
||||
@deftypefunx cl_object ECL_STRUCT_LENGTH (cl_object x)
|
||||
|
|
@ -762,15 +764,15 @@ Convenience functions for the structures.
|
|||
|
||||
@subheading Instances
|
||||
|
||||
@cppindex ECL_CLASS_OF
|
||||
@cppindex ECL_SPEC_FLAG
|
||||
@cppindex ECL_SPEC_OBJECT
|
||||
@cppindex ECL_CLASS_NAME
|
||||
@cppindex ECL_CLASS_SUPERIORS
|
||||
@cppindex ECL_CLASS_INFERIORS
|
||||
@cppindex ECL_CLASS_SLOTS
|
||||
@cppindex ECL_CLASS_CPL
|
||||
@cppindex ECL_INSTANCEP
|
||||
@cppdef ECL_CLASS_OF
|
||||
@cppdef ECL_SPEC_FLAG
|
||||
@cppdef ECL_SPEC_OBJECT
|
||||
@cppdef ECL_CLASS_NAME
|
||||
@cppdef ECL_CLASS_SUPERIORS
|
||||
@cppdef ECL_CLASS_INFERIORS
|
||||
@cppdef ECL_CLASS_SLOTS
|
||||
@cppdef ECL_CLASS_CPL
|
||||
@cppdef ECL_INSTANCEP
|
||||
|
||||
@deftypefun cl_object ECL_CLASS_OF (cl_object x)
|
||||
@deftypefunx cl_object ECL_SPEC_FLAG (cl_object x)
|
||||
|
|
@ -791,10 +793,9 @@ interpreted. The objects of type @code{t_bytecodes} are implicitly
|
|||
constructed by a call to eval, but can also be explicitly constructed
|
||||
with the @code{si_make_lambda} function.
|
||||
|
||||
@anchor{si_safe_eval}
|
||||
@cppindex si_safe_eval
|
||||
@cppindex cl_safe_eval
|
||||
@cppindex cl_eval
|
||||
@cppdef si_safe_eval
|
||||
@cppdef cl_safe_eval
|
||||
@cppdef cl_eval
|
||||
@defun si:safe-eval form env &optional err-value
|
||||
@end defun
|
||||
@deftypefun cl_object si_safe_eval (cl_narg narg, cl_object form, cl_object env, ...)
|
||||
|
|
@ -827,7 +828,7 @@ si_safe_eval(3, form, ECL_NIL, ecl_make_fixnum(3)); /* on error function will re
|
|||
@end example
|
||||
@end deftypefun
|
||||
|
||||
@cppindex si_make_lambda
|
||||
@cppdef si_make_lambda
|
||||
@deftypefun cl_object si_make_lambda (cl_object name, cl_object def)
|
||||
Builds an interpreted lisp function with name given by the symbol name
|
||||
and body given by @code{def}.
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ To port ECL to a new architecture, the following steps are required:
|
|||
|
||||
@enumerate
|
||||
@item Ensure that the GNU Multiprecision library supports this machine.
|
||||
@item Ensure that the Boehm-Weiser garbage collector is supported by that architecture. Alternatively, port ECL's own garbage collector @code{src/c/alloc.d} and @code{src/c/gbc.d} to that platform.
|
||||
@item Fix @code{src/aclocal.in}, @code{src/h/config.h.in} and @code{src/h/ecl.h} so that they supply flags for the new host machine.
|
||||
@item Fix the machine dependent code in @code{src/c/}. The most critical parts are in the @code{unix*.d} and @code{thread*.d} files.
|
||||
@item Ensure that the Boehm-Weiser garbage collector is supported by that architecture. Alternatively, port ECL's own garbage collector @file{src/c/alloc.d} and @file{src/c/gbc.d} to that platform.
|
||||
@item Fix @file{src/aclocal.in}, @file{src/h/config.h.in} and @file{src/h/ecl.h} so that they supply flags for the new host machine.
|
||||
@item Fix the machine dependent code in @file{src/c/}. The most critical parts are in the @file{unix*.d} and @file{thread*.d} files.
|
||||
@item Compile as in any other platform.
|
||||
@item Run the tests and compare to the results of other platforms.
|
||||
@end enumerate
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
@subheading In-house DFFI
|
||||
|
||||
Commit @code{10bd3b613fd389da7640902c2b88a6e36088c920}. Native DFFI was
|
||||
replaced by a @code{libffi} long time ago, but we have maintained the
|
||||
code as a fallback. Due to small number of supported platforms and no
|
||||
real use it has been removed in 2016.
|
||||
replaced by a @url{https://sourceware.org/libffi/,libffi} long time ago,
|
||||
but we have maintained the code as a fallback. Due to small number of
|
||||
supported platforms and no real use it has been removed in 2016.
|
||||
|
||||
@c @node In-house GC
|
||||
@subheading In-house GC
|
||||
|
|
|
|||
|
|
@ -4,265 +4,263 @@
|
|||
@subsection src/c
|
||||
|
||||
@multitable {aaaaaaaaaaaaaaa}{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
|
||||
@item alloc_2.d
|
||||
@item @file{alloc_2.d}
|
||||
@tab memory allocation based on the Boehm GC
|
||||
|
||||
@item all_symbols.d
|
||||
@item @file{all_symbols.d}
|
||||
@tab name mangler and symbol initialization
|
||||
|
||||
@item apply.d
|
||||
@item @file{apply.d}
|
||||
@tab interface to C call mechanism
|
||||
|
||||
@item arch/*
|
||||
@item @file{arch/*}
|
||||
@tab architecture dependant code
|
||||
|
||||
@item array.d
|
||||
@item @file{array.d}
|
||||
@tab array routines
|
||||
|
||||
@item assignment.c
|
||||
@item @file{assignment.c}
|
||||
@tab assignment
|
||||
|
||||
@item backq.d
|
||||
@item @file{backq.d}
|
||||
@tab backquote mechanism
|
||||
|
||||
@item big.d
|
||||
@item @file{big.d}
|
||||
@tab bignum routines based on the GMP
|
||||
|
||||
@item big_ll.d
|
||||
@item @file{big_ll.d}
|
||||
@tab bignum emulation with long long
|
||||
|
||||
@item cfun.d
|
||||
@item @file{cfun.d}
|
||||
@tab compiled functions
|
||||
|
||||
@item cfun_dispatch.d
|
||||
@item @file{cfun_dispatch.d}
|
||||
@tab trampolines for functions
|
||||
|
||||
@item character.d
|
||||
@item @file{character.d}
|
||||
@tab character routines
|
||||
|
||||
@item char_ctype.d
|
||||
@item @file{char_ctype.d}
|
||||
@tab character properties.
|
||||
|
||||
@item cinit.d
|
||||
@item @file{cinit.d}
|
||||
@tab lisp initialization
|
||||
|
||||
@item clos/accessor.d
|
||||
@item @file{clos/accessor.d}
|
||||
@tab dispatch for slots
|
||||
|
||||
@item clos/cache.d
|
||||
@item @file{clos/cache.d}
|
||||
@tab thread-local cache for a variety of operations
|
||||
|
||||
@item clos/gfun.d
|
||||
@item @file{clos/gfun.d}
|
||||
@tab dispatch for generic functions
|
||||
|
||||
@item clos/instance.d
|
||||
@item @file{clos/instance.d}
|
||||
@tab CLOS interface
|
||||
|
||||
@item cmpaux.d
|
||||
@item @file{cmpaux.d}
|
||||
@tab auxiliaries used in compiled Lisp code
|
||||
|
||||
@item compiler.d
|
||||
@item @file{compiler.d}
|
||||
@tab bytecode compiler
|
||||
|
||||
@item cons.d
|
||||
@item @file{cons.d}
|
||||
@tab list manipulation macros & functions (auto generated)
|
||||
|
||||
@item disassembler.d
|
||||
@item @file{disassembler.d}
|
||||
@tab bytecodes disassembler utilities
|
||||
|
||||
@item dpp.c
|
||||
@item @file{dpp.c}
|
||||
@tab defun preprocessor
|
||||
|
||||
@item ecl_constants.h
|
||||
@item @file{ecl_constants.h}
|
||||
@tab constant values for all_symbols.d
|
||||
|
||||
@item ecl_features.h
|
||||
@item @file{ecl_features.h}
|
||||
@tab names of features compiled into ECL
|
||||
|
||||
@item error.d
|
||||
@item @file{error.d}
|
||||
@tab error handling
|
||||
|
||||
@item eval.d
|
||||
@item @file{eval.d}
|
||||
@tab evaluation
|
||||
|
||||
@item ffi/backtrace.d
|
||||
@item @file{ffi/backtrace.d}
|
||||
@tab C backtraces
|
||||
|
||||
@item ffi/cdata.d
|
||||
@item @file{ffi/cdata.d}
|
||||
@tab data for compiled files
|
||||
|
||||
@item ffi/libraries.d
|
||||
@item @file{ffi/libraries.d}
|
||||
@tab shared library and bundle opening / copying / closing
|
||||
|
||||
@item ffi/mmap.d
|
||||
@item @file{ffi/mmap.d}
|
||||
@tab mapping of binary files
|
||||
|
||||
@item ffi.d
|
||||
@item @file{ffi.d}
|
||||
@tab user defined data types and foreign functions interface
|
||||
|
||||
@item file.d
|
||||
@item @file{file.d}
|
||||
@tab file interface (implementation dependent)
|
||||
|
||||
@item format.d
|
||||
@item @file{format.d}
|
||||
@tab format (this isn't ANSI compliant, we need it for bootstrapping though)
|
||||
|
||||
@item hash.d
|
||||
@item @file{hash.d}
|
||||
@tab hash tables
|
||||
|
||||
@item interpreter.d
|
||||
@item @file{interpreter.d}
|
||||
@tab bytecode interpreter
|
||||
|
||||
@item iso_latin_names.h
|
||||
@item @file{iso_latin_names.h}
|
||||
@tab character names in ISO-LATIN-1
|
||||
|
||||
@item list.d
|
||||
@item @file{list.d}
|
||||
@tab list manipulating routines
|
||||
|
||||
@item load.d
|
||||
@item @file{load.d}
|
||||
@tab binary loader (contains also open_fasl_data)
|
||||
|
||||
@item macros.d
|
||||
@item @file{macros.d}
|
||||
@tab macros and environment
|
||||
|
||||
@item main.d
|
||||
@item @file{main.d}
|
||||
@tab ecl boot process
|
||||
|
||||
@item Makefile.in
|
||||
@item @file{Makefile.in}
|
||||
@tab Makefile for ECL core library
|
||||
|
||||
@item mapfun.d
|
||||
@item @file{mapfun.d}
|
||||
@tab mapping
|
||||
|
||||
@item multival.d
|
||||
@item @file{multival.d}
|
||||
@tab multiple values
|
||||
|
||||
@item newhash.d
|
||||
@item @file{newhash.d}
|
||||
@tab hashing routines
|
||||
|
||||
@item num_arith.d
|
||||
@item @file{num_arith.d}
|
||||
@tab arithmetic operations
|
||||
|
||||
@item number.d
|
||||
@item @file{number.d}
|
||||
@tab constructing numbers
|
||||
|
||||
@c these files need to be cleaned
|
||||
@item numbers/*.d
|
||||
@item @file{numbers/*.d}
|
||||
@tab arithmetic operations (abs, atan, plusp etc)
|
||||
|
||||
@item num_co.d
|
||||
@item @file{num_co.d}
|
||||
@tab operations on floating-point numbers (implementation dependent)
|
||||
|
||||
@item num_log.d
|
||||
@item @file{num_log.d}
|
||||
@tab logical operations on numbers
|
||||
|
||||
@item num_pred.d
|
||||
@item @file{num_pred.d}
|
||||
@tab predicates on numbers
|
||||
|
||||
@item num_rand.d
|
||||
@item @file{num_rand.d}
|
||||
@tab random numbers
|
||||
|
||||
@item package.d
|
||||
@item @file{package.d}
|
||||
@tab packages (OS dependent)
|
||||
|
||||
@item pathname.d
|
||||
@item @file{pathname.d}
|
||||
@tab pathnames
|
||||
|
||||
@item predicate.d
|
||||
@item @file{predicate.d}
|
||||
@tab predicates
|
||||
|
||||
@item print.d
|
||||
@item @file{print.d}
|
||||
@tab print
|
||||
|
||||
@item printer/*.d
|
||||
@item @file{printer/*.d}
|
||||
@tab printer utilities and object representations
|
||||
|
||||
@item read.d
|
||||
@item @file{read.d}
|
||||
@tab reader
|
||||
|
||||
@item reader/parse_integer.d
|
||||
@item reader/parse_number.d
|
||||
@item @file{reader/parse_integer.d}
|
||||
@item @file{reader/parse_number.d}
|
||||
|
||||
@item reference.d
|
||||
@item @file{reference.d}
|
||||
@tab reference in Constants and Variables
|
||||
|
||||
@item sequence.d
|
||||
@item @file{sequence.d}
|
||||
@tab sequence routines
|
||||
|
||||
@item serialize.d
|
||||
@item @file{serialize.d}
|
||||
@tab serialize a bunch of lisp data
|
||||
|
||||
@item sse2.d
|
||||
@item @file{sse2.d}
|
||||
@tab SSE2 vector type support
|
||||
|
||||
@item stacks.d
|
||||
@item @file{stacks.d}
|
||||
@tab binding/history/frame stacks
|
||||
|
||||
@item string.d
|
||||
@item @file{string.d}
|
||||
@tab string routines
|
||||
|
||||
@item structure.d
|
||||
@item @file{structure.d}
|
||||
@tab structure interface
|
||||
|
||||
@item symbol.d
|
||||
@item @file{symbol.d}
|
||||
@tab symbols
|
||||
|
||||
@item symbols_list.h
|
||||
@item symbols_list2.h
|
||||
@item @file{symbols_list.h}
|
||||
@item @file{symbols_list2.h}
|
||||
@tab The latter is generated from the first. The first has to contain all
|
||||
symbols on the system which aren't local.
|
||||
|
||||
@item tcp.d
|
||||
@item @file{tcp.d}
|
||||
@tab stream interface to TCP
|
||||
|
||||
@item time.d
|
||||
@item @file{time.d}
|
||||
@tab time routines
|
||||
|
||||
@item typespec.d
|
||||
@item @file{typespec.d}
|
||||
@tab type specifier routines
|
||||
|
||||
@item unicode/*
|
||||
@item @file{unicode/*}
|
||||
@tab unicode definitions
|
||||
|
||||
@item unixfsys.d
|
||||
@item @file{unixfsys.d}
|
||||
@tab Unix file system interface
|
||||
|
||||
@item unixint.d
|
||||
@item @file{unixint.d}
|
||||
@tab Unix interrupt interface.
|
||||
|
||||
@item unixsys.d
|
||||
@item @file{unixsys.d}
|
||||
@tab Unix shell interface
|
||||
|
||||
@item vector_push.d
|
||||
@item @file{vector_push.d}
|
||||
@tab vector optimizations
|
||||
|
||||
@headitem threads/
|
||||
|
||||
@item atomic.d
|
||||
@item @file{threads/atomic.d}
|
||||
@tab atomic operations
|
||||
|
||||
@item barrier.d
|
||||
@item @file{threads/barrier.d}
|
||||
@tab wait barriers
|
||||
|
||||
@item condition_variable.d
|
||||
@item @file{threads/condition_variable.d}
|
||||
@tab condition variables for native threads
|
||||
@c implement me: @code{mp_condition_variable_timedwait}
|
||||
|
||||
@item mailbox.d
|
||||
@item @file{threads/mailbox.d}
|
||||
@tab thread communication queue
|
||||
|
||||
@item mutex.d
|
||||
@item @file{threads/mutex.d}
|
||||
@tab mutually exclusive locks.
|
||||
|
||||
@item process.d
|
||||
@item @file{threads/process.d}
|
||||
@tab native threads
|
||||
|
||||
@item queue.d
|
||||
@item @file{threads/queue.d}
|
||||
@tab waiting queue for threads
|
||||
|
||||
@item rwlock.d
|
||||
@item @file{threads/rwlock.d}
|
||||
@tab POSIX read-write locks
|
||||
|
||||
@item semaphore.d
|
||||
@item @file{threads/semaphore.d}
|
||||
@tab POSIX-like semaphores
|
||||
|
||||
@end multitable
|
||||
|
|
|
|||
|
|
@ -1,60 +1,108 @@
|
|||
html { background: #FFF; }
|
||||
/* colors */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
/* dark theme */
|
||||
html { color: seashell;
|
||||
background: #1A1A1A; }
|
||||
body { background: #1A1A1A; }
|
||||
th { border-bottom: 2px solid lightgray; }
|
||||
h1, h2, h3, h4, h5 { background-image: linear-gradient(to left, #202020, #3A3A3A); }
|
||||
code, var, code a { color: darkorange;
|
||||
background: #2A2A2A; }
|
||||
a { color: seashell; }
|
||||
pre { background: #2A2A2A;
|
||||
color: seashell;
|
||||
/* mark longer code block with stripe on the left */
|
||||
border-left: 5px solid darkorange;
|
||||
padding-left: 10px; }
|
||||
pre.screen { background: #2A2A2A;
|
||||
border: 1px solid lightgray; }
|
||||
pre.programlisting { background: #2A2A2A;
|
||||
border-left: 1px solid lightgray;
|
||||
border-top: 1px solid lightgray; }
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
/* light theme */
|
||||
html { background: white }
|
||||
body { background: white }
|
||||
th { border-bottom: 2px solid gray; }
|
||||
h1, h2, h3, h4, h5 { background: lightgray; }
|
||||
code, var, code a { color: darkred;
|
||||
background: whitesmoke; }
|
||||
a { color: #000; }
|
||||
pre { background: whitesmoke;
|
||||
color: black;
|
||||
/* mark longer code block with stripe on the left */
|
||||
border-left: 5px solid darkred;
|
||||
padding-left: 10px; }
|
||||
pre.screen { background: #EEE;
|
||||
border: 1px solid black; }
|
||||
pre.programlisting { background: #EEEEEE;
|
||||
border-left: 1px solid black;
|
||||
border-top: 1px solid black; }
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 1em 125px 0 10%;
|
||||
line-height: 1.5em;
|
||||
padding: 0 2em 1em 2em;
|
||||
background: #FFF;
|
||||
font: 12px Verdana,Arial, sans-serif
|
||||
margin: 1em 125px 0 10%;
|
||||
line-height: 1.5em;
|
||||
padding: 0 2em 1em 2em;
|
||||
font: 13px Verdana,Arial, sans-serif
|
||||
}
|
||||
ul, dd, dl, dt { margin-top: 0; margin-bottom: 0; }
|
||||
p, code, td, dl, dt {
|
||||
line-height: 1.5em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
table {
|
||||
font: inherit;
|
||||
font: inherit;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
th, td {
|
||||
vertical-align: top;
|
||||
vertical-align: top;
|
||||
}
|
||||
h1, h2, h3, h4, h5 { background: #EEE; }
|
||||
h1, h2, h3 { padding-left: 15px; }
|
||||
h4, h5 { padding-left: 5px; }
|
||||
code, pre {
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
}
|
||||
code {
|
||||
background: #CDC;
|
||||
var {
|
||||
font-size: 1em;
|
||||
}
|
||||
/* links inside code appear the same as the code itself */
|
||||
code a {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* but get an underline when hovering */
|
||||
code a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* ordinary links appear in bold */
|
||||
a { font-weight: bold; }
|
||||
pre.verbatim {
|
||||
margin: 0 0 0 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
pre.screen {
|
||||
font-weight: bold;
|
||||
background: #EEE;
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
font-weight: bold;
|
||||
padding: 0.5em;
|
||||
}
|
||||
pre.programlisting {
|
||||
background: #EEEEEE;
|
||||
border-left: 1px solid black;
|
||||
border-top: 1px solid black;
|
||||
padding: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
a { color: #000; font-weight: bold; }
|
||||
div p { padding: 0 2em }
|
||||
li p { padding: 0; margin: 0 }
|
||||
hr { display: none; }
|
||||
div.funcsynopsis p {
|
||||
text-indent: -2em;
|
||||
text-indent: -2em;
|
||||
}
|
||||
div.variablelist {
|
||||
padding: 0 2em;
|
||||
padding: 0 2em;
|
||||
}
|
||||
.type, .funcsynopsis, .symbol {
|
||||
font-family: monospace;
|
||||
font-family: monospace;
|
||||
}
|
||||
.type, .symbol, .replaceable {
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
* Compiling with ECL::
|
||||
* Compiling with ASDF::
|
||||
* C compiler configuration::
|
||||
@c * Compiling with Matroska::
|
||||
|
||||
@end menu
|
||||
@c * Compiling with Matroska::
|
||||
|
||||
@cindex System building
|
||||
@cindex Creating executables and libraries
|
||||
|
|
@ -20,7 +19,7 @@ programs. ECL is especially powerful on combining lisp programs with C
|
|||
programs. You can embed ECL as a lisp engine in C programs, or call C
|
||||
functions via @ref{Foreign Function Interface}. We explain file types
|
||||
generated by some compilation approaches. For the examples,
|
||||
a GNU/Linux system and gcc as a development environment are assumed.
|
||||
a GNU/Linux system and gcc as a development environment are assumed.
|
||||
|
||||
You can generate the following files with ECL:
|
||||
|
||||
|
|
@ -97,7 +96,7 @@ bundles. FASC files are faster to compile, but generally slower to run.
|
|||
|
||||
If you want to make a library which is loaded dynamically from a lisp
|
||||
program, you should choose the fasl file format. Under the hood native fasls
|
||||
are just a shared library files.
|
||||
are just shared library files.
|
||||
|
||||
This means you can load fasl files with @code{dlopen} and initialize it
|
||||
by calling a init function from C programs, but this is not an intended
|
||||
|
|
@ -113,7 +112,7 @@ Creating a fasl file from one lisp file is very easy.
|
|||
|
||||
To create a fasl file from more lisp files, firstly you have to compile
|
||||
each lisp file into an object file, and then combine them with
|
||||
c:build-fasl.
|
||||
@code{c:build-fasl}.
|
||||
|
||||
@exindex Building native FASL
|
||||
@lisp
|
||||
|
|
@ -136,10 +135,11 @@ c:build-fasl.
|
|||
@subsubsection Object file
|
||||
|
||||
Object files work as an intermediate file format. If you want to compile
|
||||
more than two lisp files, you might better to compile with a :system-p t
|
||||
option, which generates object files (instead of a fasl).
|
||||
more than two lisp files, you might better to compile with a
|
||||
@code{:system-p t} option, which generates object files (instead of a
|
||||
fasl).
|
||||
|
||||
On linux systems, ECL invokes gcc -c to generate object files.
|
||||
On linux systems, ECL invokes @code{gcc -c} to generate object files.
|
||||
|
||||
An object file consists of some functions in C:
|
||||
|
||||
|
|
@ -184,8 +184,8 @@ files act as intermediate files.
|
|||
@subsubsection Static library
|
||||
|
||||
ECL can compile lisp programs to static libraries, which can be linked
|
||||
with C programs. A static library is created by c:build-static-library
|
||||
with some compiled object files.
|
||||
with C programs. A static library is created by
|
||||
@code{c:build-static-library} with some compiled object files.
|
||||
|
||||
@exindex Building static library
|
||||
@lisp
|
||||
|
|
@ -205,6 +205,7 @@ name of this function is specified by the @code{:init-name} option. In this
|
|||
example, it is then @code{init_hello_goodbye}. The usage of this function is
|
||||
shown below:
|
||||
|
||||
@cppdef ecl_init_module
|
||||
@exindex Initializing static/shared library in C/C++
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -230,15 +231,15 @@ main(int argc, char **argv)
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
Because the program itself does not know the type of the init
|
||||
function, a prototype declaration is inserted. After booting up the
|
||||
lisp environment, it invokes @code{init_hello_goodbye} via
|
||||
@code{ecl_init_module}. @code{init_hello_goodbye} takes an argument, and
|
||||
@code{ecl_init_module} supplies an appropriate one. Now that the
|
||||
initialization is finished, we can use functions and other stuff
|
||||
defined in the library.
|
||||
Because the program itself does not know the type of the init function,
|
||||
a prototype declaration is inserted. After booting up the lisp
|
||||
environment, it invokes @code{init_hello_goodbye} via
|
||||
@coderef{ecl_init_module}. @code{init_hello_goodbye} takes an argument,
|
||||
and @coderef{ecl_init_module} supplies an appropriate one. Now that the
|
||||
initialization is finished, we can use functions and other stuff defined
|
||||
in the library.
|
||||
|
||||
@strong{DEPRECATED} @code{read_VV} - equivalent to @code{ecl_init_module}
|
||||
@strong{DEPRECATED} @code{read_VV} - equivalent to @coderef{ecl_init_module}
|
||||
|
||||
@node Shared library
|
||||
@subsubsection Shared library
|
||||
|
|
@ -302,19 +303,20 @@ format. In case of @emph{Portable FASL} the bytecodes compiler is needed.
|
|||
@subsection Compiling with ASDF
|
||||
|
||||
First, let's disregard the simple situation in which we write Lisp
|
||||
without depending on any other Lisp libraries. A more practical
|
||||
example is to build a library that depends on other asdf systems. ECL
|
||||
provides a useful extension for asdf called @code{asdf:make-build},
|
||||
which offers an abstraction for building libraries directly from
|
||||
system definitions.
|
||||
without depending on any other Lisp libraries. A more practical example
|
||||
is to build a library that depends on other
|
||||
@uref{https://common-lisp.net/project/asdf/,asdf}, systems. ECL provides
|
||||
a useful extension for asdf called @code{asdf:make-build}, which offers
|
||||
an abstraction for building libraries directly from system definitions.
|
||||
|
||||
To download dependencies you may use Quicklisp to load your system
|
||||
(with dependencies defined). Make sure you can successfully load and
|
||||
run your library in the ECL REPL (or @code{*slime-repl*}). Don't worry
|
||||
about other libraries loaded in your image – ECL will only build and
|
||||
pack libraries your project depends on (that is, all dependencies you
|
||||
put in your @code{.asd} file, and their dependencies - nothing more,
|
||||
despite the fact that other libraries may be loaded).
|
||||
To download dependencies you may use
|
||||
@uref{https://www.quicklisp.org,Quicklisp} to load your system (with
|
||||
dependencies defined). Make sure you can successfully load and run your
|
||||
library in the ECL REPL (or @code{*slime-repl*}). Don't worry about
|
||||
other libraries loaded in your image – ECL will only build and pack
|
||||
libraries your project depends on (that is, all dependencies you put in
|
||||
your @code{.asd} file, and their dependencies - nothing more, despite
|
||||
the fact that other libraries may be loaded).
|
||||
|
||||
@menu
|
||||
* Example code to build::
|
||||
|
|
@ -460,13 +462,13 @@ REPL):
|
|||
:init-name "init_bt")
|
||||
@end lisp
|
||||
|
||||
Note that we haven't specified @code{:monolithic t}, so we need to
|
||||
build @code{bordeaux-threads} as well because @code{cl-fad} depends on
|
||||
it. The building sequence doesn't matter and the resultant ~.so~ files
|
||||
can also be used in your future programs if these libraries are not
|
||||
Note that we haven't specified @code{:monolithic t}, so we need to build
|
||||
@code{bordeaux-threads} as well because @code{cl-fad} depends on it. The
|
||||
building sequence doesn't matter and the resultant @code{.so} files can
|
||||
also be used in your future programs if these libraries are not
|
||||
modified.
|
||||
|
||||
We need to initialize all these modules using @code{ecl_init_module}
|
||||
We need to initialize all these modules using @coderef{ecl_init_module}
|
||||
in the correct order. (@code{bordeaux-threads} must be initialized
|
||||
before @code{cl-fad}; @code{cl-fad} and @code{alexandria} must be
|
||||
initialized before @code{complex-ecample}.)
|
||||
|
|
@ -520,9 +522,9 @@ This will show:
|
|||
Factorial of 5 is: 120
|
||||
@end example
|
||||
|
||||
Note we don't need to pass the current path in ~LD_LIBRARY_PATH~ here,
|
||||
since our Lisp library is statically bundled with the executable. The
|
||||
result is the same as the shared library example above. You can also
|
||||
Note we don't need to pass the current path in @code{LD_LIBRARY_PATH}
|
||||
here, since our Lisp library is statically bundled with the executable.
|
||||
The result is the same as the shared library example above. You can also
|
||||
build all dependent libraries separately as static libraries.
|
||||
|
||||
@node C compiler configuration
|
||||
|
|
|
|||
|
|
@ -41,11 +41,13 @@ are the arguments that these routines expect, what are the calling
|
|||
conventions and where are these routines to be found.
|
||||
@end table
|
||||
|
||||
On top of these components sits a higher level interface written entirely in lisp, with which
|
||||
you will actually declare and use foreign variables, functions and libraries. In the following
|
||||
sections we describe both the details of the low-level components (Section 3.2, Section 3.3),
|
||||
and of the higher level interface (Section 3.4). It is highly recommended that you read all
|
||||
sections.
|
||||
On top of these components sits a higher level interface written
|
||||
entirely in lisp, with which you will actually declare and use foreign
|
||||
variables, functions and libraries. In the following sections we
|
||||
describe both the details of the low-level components (@xref{Two kinds
|
||||
of FFI} and @ref{Foreign objects}), and of the higher level interface
|
||||
(@xref{Higher level interfaces}). It is highly recommended that you read
|
||||
all sections.
|
||||
|
||||
@node Two kinds of FFI
|
||||
@subsection Two kinds of FFI
|
||||
|
|
@ -112,8 +114,8 @@ section @emph{Supported Platforms} at
|
|||
|
||||
@ftindex DFFI
|
||||
You can test if your copy of ECL was built with DFFI by inspecting
|
||||
whether the symbol @var{:DFFI} is present in the list from variable
|
||||
@var{*FEATURES*}.
|
||||
whether the symbol @code{:dffi} is present in the list from variable
|
||||
@code{*features*}.
|
||||
|
||||
@node Foreign objects
|
||||
@subsection Foreign objects
|
||||
|
|
@ -137,7 +139,7 @@ memory and deallocated when no longer in use.
|
|||
A foreign object may contain many different kinds of data: integers,
|
||||
floating point numbers, C structures, unions, etc. The actual type of
|
||||
the object is stored in a list or a symbol which is understood by the
|
||||
higher level interface (Section 3.4).
|
||||
higher level interface (@xref{Higher level interfaces}).
|
||||
|
||||
The most important component of the object is the memory region where
|
||||
data is stored. By default ECL assumes that the user will perform
|
||||
|
|
@ -151,9 +153,9 @@ valid, ECL should not attempt to automatically destroy the object.
|
|||
|
||||
In many cases, however, it is desirable to automatically destroy foreign
|
||||
objects once they have been used. The higher level interfaces UFFI and
|
||||
CFFI provide tools for doing this. For instance, in the following
|
||||
example adapted from the UFFI documentation, the string @var{NAME} is
|
||||
automatically deallocated
|
||||
@url{https://common-lisp.net/project/cffi/,CFFI} provide tools for doing
|
||||
this. For instance, in the following example adapted from the UFFI
|
||||
documentation, the string @var{name} is automatically deallocated
|
||||
|
||||
@lisp
|
||||
(ffi:def-function ("gethostname" c-gethostname)
|
||||
|
|
@ -180,10 +182,11 @@ version 1.8 (api for >=v2.0 is provided by cffi-uffi-compat system
|
|||
shipped with CFFI). Code designed for UFFI library should run mostly
|
||||
unchanged with ECL. Note, that api resides in ffi package, not uffi, to
|
||||
prevent conflicts with cffi-uffi-compat. New code shouldn't use this
|
||||
interface preferring CFFI.
|
||||
interface preferring @url{https://common-lisp.net/project/cffi/,CFFI}.
|
||||
@item
|
||||
The CFFI library features a complete backend for ECL. This method of
|
||||
interfacing with the foreign libraries is preferred over using UFFI.
|
||||
The @url{https://common-lisp.net/project/cffi/,CFFI} library features a
|
||||
complete backend for ECL. This method of interfacing with the foreign
|
||||
libraries is preferred over using UFFI.
|
||||
@item
|
||||
ECL's own low level interface. Only to be used if ECL is your deployment
|
||||
platform. It features some powerful constructs that allow you to mix
|
||||
|
|
@ -208,7 +211,7 @@ You need to specify the libraries you use and do it at the toplevel, so
|
|||
that the compiler may include them at link time.
|
||||
@item
|
||||
Every function you will use has to be declared using
|
||||
@code{ffi:def-function}.
|
||||
@coderef{ffi:def-function}.
|
||||
@end itemize
|
||||
|
||||
@lisp
|
||||
|
|
@ -239,9 +242,10 @@ Build and load this module with (compile-file "uffi.lsp" :load t)
|
|||
@subsubheading CFFI example
|
||||
@exindex CFFI usage
|
||||
|
||||
The CFFI library is an independent project and it is not shipped with
|
||||
ECL. If you wish to use it you can go to their homepage, download the
|
||||
code and build it using ASDF.
|
||||
The @url{https://common-lisp.net/project/cffi/,CFFI} library is an
|
||||
independent project and it is not shipped with ECL. If you wish to use
|
||||
it you can go to their homepage, download the code and build it using
|
||||
ASDF.
|
||||
|
||||
CFFI differs slightly from UFFI in that functions may be used even
|
||||
without being declared beforehand.
|
||||
|
|
@ -280,7 +284,7 @@ Build and load this module with (compile-file "cffi.lsp" :load t)
|
|||
@exindex SFFI usage
|
||||
|
||||
To compare with the previous pieces of code, we show how the previous programs would be
|
||||
written using @code{ffi:clines} and @code{ffi:c-inline}.
|
||||
written using @coderef{ffi:clines} and @coderef{ffi:c-inline}.
|
||||
|
||||
@lisp
|
||||
#|
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
@lspindex ffi:*use-dffi*
|
||||
@defvr Variable {ffi:*use-dffi*}
|
||||
This variable controls whether @code{DFFI} is used or not.
|
||||
This variable controls whether DFFI is used or not.
|
||||
@end defvr
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:clines
|
||||
@lspdef ffi:clines
|
||||
@defspec ffi:clines c/c++-code*
|
||||
|
||||
Insert C declarations and definitions
|
||||
|
|
@ -17,25 +17,25 @@ One or more strings with C definitions. Not evaluated.
|
|||
No value.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This special form inserts C code from strings passed in the
|
||||
@var{arguments} directly in the file that results from compiling lisp
|
||||
sources. Contrary to @code{ffi:c-inline}, this function may have no
|
||||
sources. Contrary to @coderef{ffi:c-inline}, this function may have no
|
||||
executable statements, accepts no input value and returns no value.
|
||||
|
||||
The main use of @code{ffi:clines} is to declare or define C variables
|
||||
The main use of @coderef{ffi:clines} is to declare or define C variables
|
||||
and functions that are going to be used later in other FFI
|
||||
statements. All statements from @var{arguments} are grouped at the
|
||||
beginning of the produced header file.
|
||||
|
||||
@code{ffi:clines} is a special form that can only be used in lisp
|
||||
@coderef{ffi:clines} is a special form that can only be used in lisp
|
||||
compiled files as a toplevel form. Other uses will lead to an error
|
||||
being signaled, either at the compilation time or when loading the
|
||||
file.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:clines} adding c toplevel declarations
|
||||
In this example the @code{ffi:clines} statement is required to get
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:clines} adding c toplevel declarations
|
||||
In this example the @coderef{ffi:clines} statement is required to get
|
||||
access to the C function @code{cos}:
|
||||
@lisp
|
||||
(ffi:clines "#include <math.h>")
|
||||
|
|
@ -44,7 +44,7 @@ access to the C function @code{cos}:
|
|||
@end lisp
|
||||
@end defspec
|
||||
|
||||
@lspindex ffi:c-inline
|
||||
@lspdef ffi:c-inline
|
||||
@defspec ffi:c-inline (lisp-values) (arg-c-types) return-type c/c++-code @
|
||||
&key (side-effects t) (one-liner nil)
|
||||
|
||||
|
|
@ -56,20 +56,20 @@ One or more lisp expressions. Evaluated.
|
|||
@item arg-c-types
|
||||
One or more valid FFI types. Evaluated.
|
||||
@item return-type
|
||||
Valid FFI type or (VALUES ffi-type*).
|
||||
Valid FFI type or @code{(values ffi-type*)}.
|
||||
@item c/c++-code
|
||||
String containing valid C code plus some valid escape forms.
|
||||
@item one-liner
|
||||
Boolean indicating, if the expression is a valid R-value. Defaults to
|
||||
@code{NIL}.
|
||||
@code{nil}.
|
||||
@item side-effects
|
||||
Boolean indicating, if the expression causes side effects. Defaults to
|
||||
@code{T}.
|
||||
@code{t}.
|
||||
@item returns
|
||||
One or more lisp values.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This is a special form which can be only used in compiled code and whose
|
||||
purpose is to execute some C code getting and returning values from and
|
||||
to the lisp environment.
|
||||
|
|
@ -86,16 +86,16 @@ mixes C expressions with two kind of escape forms.
|
|||
The first kind of escape form are made of a hash and a letter or a
|
||||
number, as in: @code{#0}, @code{#1}, ..., until @code{#z}. These codes
|
||||
are replaced by the corresponding input values. The second kind of
|
||||
escape form has the format @verb{|@(return [n])|}, it can be used as
|
||||
escape form has the format @code{@@(return [n])}, it can be used as
|
||||
lvalue in a C expression and it is used to set the n-th output value of
|
||||
the @code{ffi:c-inline} form.
|
||||
the @coderef{ffi:c-inline} form.
|
||||
|
||||
When the parameter @var{one-liner} is true, then the C template must be
|
||||
a simple C statement that outputs a value. In this case the use of
|
||||
@verb{|@(return)|} is not allowed. When the parameter @var{one-liner} is
|
||||
@code{@@(return)} is not allowed. When the parameter @var{one-liner} is
|
||||
false, then the C template may be a more complicated block form, with
|
||||
braces, conditionals, loops and spanning multiple lines. In this case
|
||||
the output of the form can only be set using @verb{|@(return)|}.
|
||||
the output of the form can only be set using @code{@@(return)}.
|
||||
|
||||
Parameter @var{side-effects} set to false will indicate, that the
|
||||
functions causes no side-effects. This information is used by the
|
||||
|
|
@ -104,11 +104,11 @@ false, but the function may cause the side effects, then results are
|
|||
undefined.
|
||||
|
||||
Note that the conversion between lisp arguments and FFI types is
|
||||
automatic. Note also that @code{ffi:c-inline} cannot be used in
|
||||
automatic. Note also that @coderef{ffi:c-inline} cannot be used in
|
||||
interpreted or bytecompiled code! Such usage will signal an error.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:c-inline} inlining c code
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:c-inline} inlining c code
|
||||
The following example implements the transcendental function SIN using
|
||||
the C equivalent:
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ the C equivalent:
|
|||
:side-effects nil))
|
||||
@end lisp
|
||||
|
||||
This function can also be implemented using the @verb{|@(return)|} form
|
||||
This function can also be implemented using the @code{@@(return)} form
|
||||
as follows:
|
||||
|
||||
@lisp
|
||||
|
|
@ -136,7 +136,7 @@ as follows:
|
|||
The following example is slightly more complicated as it involves loops
|
||||
and two output values:
|
||||
|
||||
@exindex @code{ffi:c-inline} returning multiple values
|
||||
@exindex @coderef{ffi:c-inline} returning multiple values
|
||||
@lisp
|
||||
@verbatim
|
||||
(defun sample (x)
|
||||
|
|
@ -155,7 +155,7 @@ and two output values:
|
|||
@end lisp
|
||||
@end defspec
|
||||
|
||||
@lspindex ffi:c-progn
|
||||
@lspdef ffi:c-progn
|
||||
@defspec ffi:c-progn args &body body
|
||||
|
||||
Interleave C statements with the Lisp code
|
||||
|
|
@ -167,14 +167,14 @@ Lisp arguments. Evaluated.
|
|||
No value.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This form is used for it's side effects. It allows for interleaving C
|
||||
statements with the Lisp code. The argument types doesn't have to be
|
||||
declared – in such case the objects type in the C world will be
|
||||
@code{cl_object}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:c-progn} interleaving c and lisp code
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:c-progn} interleaving c and lisp code
|
||||
@lisp
|
||||
@verbatim
|
||||
(lambda (i)
|
||||
|
|
@ -195,7 +195,7 @@ declared – in such case the objects type in the C world will be
|
|||
@c XXX: SFFI returns one-element list pointer, while DFFI returns just a
|
||||
@c pointer. This is probably a bug.
|
||||
|
||||
@lspindex ffi:defcallback
|
||||
@lspdef ffi:defcallback
|
||||
@defspec ffi:defcallback name ret-type arg-desc &body body
|
||||
|
||||
@table @var
|
||||
|
|
@ -211,13 +211,13 @@ Function body.
|
|||
Pointer to the defined callback.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Defines Lisp function and generates a callback for the C world, which
|
||||
may be passed to these functions. Note, that this special operator has
|
||||
also a dynamic variant (with the same name and interface).
|
||||
@end defspec
|
||||
|
||||
@lspindex ffi:defcbody
|
||||
@lspdef ffi:defcbody
|
||||
@defmac ffi:defcbody name arg-types result-type c-expression
|
||||
|
||||
Define C function under the lisp name
|
||||
|
|
@ -233,16 +233,16 @@ Result type of the C function (may be @code{(values ...)}.
|
|||
Defined function name.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
The compiler defines a Lisp function named by @var{NAME} whose body
|
||||
consists of the C code of the string @var{C-EXPRESSION}. In the
|
||||
@var{C-EXPRESSION} one can reference the arguments of the function as
|
||||
@paragraph Description
|
||||
The compiler defines a Lisp function named by @var{name} whose body
|
||||
consists of the C code of the string @var{c-expression}. In the
|
||||
@var{c-expression} one can reference the arguments of the function as
|
||||
@code{#0}, @code{#1}, etc.
|
||||
|
||||
The interpreter ignores this form.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:defentry
|
||||
@lspdef ffi:defentry
|
||||
@defmac ffi:defentry name arg-types c-name &key no-interrupts
|
||||
|
||||
@table @var
|
||||
|
|
@ -253,26 +253,26 @@ Lisp name for the function.
|
|||
Argument types of the C function.
|
||||
|
||||
@item c-name
|
||||
If @var{C-NAME} is a list, then C function result type is declared as
|
||||
@code{(CAR C-NAME)} and its name is @code{(STRING (CDR C-NAME))}.
|
||||
If @var{c-name} is a list, then C function result type is declared as
|
||||
@code{(car c-name)} and its name is @code{(string (cdr c-name))}.
|
||||
|
||||
If it's an atom, then the result type is @code{:OBJECT}, and function
|
||||
name is @code{(STRING C-NAME)}.
|
||||
If it's an atom, then the result type is @code{:object}, and function
|
||||
name is @code{(string c-name)}.
|
||||
|
||||
@item returns
|
||||
Lisp function @code{NAME}.
|
||||
Lisp function @code{name}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
The compiler defines a Lisp function named by @var{NAME} whose body
|
||||
@paragraph Description
|
||||
The compiler defines a Lisp function named by @var{name} whose body
|
||||
consists of a calling sequence to the C language function named by
|
||||
@var{C-NAME}.
|
||||
@var{c-name}.
|
||||
|
||||
The interpreter ignores this form.
|
||||
@end defmac
|
||||
|
||||
@c XXX> note sure if this works
|
||||
@c @subsubheading @code{definline}
|
||||
@c @paragraph @code{definline}
|
||||
@c @lspindex ffi:definline
|
||||
@c @defmac ffi:definline fun arg-types result-type code
|
||||
@c @table @var
|
||||
|
|
@ -283,24 +283,24 @@ The interpreter ignores this form.
|
|||
@c @end table
|
||||
@c @end defmac
|
||||
|
||||
@c @subsubheading Description
|
||||
@c @paragraph Description
|
||||
@c DEFINLINE behaves like a DEFCBODY (see), but also instructs the LISP
|
||||
@c compiler to expand inline any call to function SYMBOL into code
|
||||
@c corresponding to the C language expression C/C++-CODE, whenever it can
|
||||
@c determine that the actual arguments are of the specified type.
|
||||
@c <XXX
|
||||
|
||||
@lspindex ext:with-backend
|
||||
@lspdef ext:with-backend
|
||||
@defspec ext:with-backend &key bytecodes c/c++
|
||||
|
||||
Use different code depending on the backend.
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Depending on whether the bytecodes or C compiler is used, this form will
|
||||
emit the code given in the corresponding keyword argument.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ext:with-backend} use different code for c and bytecodes compiler
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ext:with-backend} use different code for c and bytecodes compiler
|
||||
@verbatim
|
||||
CL-USER> (defmacro test ()
|
||||
'(ext:with-backend :c/c++ "c/c++" :bytecodes "bytecodes"))
|
||||
|
|
@ -315,12 +315,13 @@ CL-USER> (funcall (compile nil (lambda () (test))))
|
|||
@end verbatim
|
||||
@end defspec
|
||||
|
||||
@lspindex ffi:defla
|
||||
@lspdef ffi:defla
|
||||
@defmac ffi:defla name args &body body
|
||||
|
||||
Provide Lisp alternative for interpreted code.
|
||||
|
||||
@subsubheading Description
|
||||
Used to DEFine Lisp Alternative. For the interpreter, DEFLA is equivalent to
|
||||
DEFUN, but the compiler ignores this form.
|
||||
@paragraph Description
|
||||
Used to DEFine Lisp Alternative. For the interpreter,
|
||||
@coderef{ffi:defla} is equivalent to @code{defun}, but the compiler
|
||||
ignores this form.
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ A generic lisp object (i.e. a @code{cl_object} in C)
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:def-constant
|
||||
@lspdef ffi:def-constant
|
||||
@defmac ffi:def-constant name value &key (export nil)
|
||||
|
||||
Binds a symbol to a constant.
|
||||
|
|
@ -112,30 +112,30 @@ A symbol that will be bound to the value.
|
|||
@item value
|
||||
An evaluated form that is bound the the name.
|
||||
@item export
|
||||
When @code{T}, the name is exported from the current package. Defaults
|
||||
to @code{NIL}.
|
||||
When @code{t}, the name is exported from the current package. Defaults
|
||||
to @code{nil}.
|
||||
@item returns
|
||||
Constant name.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This is a thin wrapper around @code{defconstant}. It evaluates at
|
||||
compile-time and optionally exports the symbol from the package.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-constant} defining constants
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-constant} defining constants
|
||||
@lisp
|
||||
(ffi:def-constant pi2 (* 2 pi))
|
||||
(ffi:def-constant exported-pi2 (* 2 pi) :export t)
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side Effects
|
||||
@paragraph Side Effects
|
||||
Creates a new special variable.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:def-foreign-type
|
||||
@lspdef ffi:def-foreign-type
|
||||
@defmac ffi:def-foreign-type name definition
|
||||
|
||||
Defines a new foreign type
|
||||
|
|
@ -149,24 +149,24 @@ A form that is not evaluated that defines the new foreign type.
|
|||
Foreign type designator (@var{value}).
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Defines a new foreign type
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-foreign-type} examples
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-foreign-type} examples
|
||||
@lisp
|
||||
(ffi:def-foreign-type my-generic-pointer :pointer-void)
|
||||
(ffi:def-foreign-type a-double-float :double-float)
|
||||
(ffi:def-foreign-type char-ptr (* :char))
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
@paragraph Side effects
|
||||
Defines a new foreign type.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:null-char-p
|
||||
@lspdef ffi:null-char-p
|
||||
@defun ffi:null-char-p char
|
||||
|
||||
Tests a character for NULL value
|
||||
|
|
@ -178,13 +178,13 @@ A character or integer.
|
|||
A boolean flag indicating if @var{char} is a NULL value.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
A predicate testing if a character or integer is NULL. This abstracts
|
||||
the difference in implementations where some return a character and some
|
||||
return a integer whence dereferencing a C character pointer.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:null-char-p} example
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:null-char-p} example
|
||||
@lisp
|
||||
(ffi:def-array-pointer ca :unsigned-char)
|
||||
(let ((fs (ffi:convert-to-foreign-string "ab")))
|
||||
|
|
@ -205,7 +205,7 @@ Aggregate types are comprised of one or more primitive types.
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:def-enum
|
||||
@lspdef ffi:def-enum
|
||||
@defmac ffi:def-enum name fields &key separator-string
|
||||
|
||||
Defines a C enumeration
|
||||
|
|
@ -224,15 +224,15 @@ set to 1+ this value.
|
|||
A string that governs the creation of constants. The default is "#".
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Declares a C enumeration. It generates constants with integer values for
|
||||
the elements of the enumeration. The symbols for the these constant
|
||||
values are created by the concatenation of the enumeration name,
|
||||
separator-string, and field symbol. Also creates a foreign type with the
|
||||
name name of type @code{:int}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-enum} sample enumerations
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-enum} sample enumerations
|
||||
@lisp
|
||||
(ffi:def-enum abc (:a :b :c))
|
||||
;; Creates constants abc#a (1), abc#b (2), abc#c (3) and defines
|
||||
|
|
@ -243,12 +243,13 @@ name name of type @code{:int}.
|
|||
;; the foreign type efoo to be :int
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
@paragraph Side effects
|
||||
Creates a @code{:int} foreign type, defines constants.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspdef ffi:def-struct
|
||||
@defmac ffi:def-struct name &rest fields
|
||||
|
||||
Defines a C structure
|
||||
|
|
@ -261,13 +262,13 @@ A variable number of field definitions. Each definition is a list
|
|||
consisting of a symbol naming the field followed by its foreign type.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Declares a structure. A special type is available as a slot in the
|
||||
field. It is a pointer that points to an instance of the parent
|
||||
structure. It's type is @code{:pointer-self}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-struct} defining C structure
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-struct} defining C structure
|
||||
@lisp
|
||||
(ffi:def-struct foo (a :unsigned-int)
|
||||
(b (* :char))
|
||||
|
|
@ -275,13 +276,13 @@ structure. It's type is @code{:pointer-self}.
|
|||
(next :pointer-self))
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
@paragraph Side effects
|
||||
Creates a foreign type.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:get-slot-value
|
||||
@lspdef ffi:get-slot-value
|
||||
@defun ffi:get-slot-value obj type field
|
||||
|
||||
Retrieves a value from a slot of a structure
|
||||
|
|
@ -294,15 +295,15 @@ The name of the foreign structure.
|
|||
@item field
|
||||
The name of the desired field in the foreign structure.
|
||||
@item returns
|
||||
The value of the @code{field} in the structure @code{obj}.
|
||||
The value of the @var{field} in the structure @var{obj}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Accesses a slot value from a structure. This is generalized and can be
|
||||
used with @code{setf}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:get-slot-value} manipulating a struct field
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:get-slot-value} manipulating a struct field
|
||||
@lisp
|
||||
(ffi:get-slot-value foo-ptr 'foo-structure 'field-name)
|
||||
(setf (ffi:get-slot-value foo-ptr 'foo-structure 'field-name) 10)
|
||||
|
|
@ -311,7 +312,7 @@ used with @code{setf}.
|
|||
|
||||
|
||||
|
||||
@lspindex ffi:get-slot-pointer
|
||||
@lspdef ffi:get-slot-pointer
|
||||
@defun ffi:get-slot-pointer obj type field
|
||||
|
||||
Retrieves a pointer from a slot of a structure
|
||||
|
|
@ -327,12 +328,12 @@ The name of the desired field in the foreign structure.
|
|||
The value of the pointer @var{field} in the structure @var{obj}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
This is similar to @code{get-slot-value}. It is used when the value of
|
||||
a slot is a pointer type.
|
||||
@paragraph Description
|
||||
This is similar to @coderef{ffi:get-slot-value}. It is used when the
|
||||
value of a slot is a pointer type.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:get-slot-value} usage
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:get-slot-value} usage
|
||||
@lisp
|
||||
(ffi:get-slot-pointer foo-ptr 'foo-structure 'my-char-ptr)
|
||||
@end lisp
|
||||
|
|
@ -340,7 +341,7 @@ a slot is a pointer type.
|
|||
|
||||
|
||||
|
||||
@lspindex ffi:def-array-pointer
|
||||
@lspdef ffi:def-array-pointer
|
||||
@defmac ffi:def-array-pointer name type
|
||||
|
||||
Defines a pointer to an array of @var{type}
|
||||
|
|
@ -352,22 +353,22 @@ A name of the new foreign type.
|
|||
The foreign type of the array elements.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Defines a type that is a pointer to an array of @var{type}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-array-pointer} usage
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-array-pointer} usage
|
||||
@lisp
|
||||
(ffi:def-array-pointer byte-array-pointer :unsigned-char)
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
@paragraph Side effects
|
||||
Defines a new foreign type.
|
||||
@end defmac
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:deref-array
|
||||
@lspdef ffi:deref-array
|
||||
@defun ffi:deref-array array type position
|
||||
|
||||
Dereference an array
|
||||
|
|
@ -383,24 +384,24 @@ An integer specifying the position to retrieve from the @var{array}.
|
|||
The value stored in the @var{position} of the @var{array}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Dereferences (retrieves) the value of the foreign array
|
||||
element. @code{setf}-able.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:deref-array} retrieving array element
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:deref-array} retrieving array element
|
||||
@lisp
|
||||
(ffi:def-array-pointer ca :char)
|
||||
(let ((fs (ffi:convert-to-foreign-string "ab")))
|
||||
(values (ffi:null-char-p (ffi:deref-array fs 'ca 0))
|
||||
(ffi:null-char-p (ffi:deref-array fs 'ca 2))))
|
||||
;; => NIL T
|
||||
@lisp
|
||||
@end lisp
|
||||
@end defun
|
||||
|
||||
|
||||
|
||||
@lspindex ffi:def-union
|
||||
@lspdef ffi:def-union
|
||||
@defmac ffi:def-union name &rest fields
|
||||
|
||||
Defines a foreign union type
|
||||
|
|
@ -412,11 +413,11 @@ A name of the new union type.
|
|||
A list of fields of the union in form @code{(field-name field-type)}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Defines a foreign union type.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-union} union definition and usage
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-union} union definition and usage
|
||||
@lisp
|
||||
(ffi:def-union test-union
|
||||
(a-char :char)
|
||||
|
|
@ -430,7 +431,7 @@ Defines a foreign union type.
|
|||
;; => #\A
|
||||
@end lisp
|
||||
|
||||
@subsubheading Side effects
|
||||
@paragraph Side effects
|
||||
Defines a new foreign type.
|
||||
@end defmac
|
||||
|
||||
|
|
@ -444,7 +445,7 @@ can be freed.
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:allocate-foreign-object
|
||||
@lspdef ffi:allocate-foreign-object
|
||||
@defun ffi:allocate-foreign-object type &optional size
|
||||
|
||||
Allocates an instance of a foreign object
|
||||
|
|
@ -460,12 +461,12 @@ parameter is evaluated.
|
|||
A pointer to the foreign object.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Allocates an instance of a foreign object. It returns a pointer to the
|
||||
object.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:allocate-foreign-object} allocating structure object
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:allocate-foreign-object} allocating structure object
|
||||
@lisp
|
||||
(ffi:def-struct ab (a :int) (b :double))
|
||||
;; => (:STRUCT (A :INT) (B :DOUBLE))
|
||||
|
|
@ -474,7 +475,7 @@ object.
|
|||
@end lisp
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:free-foreign-object
|
||||
@lspdef ffi:free-foreign-object
|
||||
@defun ffi:free-foreign-object ptr
|
||||
|
||||
Frees memory that was allocated for a foreign object
|
||||
|
|
@ -484,11 +485,11 @@ Frees memory that was allocated for a foreign object
|
|||
A pointer to the allocated foreign object to free.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Frees memory that was allocated for a foreign object.
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:with-foreign-object
|
||||
@lspdef ffi:with-foreign-object
|
||||
@defmac ffi:with-foreign-object (var type) &body body
|
||||
|
||||
Wraps the allocation, binding and destruction of a foreign object around
|
||||
|
|
@ -505,12 +506,12 @@ Code to be evaluated.
|
|||
The result of evaluating the body.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This function wraps the allocation, binding, and destruction of a
|
||||
foreign object around the body of code.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:with-foreign-object} macro usage
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:with-foreign-object} macro usage
|
||||
@lisp
|
||||
(defun gethostname2 ()
|
||||
"Returns the hostname"
|
||||
|
|
@ -521,7 +522,7 @@ foreign object around the body of code.
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:size-of-foreign-type
|
||||
@lspdef ffi:size-of-foreign-type
|
||||
@defmac ffi:size-of-foreign-type ftype
|
||||
|
||||
Returns the number of data bytes used by a foreign object type
|
||||
|
|
@ -533,12 +534,12 @@ A foreign type specifier. This parameter is evaluated.
|
|||
Number of data bytes used by a foreign object @var{ftype}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Returns the number of data bytes used by a foreign object type. This
|
||||
does not include any Lisp storage overhead.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:size-of-foreign-type}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:size-of-foreign-type}
|
||||
@lisp
|
||||
(ffi:size-of-foreign-type :unsigned-byte)
|
||||
;; => 1
|
||||
|
|
@ -547,7 +548,7 @@ does not include any Lisp storage overhead.
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:pointer-address
|
||||
@lspdef ffi:pointer-address
|
||||
@defun ffi:pointer-address ptr
|
||||
|
||||
Returns the address of a pointer
|
||||
|
|
@ -559,11 +560,11 @@ A pointer to a foreign object.
|
|||
An integer representing the pointer's address.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Returns the address as an integer of a pointer.
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:deref-pointer
|
||||
@lspdef ffi:deref-pointer
|
||||
@defun ffi:deref-pointer ptr ftype
|
||||
|
||||
Dereferences a pointer
|
||||
|
|
@ -577,15 +578,16 @@ Foreign type of the object being pointed to.
|
|||
The value of the object where the pointer points.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Returns the object to which a pointer points. @code{setf}-able.
|
||||
|
||||
@subsubheading Notes
|
||||
Casting of the pointer may be performed with @code{with-cast-pointer}
|
||||
together with the @code{deref-pointer}/@code{deref-array}.
|
||||
@paragraph Notes
|
||||
Casting of the pointer may be performed with
|
||||
@coderef{ffi:with-cast-pointer} together with
|
||||
@coderef{ffi:deref-pointer}/@coderef{ffi:deref-array}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:deref-pointer}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:deref-pointer}
|
||||
@lisp
|
||||
(let ((intp (ffi:allocate-foreign-object :int)))
|
||||
(setf (ffi:deref-pointer intp :int) 10)
|
||||
|
|
@ -596,7 +598,7 @@ together with the @code{deref-pointer}/@code{deref-array}.
|
|||
@end lisp
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:ensure-char-character
|
||||
@lspdef ffi:ensure-char-character
|
||||
@defun ffi:ensure-char-character object
|
||||
|
||||
Ensures that a dereferenced @code{:char} pointer is a character
|
||||
|
|
@ -608,12 +610,12 @@ Either a character or a integer specifying a character code.
|
|||
A character.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Ensures that an objects obtained by dereferencing @code{:char} and
|
||||
@code{:unsigned-char} pointers is a lisp character.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:ensure-char-character}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:ensure-char-character}
|
||||
@lisp
|
||||
(let ((fs (ffi:convert-to-foreign-string "a")))
|
||||
(prog1
|
||||
|
|
@ -622,12 +624,12 @@ Ensures that an objects obtained by dereferencing @code{:char} and
|
|||
;; => #\a
|
||||
@end lisp
|
||||
|
||||
@subsubheading Exceptional Situations
|
||||
@paragraph Exceptional Situations
|
||||
Depending upon the implementation and what UFFI expects, this macro may
|
||||
signal an error if the object is not a character or integer.
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:ensure-char-integer
|
||||
@lspdef ffi:ensure-char-integer
|
||||
@defun ffi:ensure-char-integer object
|
||||
|
||||
Ensures that a dereferenced @code{:char} pointer is an integer
|
||||
|
|
@ -639,12 +641,12 @@ Either a character or a integer specifying a character code.
|
|||
An integer.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Ensures that an objects obtained by dereferencing @code{:char} and
|
||||
@code{:unsigned-char} pointers is a lisp integer.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:ensure-char-integer}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:ensure-char-integer}
|
||||
@lisp
|
||||
(let ((fs (ffi:convert-to-foreign-string "a")))
|
||||
(prog1
|
||||
|
|
@ -653,12 +655,12 @@ Ensures that an objects obtained by dereferencing @code{:char} and
|
|||
;; => 96
|
||||
@end lisp
|
||||
|
||||
@subsubheading Exceptional Situations
|
||||
@paragraph Exceptional Situations
|
||||
Depending upon the implementation and what UFFI expects, this macro may
|
||||
signal an error if the object is not a character or integer.
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:make-null-pointer
|
||||
@lspdef ffi:make-null-pointer
|
||||
@defun ffi:make-null-pointer ftype
|
||||
|
||||
Create a NULL pointer of a specified type
|
||||
|
|
@ -671,7 +673,7 @@ The NULL pointer of type @var{ftype}.
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:null-pointer-p
|
||||
@lspdef ffi:null-pointer-p
|
||||
@defun ffi:null-pointer-p ptr
|
||||
|
||||
Tests a pointer for NULL value
|
||||
|
|
@ -684,13 +686,13 @@ The boolean flag.
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@lspindex ffi:+null-cstring-pointer+
|
||||
@lspdef ffi:+null-cstring-pointer+
|
||||
@defvr Variable {ffi:+null-cstring-pointer+}
|
||||
A NULL cstring pointer. This can be used for testing if a cstring
|
||||
returned by a function is NULL.
|
||||
@end defvr
|
||||
|
||||
@lspindex ffi:with-cast-pointer
|
||||
@lspdef ffi:with-cast-pointer
|
||||
@defmac ffi:with-cast-pointer (var ptr ftype) &body body
|
||||
|
||||
Wraps a body of code with a pointer cast to a new type
|
||||
|
|
@ -706,13 +708,13 @@ A foreign type of the object being pointed to.
|
|||
The value of the object where the pointer points.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Executes @var{body} with @var{ptr} cast to be a pointer to type
|
||||
@var{ftype}. @var{var} will be bound to this value during the
|
||||
execution of @var{body}.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:with-cast-pointer}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:with-cast-pointer}
|
||||
@lisp
|
||||
(ffi:with-foreign-object (size :int)
|
||||
;; FOO is a foreign function returning a :POINTER-VOID
|
||||
|
|
@ -727,7 +729,7 @@ execution of @var{body}.
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:def-foreign-var
|
||||
@lspdef ffi:def-foreign-var
|
||||
@defmac ffi:def-foreign-var name type module
|
||||
|
||||
Defines a symbol macro to access a variable in foreign code
|
||||
|
|
@ -745,15 +747,15 @@ A foreign type of the foreign variable.
|
|||
@item module
|
||||
Either a string specifying the module (or library) the foreign
|
||||
variable resides in, @code{:default} if no module needs to be loaded
|
||||
or @code{NIL} to use SFFI.
|
||||
or @code{nil} to use SFFI.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Defines a symbol macro which can be used to access (get and set) the
|
||||
value of a variable in foreign code.
|
||||
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-foreign-var} places in foreign world
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-foreign-var} places in foreign world
|
||||
|
||||
C code defining foreign structure, standalone integer and the accessor:
|
||||
@example
|
||||
|
|
@ -867,7 +869,7 @@ an example of handling such a function.
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:convert-from-cstring
|
||||
@lspdef ffi:convert-from-cstring
|
||||
@defmac ffi:convert-from-cstring object
|
||||
Converts a @code{cstring} to a Lisp string
|
||||
@table @var
|
||||
|
|
@ -877,12 +879,12 @@ A @code{cstring}
|
|||
A Lisp string
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Converts a Lisp string to a cstring. This is most often used when
|
||||
processing the results of a foreign function that returns a cstring.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:convert-to-cstring
|
||||
@lspdef ffi:convert-to-cstring
|
||||
@defmac ffi:convert-to-cstring object
|
||||
Converts a Lisp string to a @code{cstring}
|
||||
@table @var
|
||||
|
|
@ -892,28 +894,28 @@ A Lisp string
|
|||
A @code{cstring}
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Converts a Lisp string to a @code{cstring}. The @code{cstring} should
|
||||
be freed with @code{free-cstring}.
|
||||
@subsubheading Side Effects
|
||||
be freed with @coderef{ffi:free-cstring}.
|
||||
@paragraph Side Effects
|
||||
This function allocates memory.
|
||||
@end defmac
|
||||
|
||||
|
||||
@lspindex ffi:free-cstring
|
||||
@lspdef ffi:free-cstring
|
||||
@defmac ffi:convert-from-cstring cstring
|
||||
Free memory used by @var{cstring}
|
||||
@table @var
|
||||
@item cstring
|
||||
@code{cstring} to be freed.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
Frees any memory possibly allocated by @code{convert-to-cstring}. On ECL, a
|
||||
@code{cstring} is just the Lisp string itself.
|
||||
@paragraph Description
|
||||
Frees any memory possibly allocated by @coderef{ffi:convert-to-cstring}.
|
||||
On ECL, a @code{cstring} is just the Lisp string itself.
|
||||
@end defmac
|
||||
|
||||
|
||||
@lspindex ffi:with-cstring
|
||||
@lspdef ffi:with-cstring
|
||||
@defmac ffi:with-cstring (cstring string) &body body
|
||||
Binds a newly created @code{cstring}
|
||||
@table @var
|
||||
|
|
@ -926,10 +928,10 @@ The body of where the @var{cstring} will be bound.
|
|||
@item returns
|
||||
Result of evaluating the @var{body}.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Binds a symbol to a @code{cstring} created from conversion of a
|
||||
@var{string}. Automatically frees the @var{cstring}.
|
||||
@subsubheading Examples
|
||||
@paragraph Examples
|
||||
@exindex @code{with-cstring}
|
||||
@lisp
|
||||
(ffi:def-function ("getenv" c-getenv)
|
||||
|
|
@ -944,7 +946,7 @@ Binds a symbol to a @code{cstring} created from conversion of a
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:with-cstrings
|
||||
@lspdef ffi:with-cstrings
|
||||
@defmac ffi:with-cstrings bindings &body body
|
||||
Binds a newly created @code{cstrings}
|
||||
@table @var
|
||||
|
|
@ -956,13 +958,13 @@ The body of where the @var{bindings} will be bound.
|
|||
@item returns
|
||||
Result of evaluating the @var{body}.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Binds a symbols to a @code{cstring}s created from conversion of a
|
||||
@var{string}s. Automatically frees the @var{cstring}s. This macro works
|
||||
similar to @code{let*}. Based on @code{with-cstring}.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:convert-from-foreign-string
|
||||
@lspdef ffi:convert-from-foreign-string
|
||||
@defmac ffi:convert-from-foreign-string foreign-string &key length (null-terminated-p t)
|
||||
Converts a foreign string into a Lisp string
|
||||
@table @var
|
||||
|
|
@ -972,17 +974,17 @@ A foreign string.
|
|||
The length of the foreign string to convert. The default is the length
|
||||
of the string until a NULL character is reached.
|
||||
@item null-terminated-p
|
||||
A boolean flag with a default value of @code{T}. When true, the string is
|
||||
A boolean flag with a default value of @code{t}. When true, the string is
|
||||
converted until the first NULL character is reached.
|
||||
@item returns
|
||||
A Lisp string.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Returns a Lisp string from a foreign string. Can translate ASCII and
|
||||
binary strings.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:convert-to-foreign-string
|
||||
@lspdef ffi:convert-to-foreign-string
|
||||
@defmac ffi:convert-to-foreign-string string
|
||||
Converts a Lisp string to a foreign string
|
||||
@table @var
|
||||
|
|
@ -991,29 +993,29 @@ A Lisp string.
|
|||
@item returns
|
||||
A foreign string.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Converts a Lisp string to a foreign string. Memory should be freed with
|
||||
@code{free-foreign-object}.
|
||||
@coderef{ffi:free-foreign-object}.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:allocate-foreign-string
|
||||
@lspdef ffi:allocate-foreign-string
|
||||
@defmac ffi:allocate-foreign-string size &key unsigned
|
||||
Allocates space for a foreign string
|
||||
@table @var
|
||||
@item size
|
||||
The size of the space to be allocated in bytes.
|
||||
@item unsigned
|
||||
A boolean flag with a default value of @code{T}. When true, marks the pointer
|
||||
A boolean flag with a default value of @code{t}. When true, marks the pointer
|
||||
as an @code{:unsigned-char}.
|
||||
@item returns
|
||||
A foreign string which has undefined contents.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Allocates space for a foreign string. Memory should be freed with
|
||||
@code{free-foreign-object}.
|
||||
@coderef{ffi:free-foreign-object}.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:with-foreign-string
|
||||
@lspdef ffi:with-foreign-string
|
||||
@defmac ffi:with-foreign-string (foreign-string string) &body body
|
||||
Binds a newly allocated @code{foreign-string}
|
||||
@table @var
|
||||
|
|
@ -1026,13 +1028,13 @@ The body of where the @var{foreign-string} will be bound.
|
|||
@item returns
|
||||
Result of evaluating the @var{body}.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Binds a symbol to a @code{foreign-string} created from conversion of a
|
||||
@var{string}. Automatically deallocates the @var{foreign-string}.
|
||||
@subsubheading Examples
|
||||
@paragraph Examples
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:with-foreign-strings
|
||||
@lspdef ffi:with-foreign-strings
|
||||
@defmac ffi:with-foreign-strings bindings &body body
|
||||
Binds a newly created @code{foreign string}
|
||||
@table @var
|
||||
|
|
@ -1045,10 +1047,10 @@ The body of where the @var{bindings} will be bound.
|
|||
@item returns
|
||||
Result of evaluating the @var{body}.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Binds a symbols to a @code{foreign-string}s created from conversion of a
|
||||
@var{string}s. Automatically frees the @var{foreign-string}s. This macro
|
||||
works similar to @code{let*}. Based on @code{with-foreign-string}.
|
||||
works similar to @code{let*}. Based on @coderef{ffi:with-foreign-string}.
|
||||
@end defmac
|
||||
|
||||
@node Functions and Libraries
|
||||
|
|
@ -1057,7 +1059,7 @@ works similar to @code{let*}. Based on @code{with-foreign-string}.
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ffi:def-function
|
||||
@lspdef ffi:def-function
|
||||
@defmac ffi:def-function name args &key module (returning :void) (call :cdecl)
|
||||
@table @var
|
||||
@item name
|
||||
|
|
@ -1068,16 +1070,16 @@ case-insensitive Lisp implementations. If it is a list, the first item
|
|||
is a string specifying the foreign function name and the second it is a
|
||||
symbol stating the Lisp name.
|
||||
@item args
|
||||
A list of argument declarations. If @code{NIL}, indicates that the function
|
||||
A list of argument declarations. If @code{nil}, indicates that the function
|
||||
does not take any arguments.
|
||||
@item module
|
||||
Either a string specifying which module (or library) that the foreign
|
||||
function resides, @code{:default} if no module needs to be loaded or
|
||||
@code{NIL} to use SFFI.
|
||||
@code{nil} to use SFFI.
|
||||
@item call
|
||||
Function calling convention. May be one of @code{:default}, @code{:cdecl},
|
||||
@code{:sysv}, @code{:stdcall}, @code{:win64} and
|
||||
@code{unix64}.
|
||||
@code{:unix64}.
|
||||
|
||||
This argument is used only when we're using the dynamic function
|
||||
interface. If ECL is built without the DFFI support, then it uses SFFI
|
||||
|
|
@ -1086,10 +1088,10 @@ the @var{call} argument is ignored.
|
|||
A declaration specifying the result type of the foreign function.
|
||||
@code{:void} indicates that the function does not return any value.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Declares a foreign function.
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:def-function}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:def-function}
|
||||
@lisp
|
||||
(ffi:def-function "gethostname"
|
||||
((name (* :unsigned-char))
|
||||
|
|
@ -1098,7 +1100,7 @@ Declares a foreign function.
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:load-foreign-library
|
||||
@lspdef ffi:load-foreign-library
|
||||
@defmac ffi:load-foreign-library filename &key module supporting-libraries force-load system-library
|
||||
@table @var
|
||||
@item filename
|
||||
|
|
@ -1114,30 +1116,30 @@ the foreign library.
|
|||
previously loaded.
|
||||
@item system-library
|
||||
Denotes if the loaded library is a system library (accessible with the
|
||||
correct linker flags). If @code{T}, then SFFI is used and the linking is
|
||||
correct linker flags). If @code{t}, then SFFI is used and the linking is
|
||||
performed after compilation of the module. Otherwise (default) both SFFI
|
||||
and DFFI are used, but SFFI only during the compilation.
|
||||
@item returns
|
||||
A generalized boolean @emph{true} if the library was able to be loaded
|
||||
successfully or if the library has been previously loaded, otherwise
|
||||
@code{NIL}.
|
||||
@code{nil}.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Loads a foreign library. Ensures that a library is only loaded once
|
||||
during a session.
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:load-foreign-library}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:load-foreign-library}
|
||||
@lisp
|
||||
(ffi:load-foreign-library #p"/usr/lib/libmagic.so.1")
|
||||
;; => #<codeblock "/usr/lib/libmagic.so">
|
||||
@end lisp
|
||||
@subsubheading Side Effects
|
||||
@paragraph Side Effects
|
||||
Loads the foreign code into the Lisp system.
|
||||
@subsubheading Affected by
|
||||
@paragraph Affected by
|
||||
Ability to load the file.
|
||||
@end defmac
|
||||
|
||||
@lspindex ffi:find-foreign-library
|
||||
@lspdef ffi:find-foreign-library
|
||||
@defun ffi:find-foreign-library names directories &key drive-letters types
|
||||
Finds a foreign library file
|
||||
@table @var
|
||||
|
|
@ -1151,17 +1153,17 @@ A string or list of strings containing the drive letters for the library
|
|||
file.
|
||||
@item types
|
||||
A string or list of strings containing the file type of the library
|
||||
file. Default is @code{NIL}. If @code{NIL}, will use a default type
|
||||
file. Default is @code{nil}. If @code{nil}, will use a default type
|
||||
based on the currently running implementation.
|
||||
@item returns
|
||||
A path containing the path to the @emph{first} file found, or
|
||||
@code{NIL} if the library file was not found.
|
||||
@code{nil} if the library file was not found.
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Finds a foreign library by searching through a number of possible
|
||||
locations. Returns the path of the first found file.
|
||||
@subsubheading Examples
|
||||
@exindex @code{ffi:find-foreign-library}
|
||||
@paragraph Examples
|
||||
@exindex @coderef{ffi:find-foreign-library}
|
||||
@lisp
|
||||
(ffi:find-foreign-library '("libz" "libmagic")
|
||||
'("/usr/local/lib/" "/usr/lib/")
|
||||
|
|
@ -1184,15 +1186,15 @@ locations. Returns the path of the first found file.
|
|||
@c One value? More?
|
||||
@c @end table
|
||||
|
||||
@c @subsubheading Description
|
||||
@c @paragraph Description
|
||||
@c Description here
|
||||
|
||||
@c @subsubheading Examples
|
||||
@c @paragraph Examples
|
||||
@c @exindex @code{ffi:} sample run
|
||||
@c @lisp
|
||||
|
||||
@c @end lisp
|
||||
|
||||
@c @subsubheading Side effects
|
||||
@c @paragraph Side effects
|
||||
@c foo bar
|
||||
@c @end defmac
|
||||
|
|
|
|||
|
|
@ -44,28 +44,29 @@ Beginning with version 9.2.1, ECL operates a tighter control of the resources it
|
|||
|
||||
The customizable limits are listed in @ref{tab:mem-limits}, but they need a careful description.
|
||||
|
||||
@lspindex ext:heap-size
|
||||
@lspindex ext:c-stack
|
||||
@lspindex ext:binding-stack
|
||||
@lspindex ext:lisp-stack
|
||||
@lspdef ext:heap-size
|
||||
@lspdef ext:c-stack
|
||||
@lspdef ext:binding-stack
|
||||
@lspdef ext:frame-stack
|
||||
@lspdef ext:lisp-stack
|
||||
@itemize
|
||||
@item
|
||||
@code{ext:heap-size} limits the total amount of memory which is available for lisp objects. This is the memory used when you create conses, arrays, structures, etc.
|
||||
@coderef{ext:heap-size} limits the total amount of memory which is available for lisp objects. This is the memory used when you create conses, arrays, structures, etc.
|
||||
@item
|
||||
@code{ext:c-stack} controls the size of the stack for compiled code, including ECL's library itself. This limit is less stringent than the others. For instance, when code is compiled with low safety settings, checks for this stack limit are usually omitted, for performance reasons.
|
||||
@coderef{ext:c-stack} controls the size of the stack for compiled code, including ECL's library itself. This limit is less stringent than the others. For instance, when code is compiled with low safety settings, checks for this stack limit are usually omitted, for performance reasons.
|
||||
@item
|
||||
@code{ext:binding-stack} controls the number of nested bindings for special variables. The current value is usually safe enough, unless you have deep recursive functions that bind special variables, which is not really a good idea.
|
||||
@coderef{ext:binding-stack} controls the number of nested bindings for special variables. The current value is usually safe enough, unless you have deep recursive functions that bind special variables, which is not really a good idea.
|
||||
@item
|
||||
@code{ext:frame-stack} controls the number of nested blocks, tagbodys and other control structures. It affects both interpreted and compiled code, but quite often compiled code optimizes away these stack frames, saving memory and not being affected by this limit.
|
||||
@coderef{ext:frame-stack} controls the number of nested blocks, tagbodys and other control structures. It affects both interpreted and compiled code, but quite often compiled code optimizes away these stack frames, saving memory and not being affected by this limit.
|
||||
@item
|
||||
@code{ext:lisp-stack} controls the size of the interpreter stack. It only affects interpreted code.
|
||||
@coderef{ext:lisp-stack} controls the size of the interpreter stack. It only affects interpreted code.
|
||||
@end itemize
|
||||
|
||||
If you look at @ref{tab:mem-limits}, some of these limits may seem very stringent, but they exist to allow detecting and correcting both stack and memory overflow conditions. Larger values can be set systematically either in the @file{~/.eclrc} initialization file, or using the command line options from the table.
|
||||
|
||||
@node Memory conditions
|
||||
@subsection Memory conditions
|
||||
When ECL surpasses or approaches the memory limits it will signal a Common Lisp condition. There are two types of conditions, @code{ext:stack-overflow} and @code{ext:storage-exhausted}, for stack and heap overflows, respectively. Both errors are correctable, as the following session shows:
|
||||
When ECL surpasses or approaches the memory limits it will signal a Common Lisp condition. There are two types of conditions, @coderef{ext:stack-overflow} and @coderef{ext:storage-exhausted}, for stack and heap overflows, respectively. Both errors are correctable, as the following session shows:
|
||||
@lisp
|
||||
> (defun foo (x) (foo x))
|
||||
|
||||
|
|
@ -101,6 +102,6 @@ If the finalizer is invoked and it makes the object reachable, for instance, by
|
|||
ECL will strive to call finalizers before the environment is closed and the program is finished, but this mechanism may fail when exiting in a non ordinary way.
|
||||
@end itemize
|
||||
|
||||
The implementation is based on two functions, @code{ext:set-finalizer} and @code{ext:get-finalizer}, which allow setting and querying the finalizer functions for certain objects.
|
||||
The implementation is based on two functions, @coderef{ext:set-finalizer} and @coderef{ext:get-finalizer}, which allow setting and querying the finalizer functions for certain objects.
|
||||
|
||||
@include extensions/memory_ref.txi
|
||||
|
|
|
|||
|
|
@ -3,16 +3,16 @@
|
|||
|
||||
@subsubheading Reference
|
||||
|
||||
@lspindex ext:stack-overflow
|
||||
@lspdef ext:stack-overflow
|
||||
@deftp Condition ext:stack-overflow
|
||||
|
||||
Stack overflow condition
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:stack-overflow, storage-condition, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:stack-overflow}, @code{storage-condition}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Methods
|
||||
@lspindex ext:stack-overflow-size
|
||||
@paragraph Methods
|
||||
@lspdef ext:stack-overflow-size
|
||||
@defun ext:stack-overflow-size condition
|
||||
@table @var
|
||||
@item returns
|
||||
|
|
@ -20,30 +20,30 @@ A non-negative integer.
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@lspindex ext:stack-overflow-type
|
||||
@lspdef ext:stack-overflow-type
|
||||
@defun ext:stack-overflow-type condition
|
||||
@table @var
|
||||
@item returns
|
||||
A symbol from @ref{tab:mem-limits}, except @code{ext:heap-size}.
|
||||
A symbol from @ref{tab:mem-limits}, except @coderef{ext:heap-size}.
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This condition is signaled when one of the stack limits in @ref{tab:mem-limits} are violated or dangerously approached. It can be handled by resetting the limits and continuing, or jumping to an outer control point.
|
||||
|
||||
@end deftp
|
||||
|
||||
|
||||
@lspindex ext:storage-exhausted
|
||||
@lspdef ext:storage-exhausted
|
||||
@deftp Condition ext:storage-exhausted
|
||||
|
||||
Memory overflow condition
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:storage-exhausted, storage-condition, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:storage-exhausted}, @code{storage-condition}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Description
|
||||
This condition is signaled when ECL exhausts the @code{ext:heap-size} limit from @ref{tab:mem-limits}. In handling this condition ECL follows this logic:
|
||||
@paragraph Description
|
||||
This condition is signaled when ECL exhausts the @coderef{ext:heap-size} limit from @ref{tab:mem-limits}. In handling this condition ECL follows this logic:
|
||||
@itemize
|
||||
@item
|
||||
If the heap size limit was set to 0 (that is no limit), but there is some free space in the safety region ECL frees this space and issues a non-restartable error. The user may jump to an outer point or quit.
|
||||
|
|
@ -55,43 +55,43 @@ This condition is signaled when ECL exhausts the @code{ext:heap-size} limit from
|
|||
@end deftp
|
||||
|
||||
|
||||
@lspindex ext:get-finalizer
|
||||
@lspdef ext:get-finalizer
|
||||
@defun ext:get-finalizer object
|
||||
@table @var
|
||||
@item object
|
||||
Any lisp object.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
This function returns the finalizer associated to an object, or @code{NIL}.
|
||||
@paragraph Description
|
||||
This function returns the finalizer associated to an object, or @code{nil}.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspindex ext:get-limit
|
||||
@lspdef ext:get-limit
|
||||
@defun ext:get-limit concept
|
||||
@table @var
|
||||
@item concept
|
||||
A symbol.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Queries the different memory and stack limits that condition ECL's behavior. The value to be queried is denoted by the symbol @var{concept}, which should be one from the list: @ref{tab:mem-limits}
|
||||
@end defun
|
||||
|
||||
@lspindex ext:set-finalizer
|
||||
@lspdef ext:set-finalizer
|
||||
@defun ext:set-finalizer object function
|
||||
Associate a finalizer to an object.
|
||||
@table @var
|
||||
@item object
|
||||
Any lisp object.
|
||||
@item function
|
||||
A function or closure that takes one argument or @code{NIL}.
|
||||
A function or closure that takes one argument or @code{nil}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
If @var{function} is @code{NIL}, no finalizer is associated to the object. Otherwise @var{function} must be a function or a closure of one argument, which will be invoked before the object is destroyed.
|
||||
@paragraph Description
|
||||
If @var{function} is @code{nil}, no finalizer is associated to the object. Otherwise @var{function} must be a function or a closure of one argument, which will be invoked before the object is destroyed.
|
||||
|
||||
@subsubheading Example
|
||||
@paragraph Example
|
||||
Close a file associated to an object.
|
||||
|
||||
@lisp
|
||||
|
|
@ -117,7 +117,7 @@ Close a file associated to an object.
|
|||
@end defun
|
||||
|
||||
|
||||
@lspindex ext:set-limit
|
||||
@lspdef ext:set-limit
|
||||
@defun ext:set-limit concept value
|
||||
Set a memory or stack limit.
|
||||
@table @var
|
||||
|
|
|
|||
|
|
@ -9,37 +9,37 @@ similar to @code{setf}.
|
|||
@subsection Atomic operations dictionary
|
||||
|
||||
@subsubheading C Reference
|
||||
@cppindex ecl_compare_and_swap
|
||||
@cppdef ecl_compare_and_swap
|
||||
@deftypefun cl_object ecl_compare_and_swap (cl_object *slot, cl_object old, cl_object new)
|
||||
|
||||
Perform an atomic compare and swap operation on @var{slot} and return
|
||||
the previous value stored in @var{slot}. If the return value is equal
|
||||
to @var{old} (comparison by @code{==}), the operation has succeeded.
|
||||
This is a inline-only function defined in ``ecl/ecl_atomics.h''.
|
||||
This is a inline-only function defined in "ecl/ecl_atomics.h".
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_atomic_incf
|
||||
@cppdef ecl_atomic_incf
|
||||
@deftypefun cl_object ecl_atomic_incf (cl_object *slot, cl_object increment)
|
||||
@end deftypefun
|
||||
@cppindex ecl_atomic_incf_by_fixnum
|
||||
@cppdef ecl_atomic_incf_by_fixnum
|
||||
@deftypefun cl_object ecl_atomic_incf_by_fixnum (cl_object *slot, cl_fixnum increment)
|
||||
|
||||
Atomically increment @var{slot} by the given increment and return the
|
||||
previous value stored in @var{slot}. The consequences are undefined if
|
||||
the value of @var{slot} is not of type @code{fixnum}.
|
||||
@code{ecl_atomic_incf} signals an error if @var{increment} is not of
|
||||
@coderef{ecl_atomic_incf} signals an error if @var{increment} is not of
|
||||
type @code{fixnum}. This is a inline-only function defined in
|
||||
``ecl/ecl_atomics.h''.
|
||||
"ecl/ecl_atomics.h".
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_atomic_index_incf
|
||||
@cppdef ecl_atomic_index_incf
|
||||
@deftypefun cl_index ecl_atomic_index_incf (cl_index *slot);
|
||||
|
||||
Atomically increment @var{slot} by 1 and return the new value stored
|
||||
in @var{slot}.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_atomic_get
|
||||
@cppdef ecl_atomic_get
|
||||
@deftypefun cl_object ecl_atomic_get (cl_object *slot)
|
||||
|
||||
Perform a volatile load of the object in @var{slot} and then
|
||||
|
|
@ -47,26 +47,25 @@ atomically set @var{slot} to @code{ECL_NIL}. Returns the value
|
|||
previously stored in @var{slot}.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_atomic_push
|
||||
@cppdef ecl_atomic_push
|
||||
@deftypefun void ecl_atomic_push (cl_object *slot, cl_object o)
|
||||
@end deftypefun
|
||||
@cppindex ecl_atomic_pop
|
||||
@cppdef ecl_atomic_pop
|
||||
@deftypefun cl_object ecl_atomic_pop (cl_object *slot)
|
||||
|
||||
Like push/pop but atomic.
|
||||
@end deftypefun
|
||||
|
||||
@subsubheading Lisp Reference
|
||||
@lspindex mp:atomic-incf
|
||||
@lspdef mp:atomic-incf
|
||||
@lspdef mp:atomic-decf
|
||||
@defmac mp:atomic-incf place &optional (increment 1)
|
||||
@end defmac
|
||||
@lspindex mp:atomic-decf
|
||||
@defmac mp:atomic-decf place &optional (increment 1)
|
||||
@defmacx mp:atomic-decf place &optional (increment 1)
|
||||
|
||||
Atomically increments/decrements the fixnum stored in @var{place} by
|
||||
the given @var{increment} and returns the value of @var{place} before
|
||||
the increment. Incrementing and decrementing is done using modular
|
||||
arithmetic, so that @code{mp:atomic-incf} of a place whose value is
|
||||
arithmetic, so that @coderef{mp:atomic-incf} of a place whose value is
|
||||
@code{most-positive-fixnum} by 1 results in
|
||||
@code{most-negative-fixnum} stored in place.
|
||||
|
||||
|
|
@ -85,7 +84,7 @@ The consequences are undefined if the value of @var{place} is not of
|
|||
type @code{fixnum}.
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:compare-and-swap
|
||||
@lspdef mp:compare-and-swap
|
||||
@defmac mp:compare-and-swap place old new
|
||||
|
||||
Atomically stores @var{new} in @var{place} if @var{old} is @code{eq}
|
||||
|
|
@ -102,8 +101,8 @@ Currently, the following places are supported:
|
|||
accessor@footnote{The creation of atomic structure slot accessors can be
|
||||
deactivated by supplying a @code{(:atomic-accessors nil)} option to
|
||||
@code{defstruct}.} or any other place for which a compare-and-swap
|
||||
expansion was defined by @code{mp:defcas} or
|
||||
@code{mp:define-cas-expander}.
|
||||
expansion was defined by @coderef{mp:defcas} or
|
||||
@coderef{mp:define-cas-expander}.
|
||||
|
||||
For @code{slot-value}, @code{slot-unbound} is called if the slot is
|
||||
unbound unless @var{old} is @code{eq} to @code{si:unbound}, in which
|
||||
|
|
@ -112,7 +111,7 @@ Additionally, the object should have no applicable methods defined for
|
|||
@code{slot-value-using-class} or @code{(setf slot-value-using-class)}.
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:atomic-update
|
||||
@lspdef mp:atomic-update
|
||||
@defmac mp:atomic-update place update-fn &rest arguments
|
||||
|
||||
Atomically updates the CAS-able @var{place} to the value returned by
|
||||
|
|
@ -147,17 +146,16 @@ the result would be unpredictable.
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:atomic-push
|
||||
@lspdef mp:atomic-push
|
||||
@lspdef mp:atomic-pop
|
||||
@defmac mp:atomic-push obj place
|
||||
@end defmac
|
||||
@lspindex mp:atomic-pop
|
||||
@defmac mp:atomic-pop place
|
||||
@defmacx mp:atomic-pop place
|
||||
|
||||
Like @code{push}/@code{pop}, but atomic. @var{place} must be CAS-able
|
||||
and may be read multiple times before the update succeeds.
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:define-cas-expander
|
||||
@lspdef mp:define-cas-expander
|
||||
@defmac mp:define-cas-expander accessor lambda-list &body body
|
||||
|
||||
Define a compare-and-swap expander similar to
|
||||
|
|
@ -165,7 +163,7 @@ Define a compare-and-swap expander similar to
|
|||
generalized-variables @code{(accessor ...)}. When a form
|
||||
@code{(mp:compare-and-swap (accessor arg1 ... argn) old new)} is
|
||||
evaluated, the forms given in the body of
|
||||
@code{mp:define-cas-expander} are evaluated in order with the
|
||||
@coderef{mp:define-cas-expander} are evaluated in order with the
|
||||
parameters in @code{lambda-list} bound to @code{arg1 ... argn}. The
|
||||
body must return six values
|
||||
@lisp
|
||||
|
|
@ -188,35 +186,49 @@ variables, unlike in @code{define-setf-expander}). The whole
|
|||
Note that it is up to the user of this macro to ensure atomicity for
|
||||
the resulting compare-and-swap expansions.
|
||||
|
||||
@exindex CAS expansion definition
|
||||
Example:
|
||||
@exindex Define a compare-and-swap expansion
|
||||
@paragraph Example
|
||||
|
||||
CAS expansion for @code{mp:process-name}. A process is defined as
|
||||
follows in C:
|
||||
@example
|
||||
@verbatim
|
||||
struct ecl_process {
|
||||
_ECL_HDR;
|
||||
cl_object name;
|
||||
cl_object function;
|
||||
...
|
||||
};
|
||||
@end verbatim
|
||||
@end example
|
||||
|
||||
Hence we can define a CAS expander as (omitting type checks):
|
||||
@coderef{mp:define-cas-expander} can be used to define a more
|
||||
convienient compare-and-swap expansion for a class slot. Consider the
|
||||
following class:
|
||||
@lisp
|
||||
(mp:define-cas-expander mp:process-name (x)
|
||||
(let ((old (gensym)) (new (gensym)))
|
||||
(defclass food ()
|
||||
((name :initarg :name)
|
||||
(deliciousness :initform 5 :type '(integer 0 10)
|
||||
:accessor food-deliciousness)))
|
||||
|
||||
(defvar *spätzle* (make-instance 'food :name "Spätzle"))
|
||||
@end lisp
|
||||
We can't just use @coderef{mp:compare-and-swap} on
|
||||
@code{*spätzle*}:
|
||||
@lisp
|
||||
> (mp:compare-and-swap (food-deliciousness *x*) 5 10)
|
||||
|
||||
Condition of type: SIMPLE-ERROR
|
||||
Cannot get the compare-and-swap expansion of (FOOD-DELICIOUSNESS *X*).
|
||||
@end lisp
|
||||
We can use @code{symbol-value}, but let's define a more convenient
|
||||
compare-and-swap expander:
|
||||
@lisp
|
||||
(mp:define-cas-expander food-deliciousness (food)
|
||||
(let ((old (gensym))
|
||||
(new (gensym)))
|
||||
(values nil nil old new
|
||||
`(ffi:c-inline (,x ,old ,new) (:object :object :object) :object
|
||||
"ecl_compare_and_swap(&(#0)->process.name,#1,#2)"
|
||||
:one-liner t)
|
||||
`(mp:process-name ,x))))
|
||||
`(progn (check-type ,new (integer 0 10))
|
||||
(mp:compare-and-swap (slot-value ,food 'deliciousness)
|
||||
,old ,new))
|
||||
`(food-deliciousness ,food))))
|
||||
@end lisp
|
||||
Now finally, we can safely store our rating:
|
||||
@lisp
|
||||
> (mp:compare-and-swap (food-deliciousness *spätzle*) 5 10)
|
||||
|
||||
5
|
||||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:defcas
|
||||
@lspdef mp:defcas
|
||||
@defmac mp:defcas accessor cas-fun &optional documentation
|
||||
|
||||
Define a compare-and-swap expansion similar to the short form
|
||||
|
|
@ -229,16 +241,16 @@ Note that it is up to the user of this macro to ensure atomicity for
|
|||
the resulting compare-and-swap expansions.
|
||||
@end defmac
|
||||
|
||||
@lspindex mp:remcas
|
||||
@lspdef mp:remcas
|
||||
@defun mp:remcas symbol
|
||||
|
||||
Remove a compare-and-swap expansion. It is an equivalent of
|
||||
@code{fmakunbound (setf symbol)} for cas expansions.
|
||||
@end defun
|
||||
|
||||
@lspindex mp:get-cas-expansion
|
||||
@lspdef mp:get-cas-expansion
|
||||
@defun mp:get-cas-expansion place &optional environment
|
||||
|
||||
Returns the compare-and-swap expansion forms and variables as
|
||||
defined in @code{mp:define-cas-expander} for @var{place} as six values.
|
||||
Returns the compare-and-swap expansion forms and variables as defined in
|
||||
@coderef{mp:define-cas-expander} for @var{place} as six values.
|
||||
@end defun
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ true (e.g new client connects to the server).
|
|||
@subsection Condition variables dictionary
|
||||
|
||||
|
||||
@cppindex mp_make_condition_variable
|
||||
@lspindex mp:make-condition-variable
|
||||
@cppdef mp_make_condition_variable
|
||||
@lspdef mp:make-condition-variable
|
||||
|
||||
@deftypefun cl_object mp_make_condition_variable ()
|
||||
@end deftypefun
|
||||
|
|
@ -19,53 +19,53 @@ Creates a condition variable.
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_condition_variable_wait
|
||||
@lspindex mp:condition-variable-wait
|
||||
@cppdef mp_condition_variable_wait
|
||||
@lspdef mp:condition-variable-wait
|
||||
|
||||
@deftypefun cl_object mp_condition_variable_wait (cl_object cv, cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:condition-variable-wait cv lock
|
||||
Release @code{lock} and suspend thread until condition
|
||||
@code{mp:condition-variable-signal} is called on @code{cv}. When thread
|
||||
resumes re-aquire @code{lock}.
|
||||
Release @var{lock} and suspend thread until condition
|
||||
@coderef{mp:condition-variable-signal} is called on @var{cv}. When thread
|
||||
resumes re-aquire @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_condition_variable_timedwait
|
||||
@lspindex mp:condition-variable-timedwait
|
||||
@cppdef mp_condition_variable_timedwait
|
||||
@lspdef mp:condition-variable-timedwait
|
||||
|
||||
@deftypefun cl_object mp_condition_variable_timedwait (cl_object cv, cl_object lock, cl_object seconds)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:condition-variable-timedwait cv lock seconds
|
||||
@code{mp:condition-variable-wait} which timeouts after @code{seconds}
|
||||
@coderef{mp:condition-variable-wait} which timeouts after @var{seconds}
|
||||
seconds.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_condition_variable_signal
|
||||
@lspindex mp:condition-variable-signal
|
||||
@cppdef mp_condition_variable_signal
|
||||
@lspdef mp:condition-variable-signal
|
||||
|
||||
@deftypefun cl_object mp_condition_variable_signal (cl_object cv)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:condition-variable-signal cv
|
||||
Signal @code{cv} (wakes up only one waiter). After signal, signaling
|
||||
Signal @var{cv} (wakes up only one waiter). After signal, signaling
|
||||
thread keeps lock, waking thread goes on the queue waiting for the lock.
|
||||
|
||||
See @code{mp:condition-variable-wait}.
|
||||
See @coderef{mp:condition-variable-wait}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_condition_variable-broadcast
|
||||
@lspindex mp:condition-variable-broadcast
|
||||
@cppdef mp_condition_variable-broadcast
|
||||
@lspdef mp:condition-variable-broadcast
|
||||
|
||||
@deftypefun cl_object mp_condition_variable_broadcast (cl_object cv)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:condition-variable-broadcast cv
|
||||
Signal @code{cv} (wakes up all waiters).
|
||||
Signal @var{cv} (wakes up all waiters).
|
||||
|
||||
See @code{mp:condition-variable-wait}.
|
||||
See @coderef{mp:condition-variable-wait}.
|
||||
@end defun
|
||||
|
|
|
|||
|
|
@ -10,117 +10,116 @@ can't).
|
|||
@subsection Locks dictionary
|
||||
|
||||
|
||||
@cppindex ecl_make_lock
|
||||
@cppdef ecl_make_lock
|
||||
|
||||
@deftypefun cl_object ecl_make_lock (cl_object name, bool recursive)
|
||||
C/C++ equivalent of @code{mp:make-lock} without @code{key} arguments.
|
||||
C/C++ equivalent of @coderef{mp:make-lock} without @var{key} arguments.
|
||||
|
||||
See @code{mp:make-lock}.
|
||||
See @coderef{mp:make-lock}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@lspindex mp:make-lock
|
||||
@lspdef mp:make-lock
|
||||
|
||||
@defun mp:make-lock &key name (recursive nil)
|
||||
Creates a lock @code{name}. If @code{recursive} isn't @code{nil}, then
|
||||
the created lock is recursive.
|
||||
Creates a lock named @var{name}. If @var{recursive} is true, a recursive
|
||||
lock is created that can be locked multiple times by the same thread.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_recursive_lock_p
|
||||
@lspindex mp:recursive-lock-p
|
||||
@cppdef mp_recursive_lock_p
|
||||
@lspdef mp:recursive-lock-p
|
||||
|
||||
@deftypefun cl_object mp_recursive_lock_p (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:recursive-lock-p lock
|
||||
Predicate verifying if @code{lock} is recursive.
|
||||
Predicate verifying if @var{lock} is recursive.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_holding_lock_p
|
||||
@lspindex mp:holding-lock-p
|
||||
@cppdef mp_holding_lock_p
|
||||
@lspdef mp:holding-lock-p
|
||||
|
||||
@deftypefun cl_object mp_holding_lock_p (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:holding-lock-p lock
|
||||
Predicate verifying if the current thread holds @code{lock}.
|
||||
Predicate verifying if the current thread holds @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_lock_name
|
||||
@lspindex mp:lock-name
|
||||
@cppdef mp_lock_name
|
||||
@lspdef mp:lock-name
|
||||
|
||||
@deftypefun cl_object mp_lock_name (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:lock_name lock
|
||||
Returns @code{lock} name.
|
||||
Returns the name of @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspindex mp_lock_owner
|
||||
@lspindex mp:lock-owner
|
||||
@lspdef mp_lock_owner
|
||||
@lspdef mp:lock-owner
|
||||
|
||||
@deftypefun cl_object mp_lock_owner (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:lock_owner lock
|
||||
Returns process owning @code{lock} (or @code{nil} if it is free). For
|
||||
testing whether the current thread is holding a lock see
|
||||
@code{holding-lock-p}.
|
||||
@defun mp:lock-owner lock
|
||||
Returns the process owning @var{lock}. For testing whether the current
|
||||
thread is holding a lock see @coderef{mp:holding-lock-p}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_lock_count
|
||||
@lspindex mp:lock-count
|
||||
@cppdef mp_lock_count
|
||||
@lspdef mp:lock-count
|
||||
|
||||
@deftypefun cl_object mp_lock_count (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:lock-count lock
|
||||
Returns number of processes waiting for @code{lock}.
|
||||
Returns number of processes waiting for @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_get_lock_wait
|
||||
@cppindex mp_get_lock_nowait
|
||||
@lspindex mp:get-lock
|
||||
@cppdef mp_get_lock_wait
|
||||
@cppdef mp_get_lock_nowait
|
||||
@lspdef mp:get-lock
|
||||
|
||||
@deftypefun cl_object mp_get_lock_wait (cl_object lock)
|
||||
Grabs a lock (blocking if @code{lock} is already taken). Returns
|
||||
Grabs a lock (blocking if @var{lock} is already taken). Returns
|
||||
@code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun cl_object mp_get_lock_nowait
|
||||
Grabs a lock if free (non-blocking). If @code{lock} is already taken
|
||||
Grabs a lock if free (non-blocking). If @var{lock} is already taken
|
||||
returns @code{ECL_NIL}, otherwise @code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:get-lock lock &optional (wait t)
|
||||
Tries to acquire a lock. @code{wait} indicates whenever function should
|
||||
block or give up if @code{lock} is already taken. If @code{wait} is
|
||||
@code{nil} and @code{lock} can't be acquired returns
|
||||
Tries to acquire a lock. @var{wait} indicates whether function should
|
||||
block or give up if @var{lock} is already taken. If @var{wait} is
|
||||
@code{nil} and @var{lock} can't be acquired returns
|
||||
@code{nil}. Succesful operation returns @code{t}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_giveup_lock
|
||||
@lspindex mp:giveup-lock
|
||||
@cppdef mp_giveup_lock
|
||||
@lspdef mp:giveup-lock
|
||||
|
||||
@deftypefun cl_object mp_giveup_lock (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:giveup_lock lock
|
||||
Releases @code{lock}.
|
||||
@defun mp:giveup-lock lock
|
||||
Releases @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspindex mp:with-lock
|
||||
@lspdef mp:with-lock
|
||||
|
||||
@defmac mp:with-lock (lock-form) &body body
|
||||
Acquire lock for the dynamic scope of @code{body}, which is executed
|
||||
Acquire lock for the dynamic scope of @var{body}, which is executed
|
||||
with the lock held by current thread. Returns the values of body.
|
||||
|
||||
@c (lock-form &key wait-p timeout)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ Process is a primitive representing native thread.
|
|||
@node Processes dictionary
|
||||
@subsection Processes dictionary
|
||||
|
||||
@cppindex mp_all_processes
|
||||
@lspindex mp:all-processes
|
||||
@cppdef mp_all_processes
|
||||
@lspdef mp:all-processes
|
||||
|
||||
@deftypefun cl_object mp_all_processes ()
|
||||
@end deftypefun
|
||||
|
|
@ -22,8 +22,8 @@ expired before this copy is returned.
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_exit_process
|
||||
@lspindex mp:exit-process
|
||||
@cppdef mp_exit_process
|
||||
@lspdef mp:exit-process
|
||||
|
||||
@deftypefun cl_object mp_exit_process () ecl_attr_noreturn
|
||||
@end deftypefun
|
||||
|
|
@ -32,26 +32,26 @@ expired before this copy is returned.
|
|||
|
||||
When called from a running task, this function immediately causes the
|
||||
task to finish. When invoked from the main thread, it is equivalent to
|
||||
invoking @code{ext:quit} with exit code 0.
|
||||
invoking @coderef{ext:quit} with exit code 0.
|
||||
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_interrupt_process
|
||||
@lspindex mp:interrupt-process
|
||||
@cppdef mp_interrupt_process
|
||||
@lspdef mp:interrupt-process
|
||||
|
||||
@deftypefun cl_object mp_interrupt_process (cl_object process, cl_object function)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:interrupt-process process function
|
||||
|
||||
Interrupt a task. This @code{function} sends a signal to a running
|
||||
@code{process}. When the task is free to process that signal, it will
|
||||
Interrupt a task. This function sends a signal to a running
|
||||
@var{process}. When the task is free to process that signal, it will
|
||||
stop whatever it is doing and execute the given function.
|
||||
|
||||
@strong{WARNING:} Use with care! Interrupts can happen anywhere,
|
||||
except in code regions explicitely protected with
|
||||
@code{mp:without-interrupts}. This can lead to dangerous situations
|
||||
@coderef{mp:without-interrupts}. This can lead to dangerous situations
|
||||
when interrupting functions which are not thread safe. In particular,
|
||||
one has to consider:
|
||||
@itemize
|
||||
|
|
@ -62,7 +62,7 @@ one has to consider:
|
|||
@exindex Process interruption
|
||||
Example:
|
||||
|
||||
Kill a task that is doing nothing (See @code{mp:process-kill}).
|
||||
Kill a task that is doing nothing (See @coderef{mp:process-kill}).
|
||||
|
||||
@lisp
|
||||
(flet ((task-to-be-killed ()
|
||||
|
|
@ -76,8 +76,8 @@ Kill a task that is doing nothing (See @code{mp:process-kill}).
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_make_process
|
||||
@lspindex mp:make-process
|
||||
@cppdef mp_make_process
|
||||
@lspdef mp:make-process
|
||||
|
||||
@deftypefun cl_object mp_make_process (cl_narg narg, ...)
|
||||
@end deftypefun
|
||||
|
|
@ -85,33 +85,33 @@ Kill a task that is doing nothing (See @code{mp:process-kill}).
|
|||
@defun mp:make-process &key name initial-bindings
|
||||
|
||||
Create a new thread. This function creates a separate task with a name
|
||||
set to @code{name} and no function to run. See also
|
||||
@code{mp:process-run-function}. Returns newly created process.
|
||||
set to @var{name} and no function to run. See also
|
||||
@coderef{mp:process-run-function}. Returns newly created process.
|
||||
|
||||
If @code{initial-bindings} is false, the new process inherits local
|
||||
If @var{initial-bindings} is false, the new process inherits local
|
||||
bindings to special variables (i.e. binding a special variable with
|
||||
@code{let} or @code{let*}) from the current thread, otherwise the new
|
||||
thread possesses no local bindings.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_active_p
|
||||
@lspindex mp:process-active-p
|
||||
@cppdef mp_process_active_p
|
||||
@lspdef mp:process-active-p
|
||||
|
||||
@deftypefun cl_object mp_process_active_p (cl_object process)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-active-p process
|
||||
|
||||
Returns @code{t} when @code{process} is active, @code{nil}
|
||||
otherwise. Signals an error if @code{process} doesn't designate a valid
|
||||
Returns @code{t} when @var{process} is active, @code{nil}
|
||||
otherwise. Signals an error if @var{process} doesn't designate a valid
|
||||
process.
|
||||
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_enable
|
||||
@lspindex mp:process-enable
|
||||
@cppdef mp_process_enable
|
||||
@lspdef mp:process-enable
|
||||
|
||||
@deftypefun cl_object mp_process_enable (cl_object process)
|
||||
@end deftypefun
|
||||
|
|
@ -119,13 +119,13 @@ process.
|
|||
@defun mp:process-enable process
|
||||
|
||||
The argument to this function should be a process created by
|
||||
@code{mp:make-process}, which has a function associated as per
|
||||
@code{mp:process-preset} but which is not yet running. After invoking
|
||||
@coderef{mp:make-process}, which has a function associated as per
|
||||
@coderef{mp:process-preset} but which is not yet running. After invoking
|
||||
this function a new thread will be created in which the associated
|
||||
function will be executed. Returns @code{process} if the thread
|
||||
function will be executed. Returns @var{process} if the thread
|
||||
creation was successful and @code{nil} otherwise.
|
||||
|
||||
@exindex Possible implementation of @code{mp:process-run-function}:
|
||||
@exindex Possible implementation of @coderef{mp:process-run-function}:
|
||||
|
||||
@lisp
|
||||
(defun process-run-function (process-name process-function &rest args)
|
||||
|
|
@ -136,8 +136,8 @@ creation was successful and @code{nil} otherwise.
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_yield
|
||||
@lspindex mp:process-yield
|
||||
@cppdef mp_process_yield
|
||||
@lspdef mp:process-yield
|
||||
|
||||
@deftypefun cl_object mp_process_yield ()
|
||||
@end deftypefun
|
||||
|
|
@ -147,20 +147,20 @@ Yield the processor to other threads.
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process-join
|
||||
@lspindex mp:process-join
|
||||
@cppdef mp_process-join
|
||||
@lspdef mp:process-join
|
||||
|
||||
@deftypefun cl_object mp_process_join (cl_object process)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-join process
|
||||
Suspend current thread until @code{process} exits. Return the result
|
||||
values of the @code{process} function.
|
||||
Suspend current thread until @var{process} exits. Return the result
|
||||
values of the @var{process} function.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_kill
|
||||
@lspindex mp:process-kill
|
||||
@cppdef mp_process_kill
|
||||
@lspdef mp:process-kill
|
||||
|
||||
@deftypefun cl_object mp_process_kill (cl_object process)
|
||||
@end deftypefun
|
||||
|
|
@ -184,15 +184,15 @@ Kill a task that is doing nothing
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_suspend
|
||||
@lspindex mp:process-suspend
|
||||
@cppdef mp_process_suspend
|
||||
@lspdef mp:process-suspend
|
||||
|
||||
@deftypefun cl_object mp_process_suspend (cl_object process)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-suspend process
|
||||
Suspend a running @code{process}. May be resumed with
|
||||
@code{mp:process-resume}.
|
||||
Suspend a running @var{process}. May be resumed with
|
||||
@coderef{mp:process-resume}.
|
||||
|
||||
@exindex Suspend and resume process
|
||||
Example:
|
||||
|
|
@ -218,55 +218,55 @@ Example:
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_resume
|
||||
@lspindex mp:process-resume
|
||||
@cppdef mp_process_resume
|
||||
@lspdef mp:process-resume
|
||||
|
||||
@deftypefun cl_object mp_process_resume (cl_object process)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-resume process
|
||||
Resumes a suspended @code{process}. See example in
|
||||
@code{mp:process-suspend}.
|
||||
Resumes a suspended @var{process}. See example in
|
||||
@coderef{mp:process-suspend}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_name
|
||||
@lspindex mp:process-name
|
||||
@cppdef mp_process_name
|
||||
@lspdef mp:process-name
|
||||
|
||||
@deftypefun cl_object mp_process_name (cl_object process)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-name process
|
||||
Returns the name of a @code{process} (if any).
|
||||
Returns the name of a @var{process} (if any).
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_preset
|
||||
@lspindex mp:process-preset
|
||||
@cppdef mp_process_preset
|
||||
@lspdef mp:process-preset
|
||||
|
||||
@deftypefun cl_object mp_process_preset (cl_narg narg, cl_object process, cl_object function, ...)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-preset process function &rest function-args
|
||||
|
||||
Associates a @code{function} to call with the arguments
|
||||
@code{function-args}, with a stopped @code{process}. The function will
|
||||
Associates a @var{function} to call with the arguments
|
||||
@var{function-args}, with a stopped @var{process}. The function will
|
||||
be the entry point when the task is enabled in the future.
|
||||
|
||||
See @code{mp:enable-process} and @code{mp:process-run-function}.
|
||||
See @coderef{mp:process-enable} and @coderef{mp:process-run-function}.
|
||||
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_process_run_function
|
||||
@lspindex mp:process-run-function
|
||||
@cppdef mp_process_run_function
|
||||
@lspdef mp:process-run-function
|
||||
|
||||
@deftypefun cl_object mp_process_run_function (cl_narg narg, cl_object name, cl_object function, ...)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:process-run-function name function &rest function-args
|
||||
Create a new process using @code{mp:make-process}, associate a function
|
||||
to it and start it using @code{mp:process-preset}.
|
||||
Create a new process using @coderef{mp:make-process}, associate a function
|
||||
to it and start it using @coderef{mp:process-preset}.
|
||||
|
||||
@exindex mp:process-run-function usage
|
||||
Example:
|
||||
|
|
@ -282,8 +282,8 @@ Example:
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_current_process
|
||||
@lspindex mp:*current-process*
|
||||
@cppdef mp_current_process
|
||||
@lspdef mp:*current-process*
|
||||
|
||||
@deftypefun cl_object mp_current_process ()
|
||||
@end deftypefun
|
||||
|
|
@ -293,8 +293,8 @@ Returns/holds the current process of a caller.
|
|||
@end defvr
|
||||
|
||||
|
||||
@cppindex mp_block_signals
|
||||
@lspindex mp:block-signals
|
||||
@cppdef mp_block_signals
|
||||
@lspdef mp:block-signals
|
||||
|
||||
@deftypefun cl_object mp_block_signals ()
|
||||
@end deftypefun
|
||||
|
|
@ -302,88 +302,89 @@ Returns/holds the current process of a caller.
|
|||
@defun mp:block-signals
|
||||
Blocks process for interrupts and returns the previous sigmask.
|
||||
|
||||
See @code{mp:interrupt-process}.
|
||||
See @coderef{mp:interrupt-process}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_restore_signals
|
||||
@lspindex mp:restore-signals
|
||||
@cppdef mp_restore_signals
|
||||
@lspdef mp:restore-signals
|
||||
|
||||
@deftypefun cl_object mp_restore_signals (cl_object sigmask)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:restore-signals sigmask
|
||||
Enables the interrupts from @code{sigmask}.
|
||||
Enables the interrupts from @var{sigmask}.
|
||||
|
||||
See @code{mp:interrupt-process}.
|
||||
See @coderef{mp:interrupt-process}.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspindex mp:without-interrupts
|
||||
@lspindex allow-with-interrupts
|
||||
@lspindex with-local-interrupts
|
||||
@lspindex with-restored-interrupts
|
||||
@lspdef mp:without-interrupts
|
||||
@lspdef mp:allow-with-interrupts
|
||||
@lspdef mp:with-local-interrupts
|
||||
@lspdef mp:with-restored-interrupts
|
||||
|
||||
@defmac mp:without-interrupts &body body
|
||||
|
||||
Executes @code{body} with all deferrable interrupts disabled. Deferrable
|
||||
interrupts arriving during execution of the @code{body} take effect
|
||||
after @code{body} has been executed.
|
||||
Executes @var{body} with all deferrable interrupts disabled. Deferrable
|
||||
interrupts arriving during execution of the @var{body} take effect
|
||||
after @var{body} has been executed.
|
||||
|
||||
Deferrable interrupts include most blockable POSIX signals, and
|
||||
@code{mp:interrupt-process}. Does not interfere with garbage collection,
|
||||
and unlike in many traditional Lisps using userspace threads, in ECL
|
||||
@code{mp:without-interrupts} does not inhibit scheduling of other
|
||||
threads.
|
||||
@coderef{mp:interrupt-process}. Does not interfere with garbage
|
||||
collection, and unlike in many traditional Lisps using userspace
|
||||
threads, in ECL @coderef{mp:without-interrupts} does not inhibit
|
||||
scheduling of other threads.
|
||||
|
||||
Binds @code{allow-with-interrupts}, @code{with-local-interrupts} and
|
||||
@code{with-restored-interrupts} as a local macros.
|
||||
Binds @coderef{mp:allow-with-interrupts},
|
||||
@coderef{mp:with-local-interrupts} and
|
||||
@coderef{mp:with-restored-interrupts} as a local macros.
|
||||
|
||||
@code{with-restored-interrupts} executes the body with interrupts enabled if
|
||||
and only if the @code{without-interrupts} was in an environment in which
|
||||
interrupts were allowed.
|
||||
@coderef{mp:with-restored-interrupts} executes the body with interrupts
|
||||
enabled if and only if the @coderef{mp:without-interrupts} was in an
|
||||
environment in which interrupts were allowed.
|
||||
|
||||
@code{allow-with-interrupts} allows the @code{with-interrupts} to take
|
||||
effect during the dynamic scope of its body, unless there is an outer
|
||||
@code{without-interrupts} without a corresponding
|
||||
@code{allow-with-interrupts}.
|
||||
@coderef{mp:allow-with-interrupts} allows the
|
||||
@coderef{mp:with-interrupts} to take effect during the dynamic scope of
|
||||
its body, unless there is an outer @coderef{mp:without-interrupts}
|
||||
without a corresponding @coderef{mp:allow-with-interrupts}.
|
||||
|
||||
@code{with-local-interrupts} executes its body with interrupts enabled
|
||||
provided that there is an @code{allow-with-interrupts} for every
|
||||
@code{without-interrupts} surrounding the current
|
||||
one. @code{with-local-interrupts} is equivalent to:
|
||||
@coderef{mp:with-local-interrupts} executes its body with interrupts
|
||||
enabled provided that there is an @coderef{mp:allow-with-interrupts} for
|
||||
every @coderef{mp:without-interrupts} surrounding the current one.
|
||||
@coderef{mp:with-local-interrupts} is equivalent to:
|
||||
|
||||
@lisp
|
||||
(allow-with-interrupts (with-interrupts ...))
|
||||
(mp:allow-with-interrupts (mp:with-interrupts ...))
|
||||
@end lisp
|
||||
|
||||
Care must be taken not to let either @code{allow-with-interrupts} or
|
||||
@code{with-local-interrupts} appear in a function that escapes from
|
||||
inside the @code{without-interrupts} in:
|
||||
Care must be taken not to let either @coderef{mp:allow-with-interrupts}
|
||||
or @coderef{mp:with-local-interrupts} appear in a function that escapes
|
||||
from inside the @coderef{mp:without-interrupts} in:
|
||||
|
||||
@lisp
|
||||
(without-interrupts
|
||||
(mp:without-interrupts
|
||||
;; The body of the lambda would be executed with WITH-INTERRUPTS allowed
|
||||
;; regardless of the interrupt policy in effect when it is called.
|
||||
(lambda () (allow-with-interrupts ...)))
|
||||
(lambda () (mp:allow-with-interrupts ...)))
|
||||
|
||||
(without-interrupts
|
||||
(mp:without-interrupts
|
||||
;; The body of the lambda would be executed with interrupts enabled
|
||||
;; regardless of the interrupt policy in effect when it is called.
|
||||
(lambda () (with-local-interrupts ...)))
|
||||
(lambda () (mp:with-local-interrupts ...)))
|
||||
@end lisp
|
||||
@end defmac
|
||||
|
||||
|
||||
@lspindex mp:with-interrupts
|
||||
@lspdef mp:with-interrupts
|
||||
@defmac mp:with-interrupts &body body
|
||||
Executes @code{body} with deferrable interrupts conditionally
|
||||
Executes @var{body} with deferrable interrupts conditionally
|
||||
enabled. If there are pending interrupts they take effect prior to
|
||||
executing @code{body}.
|
||||
executing @var{body}.
|
||||
|
||||
As interrupts are normally allowed @code{with-interrupts} only makes
|
||||
sense if there is an outer @code{without-interrupts} with a
|
||||
corresponding @code{allow-with-interrupts}: interrupts are not enabled
|
||||
if any outer @code{without-interrupts} is not accompanied by
|
||||
@code{allow-with-interrupts}.
|
||||
As interrupts are normally allowed @coderef{mp:with-interrupts} only
|
||||
makes sense if there is an outer @coderef{mp:without-interrupts} with a
|
||||
corresponding @coderef{mp:allow-with-interrupts}: interrupts are not
|
||||
enabled if any outer @coderef{mp:without-interrupts} is not accompanied
|
||||
by @coderef{mp:allow-with-interrupts}.
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -17,102 +17,100 @@ Readers-writers locks are an optional feature, which is available if
|
|||
@subsection Read-Write locks dictionary
|
||||
|
||||
|
||||
@cppindex ecl_make_rwlock
|
||||
@cppdef ecl_make_rwlock
|
||||
|
||||
@deftypefun cl_object ecl_make_rwlock (cl_object name)
|
||||
C/C++ equivalent of @code{mp:make-rwlock} without @code{key} arguments.
|
||||
C/C++ equivalent of @coderef{mp:make-rwlock} without @code{key} arguments.
|
||||
|
||||
See @code{mp:make-rwlock}.
|
||||
See @coderef{mp:make-rwlock}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@lspindex mp:make_rwlock
|
||||
@lspdef mp:make-rwlock
|
||||
|
||||
@defun mp:make_rwlock &key name
|
||||
Creates a rwlock with @code{name}.
|
||||
@defun mp:make-rwlock &key name
|
||||
Creates a rwlock named @var{name}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_rwlock_name
|
||||
@lspindex mp:rwlock-name
|
||||
@cppdef mp_rwlock_name
|
||||
@lspdef mp:rwlock-name
|
||||
|
||||
@deftypefun cl_object mp_rwlock_name (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:rwlock_name lock
|
||||
Returns @code{lock} name.
|
||||
@defun mp:rwlock-name lock
|
||||
Returns the name of @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_get_rwlock_read_wait
|
||||
@cppindex mp_get_rwlock_read_nowait
|
||||
@lspindex mp:get-rwlock-read
|
||||
@cppdef mp_get_rwlock_read_wait
|
||||
@cppdef mp_get_rwlock_read_nowait
|
||||
@lspdef mp:get-rwlock-read
|
||||
|
||||
@deftypefun cl_object mp_get_rwlock_read_wait (cl_object lock)
|
||||
Acquires @code{lock} (blocks if @code{lock} is already taken with
|
||||
@code{mp:get-rwlock-write}. Lock may be acquired by multiple
|
||||
Acquires @var{lock} (blocks if @var{lock} is already taken with
|
||||
@coderef{mp:get-rwlock-write}. Lock may be acquired by multiple
|
||||
readers). Returns @code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun cl_object mp_get_rwlock_read_nowait
|
||||
Tries to acquire @code{lock}. If @code{lock} is already taken with
|
||||
@code{mp:get-rwlock-write} returns @code{ECL_NIL}, otherwise
|
||||
Tries to acquire @var{lock}. If @var{lock} is already taken with
|
||||
@coderef{mp:get-rwlock-write} returns @code{ECL_NIL}, otherwise
|
||||
@code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:get-rwlock-read lock &optional (wait t)
|
||||
Tries to acquire @code{lock}. @code{wait} indicates whenever function
|
||||
should block or give up if @code{lock} is already taken with
|
||||
@code{mp:get-rwlock-write}.
|
||||
Tries to acquire @var{lock}. @var{wait} indicates whenever function
|
||||
should block or give up if @var{lock} is already taken with
|
||||
@coderef{mp:get-rwlock-write}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_get_rwlock_write_wait
|
||||
@cppindex mp_get_rwlock_write_nowait
|
||||
@lspindex mp:get-rwlock-write
|
||||
@cppdef mp_get_rwlock_write_wait
|
||||
@cppdef mp_get_rwlock_write_nowait
|
||||
@lspdef mp:get-rwlock-write
|
||||
|
||||
@deftypefun cl_object mp_get_rwlock_write_wait (cl_object lock)
|
||||
Acquires @code{lock} (blocks if @code{lock} is already taken). Returns
|
||||
Acquires @var{lock} (blocks if @var{lock} is already taken). Returns
|
||||
@code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun cl_object mp_get_rwlock_write_nowait
|
||||
Tries to acquire @code{lock}. If @code{lock} is already taken returns
|
||||
Tries to acquire @var{lock}. If @var{lock} is already taken returns
|
||||
@code{ECL_NIL}, otherwise @code{ECL_T}.
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:get-rwlock-write lock &optional (wait t)
|
||||
Tries to acquire @code{lock}. @code{wait} indicates whenever function
|
||||
should block or give up if @code{lock} is already taken.
|
||||
Tries to acquire @var{lock}. @var{wait} indicates whenever function
|
||||
should block or give up if @var{lock} is already taken.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_giveup_rwlock_read
|
||||
@cppindex mp_giveup_rwlock_write
|
||||
@cppdef mp_giveup_rwlock_read
|
||||
@cppdef mp_giveup_rwlock_write
|
||||
|
||||
@lspindex mp:giveup-rwlock-read
|
||||
@lspindex mp:giveup-rwlock-write
|
||||
@lspdef mp:giveup-rwlock-read
|
||||
@lspdef mp:giveup-rwlock-write
|
||||
|
||||
|
||||
@deftypefun cl_object mp_giveup_rwlock_read (cl_object lock)
|
||||
@end deftypefun
|
||||
@deftypefun cl_object mp_giveup_rwlock_write (cl_object lock)
|
||||
@deftypefunx cl_object mp_giveup_rwlock_write (cl_object lock)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:giveup-rwlock-read lock
|
||||
@end defun
|
||||
@defun mp:giveup-rwlock-write lock
|
||||
Release @code{lock}.
|
||||
@defunx mp:giveup-rwlock-write lock
|
||||
Release @var{lock}.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspindex mp:with-rwlock
|
||||
@lspdef mp:with-rwlock
|
||||
|
||||
@defmac mp:with-rwlock (lock operation) &body body
|
||||
Acquire rwlock for the dynamic scope of @code{body} for operation
|
||||
@code{operation}, which is executed with the lock held by current
|
||||
Acquire rwlock for the dynamic scope of @var{body} for operation
|
||||
@var{operation}, which is executed with the lock held by current
|
||||
thread. Returns the values of body.
|
||||
|
||||
Valid values of argument @code{operation} are @code{:read} or
|
||||
Valid values of argument @var{operation} are @code{:read} or
|
||||
@code{:write} (for reader and writer access accordingly).
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -9,59 +9,59 @@ of concurrent threads allowed to access it is limited.
|
|||
@subsection Semaphores dictionary
|
||||
|
||||
|
||||
@cppindex ecl_make_semaphore
|
||||
@cppdef ecl_make_semaphore
|
||||
@deftypefun cl_object ecl_make_semaphore (cl_object name, cl_fixnum count)
|
||||
C/C++ equivalent of @code{mp:make-sempahore} without @code{key}
|
||||
C/C++ equivalent of @coderef{mp:make-semaphore} without @code{key}
|
||||
arguments.
|
||||
|
||||
See @code{mp:make-sempahore}.
|
||||
See @coderef{mp:make-semaphore}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex mp_make_semaphore
|
||||
@lspindex mp:make-semaphore
|
||||
@cppdef mp_make_semaphore
|
||||
@lspdef mp:make-semaphore
|
||||
|
||||
@defun mp:make-semaphore &key name count
|
||||
Creates a counting semaphore @code{name} with a resource count
|
||||
@code{count}.
|
||||
Creates a counting semaphore @var{name} with a resource count
|
||||
@var{count}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_semaphore_name
|
||||
@lspindex mp:semaphore-name
|
||||
@cppdef mp_semaphore_name
|
||||
@lspdef mp:semaphore-name
|
||||
|
||||
@deftypefun cl_object mp_semaphore_name (cl_object semaphore)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:semaphore-name semaphore
|
||||
Returns @code{semaphore} name.
|
||||
Returns the name of @var{semaphore}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_semaphore_count
|
||||
@lspindex mp:semaphore-count
|
||||
@cppdef mp_semaphore_count
|
||||
@lspdef mp:semaphore-count
|
||||
|
||||
@deftypefun cl_object mp_semaphore_count (cl_object semaphore)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:semaphore-count semaphore
|
||||
Returns @code{semaphore} count of resources.
|
||||
Returns the resource count of @var{semaphore}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_semaphore_wait_count
|
||||
@lspindex mp:semaphore-wait-count
|
||||
@cppdef mp_semaphore_wait_count
|
||||
@lspdef mp:semaphore-wait-count
|
||||
|
||||
@deftypefun cl_object mp_semaphore_wait_count (cl_object semaphore)
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:semaphore-wait-count semaphore
|
||||
Returns number of threads waiting on @code{semaphore}.
|
||||
Returns the number of threads waiting on @var{semaphore}.
|
||||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_wait_on_semaphore
|
||||
@lspindex mp:wait-on-semaphore
|
||||
@cppdef mp_wait_on_semaphore
|
||||
@lspdef mp:wait-on-semaphore
|
||||
|
||||
@deftypefun cl_object mp_wait_on_semaphore (cl_object semaphore)
|
||||
@end deftypefun
|
||||
|
|
@ -72,8 +72,8 @@ resource count before semaphore was acquired.
|
|||
@end defun
|
||||
|
||||
|
||||
@cppindex mp_try_get_semaphore
|
||||
@lspindex mp:try-get-semaphore
|
||||
@cppdef mp_try_get_semaphore
|
||||
@lspdef mp:try-get-semaphore
|
||||
|
||||
@deftypefun cl_object mp_try_get_semaphore (cl_object semaphore)
|
||||
@end deftypefun
|
||||
|
|
@ -85,12 +85,12 @@ was acquired.
|
|||
@end defun
|
||||
|
||||
|
||||
@lspindex mp_signal_semaphore
|
||||
@lspindex mp:signal-semaphore
|
||||
@lspdef mp_signal_semaphore
|
||||
@lspdef mp:signal-semaphore
|
||||
|
||||
@deftypefun cl_object mp_signal_semaphore (cl_narg n, cl_object sem, ...);
|
||||
@end deftypefun
|
||||
|
||||
@defun mp:signal-semaphore semaphore &optional (count 1)
|
||||
Releases @code{count} units of a resource on @code{semaphore}.
|
||||
Releases @var{count} units of a resource on @var{semaphore}.
|
||||
@end defun
|
||||
|
|
|
|||
|
|
@ -12,12 +12,15 @@
|
|||
@cindex Command line processing
|
||||
@node Command line arguments
|
||||
@subsection Command line arguments
|
||||
|
||||
@lspdef ext:*help-message*
|
||||
@deftypevar string ext:*help-message*
|
||||
Command line help message. Initial value is ECL help message. This
|
||||
variable contains the help message which is output when ECL is invoked
|
||||
with the @code{--help}.
|
||||
@end deftypevar
|
||||
|
||||
@lspdef ext:*lisp-init-file-list*
|
||||
@deftypevar list-of-pathname-designators ext:*lisp-init-file-list*
|
||||
ECL initialization files. Initial value is @code{'("~/.ecl"
|
||||
"~/.eclrc")}. This variable contains the names of initialization files
|
||||
|
|
@ -25,17 +28,19 @@ that are loaded by ECL or embedding programs. The loading of
|
|||
initialization files happens automatically in ECL unless invoked with
|
||||
the option @code{--norc}. Whether initialization files are loaded or
|
||||
not is controlled by the command line options rules, as described in
|
||||
@code{ext:process-command-args}.
|
||||
@coderef{ext:process-command-args}.
|
||||
@end deftypevar
|
||||
|
||||
@lspdef ext:+default-command-arg-rules+
|
||||
@deftypevar list-of-lists ext:+default-command-arg-rules+
|
||||
ECL command line options. This constant contains a list of rules for
|
||||
parsing the command line arguments. This list is made of all the
|
||||
options which ECL accepts by default. It can be passed as first
|
||||
argument to @code{ext:process-command-args}, and you can use it as a
|
||||
argument to @coderef{ext:process-command-args}, and you can use it as a
|
||||
starting point to extend ECL.
|
||||
@end deftypevar
|
||||
|
||||
@lspdef ext:command-args
|
||||
@defun ext:command-args
|
||||
Original list of command line arguments. This function returns the
|
||||
list of command line arguments passed to either ECL or the program it
|
||||
|
|
@ -45,15 +50,16 @@ name of the program as it was invoked. You should not count on the
|
|||
filename to be resolved.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:process-command-args
|
||||
@defun ext:process-command-args &key args rules
|
||||
|
||||
@defvr argument args
|
||||
A list of strings. Defaults to the output of @code{ext:command-args}.
|
||||
@end defvr
|
||||
@defvr argument rules
|
||||
@table @var
|
||||
@item args
|
||||
A list of strings. Defaults to the output of @coderef{ext:command-args}.
|
||||
@item rules
|
||||
A list of lists. Defaults to the value of
|
||||
@code{ext:+default-command-arg-rules+}.
|
||||
@end defvr
|
||||
@coderef{ext:+default-command-arg-rules+}.
|
||||
@end table
|
||||
|
||||
This function processes the command line arguments passed to either
|
||||
ECL or the program that embeds it. It uses the list of rules rules,
|
||||
|
|
@ -61,51 +67,47 @@ which has the following syntax:
|
|||
|
||||
@code{(option-name nargs template [:stop | :noloadrc | :loadrc]*)}
|
||||
|
||||
@defvr opt option-name
|
||||
@table @code
|
||||
@item option-name
|
||||
A string with the option prefix as typed by the user. For instance
|
||||
@code{--help}, @code{-?}, @code{--compile}, etc.
|
||||
@end defvr
|
||||
|
||||
@defvr opt nargs
|
||||
@item nargs
|
||||
A non-negative integer denoting the number of arguments taken by this
|
||||
option.
|
||||
@end defvr
|
||||
|
||||
@defvr opt template
|
||||
@item template
|
||||
A lisp form, not evaluated, where numbers from 0 to nargs will be
|
||||
replaced by the corresponding option argument.
|
||||
@end defvr
|
||||
|
||||
@defvr opt :stop
|
||||
@item :stop
|
||||
If present, parsing of arguments stops after this option is found and
|
||||
processed. The list of remaining arguments is passed to the
|
||||
rule. ECL's top-level uses this option with the @code{--} command line
|
||||
option to set @code{ext:*unprocessed-ecl-command-args*} to the list of
|
||||
remaining arguments.
|
||||
@end defvr
|
||||
|
||||
@defvr opt :noloadrc
|
||||
@defvrx opt :loadrc
|
||||
@item :noloadrc, :loadrc
|
||||
Determine whether the lisp initialization files in
|
||||
@code{ext:*lisp-init-file-list*} will be loaded before processing
|
||||
@coderef{ext:*lisp-init-file-list*} will be loaded before processing
|
||||
all forms.
|
||||
@end defvr
|
||||
@end table
|
||||
|
||||
@code{ext:process-command-args} works as follows. First of all, it
|
||||
@coderef{ext:process-command-args} works as follows. First of all, it
|
||||
parses all the command line arguments, except for the first one, which
|
||||
is assumed to contain the program name. Each of these arguments is
|
||||
matched against the rules, sequentially, until one of the patterns
|
||||
succeeds.
|
||||
|
||||
A special name @code{*DEFAULT*}, matches any unknown command line
|
||||
option. If there is no @code{*DEFAULT*} rule and no match is found, an
|
||||
A special name @code{*default*}, matches any unknown command line
|
||||
option. If there is no @code{*default*} rule and no match is found, an
|
||||
error is signaled. For each rule that succeeds, the function
|
||||
constructs a lisp statement using the template.
|
||||
|
||||
After all arguments have been processed,
|
||||
@code{ext:process-command-args}, and there were no occurrences of
|
||||
@coderef{ext:process-command-args}, and there were no occurrences of
|
||||
@code{:noloadrc}, the first existing file listed in
|
||||
@code{ext:*lisp-init-file-list*} will be loaded. Finally, the list of
|
||||
@coderef{ext:*lisp-init-file-list*} will be loaded. Finally, the list of
|
||||
lisp statements will be evaluated.
|
||||
@end defun
|
||||
|
||||
|
|
@ -114,7 +116,7 @@ lisp statements will be evaluated.
|
|||
|
||||
The following piece of code implements the ls command using
|
||||
lisp. Instructions for building this program are found under
|
||||
@code{ecl/examples/cmdline/ls.lsp}.
|
||||
@file{examples/cmdline/ls.lsp}.
|
||||
|
||||
@lisp
|
||||
@verbatim
|
||||
|
|
@ -147,25 +149,26 @@ ls [--help | -?] filename*
|
|||
@subsection External processes
|
||||
|
||||
ECL provides several facilities for invoking and communicating with
|
||||
@code{ext:external-process}. If one just wishes to execute some
|
||||
program, without caring for its output, then probably
|
||||
@code{ext:system} is the best function. In all other cases it is
|
||||
preferable to use @code{ext:run-program}, which opens pipes to
|
||||
communicate with the program and manipulate it while it runs on the
|
||||
background.
|
||||
external processes. If one just wishes to execute some program, without
|
||||
caring for its output, then probably @coderef{ext:system} is the best
|
||||
function. In all other cases it is preferable to use
|
||||
@coderef{ext:run-program}, which opens pipes to communicate with the
|
||||
program and manipulate it while it runs on the background.
|
||||
|
||||
External process is a structure created with @code{ext:run-program}
|
||||
External process is a structure created with @coderef{ext:run-program}
|
||||
(returned as third value). It is programmer responsibility, to call
|
||||
@code{ext:external-process-wait} on finished processes, however during
|
||||
@coderef{ext:external-process-wait} on finished processes, however during
|
||||
garbage collection object will be finalized.
|
||||
|
||||
@lspdef ext:external-process-pid
|
||||
@defun ext:external-process-pid process
|
||||
Returns process PID or @code{nil} if already finished.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:external-process-status
|
||||
@defun ext:external-process-status process
|
||||
Updates process status. @code{ext:external-process-status} calls
|
||||
@code{ext:external-process-wait} if process has not finished yet
|
||||
Updates process status. @coderef{ext:external-process-status} calls
|
||||
@coderef{ext:external-process-wait} if process has not finished yet
|
||||
(non-blocking call). Returns two values:
|
||||
|
||||
@code{status} - member of @code{(:abort :error :exited :signalled
|
||||
|
|
@ -175,40 +178,45 @@ Updates process status. @code{ext:external-process-status} calls
|
|||
it is a signal code. Otherwise NIL.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:external-process-wait
|
||||
@defun ext:external-process-wait process wait
|
||||
If the second argument is non-NIL, function blocks until external
|
||||
process is finished. Otherwise status is updated. Returns two values
|
||||
(see @code{ext:external-process-status}).
|
||||
(see @coderef{ext:external-process-status}).
|
||||
@end defun
|
||||
|
||||
@lspdef ext:terminate-process
|
||||
@defun ext:terminate-process process &optional force
|
||||
Terminates external process.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:external-process-input
|
||||
@lspdef ext:external-process-output
|
||||
@lspdef ext:external-process-error-stream
|
||||
@defun ext:external-process-input process
|
||||
@defunx ext:external-process-output process
|
||||
@defunx ext:external-process-error-stream process
|
||||
Process stream accessors (read-only).
|
||||
@end defun
|
||||
|
||||
@lspindex ext:run-program
|
||||
@lspdef ext:run-program
|
||||
@defun ext:run-program command argv @
|
||||
&key input output error wait environ @
|
||||
if-input-does-not-exist if-output-exists if-error-exists @
|
||||
external-format #+windows escape-arguments
|
||||
|
||||
@code{run-program} creates a new process specified by the
|
||||
@coderef{ext:run-program} creates a new process specified by the
|
||||
@var{command} argument. @var{argv} are the standard arguments that can
|
||||
be passed to a program. For no arguments, use @code{nil} (which means
|
||||
that just the name of the program is passed as arg 0).
|
||||
|
||||
@code{run-program} will return three values - two-way stream for
|
||||
@coderef{ext:run-program} will return three values - two-way stream for
|
||||
communication, return code or @code{nil} (if process is called
|
||||
asynchronously), and @code{ext:external-process} object holding
|
||||
process state.
|
||||
|
||||
It is programmer responsibility to call
|
||||
@code{ext:external-process-wait} on finished process, however ECL
|
||||
@coderef{ext:external-process-wait} on finished process, however ECL
|
||||
associates @ref{Finalization, finalizer} with the object calling it
|
||||
when the object is garbage collected. If process didn't finish but is
|
||||
not referenced, finalizer will be invoked once more during next
|
||||
|
|
@ -216,71 +224,68 @@ garbage collection.
|
|||
|
||||
The @code{&key} arguments have the following meanings:
|
||||
|
||||
@defvr argument input
|
||||
@table @var
|
||||
@item input
|
||||
Either @code{t}, @code{nil}, a pathname, a string, a stream or
|
||||
@code{:stream}. If @code{t} the standard input for the current process
|
||||
is inherited. If @code{nil}, @code{/dev/null} is used. If a pathname
|
||||
(or a string), the file so specified is used. If a stream, all the
|
||||
input is read from that stream and sent to the subprocess. If
|
||||
@code{:stream}, the @code{external-process-input} slot is filled in
|
||||
with a stream that sends its output to the process. Defaults to
|
||||
@code{:stream}.
|
||||
@end defvr
|
||||
is inherited. If @code{nil}, @code{/dev/null} is used. If a pathname (or
|
||||
a string), the file so specified is used. If a stream, all the input is
|
||||
read from that stream and sent to the subprocess. If @code{:stream}, the
|
||||
@coderef{ext:external-process-input} slot is filled in with a stream
|
||||
that sends its output to the process. Defaults to @code{:stream}.
|
||||
|
||||
@defvr argument if-input-does-not-exist
|
||||
can be one of: @code{:error} to generate an error @code{:create} to
|
||||
@item if-input-does-not-exist
|
||||
Can be one of: @code{:error} to generate an error @code{:create} to
|
||||
create an empty file @code{nil} (the default) to return nil from
|
||||
@code{run-program}
|
||||
@end defvr
|
||||
@coderef{ext:run-program}
|
||||
|
||||
@defvr argument output
|
||||
@item output
|
||||
Either @code{t}, @code{nil}, a pathname, a string, a stream, or
|
||||
@code{:stream}. If @code{t}, the standard output for the current
|
||||
process is inherited. If @code{nil}, @code{/dev/null} is used. If a
|
||||
pathname (or as string), the file so specified is used. If a stream,
|
||||
all the output from the process is written to this stream. If
|
||||
@code{:stream}, the @code{external-process-output} slot is filled in
|
||||
with a stream that can be read to get the output. Defaults to
|
||||
@code{:stream}.
|
||||
@end defvr
|
||||
@code{:stream}. If @code{t}, the standard output for the current process
|
||||
is inherited. If @code{nil}, @code{/dev/null} is used. If a pathname (or
|
||||
as string), the file so specified is used. If a stream, all the output
|
||||
from the process is written to this stream. If @code{:stream}, the
|
||||
@coderef{ext:external-process-output} slot is filled in with a stream
|
||||
that can be read to get the output. Defaults to @code{:stream}.
|
||||
|
||||
@defvr argument if-output-exists
|
||||
@end defvr
|
||||
@item if-output-exists
|
||||
Can be one of: @code{:error} (the default) to generate an error,
|
||||
@code{:supersede} to supersede the file with output from the program,
|
||||
@code{:append} to append output from the program to the file or
|
||||
@code{nil} to return @code{nil} from @coderef{ext:run-program}.
|
||||
|
||||
@defvr argument error
|
||||
@item error
|
||||
Same as @code{:output}, except that @code{:error} can also be
|
||||
specified as @code{:output} in which case all error output is routed
|
||||
to the same place as normal output. Defaults to @code{:output}.
|
||||
@end defvr
|
||||
|
||||
@defvr argument if-error-exists
|
||||
@item if-error-exists
|
||||
Same as @code{:if-output-exists}.
|
||||
@end defvr
|
||||
|
||||
@defvr argument wait
|
||||
If non-NIL (default), wait until the created process finishes. If
|
||||
@item wait
|
||||
If non-@code{nil} (default), wait until the created process finishes. If
|
||||
@code{nil}, continue running Lisp until the program finishes.
|
||||
@end defvr
|
||||
|
||||
@defvr argument environ
|
||||
@item environ
|
||||
A list of STRINGs describing the new Unix environment (as in "man
|
||||
environ"). The default is to copy the environment of the current
|
||||
process. To extend existing environment (instead of replacing it),
|
||||
use @code{:environ (append *my-env* (ext:environ))}.
|
||||
|
||||
If non-NIL @code{environ} argument is supplied, then first argument to
|
||||
@code{ext:run-program} @code{command} must be full path to the file.
|
||||
@end defvr
|
||||
If non-@code{nil} @code{environ} argument is supplied, then first
|
||||
argument to @coderef{ext:run-program}, @var{command}, must be full path
|
||||
to the file.
|
||||
|
||||
@defvr argument external-format
|
||||
@item external-format
|
||||
The external-format to use for @code{:input}, @code{:output}, and
|
||||
@code{:error} STREAMs.
|
||||
@end defvr
|
||||
@end table
|
||||
|
||||
@emph{Windows specific options:}
|
||||
@defvr argument escape-arguments
|
||||
Controls escaping of the arguments passed to CreateProcess.
|
||||
@end defvr
|
||||
@strong{Windows specific options:}
|
||||
@table @var
|
||||
@item escape-arguments
|
||||
Controls escaping of the arguments passed to @code{CreateProcess}.
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@cindex FIFO files (named pipes)
|
||||
|
|
@ -289,8 +294,8 @@ Controls escaping of the arguments passed to CreateProcess.
|
|||
|
||||
Named pipe (known as fifo) may be created on UNIX with a shell command
|
||||
mkfifo. ECL opens such files in non-blocking
|
||||
mode. @code{ext:file-kind} will return for such file
|
||||
@code{:FIFO}. Since it is impossible to guess how many characters are
|
||||
mode. @coderef{ext:file-kind} will return for such file
|
||||
@code{:fifo}. Since it is impossible to guess how many characters are
|
||||
available in this special file @code{file-length} function will return
|
||||
NIL.
|
||||
|
||||
|
|
@ -307,15 +312,17 @@ NIL.
|
|||
@c @defun ext:argv
|
||||
@c @end defun
|
||||
|
||||
@lspdef ext:system
|
||||
@defun ext:system command
|
||||
Run shell command ignoring its output. Uses fork.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:make-pipe
|
||||
@defun ext:make-pipe
|
||||
Creates a pipe and wraps it in a two way stream.
|
||||
@end defun
|
||||
|
||||
|
||||
@lspdef ext:quit
|
||||
@defun ext:quit &optional exit-code kill-all-threads
|
||||
This function abruptly stops the execution of the program in which ECL
|
||||
is embedded. Depending on the platform, several other functions will
|
||||
|
|
@ -324,10 +331,13 @@ be invoked to free resources, close loaded modules, etc.
|
|||
The exit code is the code seen by the parent process that invoked this
|
||||
program. Normally a code other than zero denotes an error.
|
||||
|
||||
If @code{kill-all-threads} is non-NIL, tries to gently kill and join
|
||||
with running threads.
|
||||
If @var{kill-all-threads} is non-@code{nil}, tries to gently kill and
|
||||
join with running threads.
|
||||
@end defun
|
||||
|
||||
@lspdef ext:environ
|
||||
@lspdef ext:getenv
|
||||
@lspdef ext:setenv
|
||||
@defun ext:environ
|
||||
@defunx ext:getenv variable
|
||||
@defunx ext:setenv variable value
|
||||
|
|
@ -337,6 +347,14 @@ Environment accessors.
|
|||
|
||||
@c UNIX shell interface
|
||||
|
||||
@lspdef ext:getpid
|
||||
@lspdef ext:getuid
|
||||
@lspdef ext:getcwd
|
||||
@lspdef ext:chdir
|
||||
@lspdef ext:file-kind
|
||||
@lspdef ext:copy-file
|
||||
@lspdef ext:chmod
|
||||
|
||||
@defun ext:getpid
|
||||
@defunx ext:getuid
|
||||
@defunx ext:getcwd &optional (change-default-pathname-defaults NIL)
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ Example:
|
|||
@end lisp
|
||||
@end defmac
|
||||
|
||||
@lspindex ext:package-local-nicknames
|
||||
@cppindex si_package_local_nicknames
|
||||
@lspdef ext:package-local-nicknames
|
||||
@cppdef si_package_local_nicknames
|
||||
@defun {ext:package-local-nicknames} package-designator
|
||||
@end defun
|
||||
@deftypefun cl_object si_package_local_nicknames (cl_object package_designator)
|
||||
|
|
@ -69,8 +69,8 @@ local nickname is used instead of the real name in order to preserve
|
|||
print-read consistency.
|
||||
@end deftypefun
|
||||
|
||||
@lspindex ext:package-locally-nicknamed-by-list
|
||||
@cppindex si_package_locally_nicknamed_by_list
|
||||
@lspdef ext:package-locally-nicknamed-by-list
|
||||
@cppdef si_package_locally_nicknamed_by_list
|
||||
@defun {ext:package-locally-nicknamed-by-list} package-designator
|
||||
@end defun
|
||||
@deftypefun cl_object si_package_locally_nicknamed_by_list (cl_object package_designator)
|
||||
|
|
@ -78,8 +78,8 @@ Returns a list of packages which have a local nickname for the
|
|||
designated package.
|
||||
@end deftypefun
|
||||
|
||||
@lspindex ext:add-package-local-nickname
|
||||
@cppindex si_add_package_local_nickname
|
||||
@lspdef ext:add-package-local-nickname
|
||||
@cppdef si_add_package_local_nickname
|
||||
@defun {ext:add-package-local-nickname} local-nickname actual-package &optional package-designator
|
||||
@end defun
|
||||
@deftypefun cl_object si_add_package_local_nickname (cl_object local_nickname, cl_object actual_package, cl_object package_designator)
|
||||
|
|
@ -103,14 +103,14 @@ nickname, the local nickname is used instead of the real name in order
|
|||
to preserve print-read consistency.
|
||||
@end deftypefun
|
||||
|
||||
@lspindex ext:remove-package-local-nickname
|
||||
@cppindex si_remove_package_local_nickname
|
||||
@lspdef ext:remove-package-local-nickname
|
||||
@cppdef si_remove_package_local_nickname
|
||||
@defun {ext:remove-package-local-nickname} old-nickname &optional package-designator
|
||||
@end defun
|
||||
@deftypefun cl_object si_remove_package_local_nickname (cl_object old_nickname, cl_object package_designator)
|
||||
If the designated package had @var{old-nickname} as a local nickname
|
||||
for another package, it is removed. Returns true if the nickname
|
||||
existed and was removed, and @code{NIL} otherwise.
|
||||
existed and was removed, and @code{nil} otherwise.
|
||||
@end deftypefun
|
||||
|
||||
@node Package locks
|
||||
|
|
@ -193,53 +193,51 @@ Removing an existing package local nickname to a package.
|
|||
|
||||
@subsection Package Lock Dictionary
|
||||
|
||||
@lspindex ext:package-locked-p
|
||||
@lspdef ext:package-locked-p
|
||||
@defun ext:package-locked-p package
|
||||
Returns @code{t} when @code{package} is locked, @code{nil}
|
||||
otherwise. Signals an error if @code{package} doesn't designate a valid
|
||||
Returns @code{t} when @var{package} is locked, @code{nil}
|
||||
otherwise. Signals an error if @var{package} doesn't designate a valid
|
||||
package.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:lock-package
|
||||
@lspdef ext:lock-package
|
||||
@defun ext:lock-package package
|
||||
Locks @code{package} and returns @code{t}. Has no effect if package was
|
||||
Locks @var{package} and returns @code{t}. Has no effect if package was
|
||||
already locked. Signals an error if package is not a valid
|
||||
@code{package} designator
|
||||
@var{package} designator
|
||||
@end defun
|
||||
|
||||
@lspindex ext:unlock-package
|
||||
@lspdef ext:unlock-package
|
||||
@defun ext:unlock-package package
|
||||
Unlocks @code{package} and returns @code{t}. Has no effect if
|
||||
@code{package} was already unlocked. Signals an error if @code{package}
|
||||
Unlocks @var{package} and returns @code{t}. Has no effect if
|
||||
@var{package} was already unlocked. Signals an error if @var{package}
|
||||
is not a valid package designator.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:without-package-locks
|
||||
@lspdef ext:without-package-locks
|
||||
@defmac ext:without-package-locks &body body
|
||||
Ignores all runtime package lock violations during the execution of
|
||||
body. Body can begin with declarations.
|
||||
@end defmac
|
||||
|
||||
@lspindex ext:with-unlocked-packages
|
||||
@lspdef ext:with-unlocked-packages
|
||||
@defmac ext:with-unlocked-packages (&rest packages) &body body
|
||||
Unlocks @code{packages} for the dynamic scope of the
|
||||
@code{body}. Signals an error if any of @code{packages} is not a valid
|
||||
Unlocks @var{packages} for the dynamic scope of the
|
||||
@var{body}. Signals an error if any of @var{packages} is not a valid
|
||||
package designator.
|
||||
@end defmac
|
||||
|
||||
@defmac cl:defpackage name [[option]]* @result{} package
|
||||
|
||||
Options are extended to include the following:
|
||||
Options are extended to include
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@code{:lock} @var{boolean}
|
||||
@example
|
||||
:lock boolean
|
||||
@end example
|
||||
|
||||
If the argument to @code{:lock} is @code{t}, the package is initially
|
||||
locked. If @code{:lock} is not provided it defaults to @code{nil}.
|
||||
|
||||
@end itemize
|
||||
|
||||
@exindex Defpackage @code{:lock} option
|
||||
Example:
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ The first family of signals are generated by the floating point processing hardw
|
|||
|
||||
The second family of signals may seem rare, but unfortunately they still happen quite often. One scenario is wrong code that handles memory directly via FFI. Another one is undetected stack overflows, which typically result in access to protected memory regions. Finally, a very common cause of these kind of exceptions is invoking a function that has been compiled with very low security settings with arguments that are not of the expected type -- for instance, passing a float when a structure is expected.
|
||||
|
||||
The third family is related to the multiprocessing capabilities in Common Lisp systems and more precisely to the @code{mp:interrupt-process} function which is used to kill, interrupt and inspect arbitrary threads. In POSIX systems ECL informs a given thread about the need to interrupt its execution by sending a particular signal from the set which is available to the user.
|
||||
The third family is related to the multiprocessing capabilities in Common Lisp systems and more precisely to the @coderef{mp:interrupt-process} function which is used to kill, interrupt and inspect arbitrary threads. In POSIX systems ECL informs a given thread about the need to interrupt its execution by sending a particular signal from the set which is available to the user.
|
||||
|
||||
Note that in neither of these cases we should let the signal pass unnoticed. Access violations and floating point exceptions may propagate through the program causing more harm than expected, and without process interrupts we will not be able to stop and cancel different threads. The only question that remains, though, is whether such signals can be handled by the thread in which they were generated and how.
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ In systems in which this is possible, ECL creates a signal handling thread to de
|
|||
|
||||
The use of a separate thread has some nice consequences. The first one is that those signals will not interrupt any sensitive code. The second one is that the signal handling thread will be able to execute arbitrary lisp or C code, since it is not being executed in a sensitive context. Most important, this style of signal handling is the recommended one by the POSIX standards, and it is the one that Windows uses.
|
||||
|
||||
The installation of the signal handling thread is dictated by a boot time option, @code{ECL_OPT_SIGNAL_HANDLING_THREAD}, and it will only be possible in systems that support either POSIX or Windows threads.
|
||||
The installation of the signal handling thread is dictated by a boot time option, @code{ECL_OPT_SIGNAL_HANDLING_THREAD} (@pxref{tab:boot-options} for a summary of boot options), and it will only be possible in systems that support either POSIX or Windows threads.
|
||||
|
||||
Systems which embed ECL as an extension language may wish to deactivate the signal handling thread using the previously mentioned option. If this is the case, then they should take appropriate measures to avoid interrupting the code in ECL when such signals are delivered.
|
||||
|
||||
|
|
@ -94,87 +94,46 @@ The approach in ECL is more lightweight: we install our own signal handler and u
|
|||
|
||||
Systems that embed ECL may wish to deactivate completely these signal handlers. This is done using the boot options, @code{ECL_OPT_TRAP_SIGFPE}, @code{ECL_OPT_TRAP_SIGSEGV}, @code{ECL_OPT_TRAP_SIGBUS}, @code{ECL_OPT_TRAP_INTERRUPT_SIGNAL}.
|
||||
|
||||
Systems that embed ECL and want to allow handling of synchronous signals should take care to also trap the associated lisp conditions that may arise. This is automatically taken care of by functions such as @code{si_safe_eval()}, and in all other cases it can be solved by enclosing the unsafe code in a @code{CL_CATCH_ALL_BEGIN} frame.
|
||||
Systems that embed ECL and want to allow handling of synchronous signals should take care to also trap the associated lisp conditions that may arise. This is automatically taken care of by functions such as @coderef{si_safe_eval}, and in all other cases it can be solved by enclosing the unsafe code in a @coderef{CL_CATCH_ALL} frame.
|
||||
|
||||
|
||||
@node Signals and Interrupts - Considerations when embedding ECL
|
||||
@subsection Considerations when embedding ECL
|
||||
There are several approaches when handling signals and interrupts in a program that uses ECL. One is to install your own signal handlers. This is perfectly fine, but you should respect the same restrictions as ECL. Namely, you may not execute arbitrary code from those signal handlers, and in particular it will not always be safe to execute Common Lisp code from there.
|
||||
|
||||
If you want to use your own signal handlers then you should set the appropriate options before invoking @code{cl_boot()}, as explained in @code{ecl_set_option}. Note that in this case ECL will not always be able to detect floating point exceptions.
|
||||
If you want to use your own signal handlers then you should set the appropriate options before invoking @coderef{cl_boot}, as explained in @coderef{ecl_set_option}. Note that in this case ECL will not always be able to detect floating point exceptions.
|
||||
|
||||
The other option is to let ECL handle signals itself. This would be safer when the dominant part of the code is Common Lisp, but you may need to protect the code that embeds ECL from being interrupted using either the macros @code{ecl_disable_interrupts} and @code{ecl_enable_interrupts} or the POSIX functions @code{pthread_sigmaks}and @code{sigprocmask}.
|
||||
The other option is to let ECL handle signals itself. This would be safer when the dominant part of the code is Common Lisp, but you may need to protect the code that embeds ECL from being interrupted using either the macros @coderef{ecl_disable_interrupts} and @coderef{ecl_enable_interrupts} or the POSIX functions @code{pthread_sigmaks} and @code{sigprocmask}.
|
||||
|
||||
|
||||
@node Signals and Interrupts - Signals Reference
|
||||
@subsection Signals Reference
|
||||
|
||||
@lspindex mp:with-interrupts
|
||||
@lspindex mp:without-interrupts
|
||||
|
||||
@defmac mp:with-interrupts &body body
|
||||
Execute code with interrupts optionally enabled.
|
||||
@subsubheading Description
|
||||
Executes the given body with all interrupts enabled. Since interrupts are normally enabled, this macro only makes sense if there is an outer @code{mp:without-interrupts} with a corresponding @code{mp:allow-with-interrupts}: interrupts are not enabled if any outer @code{mp:without-interrupts} is not accompanied by @code{mp:allow-with-interrupts}.
|
||||
@defmacx mp:without-interrupts &body body
|
||||
Execute code with interrupts optionally enabled/disabled, @xref{Processes dictionary}.
|
||||
@end defmac
|
||||
|
||||
|
||||
@defmac mp:without-interrupts &body body
|
||||
Execute code without being interrupted.
|
||||
@subsubheading Description
|
||||
Executes the given body with all deferrable interrupts disabled. Deferrable interrupts arriving during execution of the body take effect after the body has been executed.
|
||||
|
||||
Deferrable interrupts include most blockable POSIX signals, and @code{mp:interrupt-process}. Does not interfere with garbage collection, and does not inhibit scheduling of other threads.
|
||||
|
||||
This macro is compatible with the one in SBCL and as such it also defines three other local macros @code{mp:allow-with-interrupts}, @code{mp:with-local-interrupts} and @code{mp:with-restored-interrupts}.
|
||||
|
||||
@code{mp:with-restored-interrupts} executes the body with interrupts enabled if and only if the @code{mp:without-interrupts} was in an environment in which interrupts were allowed.
|
||||
|
||||
@code{mp:allow-with-interrupts} allows the @code{mp:with-interrupts} to take effect during the dynamic scope of its body, unless there is an outer @code{mp:without-interrupts} without a corresponding @code{mp:allow-with-interrupts}.
|
||||
|
||||
@code{mp:with-local-interrupts} executes its body with interrupts enabled provided that there is an @code{mp:allow-with-interrupts} for every @code{mp:without-interrupts} surrounding the current one. @code{mp:with-local-interrupts} is equivalent to:
|
||||
|
||||
@lisp
|
||||
(allow-with-interrupts (with-interrupts ...))
|
||||
@end lisp
|
||||
|
||||
Care must be taken not to let either @code{mp:allow-with-interrupts} or @code{mp:with-local-interrupts} appear in a function that escapes from inside the @code{mp:without-interrupts} in:
|
||||
|
||||
@lisp
|
||||
(without-interrupts
|
||||
;; The body of the lambda would be executed with WITH-INTERRUPTS allowed
|
||||
;; regardless of the interrupt policy in effect when it is called.
|
||||
(lambda () (allow-with-interrupts ...)))
|
||||
|
||||
(without-interrupts
|
||||
;; The body of the lambda would be executed with interrupts enabled
|
||||
;; regardless of the interrupt policy in effect when it is called.
|
||||
(lambda () (with-local-interrupts ...)))
|
||||
@end lisp
|
||||
|
||||
@end defmac
|
||||
|
||||
|
||||
@lspindex ext:unix-signal-received
|
||||
@lspdef ext:unix-signal-received
|
||||
@deftp Condition ext:unix-signal-received
|
||||
Unix signal condition
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@code{condition}, @code{t}
|
||||
|
||||
@subsubheading Methods
|
||||
@lspindex ext:unix-signal-received-code
|
||||
@paragraph Methods
|
||||
@lspdef ext:unix-signal-received-code
|
||||
@defun ext:unix-signal-received-code condition
|
||||
Returns the signal code of @code{condition}
|
||||
Returns the signal code of @var{condition}
|
||||
@end defun
|
||||
@end deftp
|
||||
|
||||
@lspindex ext:get-signal-handler
|
||||
@lspdef ext:get-signal-handler
|
||||
@defun ext:get-signal-handler code
|
||||
Queries the currently active signal handler for @var{code}.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:set-signal-handler
|
||||
@lspdef ext:set-signal-handler
|
||||
@defun ext:set-signal-handler code handler
|
||||
Arranges for the signal @var{code} to be caught in all threads and
|
||||
sets the signal handler for it. The value of @var{handler} modifies
|
||||
|
|
@ -186,14 +145,14 @@ arguments
|
|||
@item @var{handler} is a symbol denoting a condition type
|
||||
A continuable error of the given type will be signaled
|
||||
@item @var{handler} is equal to @var{code}
|
||||
A condition of type @code{ext:unix-signal-received} with the
|
||||
A condition of type @coderef{ext:unix-signal-received} with the
|
||||
corresponding signal code will be signaled
|
||||
@item @var{handler} is @code{nil}
|
||||
The signal will be caught but no handler will be called
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@lspindex ext:catch-signal
|
||||
@lspdef ext:catch-signal
|
||||
@defun ext:catch-signal code flag &key process
|
||||
Changes the action taken on receiving the signal @var{code}.
|
||||
@var{flag} can be one of the following:
|
||||
|
|
@ -203,7 +162,7 @@ Ignore the signal
|
|||
@item @code{:default}
|
||||
Use the default signal handling strategy of the operating system
|
||||
@item @code{t} or @code{:catch}
|
||||
Catch the signal and invoke the signal handler as given by @code{ext:get-signal-handler}
|
||||
Catch the signal and invoke the signal handler as given by @coderef{ext:get-signal-handler}
|
||||
@item @code{:mask}, @code{:unmask}
|
||||
Change the signal mask of either a) the not yet enabled @var{process}
|
||||
or b) the current process, if @var{process} is not supplied
|
||||
|
|
@ -220,7 +179,7 @@ CL-USER> (ext:get-signal-handler ext:+SIGPIPE+)
|
|||
NIL
|
||||
CL-USER> (ext:set-signal-handler ext:+SIGPIPE+
|
||||
#'(lambda ()
|
||||
(format t "SIGPIPE detected in process: ~a~%" process)))
|
||||
(format t "SIGPIPE detected in process: ~a~%" mp:*current-process*)))
|
||||
#<bytecompiled-function 0x25ffca8>
|
||||
@end lisp
|
||||
Passing the SIGPIPE signal to the ECL program with @code{killall -s
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ ecl-devel@common-lisp.net.
|
|||
|
||||
@itemize Copyright
|
||||
@item
|
||||
Daniel Kochmański and Marius Gerbershagen, 2020
|
||||
@item
|
||||
Daniel Kochmański, 2016
|
||||
@item
|
||||
Juan José García-Ripoll, 2006
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@
|
|||
@c --- TAGS --- @
|
||||
|
||||
@macro cind
|
||||
C/C++ identifier
|
||||
{C/C++ identifier}
|
||||
@end macro
|
||||
@macro lind
|
||||
Common Lisp symbol
|
||||
{Common Lisp symbol}
|
||||
@end macro
|
||||
@macro ocl
|
||||
@emph{Only in Common Lisp}
|
||||
|
|
@ -121,3 +121,28 @@ Common Lisp symbol
|
|||
\left\
|
||||
@tab \right\
|
||||
@end macro
|
||||
|
||||
@macro paragraph{title}
|
||||
|
||||
@b{\title\}
|
||||
|
||||
@end macro
|
||||
|
||||
@macro coderef{code}
|
||||
@inlinefmtifelse{html, @code{@ref{\code\}}, @code{\code\}}
|
||||
@end macro
|
||||
|
||||
@macro seealso{node}
|
||||
@paragraph{See also}
|
||||
@coderef{\node\}
|
||||
@end macro
|
||||
|
||||
@macro cppdef{name}
|
||||
@anchor{\name\}
|
||||
@cppindex \name\
|
||||
@end macro
|
||||
|
||||
@macro lspdef{name}
|
||||
@anchor{\name\}
|
||||
@lspindex \name\
|
||||
@end macro
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename ecl.info
|
||||
@settitle ECL User's Guide
|
||||
@settitle ECL Manual
|
||||
@setchapternewpage odd
|
||||
@paragraphindent none
|
||||
@defcodeindex cpp
|
||||
|
|
@ -47,8 +47,6 @@ Copyright @copyright{} 2000, Juan Jose Garcia Ripoll
|
|||
Copyright @copyright{} 2015, Daniel Kochmański
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@c ************************ TOP NODE **************************
|
||||
|
||||
@ifnottex
|
||||
|
|
@ -72,21 +70,22 @@ languages.
|
|||
@menu
|
||||
* Introduction:: What @ecl{} is
|
||||
* User's guide:: Guide for the programmers using ECL
|
||||
* Developer's guide:: Guide for the ECL developers
|
||||
* Standards:: Deviations and clarifications of the standard
|
||||
* Extensions:: ECL-specific features and extensions
|
||||
* Developer's guide:: Guide for the ECL developers
|
||||
* Indexes:: Concepts, functions, variables, types and C/C++
|
||||
|
||||
* Bibliography:: Some interesting books.
|
||||
@c * List of Figures::
|
||||
@c * List of Tables::
|
||||
@end menu
|
||||
|
||||
@contents
|
||||
|
||||
@include introduction/index.txi
|
||||
@include user-guide/index.txi
|
||||
@include developer-guide/index.txi
|
||||
@include standards/index.txi
|
||||
@include extensions/index.txi
|
||||
@include developer-guide/index.txi
|
||||
@include indexes/index.txi
|
||||
|
||||
@node Bibliography
|
||||
|
|
|
|||
|
|
@ -39,7 +39,10 @@ When the elements of an array are declared to have some precise type, such as a
|
|||
@item (unsigned-byte 64) @tab uint64_t @tab 64 bits
|
||||
@item single-float or short-float @tab float @tab 32-bits IEEE float
|
||||
@item double-float @tab double @tab 64-bits IEEE float
|
||||
@c @item long-float @tab long double @tab Between 96 and 128 bits. !Not implemented
|
||||
@item long-float @tab long double @tab Between 96 and 128 bits
|
||||
@item (complex single-float) @tab float _Complex @tab 64 bits
|
||||
@item (complex double-float) @tab double _Complex @tab 128 bits
|
||||
@item (complex long-float) @tab long double _Complex @tab Between 192 and 256 bits
|
||||
@item t @tab cl_object @tab Size of a pointer.
|
||||
@end multitable
|
||||
|
||||
|
|
@ -52,18 +55,15 @@ Let us remark that some of these specialized types might not exist in your platf
|
|||
C types, limits and enumerations
|
||||
|
||||
@subsubheading Constants and types
|
||||
@cppindex ECL_ARRAY_RANK_LIMIT
|
||||
@cppindex ECL_ARRAY_DIMENSION_LIMIT
|
||||
@cppindex ECL_ARRAY_TOTAL_LIMIT
|
||||
@cppindex cl_elttype
|
||||
@cppdef ECL_ARRAY_RANK_LIMIT
|
||||
@cppdef ECL_ARRAY_DIMENSION_LIMIT
|
||||
@cppdef ECL_ARRAY_TOTAL_LIMIT
|
||||
@cppdef cl_elttype
|
||||
@defvr Constant ECL_ARRAY_RANK_LIMIT
|
||||
@end defvr
|
||||
@defvr Constant ECL_ARRAY_DIMENSION_LIMIT
|
||||
@end defvr
|
||||
@defvr Constant ECL_ARRAY_TOTAL_LIMIT
|
||||
@defvrx Constant ECL_ARRAY_DIMENSION_LIMIT
|
||||
@defvrx Constant ECL_ARRAY_TOTAL_LIMIT
|
||||
@end defvr
|
||||
@deftp enum cl_elttype @{ecl_aet_object, ...@}
|
||||
@end deftp
|
||||
|
||||
@multitable @columnfractions .25 .25 .25 .25
|
||||
@headitem Lisp or C type @tab Enumeration value @tab Lisp or C type @tab Enumeration value
|
||||
|
|
@ -79,50 +79,49 @@ C types, limits and enumerations
|
|||
@item (complex single-float) @tab ecl_aet_csf @tab (complex double-float) @tab ecl_aet_cdf
|
||||
@end multitable
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This list contains the constants that limit the rank of an array
|
||||
(@code{ECL_ARRAY_RANK_LIMIT}), the maximum size of each dimension
|
||||
(@code{ECL_ARRAY_DIMENSION_LIMIT}) and the maximum number of elements
|
||||
in an array (@code{ECL_ARRAY_TOTAL_LIMIT}).
|
||||
(@coderef{ECL_ARRAY_RANK_LIMIT}), the maximum size of each dimension
|
||||
(@coderef{ECL_ARRAY_DIMENSION_LIMIT}) and the maximum number of elements
|
||||
in an array (@coderef{ECL_ARRAY_TOTAL_LIMIT}).
|
||||
|
||||
ECL uses also internally a set of constants to describe the different
|
||||
specialized arrays. The constants form up the enumeration type
|
||||
cl_elttype. They are listed in the table above, which associates
|
||||
enumeration values with the corresponding Common Lisp element type.
|
||||
@coderef{cl_elttype}. They are listed in the table above, which
|
||||
associates enumeration values with the corresponding Common Lisp element
|
||||
type.
|
||||
@end deftp
|
||||
|
||||
@subsubsection ecl_aet_to_symbol, ecl_symbol_to_aet
|
||||
To and from element types
|
||||
|
||||
@subsubheading Functions
|
||||
@cppindex ecl_aet_to_symbol
|
||||
@cppindex ecl_symbol_to_aet
|
||||
@deftypefun cl_object ecl_aet_to_symbol (cl_elttype @var{param})
|
||||
@end deftypefun
|
||||
@deftypefun cl_elttype ecl_symbol_to_aet (cl_object @var{type})
|
||||
@end deftypefun
|
||||
@cppdef ecl_aet_to_symbol
|
||||
@cppdef ecl_symbol_to_aet
|
||||
@deftypefun cl_object ecl_aet_to_symbol (cl_elttype param)
|
||||
@deftypefunx cl_elttype ecl_symbol_to_aet (cl_object type)
|
||||
|
||||
@subsubheading Description
|
||||
@code{ecl_aet_to_symbol} returns the Lisp type associated to the elements of that specialized array class. @code{ecl_symbol_to_aet} does the converse, computing the C constant that is associated to a Lisp element type.
|
||||
@paragraph Description
|
||||
@coderef{ecl_aet_to_symbol} returns the Lisp type associated to the elements of that specialized array class. @coderef{ecl_symbol_to_aet} does the converse, computing the C constant that is associated to a Lisp element type.
|
||||
|
||||
The functions may signal an error if any of the arguments is an invalid C or Lisp type.
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection Constructors
|
||||
Creating array and vectors
|
||||
|
||||
@subsubheading Functions
|
||||
@cppindex ecl_alloc_simple_vector
|
||||
@cppindex si_make_vector
|
||||
@cppindex si_make_array
|
||||
@cppdef ecl_alloc_simple_vector
|
||||
@cppdef si_make_vector
|
||||
@cppdef si_make_array
|
||||
@deftypefun cl_object ecl_alloc_simple_vector (cl_elttype element_type, cl_index length);
|
||||
@end deftypefun
|
||||
@deftypefun cl_object si_make_vector (cl_object element_type, cl_object length, cl_object adjustablep, cl_object fill_pointerp, cl_object displaced_to, cl_object displacement);
|
||||
@end deftypefun
|
||||
@deftypefun cl_object si_make_array (cl_object element_type, cl_object dimensions, cl_object adjustablep, cl_object fill_pointerp, cl_object displaced_to, cl_object displacement);
|
||||
@end deftypefun
|
||||
@subsubheading Description
|
||||
The function @code{ecl_alloc_simple_vector} is the simplest constructor, creating a simple vector (i.e. non-adjustable and without a fill pointer), of the given size, preallocating the memory for the array data. The first argument, @emph{element_type}, is a C constant that represents a valid array element type (See cl_elttype).
|
||||
@deftypefunx cl_object si_make_vector (cl_object element_type, cl_object length, cl_object adjustablep, cl_object fill_pointerp, cl_object displaced_to, cl_object displacement);
|
||||
@deftypefunx cl_object si_make_array (cl_object element_type, cl_object dimensions, cl_object adjustablep, cl_object fill_pointerp, cl_object displaced_to, cl_object displacement);
|
||||
|
||||
The function @code{si_make_vector} does the same job but allows creating an array with fill pointer, which is adjustable or displaced to another array.
|
||||
@paragraph Description
|
||||
The function @coderef{ecl_alloc_simple_vector} is the simplest constructor, creating a simple vector (i.e. non-adjustable and without a fill pointer), of the given size, preallocating the memory for the array data. The first argument, @emph{element_type}, is a C constant that represents a valid array element type (See @coderef{cl_elttype}).
|
||||
|
||||
The function @coderef{si_make_vector} does the same job but allows creating an array with fill pointer, which is adjustable or displaced to another array.
|
||||
@itemize
|
||||
@item element_type is now a Common Lisp type descriptor, which is a symbol or list denoting a valid element type
|
||||
@item dimension is a non-negative fixnum with the vector size.
|
||||
|
|
@ -131,9 +130,9 @@ The function @code{si_make_vector} does the same job but allows creating an arra
|
|||
@item displacement is either ECL_NIL or a non-negative value with the array displacement.
|
||||
@end itemize
|
||||
|
||||
Finally, the function @code{si_make_array} does a similar job to @code{si_make_vector} but its second argument, @emph{dimension}, can be a list of dimensions, to create a multidimensional array.
|
||||
@subsubheading Examples
|
||||
Finally, the function @coderef{si_make_array} does a similar job to @coderef{si_make_vector} but its second argument, @emph{dimension}, can be a list of dimensions, to create a multidimensional array.
|
||||
|
||||
@paragraph Examples
|
||||
Create one-dimensional @code{base-string} with room for 11 characters:
|
||||
|
||||
@example
|
||||
|
|
@ -170,56 +169,51 @@ cl_object a = si_make_array(dims, type, ECL_NIL, /* adjustable */
|
|||
ECL_NIL /* displaced_to */,
|
||||
ECL_NIL /* displacement */);
|
||||
@end example
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection Accessors
|
||||
@cppindex ecl_aref
|
||||
@cppindex ecl_aset
|
||||
@cppindex ecl_aref1
|
||||
@cppindex ecl_aset1
|
||||
@cppdef ecl_aref
|
||||
@cppdef ecl_aset
|
||||
@cppdef ecl_aref1
|
||||
@cppdef ecl_aset1
|
||||
Reading and writing array elements
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_object ecl_aref (cl_object array, cl_index row_major_index);
|
||||
@deftypefunx cl_object ecl_aset (cl_object array, cl_index row_major_index, cl_object new_value);
|
||||
@deftypefunx cl_object ecl_aref1 (cl_object vector, cl_index row_major_index);
|
||||
@deftypefunx cl_object ecl_aset1 (cl_object vector, cl_index row_major_index, cl_object new_value);
|
||||
|
||||
@deftypefun cl_object ecl_aref (cl_object @var{array}, cl_index @var{row_major_index});
|
||||
@paragraph Description
|
||||
@coderef{ecl_aref} accesses an array using the supplied @emph{row_major_index}, checking the array bounds and returning a Lisp object for the value at that position. @coderef{ecl_aset} does the converse, storing a Lisp value at the given @emph{row_major_index}.
|
||||
|
||||
The first argument to @coderef{ecl_aref} or @coderef{ecl_aset} is an array of any number of dimensions. For an array of rank @code{N} and dimensions @code{d1, d2 ...} up to @code{dN}, the row major index associated to the indices (@code{i1,i2,...iN}) is computed using the formula @code{i1+d1*(i2+d3*(i3+...))}.
|
||||
|
||||
@coderef{ecl_aref1} and @coderef{ecl_aset1} are specialized versions that only work with one-dimensional arrays or vectors. They verify that the first argument is indeed a vector.
|
||||
|
||||
All functions above check that the index does not exceed the array bounds, that the values match the array element type and that the argument is an array (or a vector). If these conditions are not met, a @code{type-error} is signaled.
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_aset (cl_object @var{array}, cl_index @var{row_major_index}, cl_object @var{new_value});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_aref1 (cl_object @var{vector}, cl_index @var{row_major_index});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_aset1 (cl_object @var{vector}, cl_index @var{row_major_index}, cl_object @var{new_value});
|
||||
@end deftypefun
|
||||
|
||||
@subsubheading Description
|
||||
@code{ecl_aref} accesses an array using the supplied @emph{row_major_index}, checking the array bounds and returning a Lisp object for the value at that position. @code{ecl_aset} does the converse, storing a Lisp value at the given @emph{row_major_index}.
|
||||
|
||||
The first argument to @code{ecl_aref} or @code{ecl_aset} is an array of any number of dimensions. For an array of rank @code{N} and dimensions @code{d1, d2 ...} up to @code{dN}, the row major index associated to the indices (@code{i1,i2,...iN}) is computed using the formula @code{i1+d1*(i2+d3*(i3+...))}.
|
||||
|
||||
@code{ecl_aref1} and @code{ecl_aset1} are specialized versions that only work with one-dimensional arrays or vectors. They verify that the first argument is indeed a vector.
|
||||
|
||||
All functions above check that the index does not exceed the array bounds, that the values match the array element type and that the argument is an array (or a vector). If these conditions are not met, a type error is signaled.
|
||||
|
||||
@subsubsection Array properties
|
||||
@cppindex ecl_array_elttype
|
||||
@cppindex ecl_array_rank
|
||||
@cppindex ecl_array_dimension
|
||||
@cppdef ecl_array_elttype
|
||||
@cppdef ecl_array_rank
|
||||
@cppdef ecl_array_dimension
|
||||
Array size, fill pointer, etc.
|
||||
|
||||
@subsubheading Synopsis
|
||||
@deftypefun cl_elttype ecl_array_elttype (cl_object @var{array});
|
||||
@end deftypefun
|
||||
@deftypefun cl_index ecl_array_rank (cl_object @var{array});
|
||||
@end deftypefun
|
||||
@deftypefun cl_index ecl_array_dimension (cl_object @var{array}, cl_index @var{index});
|
||||
@end deftypefun
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_elttype ecl_array_elttype (cl_object array);
|
||||
@deftypefunx cl_index ecl_array_rank (cl_object array);
|
||||
@deftypefunx cl_index ecl_array_dimension (cl_object array, cl_index index);
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
These functions query various properties of the arrays. Some of them belong to the list of functions in the Common Lisp package, without any need for specialized versions. More precisely
|
||||
|
||||
@itemize
|
||||
@item @code{ecl_array_elttype} returns the array element type, with the encoding found in the enumeration cl_elttype.
|
||||
@item @code{ecl_array_rank} returns the number of dimensions of the vector or array.
|
||||
@item @code{ecl_array_dimension} queries the dimension of an array, where index is a non-negative integer between 0 and @code{ecl_array_dimension(array)-1}.
|
||||
@item @coderef{ecl_array_elttype} returns the array element type, with the encoding found in the enumeration cl_elttype.
|
||||
@item @coderef{ecl_array_rank} returns the number of dimensions of the vector or array.
|
||||
@item @coderef{ecl_array_dimension} queries the dimension of an array, where index is a non-negative integer between 0 and @code{ecl_array_dimension(array)-1}.
|
||||
@end itemize
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection ANSI Dictionary
|
||||
Common Lisp and C equivalence
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ ECL is fully ANSI Common-Lisp compliant in all aspects of the character data typ
|
|||
|
||||
@node Characters - Unicode vs. POSIX locale
|
||||
@subsection Unicode vs. POSIX locale
|
||||
@cfindex --enable-unicode [32|16|no]
|
||||
|
||||
There are two ways of building ECL: with C or with Unicode character codes. These build modes are accessed using the @code{--disable-unicode} and @code{--enable-unicode} configuration options, the last one being the default.
|
||||
|
||||
When using C characters we are actually relying on the char type of the C language, using the C library functions for tasks such as character conversions, comparison, etc. In this case characters are typically 8 bit wide and the character order and collation are determines by the current POSIX or C locale. This is not very accurate, leaves out many languages and character encodings but it is sufficient for small applications that do not need multilingual support.
|
||||
|
|
@ -62,88 +64,83 @@ Internally, ECL represents the @code{#\Newline} character by a single code. Howe
|
|||
@subsection C Reference
|
||||
|
||||
@subsubsection C types
|
||||
@cppindex ecl_base_char
|
||||
@cppindex ecl_character
|
||||
@cppdef ecl_base_char
|
||||
@cppdef ecl_character
|
||||
C character types
|
||||
@subsubheading Type names
|
||||
|
||||
@paragraph Type names
|
||||
@multitable {aaaaaaaaaaaaa} {aaaaaaaaa}
|
||||
@item ecl_character @tab character
|
||||
@item ecl_base_char @tab base-char
|
||||
@end multitable
|
||||
@subsubheading Description
|
||||
|
||||
ECL defines two C types to hold its characters: @code{ecl_base_char} and @code{ecl_character}.
|
||||
@paragraph Description
|
||||
ECL defines two C types to hold its characters: @coderef{ecl_base_char} and @coderef{ecl_character}.
|
||||
|
||||
@itemize
|
||||
@item When ECL is built without Unicode, they both coincide and typically match @code{unsigned char}, to cover the 256 codes that are needed.
|
||||
@item When ECL is built with Unicode, the two types are no longer equivalent, with @code{ecl_character} being larger.
|
||||
@item When ECL is built with Unicode, the two types are no longer equivalent, with @coderef{ecl_character} being larger.
|
||||
@end itemize
|
||||
|
||||
For your code to be portable and future proof, use both types to really express what you intend to do.
|
||||
|
||||
@subsubsection Constructors
|
||||
@cppindex ECL_CODE_CHAR
|
||||
@cppindex ECL_CHAR_CODE
|
||||
@cppindex ecl_char_code
|
||||
@cppindex ecl_base_char_code
|
||||
@cppdef ECL_CODE_CHAR
|
||||
@cppdef ECL_CHAR_CODE
|
||||
@cppdef ecl_char_code
|
||||
@cppdef ecl_base_char_code
|
||||
Creating and extracting characters from Lisp objects
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_object ECL_CODE_CHAR (ecl_character @var{code});
|
||||
@deftypefn Macro cl_object ECL_CODE_CHAR (ecl_character code);
|
||||
@deftypefnx Macro ecl_character ECL_CHAR_CODE (cl_object o);
|
||||
@end deftypefn
|
||||
@deftypefun ecl_character ecl_char_code (cl_object o);
|
||||
@deftypefunx ecl_base_char ecl_base_char_code (cl_object o);
|
||||
|
||||
@paragraph Description
|
||||
These functions and macros convert back and forth from C character types to Lisp. The macros @coderef{ECL_CHAR_CODE} and @coderef{ECL_CODE_CHAR} perform this coercion without checking the arguments. The functions @coderef{ecl_char_code} and @coderef{ecl_base_char_code}, on the other hand, verify that the argument has the right type and signal an error otherwise.
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ECL_CHAR_CODE (cl_object @var{o});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ecl_char_code (cl_object @var{o});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_base_char ecl_base_char_code (cl_object @var{o});
|
||||
@end deftypefun
|
||||
@subsubheading Description
|
||||
These functions and macros convert back and forth from C character types to Lisp. The macros @code{ECL_CHAR_CODE} and @code{ECL_CODE_CHAR} perform this coercion without checking the arguments. The functions @code{ecl_char_code} and @code{ecl_base_char_code}, on the other hand, verify that the argument has the right type and signal an error otherwise.
|
||||
|
||||
@subsubsection Predicates
|
||||
@cppindex ecl_base_char_p
|
||||
@cppindex ecl_alpha_char_p
|
||||
@cppindex ecl_alphanumeric_p
|
||||
@cppindex ecl_graphic_char_p
|
||||
@cppindex ecl_digit_p
|
||||
@cppindex ecl_standard_char_p
|
||||
@cppdef ecl_base_char_p
|
||||
@cppdef ecl_alpha_char_p
|
||||
@cppdef ecl_alphanumeric_p
|
||||
@cppdef ecl_graphic_char_p
|
||||
@cppdef ecl_digit_p
|
||||
@cppdef ecl_standard_char_p
|
||||
C predicates for Lisp characters
|
||||
@subsubheading Functions
|
||||
|
||||
@deftypefun bool ecl_base_char_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_alpha_char_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_alphanumericp (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_graphic_char_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_digitp (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_standard_char_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@subsubheading Description
|
||||
@subsubheading Functions
|
||||
@deftypefun bool ecl_base_char_p (ecl_character c);
|
||||
@deftypefunx bool ecl_alpha_char_p (ecl_character c);
|
||||
@deftypefunx bool ecl_alphanumericp (ecl_character c);
|
||||
@deftypefunx bool ecl_graphic_char_p (ecl_character c);
|
||||
@deftypefunx bool ecl_digitp (ecl_character c);
|
||||
@deftypefunx bool ecl_standard_char_p (ecl_character c);
|
||||
|
||||
@paragraph Description
|
||||
These functions are equivalent to their Lisp equivalents but return C booleans.
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection Character case
|
||||
@cppindex ecl_upper_case_p
|
||||
@cppindex ecl_lower_case_p
|
||||
@cppindex ecl_both_case_p
|
||||
@cppindex ecl_char_downcase
|
||||
@cppindex ecl_char_upcase
|
||||
@cppdef ecl_upper_case_p
|
||||
@cppdef ecl_lower_case_p
|
||||
@cppdef ecl_both_case_p
|
||||
@cppdef ecl_char_downcase
|
||||
@cppdef ecl_char_upcase
|
||||
C functions related to the character case
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun bool ecl_upper_case_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_lower_case_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun bool ecl_both_case_p (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ecl_char_downcase (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ecl_char_upcase (ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@subsubheading Description
|
||||
@deftypefun bool ecl_upper_case_p (ecl_character c);
|
||||
@deftypefunx bool ecl_lower_case_p (ecl_character c);
|
||||
@deftypefunx bool ecl_both_case_p (ecl_character c);
|
||||
@deftypefunx ecl_character ecl_char_downcase (ecl_character c);
|
||||
@deftypefunx ecl_character ecl_char_upcase (ecl_character c);
|
||||
|
||||
@paragraph Description
|
||||
These functions check or change the case of a character. Note that in a Unicode context, the output of these functions might not be accurate (for instance when the uppercase character has two or more codepoints).
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection ANSI Dictionary
|
||||
Common Lisp and C equivalence
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
@section Conditions
|
||||
|
||||
@subsection C Reference
|
||||
@cppindex ECL_HANDLER_CASE
|
||||
@cppindex ECL_RESTART_CASE
|
||||
@cppdef ECL_HANDLER_CASE
|
||||
|
||||
@deffn Macro ECL_HANDLER_CASE
|
||||
C macro for @clhs{m_hand_1.htm,handler-case}
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_HANDLER_CASE_BEGIN(env,names) {
|
||||
|
|
@ -18,12 +17,12 @@ ECL_HANDLER_CASE_BEGIN(env,names) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_HANDLER_CASE_BEGIN} runs a block of C code with a set of error handlers bound to the names given by the list @var{names}. The subsequent @code{ECL_HANDLER_CASE} statements specify what to do when the @var{n}-th type of conditions is found, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
@paragraph Description
|
||||
@code{ECL_HANDLER_CASE_BEGIN} runs a block of C code with a set of error handlers bound to the names given by the list @var{names}. The subsequent @coderef{ECL_HANDLER_CASE} statements specify what to do when the @var{n}-th type of conditions is found, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
|
||||
When a condition is signaled, ECL scans the list of signal handlers, looking for matches based on @code{typep}. If the match with the highest precedence belongs to the list @var{names}, ECL will perform a non-local transfer of control to the appropriate @code{ECL_HANDLER_CASE}, passing it a @var{condition} object as unique argument.
|
||||
When a condition is signaled, ECL scans the list of signal handlers, looking for matches based on @code{typep}. If the match with the highest precedence belongs to the list @var{names}, ECL will perform a non-local transfer of control to the appropriate @coderef{ECL_HANDLER_CASE}, passing it a @var{condition} object as unique argument.
|
||||
|
||||
The following example shows how to establish a handler for @code{ERROR} conditions. Note how the first value to @code{ECL_HANDLER_CASE} matches the position of the condition name in the list:
|
||||
The following example shows how to establish a handler for @code{error} conditions. Note how the first value to @coderef{ECL_HANDLER_CASE} matches the position of the condition name in the list:
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -42,9 +41,10 @@ ECL_HANDLER_CASE_BEGIN(the_env, ecl_list1(error)) {
|
|||
@end deffn
|
||||
|
||||
|
||||
@cppdef ECL_RESTART_CASE
|
||||
@deffn Macro ECL_RESTART_CASE
|
||||
C macro for @clhs{m_rst_ca.htm,restart-case}
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_RESTART_CASE_BEGIN(env,names) {
|
||||
|
|
@ -55,12 +55,12 @@ ECL_RESTART_CASE_BEGIN(env,names) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_RESTART_CASE_BEGIN} runs a block of C code with a set of restarts bound to the names given by the list @var{names}. The subsequent @code{ECL_RESTART_CASE} statements specify what to do when the @var{n}-th restart is invoked, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
@paragraph Description
|
||||
@code{ECL_RESTART_CASE_BEGIN} runs a block of C code with a set of restarts bound to the names given by the list @var{names}. The subsequent @coderef{ECL_RESTART_CASE} statements specify what to do when the @var{n}-th restart is invoked, where @var{n} is an integer denoting the position of the name in the list @var{names}.
|
||||
|
||||
When the restart is invoked, it can receive any number of arguments, which are grouped in a list and stored in a new variable created with the name @var{args}.
|
||||
|
||||
The following example shows how to establish an @var{ABORT} and a @var{USE-VALUE} restart. Note how the first value to @var{ECL_RESTART_CASE} matches the position of the restart name in the list:
|
||||
The following example shows how to establish an @var{abort} and a @var{use-value} restart. Note how the first value to @coderef{ECL_RESTART_CASE} matches the position of the restart name in the list:
|
||||
|
||||
@example
|
||||
@verbatim
|
||||
|
|
|
|||
|
|
@ -4,34 +4,34 @@
|
|||
@subsection C Reference
|
||||
|
||||
@subsubsection Accessors
|
||||
@cppindex ECL_CONS_CAR
|
||||
@cppindex ECL_CONS_CDR
|
||||
@cppindex _ecl_car
|
||||
@cppindex _ecl_cdr
|
||||
@cppdef ECL_CONS_CAR
|
||||
@cppdef ECL_CONS_CDR
|
||||
@cppdef ECL_RPLACA
|
||||
@cppdef ECL_RPLACD
|
||||
@cppdef _ecl_car
|
||||
@cppdef _ecl_cdr
|
||||
@cppdef _ecl_caar
|
||||
@cppdef _ecl_cadr
|
||||
Accessing the elements of conses
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_object ECL_CONS_CAR (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ECL_CONS_CDR (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ECL_RPLACA (cl_object @var{o}, cl_object @var{v})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ECL_RPLACD (cl_object @var{o}, cl_object @var{v})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object _ecl_car (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object _ecl_cdr (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object _ecl_caar (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object _ecl_cadr (cl_object @var{o})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ECL_CONS_CAR (cl_object o)
|
||||
@deftypefunx cl_object ECL_CONS_CDR (cl_object o)
|
||||
@deftypefunx cl_object ECL_RPLACA (cl_object o, cl_object v)
|
||||
@deftypefunx cl_object ECL_RPLACD (cl_object o, cl_object v)
|
||||
@deftypefunx cl_object _ecl_car (cl_object o)
|
||||
@deftypefunx cl_object _ecl_cdr (cl_object o)
|
||||
@deftypefunx cl_object _ecl_caar (cl_object o)
|
||||
@deftypefunx cl_object _ecl_cadr (cl_object o)
|
||||
...
|
||||
@subsubheading Description
|
||||
|
||||
@paragraph Description
|
||||
These functions access the elements of objects of type cons
|
||||
(@code{ECL_CONS_CAR}, @code{ECL_CONS_CDR}, @code{ECL_RPLACA} and
|
||||
@code{ECL_RPLACD}) or type list (@code{_ecl_car}, @code{_ecl_cdr},
|
||||
@code{_ecl_caar}, ...). They don't check the type of their arguments.
|
||||
(@coderef{ECL_CONS_CAR}, @coderef{ECL_CONS_CDR}, @coderef{ECL_RPLACA}
|
||||
and @coderef{ECL_RPLACD}) or type list (@coderef{_ecl_car},
|
||||
@coderef{_ecl_cdr}, @coderef{_ecl_caar}, ...). They don't check the type
|
||||
of their arguments.
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection ANSI Dictionary
|
||||
Common Lisp and C equivalence
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ the last binding as a visible one when the byte compiler was used.
|
|||
@node Minimal compilation
|
||||
@subsection Minimal compilation
|
||||
@cindex Bytecodes eager compilation
|
||||
@lspindex si::make-lambda
|
||||
@lspdef si::make-lambda
|
||||
Former versions of ECL, as well as many other lisps, used linked lists
|
||||
to represent code. Executing code thus meant traversing these lists and
|
||||
performing code transformations, such as macro expansion, every time
|
||||
|
|
@ -58,11 +58,12 @@ object that can be invoked. For instance,
|
|||
3
|
||||
@end lisp
|
||||
|
||||
ECL can only execute bytecodes. When a list is passed to EVAL it must be
|
||||
first compiled to bytecodes and, if the process succeeds, the resulting
|
||||
bytecodes are passed to the interpreter. Similarly, every time a
|
||||
function object is created, such as in DEFUN or DEFMACRO, the compiler
|
||||
processes the lambda form to produce a suitable bytecodes object.
|
||||
ECL can only execute bytecodes. When a list is passed to @code{eval} it
|
||||
must be first compiled to bytecodes and, if the process succeeds, the
|
||||
resulting bytecodes are passed to the interpreter. Similarly, every time
|
||||
a function object is created, such as in @code{defun} or
|
||||
@code{defmacro}, the compiler processes the lambda form to produce a
|
||||
suitable bytecodes object.
|
||||
|
||||
@cindex Eager compilation implications
|
||||
|
||||
|
|
@ -95,13 +96,13 @@ bytecodes or they have been compiled to machine code using a lisp to C
|
|||
translator and a C compiler. To the first category belong function
|
||||
loaded from lisp source files or entered at the toplevel. To the second
|
||||
category belong all functions in the ECL core environment and functions
|
||||
in files processed by compile or compile-file.
|
||||
in files processed by @code{compile} or @code{compile-file}.
|
||||
|
||||
The output of (symbol-function fun) is one of the following:
|
||||
The output of @code{(symbol-function fun)} is one of the following:
|
||||
@itemize
|
||||
@item a function object denoting the definition of the function fun,
|
||||
@item a list of the form (macro . function-object) when fun denotes a macro,
|
||||
@item or simply 'special, when fun denotes a special form, such as block, if, etc.
|
||||
@item a function object denoting the definition of the function @code{fun},
|
||||
@item a list of the form @code{(macro . function-object)} when @code{fun} denotes a macro,
|
||||
@item or simply @code{'special}, when @code{fun} denotes a special form, such as @code{block}, @code{if}, etc.
|
||||
@end itemize
|
||||
|
||||
@cindex @code{disassemble} and @code{compile} on defined functions
|
||||
|
|
@ -113,30 +114,30 @@ translated into bytecodes. Therefore, if you don't need to use compile
|
|||
and disassemble on defined functions, you should issue @code{(setq
|
||||
si:*keep-definitions* nil)} at the beginning of your session.
|
||||
|
||||
@lspindex si:*keep-definitions*
|
||||
@lspdef si:*keep-definitions*
|
||||
@defvr Variable {si:*keep-definitions*}
|
||||
If set to @code{T} ECL will preserve the compiled function source code
|
||||
If set to @code{t} ECL will preserve the compiled function source code
|
||||
for disassembly and recompilation.
|
||||
@end defvr
|
||||
|
||||
@cindex Common Lisp functions limits
|
||||
@lspindex call-arguments-limit
|
||||
@lspindex lambda-parameters-limit
|
||||
@lspindex multiple-values-limit
|
||||
@lspindex lambda-list-keywords
|
||||
@lspdef call-arguments-limit
|
||||
@lspdef lambda-parameters-limit
|
||||
@lspdef multiple-values-limit
|
||||
@lspdef lambda-list-keywords
|
||||
|
||||
In @ref{tab:fun-const} we list all Common Lisp values related to the limits of functions.
|
||||
@float Table,tab:fun-const
|
||||
@caption{Function related constants}
|
||||
@multitable @columnfractions 0.3 0.7
|
||||
@item call-arguments-limit
|
||||
@tab 65536
|
||||
@tab @code{65536}
|
||||
|
||||
@item lambda-parameters-limit
|
||||
@tab @code{call-arguments-limit}
|
||||
|
||||
@item multiple-values-limit
|
||||
@tab 64
|
||||
@tab @code{64}
|
||||
|
||||
@item lambda-list-keywords
|
||||
@tab @code{(&optional &rest &key &allow-other-keys &aux &whole &environment &body)}
|
||||
|
|
@ -154,7 +155,7 @@ ECL is implemented using either a C or a C++ compiler. This is not a limiting fa
|
|||
|
||||
The previous conventions set some burden on the C programmer that calls ECL, for she must know the type of function that is being called and supply the right number of arguments. This burden disappears for Common Lisp programmers, though.
|
||||
|
||||
As an example let us assume that the user wants to invoke two functions which are part of the ANSI @bibcite{ANSI} standard and thus are exported with a C name. The first example is cl_cos, which takes just one argument and has a signature @code{cl_object cl_cos(cl_object)}.
|
||||
As an example let us assume that the user wants to invoke two functions which are part of the ANSI @bibcite{ANSI} standard and thus are exported with a C name. The first example is @code{cl_cos}, which takes just one argument and has a signature @code{cl_object cl_cos(cl_object)}.
|
||||
|
||||
@example
|
||||
#include <math.h>
|
||||
|
|
@ -186,83 +187,81 @@ printf("\n1 + 1 is %d\n", ecl_fixnum(two));
|
|||
printf("\n1 + 1 + 1 is %d\n", ecl_fixnum(three));
|
||||
@end example
|
||||
|
||||
Another restriction of C and C++ is that functions can only take a limited number of arguments. In order to cope with this problem, ECL uses an internal stack to pass any argument above a hardcoded limit, @code{ECL_C_CALL_ARGUMENTS_LIMIT}, which is as of this writing 63. The use of this stack is transparently handled by the Common Lisp functions, such as apply, funcall and their C equivalents, and also by a set of macros, @code{cl_va_arg}, which can be used for coding functions that take an arbitrary name of arguments.
|
||||
Another restriction of C and C++ is that functions can only take a limited number of arguments. In order to cope with this problem, ECL uses an internal stack to pass any argument above a hardcoded limit, @code{ECL_C_CALL_ARGUMENTS_LIMIT}, which is as of this writing 63. The use of this stack is transparently handled by the Common Lisp functions, such as @code{apply}, @code{funcall} and their C equivalents, and also by a set of macros, @code{cl_va_arg}, which can be used for coding functions that take an arbitrary name of arguments.
|
||||
|
||||
|
||||
@node C Reference
|
||||
@subsection C Reference
|
||||
@cppindex ecl_bds_bind
|
||||
@cppindex ecl_bds_push
|
||||
@defun ecl_bds_bind (cl_env_ptr @var{cl_env}, cl_object @var{var}, cl_object @var{value});
|
||||
@end defun
|
||||
@defun ecl_bds_push (cl_env_ptr @var{cl_env}, cl_object @var{var});
|
||||
@cppdef ecl_bds_bind
|
||||
@cppdef ecl_bds_push
|
||||
@deftypefun void ecl_bds_bind (cl_env_ptr cl_env, cl_object var, cl_object value);
|
||||
@deftypefunx void ecl_bds_push (cl_env_ptr cl_env, cl_object var);
|
||||
Bind a special variable
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Establishes a variable binding for the symbol @var{var} in the Common Lisp environment @var{env}, assigning it @var{value}.
|
||||
|
||||
This macro or function is the equivalent of @clhs{s_let_l.htm,LET*} and @clhs{s_let_l.htm,LET}.
|
||||
This macro or function is the equivalent of @clhs{s_let_l.htm,let*} and @clhs{s_let_l.htm,let}.
|
||||
|
||||
@code{ecl_bds_push} does a similar thing, but reuses the old value of the same variable. It is thus the equivalent of @code{(LET ((VAR VAR)) ...)}
|
||||
@coderef{ecl_bds_push} does a similar thing, but reuses the old value of the same variable. It is thus the equivalent of @code{(let ((var var)) ...)}
|
||||
|
||||
Every variable binding must undone when no longer needed. It is best practice to match each call to @code{ecl_bds_bind} by another call to @code{ecl_bds_unwind} in the same function.
|
||||
@end defun
|
||||
Every variable binding must undone when no longer needed. It is best practice to match each call to @coderef{ecl_bds_bind} by another call to @coderef{ecl_bds_unwind1} in the same function.
|
||||
@end deftypefun
|
||||
|
||||
@cppindex ecl_bds_unwind1
|
||||
@cppindex ecl_bds_unwind_n
|
||||
@defun ecl_bds_unwind1 (cl_env_ptr @var{cl_env});
|
||||
@end defun
|
||||
@defun ecl_bds_unwind_n (cl_env_ptr @var{cl_env}, int @var{n});
|
||||
@cppdef ecl_bds_unwind1
|
||||
@cppdef ecl_bds_unwind_n
|
||||
@deftypefun void ecl_bds_unwind1 (cl_env_ptr cl_env);
|
||||
@deftypefunx void ecl_bds_unwind_n (cl_env_ptr cl_env, int n);
|
||||
Undo one variable binding
|
||||
|
||||
@subsubheading Description
|
||||
@code{ecl_bds_unwind1} undoes the outermost variable binding, restoring the original value of the symbol in the process.
|
||||
@paragraph Description
|
||||
@coderef{ecl_bds_unwind1} undoes the outermost variable binding, restoring the original value of the symbol in the process.
|
||||
|
||||
@code{ecl_bds_unwind_n} does the same, but for the @var{n} last variables.
|
||||
@coderef{ecl_bds_unwind_n} does the same, but for the @var{n} last variables.
|
||||
|
||||
Every variable binding must undone when no longer needed. It is best practice to match each call to @code{ecl_bds_bind} by another call to @code{ecl_bds_unwind} in the same function.
|
||||
@end defun
|
||||
Every variable binding must undone when no longer needed. It is best practice to match each call to @coderef{ecl_bds_bind} by another call to @coderef{ecl_bds_unwind1} in the same function.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_setq
|
||||
@deffn Macro ecl_setq (cl_env_ptr @var{cl_env}, cl_object @var{var}, cl_object @var{value});
|
||||
@cppdef ecl_setq
|
||||
@deftypefun cl_object ecl_setq (cl_env_ptr cl_env, cl_object var, cl_object value);
|
||||
C equivalent of setq
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Assigns @var{value} to the special variable denoted by the symbol @var{var}, in the Common Lisp environment @var{cl_env}.
|
||||
|
||||
This function implements a variable assignment, not a variable binding. It is thus the equivalent of @clhs{s_setq.htm,setq}.
|
||||
@end deffn
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_symbol_value
|
||||
@defun ecl_symbol_value (cl_env_ptr @var{cl_env}, cl_object @var{var});
|
||||
@subsubheading Description
|
||||
@cppdef ecl_symbol_value
|
||||
@deftypefun cl_object ecl_symbol_value (cl_env_ptr cl_env, cl_object var);
|
||||
@paragraph Description
|
||||
Retrieves the value of the special variable or constant denoted by the symbol @var{var}, in the Common Lisp environment @var{cl_env}.
|
||||
|
||||
This function implements the equivalent of @clhs{f_symb_5.htm,symbol-value} and works both on special variables and constants.
|
||||
|
||||
If the symbol is not bound, an error is signaled.
|
||||
@end defun
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_va_list
|
||||
@cppindex ecl_va_start
|
||||
@cppindex ecl_va_arg
|
||||
@cppindex ecl_va_end
|
||||
@cppdef ecl_va_list
|
||||
@cppdef ecl_va_start
|
||||
@cppdef ecl_va_arg
|
||||
@cppdef ecl_va_end
|
||||
@deffn Macro {typedef struct @{ ... @} ecl_va_list[1];}
|
||||
@end deffn
|
||||
|
||||
@deffn Macro ecl_va_start (ecl_va_list @var{arglist}, @var{last_argument}, @var{narg}, @var{n_ordinary});
|
||||
@deffn Macro ecl_va_start (ecl_va_list arglist, last_argument, narg, n_ordinary);
|
||||
@end deffn
|
||||
|
||||
@deftypefn Macro cl_object ecl_va_arg (ecl_va_list @var{arglist});
|
||||
@deftypefn Macro cl_object ecl_va_arg (ecl_va_list arglist);
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn Macro cl_object ecl_va_end (ecl_va_list @var{arglist});
|
||||
@deftypefn Macro cl_object ecl_va_end (ecl_va_list arglist);
|
||||
Accepting a variable number of arguments
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
The macros above are used to code a function that accepts an arbitrary number of arguments. We will describe them in a practical example
|
||||
|
||||
@example
|
||||
|
|
@ -283,26 +282,25 @@ cl_object my_plus(cl_narg narg, cl_object required1, ...)
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
The first thing to do is to declare the variable that will hold the arguments. This is @var{varargs} in our example and it has the type @code{ecl_va_list}.
|
||||
The first thing to do is to declare the variable that will hold the arguments. This is @var{varargs} in our example and it has the type @coderef{ecl_va_list}.
|
||||
|
||||
This arguments list is initialized with the @code{ecl_va_start} macro, based on the supplied number of arguments, @var{narg}, the number of required arguments which are passed as ordinary C arguments (1 in this case), the last such ordinary arguments, @var{required}, and the buffer for the argument list, @var{varargs}.
|
||||
This arguments list is initialized with the @coderef{ecl_va_start} macro, based on the supplied number of arguments, @var{narg}, the number of required arguments which are passed as ordinary C arguments (1 in this case), the last such ordinary arguments, @var{required}, and the buffer for the argument list, @var{varargs}.
|
||||
|
||||
Once @var{varargs} has been initialized, we can retrieve these values one by one using @code{ecl_va_arg}. Note that the returned value always has the type @code{cl_object}, for it is always a Common Lisp object.
|
||||
Once @var{varargs} has been initialized, we can retrieve these values one by one using @coderef{ecl_va_arg}. Note that the returned value always has the type @code{cl_object}, for it is always a Common Lisp object.
|
||||
|
||||
The last statement before returning the output of the function is @code{ecl_va_end}. This macro performs any required cleanup and should never be omitted.
|
||||
The last statement before returning the output of the function is @coderef{ecl_va_end}. This macro performs any required cleanup and should never be omitted.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
|
||||
@cppindex ecl_nvalues
|
||||
@cppindex ecl_nth_value
|
||||
@deftypefun cl_object ecl_nvalues (cl_env_ptr @var{env});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_nth_value (cl_env_ptr @var{env}, int @var{n});
|
||||
@cppdef ecl_nvalues
|
||||
@cppdef ecl_nth_value
|
||||
@deftypefun cl_object ecl_nvalues (cl_env_ptr env);
|
||||
@deftypefunx cl_object ecl_nth_value (cl_env_ptr env, int n);
|
||||
Accessing output values
|
||||
|
||||
@subsubheading Description
|
||||
Common Lisp functions may return zero, one or more values. In ECL, the first two cases do not require any special manipulation, as the C function returns either @code{NIL} or the first (zeroth) value directly. However, if one wishes to access additional values from a function, one needs to use these two macros or functions
|
||||
@paragraph Description
|
||||
Common Lisp functions may return zero, one or more values. In ECL, the first two cases do not require any special manipulation, as the C function returns either @code{nil} or the first (zeroth) value directly. However, if one wishes to access additional values from a function, one needs to use these two macros or functions
|
||||
|
||||
@itemize
|
||||
@item @code{ecl_nvalues(env)} returns the number of values that the function actually outputs. The single argument is the lisp environment. This value is larger or equal to 0 and smaller than @code{ECL_MULTIPLE_VALUES_LIMIT}.
|
||||
|
|
@ -311,7 +309,7 @@ Common Lisp functions may return zero, one or more values. In ECL, the first two
|
|||
|
||||
Note that in both cases these macros and functions have to be used right after the Lisp function was called. This is so because other Lisp functions might destroy the content of the return stack.
|
||||
|
||||
@subsubheading Example
|
||||
@paragraph Example
|
||||
A C/C++ excerpt:
|
||||
|
||||
@example
|
||||
|
|
@ -332,26 +330,23 @@ The somewhat equivalent Common Lisp code:
|
|||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_return0
|
||||
@cppindex ecl_return1
|
||||
@cppindex ecl_return2
|
||||
@cppindex ecl_return3
|
||||
@defun ecl_return0 (cl_env_ptr @var{cl_env});
|
||||
@end defun
|
||||
@defun ecl_return1 (cl_env_ptr @var{cl_env}, cl_object @var{value1});
|
||||
@end defun
|
||||
@defun ecl_return2 (cl_env_ptr @var{cl_env}, cl_object @var{value1}, cl_object @var{value2});
|
||||
@end defun
|
||||
@defun ecl_return3 (cl_env_ptr @var{cl_env}, cl_object @var{value1}, cl_object @var{value2}, cl_object @var{value3});
|
||||
@cppdef ecl_return0
|
||||
@cppdef ecl_return1
|
||||
@cppdef ecl_return2
|
||||
@cppdef ecl_return3
|
||||
@defmac ecl_return0 (cl_env_ptr cl_env);
|
||||
@defmacx ecl_return1 (cl_env_ptr cl_env, cl_object value1);
|
||||
@defmacx ecl_return2 (cl_env_ptr cl_env, cl_object value1, cl_object value2);
|
||||
@defmacx ecl_return3 (cl_env_ptr cl_env, cl_object value1, cl_object value2, cl_object value3);
|
||||
Returning multiple values
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Returns @var{N} values from a C/C++ function in a way that a Common Lisp function can recognize and use them. The 0-th value is returned directly, while values 1 to N are stored in the Common Lisp environment @var{cl_env}. This macro has to be used from a function which returns an object of type @code{cl_object}.
|
||||
|
||||
@end defun
|
||||
@end defmac
|
||||
|
||||
|
||||
@cppindex ECL_BLOCK_BEGIN
|
||||
@cppdef ECL_BLOCK_BEGIN
|
||||
@deffn Macro ECL_BLOCK_BEGIN
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -361,16 +356,16 @@ ECL_BLOCK_BEGIN(env,code) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_BLOCK_BEGIN} establishes a block named @var{code} that becomes visible for the Common Lisp code. This block can be used then as a target for @code{cl_return}.
|
||||
@paragraph Description
|
||||
@coderef{ECL_BLOCK_BEGIN} establishes a block named @var{code} that becomes visible for the Common Lisp code. This block can be used then as a target for @code{cl_return}.
|
||||
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @coderef{ecl_process_env}.
|
||||
|
||||
The C/C++ program has to ensure that the code in @code{ECL_BLOCK_END} gets executed, avoiding a direct exit of the block via @code{goto} or a C/C++ return.
|
||||
@end deffn
|
||||
|
||||
|
||||
@cppindex ECL_CATCH_BEGIN
|
||||
@cppdef ECL_CATCH_BEGIN
|
||||
@deffn Macro ECL_CATCH_BEGIN
|
||||
@example
|
||||
@verbatim
|
||||
|
|
@ -380,20 +375,20 @@ ECL_CATCH_BEGIN(env,tag) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_CATCH_BEGIN} establishes a destination for @code{throw} with the code given by @var{tag}.
|
||||
@paragraph Description
|
||||
@coderef{ECL_CATCH_BEGIN} establishes a destination for @code{throw} with the code given by @var{tag}.
|
||||
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @coderef{ecl_process_env}.
|
||||
|
||||
The C/C++ program has to ensure that the code in @code{ECL_CATCH_END} gets executed, avoiding a direct exit of the catch block via goto or a C/C++ return.
|
||||
@end deffn
|
||||
|
||||
|
||||
@cppindex ECL_UNWIND_PROTECT_BEGIN
|
||||
@cppdef ECL_UNWIND_PROTECT_BEGIN
|
||||
@deffn Macro ECL_UNWIND_PROTECT_BEGIN
|
||||
C macro for unwind-protect
|
||||
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@example
|
||||
@verbatim
|
||||
ECL_UNWIND_PROTECT_BEGIN(env) {
|
||||
|
|
@ -404,10 +399,10 @@ ECL_UNWIND_PROTECT_BEGIN(env) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@code{ECL_UNWIND_PROTECT_BEGIN} establishes two blocks of C code that work like the equivalent ones in Common Lisp: a protected block, contained between the "BEGIN" and the "EXIT" statement, and the exit block, appearing immediately afterwards. The form guarantees that the exit block is always executed, even if the protected block attempts to exit via some nonlocal jump construct (@code{throw}, @code{return}, etc).
|
||||
@paragraph Description
|
||||
@coderef{ECL_UNWIND_PROTECT_BEGIN} establishes two blocks of C code that work like the equivalent ones in Common Lisp: a protected block, contained between the "BEGIN" and the "EXIT" statement, and the exit block, appearing immediately afterwards. The form guarantees that the exit block is always executed, even if the protected block attempts to exit via some nonlocal jump construct (@code{throw}, @code{return}, etc).
|
||||
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @code{ecl_process_env}.
|
||||
@var{env} must be the value of the current Common Lisp environment, obtained with @coderef{ecl_process_env}.
|
||||
|
||||
The utility of this construct is limited, for it only protects against nonlocal exits caused by Common Lisp constructs: it does not interfere with C @code{goto}, @code{return} or with C++ exceptions.
|
||||
@end deffn
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
|
||||
@defun disassemble function-designator*
|
||||
Display the assembly code of a function
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@table @var
|
||||
@item function-designator
|
||||
A symbol which is bound to a function in the global environment, or a lambda form
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
As specified in ANSI @bibcite{ANSI} this function outputs the internal representation of a compiled function, or of a lambda form, as it would look after being compiled.
|
||||
|
||||
ECL only has a particular difference: it has two different compilers, one based on bytecodes and one based on the C language. The output will thus depend on the arguments and on which compiler is active at the moment in which this function is run.
|
||||
|
|
@ -31,7 +31,7 @@ ECL only has a particular difference: it has two different compilers, one based
|
|||
|
||||
@defmac trace function-name*
|
||||
Follow the execution of functions
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
(trace @var{function-name*})
|
||||
@table @var
|
||||
@item function-name
|
||||
|
|
@ -46,14 +46,14 @@ A lisp form evaluated in an special environment.
|
|||
List of symbols with traced functions.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Causes one or more functions to be traced. Each @var{function-name} can be a symbol which is bound to a function, or a list containing that symbol plus additional options. If the function bound to that symbol is called, information about the arguments and output of this function will be printed. Trace options will modify the amount of information and when it is printed.
|
||||
|
||||
Not that if the function is called from another function compiled in the same file, tracing might not be enabled. If this is the case, to enable tracing, recompile the caller with a @code{notinline} declaration for the called function.
|
||||
|
||||
trace returns a name list of those functions that were traced by the call to trace. If no @var{function-name} is given, @code{trace} simply returns a name list of all the currently traced functions.
|
||||
|
||||
Trace options cause the normal printout to be suppressed, or cause extra information to be printed. Each option is a pair of an option keyword and a value form. If an already traced function is traced again, any new options replace the old options and a warning might be printed. The lisp @emph{form} accompanying the option is evaluated in an environment where @var{sys::args} contains the list of arguments to the function.
|
||||
Trace options cause the normal printout to be suppressed, or cause extra information to be printed. Each option is a pair of an option keyword and a value form. If an already traced function is traced again, any new options replace the old options and a warning might be printed. The lisp @var{form} accompanying the option is evaluated in an environment where @var{sys::args} contains the list of arguments to the function.
|
||||
|
||||
The following options are defined:
|
||||
@table @asis
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@node Evaluation and compilation
|
||||
@section Evaluation and compilation
|
||||
|
||||
@subsection Compiler declaration @code{OPTIMIZE}
|
||||
@subsection Compiler declaration @code{optimize}
|
||||
@cindex Compiler declarations
|
||||
@lspindex optimize
|
||||
@lspindex debug
|
||||
|
|
@ -9,21 +9,21 @@
|
|||
@lspindex safety
|
||||
@lspindex space
|
||||
|
||||
The @code{OPTIMIZE} declaration includes three concepts: @code{DEBUG},
|
||||
@code{SPEED}, @code{SAFETY} and @code{SPACE}. Each of these declarations
|
||||
The @code{optimize} declaration includes three concepts: @code{debug},
|
||||
@code{speed}, @code{safety} and @code{space}. Each of these declarations
|
||||
can take one of the integer values 0, 1, 2 and 3. According to these
|
||||
values, the implementation may decide how to compile or interpret a given
|
||||
lisp form.
|
||||
|
||||
ECL currently does not use all these declarations, but some of them
|
||||
definitely affect the speed and behavior of compiled functions. For
|
||||
instance, the @code{DEBUG} declaration, as shown in
|
||||
instance, the @code{debug} declaration, as shown in
|
||||
@ref{tab:optimize-debug}, the value of debugging is zero, the function
|
||||
will not appear in the debugger and, if redefined, some functions might
|
||||
not see the redefinition.
|
||||
|
||||
@float Table, tab:optimize-debug
|
||||
@caption{Behavior for different levels of @code{DEBUG}}
|
||||
@caption{Behavior for different levels of @code{debug}}
|
||||
@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} {a} {a} {a} {a}
|
||||
@headitem Behavior
|
||||
@tab 0
|
||||
|
|
@ -52,16 +52,16 @@ not see the redefinition.
|
|||
@end multitable
|
||||
@end float
|
||||
|
||||
A bit more critical is the value of @code{SAFETY} because as shown in
|
||||
A bit more critical is the value of @code{safety} because as shown in
|
||||
@ref{tab:optimize-safety}, it may affect the safety checks generated
|
||||
by the compiler. In particular, in some circumstances the compiler may
|
||||
assume that the arguments to a function are properly typed. For
|
||||
instance, if you compile with a low value of @code{SAFETY}, and invoke
|
||||
@code{RPLACA} with an object which is not a list, the consequences are
|
||||
instance, if you compile with a low value of @code{safety}, and invoke
|
||||
@code{rplaca} with an object which is not a list, the consequences are
|
||||
unspecified.
|
||||
|
||||
@float Table, tab:optimize-safety
|
||||
@caption{Behavior for different levels of @code{SAFETY}}
|
||||
@caption{Behavior for different levels of @code{safety}}
|
||||
@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa} {a} {a} {a} {a}
|
||||
@headitem Behavior
|
||||
@tab 0
|
||||
|
|
@ -81,7 +81,7 @@ unspecified.
|
|||
@tab N
|
||||
@tab N
|
||||
|
||||
@item We believe type declarations and type inference and, if the type of a form is inferred to be right for a function, slot accessor, etc, this may be inlined. Affects functions like @code{CAR}, @code{CDR}, etc
|
||||
@item We believe type declarations and type inference and, if the type of a form is inferred to be right for a function, slot accessor, etc, this may be inlined. Affects functions like @code{car}, @code{cdr}, etc
|
||||
@tab Y
|
||||
@tab Y
|
||||
@tab N
|
||||
|
|
@ -99,7 +99,7 @@ unspecified.
|
|||
@tab N
|
||||
@tab N
|
||||
|
||||
@item The slots or fields in a lisp object are accessed directly without type checks even if the type of the object could not be inferred (see line above). Affects functions like @code{PATHNAME-TYPE}, @code{CAR}, @code{REST}, etc.
|
||||
@item The slots or fields in a lisp object are accessed directly without type checks even if the type of the object could not be inferred (see line above). Affects functions like @code{pathname-type}, @code{car}, @code{rest}, etc.
|
||||
@tab Y
|
||||
@tab N
|
||||
@tab N
|
||||
|
|
@ -120,8 +120,8 @@ compiled.
|
|||
|
||||
@subsection C Reference
|
||||
|
||||
@cppindex ecl_process_env
|
||||
@deftypefn {@cind{}} cl_object cl_env_ptr ()
|
||||
@cppdef ecl_process_env
|
||||
@deftypefn @cind{} cl_env_ptr ecl_process_env ()
|
||||
ECL stores information about each thread on a dedicated structure, which
|
||||
is the process environment. A pointer to this structure can be retrieved
|
||||
using the function or macro above. This pointer can be used for a
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ The way ECL parses a namestring is by first looking for the @var{hostname} compo
|
|||
|
||||
If this syntax also fails, then the namestring is not a valid pathname string and a @code{parse-error} will be signaled.
|
||||
|
||||
It is important to remark that in ECL, all physical namestrings result into pathnames with a version equal to @code{:NEWEST}. Pathnames which are not logical and have any other version (i. e. @code{NIL} or a number), cannot be printed readably, but can produce a valid namestring which results of ignoring the version.
|
||||
It is important to remark that in ECL, all physical namestrings result into pathnames with a version equal to @code{:newest}. Pathnames which are not logical and have any other version (i. e. @code{nil} or a number), cannot be printed readably, but can produce a valid namestring which results of ignoring the version.
|
||||
|
||||
Finally, an important rule applies to physical namestrings: if a namestring contains one or more periods `.', the last period separates the namestring into the file name and the filetype. However, a namestring with a single leading period results in a name with a period in it. This is for compatibility with Unix filenames such as @code{.bashrc}, where the leading period indicates that the file is hidden.
|
||||
|
||||
The previous rule has in important consequence, because it means that if you want to create a pathname without a name, you have to do it explicitely. In other words, ".*" is equivalent to (@code{MAKE-PATHNAME :NAME ".*" :TYPE NIL}), while (@code{MAKE-PATHNAME :NAME NIL :TYPE :WILD}) creates a pathname whose type is a wildcard.
|
||||
The previous rule has in important consequence, because it means that if you want to create a pathname without a name, you have to do it explicitely. In other words, @code{".*"} is equivalent to @code{(make-pathname :name ".*" :type nil)}, while @code{(make-pathname :name nil :type :wild)} creates a pathname whose type is a wildcard.
|
||||
|
||||
The following table illustrates how the physical pathnames work with practical examples.
|
||||
|
||||
|
|
@ -44,18 +44,18 @@ The following table illustrates how the physical pathnames work with practical e
|
|||
@caption{Examples of physical namestrings}
|
||||
@multitable @columnfractions .28 .12 .1 .3 .2
|
||||
@headitem Namestring @tab Name @tab Type @tab Directory @tab Device
|
||||
@item "foo.lsp" @tab "foo" @tab "lsp" @tab NIL @tab NIL
|
||||
@item ".bashrc" @tab ".bashrc" @tab NIL @tab NIL @tab NIL
|
||||
@item ".ecl.lsp" @tab ".ecl" @tab "lsp" @tab NIL @tab NIL
|
||||
@item "foo.*" @tab "foo" @tab :WILD @tab NIL @tab NIL
|
||||
@item "*.*" @tab :WILD @tab :WILD @tab NIL @tab NIL
|
||||
@item "ecl/build/bare.lsp" @tab "bare" @tab "lsp" @tab (:relative "ecl" "build") @tab NIL
|
||||
@item "ecl/build/" @tab NIL @tab NIL @tab (:relative "ecl" "build") @tab NIL
|
||||
@item "../../ecl/build/" @tab NIL @tab NIL @tab (:relative :up :up "ecl" "build") @tab NIL
|
||||
@item "/etc/" @tab NIL @tab NIL @tab (:absolute "etc") @tab NIL
|
||||
@item "C:/etc/" @tab NIL @tab NIL @tab (:absolute "etc") @tab "C"
|
||||
@item ".*" @tab ".*" @tab NIL @tab NIL @tab NIL
|
||||
@item #.(MAKE-PATHNAME :TYPE "*") @tab NIL @tab :WILD @tab NIL @tab NIL
|
||||
@item @code{"foo.lsp"} @tab @code{"foo"} @tab @code{"lsp"} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{".bashrc"} @tab @code{".bashrc"} @tab @code{nil} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{".ecl.lsp"} @tab @code{".ecl"} @tab @code{"lsp"} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{"foo.*"} @tab @code{"foo"} @tab @code{:wild} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{"*.*"} @tab @code{:wild} @tab @code{:wild} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{"ecl/build/bare.lsp"} @tab @code{"bare"} @tab @code{"lsp"} @tab @code{(:relative "ecl" "build")} @tab @code{nil}
|
||||
@item @code{"ecl/build/"} @tab @code{nil} @tab @code{nil} @tab @code{(:relative "ecl" "build")} @tab @code{nil}
|
||||
@item @code{"../../ecl/build/"} @tab @code{nil} @tab @code{nil} @tab @code{(:relative :up :up "ecl" "build")} @tab @code{nil}
|
||||
@item @code{"/etc/"} @tab @code{nil} @tab @code{nil} @tab @code{(:absolute "etc")} @tab @code{nil}
|
||||
@item @code{"C:/etc/"} @tab @code{nil} @tab @code{nil} @tab @code{(:absolute "etc")} @tab @code{"C"}
|
||||
@item @code{".*"} @tab @code{".*"} @tab @code{nil} @tab @code{nil} @tab @code{nil}
|
||||
@item @code{#.(make-pathname :type "*")} @tab @code{nil} @tab @code{:wild} @tab @code{nil} @tab @code{nil}
|
||||
@end multitable
|
||||
@end float
|
||||
|
||||
|
|
@ -64,16 +64,16 @@ The following table illustrates how the physical pathnames work with practical e
|
|||
ECL accepts four kind of wildcards in pathnames.
|
||||
|
||||
@itemize
|
||||
@item A single wildcard in a directory component, file name, type or version is parsed as the @code{:WILD} value. See for instance "@code{*.*}", "@code{/home/*/.bashrc}", etc
|
||||
@item A single wildcard in a directory component, file name, type or version is parsed as the @code{:wild} value. See for instance "@code{*.*}", "@code{/home/*/.bashrc}", etc
|
||||
|
||||
@item A double wildcard in a directory component, such as in "@code{/home/**/}" is parsed as the @code{:WILD-INFERIORS}, and matches any number of directories, even nested ones, such as: @code{/home/}, @code{/home/jlr}, @code{/home/jlr/lib}, etc.
|
||||
@item A double wildcard in a directory component, such as in "@code{/home/**/}" is parsed as the @code{:wild-inferiors}, and matches any number of directories, even nested ones, such as: @code{/home/}, @code{/home/jlr}, @code{/home/jlr/lib}, etc.
|
||||
|
||||
@item An isolated wildcard "@code{log*.txt}" matches any number of characters: @code{log.txt}, @code{log_back.txt}, etc.
|
||||
|
||||
@item A question mark "@code{log?.txt}" matches a single character: @code{log1.txt}, @code{log2.txt}...
|
||||
@end itemize
|
||||
|
||||
The matching rules in Common Lisp and ECL are simple but have some unintuitive consequences when compared to Unix/DOS rules. The most important one is that directories must always end with a trailing slash @code{/}, as in @code{#p"/my/home/directory/"}. Second to that, @code{NIL} values can only be matched by @code{NIL} and @code{:WILD}. Hence, "@code{*}" can only match files without file type. For some examples see @ref{Files - Dictionary}.
|
||||
The matching rules in Common Lisp and ECL are simple but have some unintuitive consequences when compared to Unix/DOS rules. The most important one is that directories must always end with a trailing slash @code{/}, as in @code{#p"/my/home/directory/"}. Second to that, @code{nil} values can only be matched by @code{nil} and @code{:wild}. Hence, "@code{*}" can only match files without file type. For some examples see @ref{Files - Dictionary}.
|
||||
|
||||
@node Filenames - C Reference
|
||||
@subsection C Reference
|
||||
|
|
|
|||
|
|
@ -15,23 +15,24 @@
|
|||
|
||||
Weak hash tables allow the garbage collector to reclaim some of the
|
||||
entries if they are not strongly referenced elsewhere. ECL supports
|
||||
four kinds of weakness in hash tables: @t{:key}, @t{:value},
|
||||
@t{:key-and-value} and @t{:key-or-value}.
|
||||
four kinds of weakness in hash tables: @code{:key}, @code{:value},
|
||||
@code{:key-and-value} and @code{:key-or-value}.
|
||||
|
||||
To make hash table weak, programmer has to provide @t{:weakness}
|
||||
keyword argument to @t{cl:make-hash-table} with the desired kind of
|
||||
weakness value (@t{NIL} means that the hash table has only strong
|
||||
To make hash table weak, programmer has to provide @code{:weakness}
|
||||
keyword argument to @code{cl:make-hash-table} with the desired kind of
|
||||
weakness value (@code{nil} means that the hash table has only strong
|
||||
references).
|
||||
|
||||
For more information see
|
||||
@url{https://www.haible.de/bruno/papers/cs/weak/WeakDatastructures-writeup.html,Weak
|
||||
References - Data Types and Implementation} by Bruno Haible.
|
||||
|
||||
@lspindex hash-table-weakness
|
||||
@deffn {ext} {hash-table-weakness} ht
|
||||
@lspdef ext:hash-table-weakness
|
||||
@defun ext:hash-table-weakness ht
|
||||
Returns type of the hash table weakness. Possible return values are:
|
||||
@t{:key}, @t{:value}, @t{:key-and-value}, @t{:key-or-value} or @t{NIL}.
|
||||
@end deffn
|
||||
@code{:key}, @code{:value}, @code{:key-and-value}, @code{:key-or-value}
|
||||
or @code{nil}.
|
||||
@end defun
|
||||
|
||||
@subsubsection Thread-safe hash tables
|
||||
@cindex Synchronized hash tables
|
||||
|
|
@ -39,29 +40,29 @@ Returns type of the hash table weakness. Possible return values are:
|
|||
|
||||
By default ECL doesn't protect hash tables from simultaneous access
|
||||
for performance reasons. Read and write access may is synchronized
|
||||
when @t{:synchronized} keyword argument to @t{make-hash-table} is
|
||||
@t{T} - @code{(make-hash-table :synchronized t)}.
|
||||
when @code{:synchronized} keyword argument to @code{make-hash-table} is
|
||||
@code{t} - @code{(make-hash-table :synchronized t)}.
|
||||
|
||||
@lspindex hash-table-synchronized-p
|
||||
@deffn {ext} {hash-table-synchronized-p} ht
|
||||
Predicate answering whenever hash table is synchronized or not.
|
||||
@end deffn
|
||||
@lspdef ext:hash-table-synchronized-p
|
||||
@defun ext:hash-table-synchronized-p ht
|
||||
Predicate answering whether hash table is synchronized or not.
|
||||
@end defun
|
||||
|
||||
@subsubsection Hash tables serialization
|
||||
@cindex Hash table serialization
|
||||
|
||||
@lspindex hash-table-content
|
||||
@deffn {ext} {hash-table-content} ht
|
||||
@lspdef hash-table-content
|
||||
@defun ext:hash-table-content ht
|
||||
Returns freshly consed list of pairs @code{(key . val)} being contents
|
||||
of the hash table.
|
||||
@end deffn
|
||||
@end defun
|
||||
|
||||
@lspindex hash-table-fill
|
||||
@deffn {ext} {hash-table-fill} ht values
|
||||
Fills @t{ht} with @t{values} being list of @code{(key . val)}. Hash
|
||||
@lspdef ext:hash-table-fill
|
||||
@defun ext:hash-table-fill ht values
|
||||
Fills @var{ht} with @var{values} being list of @code{(key . val)}. Hash
|
||||
table may have some content already, but conflicting keys will be
|
||||
overwritten.
|
||||
@end deffn
|
||||
@end defun
|
||||
|
||||
@subsubsection Custom equivalence predicate
|
||||
@cindex Hash table generic test
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ ECL supports all of the Common Lisp numeric tower, which is shown in @ref{tab:nu
|
|||
@end multitable
|
||||
@end float
|
||||
|
||||
In general, the size of a @code{FIXNUM} is determined by the word size
|
||||
In general, the size of a @code{fixnum} is determined by the word size
|
||||
of a machine, which ranges from 32 to 64 bits. Integers larger than
|
||||
this are implemented using the @url{http://www.swox.com/gmp/, GNU
|
||||
this are implemented using the @url{https://gmplib.org/, GNU
|
||||
Multiprecision library}. Rationals are implemented using two integers,
|
||||
without caring whether they are fixnum or not. Floating point numbers
|
||||
include at least the two IEEE types of 32 and 64 bits respectively.
|
||||
|
|
@ -42,7 +42,7 @@ include at least the two IEEE types of 32 and 64 bits respectively.
|
|||
@cindex long-float internal representation
|
||||
@ftindex LONG-FLOAT
|
||||
In machines where it is supported, it is possible to associate the
|
||||
lisp @code{LONG-FLOAT} with the machine type @code{long double} whose
|
||||
lisp @code{long-float} with the machine type @code{long double} whose
|
||||
size ranges from 96 to 128 bits, and which are a bit slower.
|
||||
|
||||
@cindex (complex float) internal representation
|
||||
|
|
@ -53,6 +53,9 @@ ratios all complex numbers are pairs of numbers.
|
|||
|
||||
@node Numbers - Floating point exceptions
|
||||
@subsection Floating point exceptions
|
||||
@cfindex --with-ieee-fp [YES|no]
|
||||
@cfindex --with-fpe [YES|no]
|
||||
|
||||
ECL supports two ways of dealing with special floating point values,
|
||||
such as Not a Number (NaN), infinity or denormalized floats, which can
|
||||
occur in floating point computations. Either a condition is signaled or
|
||||
|
|
@ -64,17 +67,18 @@ can be disabled at build time using the @code{--without-fpe} configure
|
|||
option. Otherwise, if both @code{--with-ieee-fp} and @code{--with-fpe}
|
||||
options are on, by default, a condition is signaled for invalid
|
||||
operation, division by zero and floating point overflows. This can be
|
||||
changed at runtime by using @code{ext:trap-fpe}. If the
|
||||
@code{ECL_OPT_TRAP_SIGFPE} boot option is false, no conditions are
|
||||
signaled by default (Note that in this case, if you enable trapping of
|
||||
floating point exceptions with @code{ext:trap-fpe}, then you have to
|
||||
install your own signal handler).
|
||||
changed at runtime by using @coderef{ext:trap-fpe}. If the
|
||||
@code{ECL_OPT_TRAP_SIGFPE} boot option is false (see
|
||||
@ref{tab:boot-options}), no conditions are signaled by default (Note
|
||||
that in this case, if you enable trapping of floating point exceptions
|
||||
with @coderef{ext:trap-fpe}, then you have to install your own signal
|
||||
handler).
|
||||
|
||||
@lspindex ext:trap-fpe
|
||||
@lspdef ext:trap-fpe
|
||||
@defun ext:trap-fpe condition flag
|
||||
Control the signaling of the floating point exceptions
|
||||
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@table @var
|
||||
@item condition
|
||||
a symbol - one of @code{last}, @code{t}, @code{division-by-zero},
|
||||
|
|
@ -85,18 +89,18 @@ a symbol - one of @code{last}, @code{t}, @code{division-by-zero},
|
|||
a generalized boolean
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
If @var{condition} is @code{last}, @var{flag} is ignored and the
|
||||
currently enabled floating point exceptions are returned in an
|
||||
implementation depended format (currently an integer). Otherwise,
|
||||
@var{flag} determines whether the current thread will signal a
|
||||
floating point exception for the conditions passed in @var{condition}.
|
||||
@var{flag} determines whether the current thread will signal a floating
|
||||
point exception for the conditions passed in @var{condition}.
|
||||
@var{condition} can be either a symbol denoting a single condition,
|
||||
@code{t} for all conditions that are enabled by default or a value
|
||||
obtained from an earlier call to @code{ext:trap-fpe} with @code{last}.
|
||||
obtained from an earlier call to @coderef{ext:trap-fpe} with
|
||||
@code{last}.
|
||||
|
||||
@subsubheading See also
|
||||
@code{ECL_WITH_LISP_FPE}
|
||||
@seealso{ECL_WITH_LISP_FPE}
|
||||
|
||||
@end defun
|
||||
|
||||
|
|
@ -148,37 +152,36 @@ true.
|
|||
NaN values are ignored, i.e. the maximum/minimum is taken only over
|
||||
the number valued parameters.
|
||||
@item Rounding functions
|
||||
All rounding functions signal an arithmetic-error if any of the given
|
||||
parameters are not number valued or infinite.
|
||||
All rounding functions signal an @code{arithmetic-error} if any of the
|
||||
given parameters are not number valued or infinite.
|
||||
@end table
|
||||
|
||||
@node Numbers - Dictionary
|
||||
@subsection Dictionary
|
||||
|
||||
@lspindex ext:short-float-positive-infinity
|
||||
@lspindex ext:short-float-negative-infinity
|
||||
@lspindex ext:single-float-positive-infinity
|
||||
@lspindex ext:single-float-negative-infinity
|
||||
@lspindex ext:double-float-positive-infinity
|
||||
@lspindex ext:double-float-negative-infinity
|
||||
@lspindex ext:long-float-positive-infinity
|
||||
@lspindex ext:long-float-negative-infinity
|
||||
@lspdef ext:short-float-positive-infinity
|
||||
@lspdef ext:short-float-negative-infinity
|
||||
@lspdef ext:single-float-positive-infinity
|
||||
@lspdef ext:single-float-negative-infinity
|
||||
@lspdef ext:double-float-positive-infinity
|
||||
@lspdef ext:double-float-negative-infinity
|
||||
@lspdef ext:long-float-positive-infinity
|
||||
@lspdef ext:long-float-negative-infinity
|
||||
@defvr Constant {ext:@{short,single,double,long@}-float-@{positive,negative@}-infinity}
|
||||
Constant positive/negative infinity for the different floating point types.
|
||||
@end defvr
|
||||
|
||||
|
||||
@lspindex ext:nan
|
||||
@lspdef ext:nan
|
||||
@defun ext:nan
|
||||
Returns a double float NaN value. Coerce to other floating point types
|
||||
to get NaN values e.g. for single floats.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:float-infinity-p
|
||||
@defun ext:float-infinity-p x
|
||||
@end defun
|
||||
@lspdef ext:float-infinity-p
|
||||
@lspindex ext:float-nan-p
|
||||
@defun ext:float-nan-p x
|
||||
@defun ext:float-infinity-p x
|
||||
@defunx ext:float-nan-p x
|
||||
Predicates to test if @var{x} is infinite or NaN.
|
||||
@end defun
|
||||
|
||||
|
|
@ -225,13 +228,13 @@ Numeric C types understood by ECL
|
|||
@item unsigned long long @tab (integer 0 ffi:c-ulong-long-max) @tab ecl_ulong_long_t @tab :ulong-long
|
||||
@end multitable
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
The table above shows the relation between C types and the equivalent Common Lisp types. All types are standard C99 types, except for two. First, @code{cl_fixnum} is the smallest signed integer that can fit a fixnum. Second, @code{cl_index} is the smallest unsigned integer that fits a fixnum and is typically the unsigned counterpart of @code{cl_fixnum}.
|
||||
|
||||
(*) @strong{DEPRECATED} Previous versions of ECL supported compilers
|
||||
that did not define the long double type. The @code{ECL_LONG_DOUBLE}
|
||||
macro and @code{long-double} feature will be removed in the next
|
||||
release.
|
||||
macro and @code{long-double} features indicating whether support for
|
||||
long double was available are removed now.
|
||||
|
||||
@cfindex --enable-c99complex [auto]
|
||||
(**) The <float> _Complex types do not exist on all platforms. When
|
||||
|
|
@ -254,62 +257,63 @@ In Lisp code, check for the presence of the associated features, shown in the fo
|
|||
Creating Lisp types from C numbers
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_object ecl_make_fixnum (cl_fixnum @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_integer (cl_fixnum @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_unsigned_integer (cl_index @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_single_float (float @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_double_float (double @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_long_float (long double @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_csfloat (float _Complex @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_cdfloat (double _Complex @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_clfloat (long double _Complex @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_uint8_t (uint8_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_int8_t (int8_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_uint16_t (uint16_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_int16_t (int16_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_uint32_t (uint32_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_int32_t (int32_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_uint64_t (uint64_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_int64_t (int64_t @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_short_t (short @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_ushort_t (unsigned short @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_int (int @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_uint (unsigned int @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_long (long @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_ulong (unsigned long @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_long_long (long long @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_ulong_long (unsigned long long @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_ratio (cl_object @var{numerator}, cl_object @var{denominator})
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_complex (cl_object @var{real}, cl_object @var{imag})
|
||||
@end deftypefun
|
||||
@cppdef ecl_make_fixnum
|
||||
@cppdef ecl_make_integer
|
||||
@cppdef ecl_make_unsigned_integer
|
||||
@cppdef ecl_make_single_float
|
||||
@cppdef ecl_make_double_float
|
||||
@cppdef ecl_make_long_float
|
||||
@cppdef ecl_make_csfloat
|
||||
@cppdef ecl_make_cdfloat
|
||||
@cppdef ecl_make_clfloat
|
||||
@cppdef ecl_make_uint8_t
|
||||
@cppdef ecl_make_int8_t
|
||||
@cppdef ecl_make_uint16_t
|
||||
@cppdef ecl_make_int16_t
|
||||
@cppdef ecl_make_uint32_t
|
||||
@cppdef ecl_make_int32_t
|
||||
@cppdef ecl_make_uint64_t
|
||||
@cppdef ecl_make_int64_t
|
||||
@cppdef ecl_make_short_t
|
||||
@cppdef ecl_make_ushort_t
|
||||
@cppdef ecl_make_int
|
||||
@cppdef ecl_make_uint
|
||||
@cppdef ecl_make_long
|
||||
@cppdef ecl_make_ulong
|
||||
@cppdef ecl_make_long_long
|
||||
@cppdef ecl_make_ulong_long
|
||||
@cppdef ecl_make_ratio
|
||||
@cppdef ecl_make_complex
|
||||
|
||||
@subsubheading Description
|
||||
@deftypefun cl_object ecl_make_fixnum (cl_fixnum n)
|
||||
@deftypefunx cl_object ecl_make_integer (cl_fixnum n)
|
||||
@deftypefunx cl_object ecl_make_unsigned_integer (cl_index n)
|
||||
@deftypefunx cl_object ecl_make_single_float (float n)
|
||||
@deftypefunx cl_object ecl_make_double_float (double n)
|
||||
@deftypefunx cl_object ecl_make_long_float (long double n)
|
||||
@deftypefunx cl_object ecl_make_csfloat (float _Complex n)
|
||||
@deftypefunx cl_object ecl_make_cdfloat (double _Complex n)
|
||||
@deftypefunx cl_object ecl_make_clfloat (long double _Complex n)
|
||||
@deftypefunx cl_object ecl_make_uint8_t (uint8_t n)
|
||||
@deftypefunx cl_object ecl_make_int8_t (int8_t n)
|
||||
@deftypefunx cl_object ecl_make_uint16_t (uint16_t n)
|
||||
@deftypefunx cl_object ecl_make_int16_t (int16_t n)
|
||||
@deftypefunx cl_object ecl_make_uint32_t (uint32_t n)
|
||||
@deftypefunx cl_object ecl_make_int32_t (int32_t n)
|
||||
@deftypefunx cl_object ecl_make_uint64_t (uint64_t n)
|
||||
@deftypefunx cl_object ecl_make_int64_t (int64_t n)
|
||||
@deftypefunx cl_object ecl_make_short_t (short n)
|
||||
@deftypefunx cl_object ecl_make_ushort_t (unsigned short n)
|
||||
@deftypefunx cl_object ecl_make_int (int n)
|
||||
@deftypefunx cl_object ecl_make_uint (unsigned int n)
|
||||
@deftypefunx cl_object ecl_make_long (long n)
|
||||
@deftypefunx cl_object ecl_make_ulong (unsigned long n)
|
||||
@deftypefunx cl_object ecl_make_long_long (long long n)
|
||||
@deftypefunx cl_object ecl_make_ulong_long (unsigned long long n)
|
||||
@deftypefunx cl_object ecl_make_ratio (cl_object numerator, cl_object denominator)
|
||||
@deftypefunx cl_object ecl_make_complex (cl_object real, cl_object imag)
|
||||
|
||||
@paragraph Description
|
||||
These functions create a Lisp object from the corresponding C
|
||||
number. If the number is an integer type, the result will always be an
|
||||
integer, which may be a bignum. If on the other hand the C number is a
|
||||
|
|
@ -317,99 +321,104 @@ float, double or long double, the result will be a float.
|
|||
|
||||
There is some redundancy in the list of functions that convert from
|
||||
cl_fixnum and cl_index to lisp. On the one hand,
|
||||
@code{ecl_make_fixnum} always creates a fixnum, dropping bits if
|
||||
necessary. On the other hand, @code{ecl_make_integer} and
|
||||
@code{ecl_make_unsigned_integer} faithfully convert to a Lisp integer,
|
||||
which may be a bignum.
|
||||
@coderef{ecl_make_fixnum} always creates a fixnum, dropping bits if
|
||||
necessary. On the other hand, @coderef{ecl_make_integer} and
|
||||
@coderef{ecl_make_unsigned_integer} faithfully convert to a Lisp
|
||||
integer, which may be a bignum.
|
||||
|
||||
Note also that some of the constructors do not use C numbers. This is
|
||||
the case of @code{ecl_make_ratio} and @code{ecl_make_complex}, because
|
||||
they are composite Lisp types. When c99 complex float support is built
|
||||
in @code{ecl_make_complex} will use C number for float types.
|
||||
the case of @coderef{ecl_make_ratio} and @coderef{ecl_make_complex},
|
||||
because they are composite Lisp types. When c99 complex float support is
|
||||
built in @coderef{ecl_make_complex} will use C number for float types.
|
||||
|
||||
These functions or macros signal no errors.
|
||||
@end deftypefun
|
||||
|
||||
@node Numbers - Number accessors
|
||||
@subsubsection Number accessors
|
||||
Unchecked conversion from Lisp types to C numbers
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_fixnum ecl_fixnum (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun float ecl_single_float (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun double ecl_double_float (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun {long double} ecl_long_float (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun {float _Complex} ecl_csfloat (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun {double _Complex} ecl_cdfloat (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@deftypefun {long double _Complex} ecl_clfloat (cl_object @var{n})
|
||||
@end deftypefun
|
||||
@cppdef ecl_fixnum
|
||||
@cppdef ecl_single_float
|
||||
@cppdef ecl_double_float
|
||||
@cppdef ecl_long_float
|
||||
@cppdef ecl_csfloat
|
||||
@cppdef ecl_cdfloat
|
||||
@cppdef ecl_clfloat
|
||||
|
||||
@subsubheading Description
|
||||
@deftypefun cl_fixnum ecl_fixnum (cl_object n)
|
||||
@deftypefunx float ecl_single_float (cl_object n)
|
||||
@deftypefunx double ecl_double_float (cl_object n)
|
||||
@deftypefunx {long double} ecl_long_float (cl_object n)
|
||||
@deftypefunx {float _Complex} ecl_csfloat (cl_object n)
|
||||
@deftypefunx {double _Complex} ecl_cdfloat (cl_object n)
|
||||
@deftypefunx {long double _Complex} ecl_clfloat (cl_object n)
|
||||
|
||||
@paragraph Description
|
||||
These functions and macros extract a C number from a Lisp object. They do not check the type of the Lisp object as they typically just access directly the value from a C structure.
|
||||
@end deftypefun
|
||||
|
||||
@node Numbers - Number coercion
|
||||
@subsubsection Number coercion
|
||||
Checked conversion from Lisp types to C numbers
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun cl_fixnum ecl_to_fixnum (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun cl_index ecl_to_unsigned_integer (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun float ecl_to_float (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun double ecl_to_double (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {long double} ecl_to_long_double (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {float _Complex} ecl_to_csfloat (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {double _Complex} ecl_to_cdfloat (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {long double _Complex} ecl_to_clfloat (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun uint8_t ecl_to_uint8_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun int8_t ecl_to_int8_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun uint16_t ecl_to_uint16_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun int16_t ecl_to_int16_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun uint32_t ecl_to_uint32_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun int32_t ecl_to_int32_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun uint64_t ecl_to_uint64_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun int64_t ecl_to_int64_t (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun short ecl_to_short (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {unsigned short} ecl_to_ushort (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun int ecl_to_int (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {unsigned int} ecl_to_uint (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun long ecl_to_long (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {unsigned long} ecl_to_ulong (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun long long ecl_to_long_long (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@deftypefun {unsigned long} long ecl_to_ulong_long (cl_object @var{n});
|
||||
@end deftypefun
|
||||
@cppdef ecl_to_fixnum
|
||||
@cppdef ecl_to_unsigned_integer
|
||||
@cppdef ecl_to_float
|
||||
@cppdef ecl_to_double
|
||||
@cppdef ecl_to_long_double
|
||||
@cppdef ecl_to_csfloat
|
||||
@cppdef ecl_to_cdfloat
|
||||
@cppdef ecl_to_clfloat
|
||||
@cppdef ecl_to_uint8_t
|
||||
@cppdef ecl_to_int8_t
|
||||
@cppdef ecl_to_uint16_t
|
||||
@cppdef ecl_to_int16_t
|
||||
@cppdef ecl_to_uint32_t
|
||||
@cppdef ecl_to_int32_t
|
||||
@cppdef ecl_to_uint64_t
|
||||
@cppdef ecl_to_int64_t
|
||||
@cppdef ecl_to_short
|
||||
@cppdef ecl_to_ushort
|
||||
@cppdef ecl_to_int
|
||||
@cppdef ecl_to_uint
|
||||
@cppdef ecl_to_long
|
||||
@cppdef ecl_to_ulong
|
||||
@cppdef ecl_to_long_long
|
||||
@cppdef ecl_to_ulong_long
|
||||
|
||||
@subsubheading Description
|
||||
@deftypefun cl_fixnum ecl_to_fixnum (cl_object n);
|
||||
@deftypefunx cl_index ecl_to_unsigned_integer (cl_object n);
|
||||
@deftypefunx float ecl_to_float (cl_object n);
|
||||
@deftypefunx double ecl_to_double (cl_object n);
|
||||
@deftypefunx {long double} ecl_to_long_double (cl_object n);
|
||||
@deftypefunx {float _Complex} ecl_to_csfloat (cl_object n);
|
||||
@deftypefunx {double _Complex} ecl_to_cdfloat (cl_object n);
|
||||
@deftypefunx {long double _Complex} ecl_to_clfloat (cl_object n);
|
||||
@deftypefunx uint8_t ecl_to_uint8_t (cl_object n);
|
||||
@deftypefunx int8_t ecl_to_int8_t (cl_object n);
|
||||
@deftypefunx uint16_t ecl_to_uint16_t (cl_object n);
|
||||
@deftypefunx int16_t ecl_to_int16_t (cl_object n);
|
||||
@deftypefunx uint32_t ecl_to_uint32_t (cl_object n);
|
||||
@deftypefunx int32_t ecl_to_int32_t (cl_object n);
|
||||
@deftypefunx uint64_t ecl_to_uint64_t (cl_object n);
|
||||
@deftypefunx int64_t ecl_to_int64_t (cl_object n);
|
||||
@deftypefunx short ecl_to_short (cl_object n);
|
||||
@deftypefunx {unsigned short} ecl_to_ushort (cl_object n);
|
||||
@deftypefunx int ecl_to_int (cl_object n);
|
||||
@deftypefunx {unsigned int} ecl_to_uint (cl_object n);
|
||||
@deftypefunx long ecl_to_long (cl_object n);
|
||||
@deftypefunx {unsigned long} ecl_to_ulong (cl_object n);
|
||||
@deftypefunx {long long} ecl_to_long_long (cl_object n);
|
||||
@deftypefunx {unsigned long long} ecl_to_ulong_long (cl_object n);
|
||||
|
||||
@paragraph Description
|
||||
These functions and macros convert a Lisp object to the corresponding
|
||||
C number type. The conversion is done through a coercion process which
|
||||
may signal an error if the argument does not fit the expected type.
|
||||
@end deftypefun
|
||||
|
||||
@node Numbers - ANSI dictionary
|
||||
@subsubsection ANSI dictionary
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ of such types may depend on the platform, but it includes at least the
|
|||
Memory allocated types on the other hand require the use of the garbage
|
||||
collector to be created. ECL abstracts this from the user providing
|
||||
enough constructors, either in the form of Common Lisp functions
|
||||
(@code{cl_make_array()}, @code{cl_complex()},...), or in the form of
|
||||
C/C++ constructors (@code{ecl_make_symbol()}, etc).
|
||||
(@code{cl_make_array}, @code{cl_complex},...), or in the form of
|
||||
C/C++ constructors (@coderef{ecl_make_symbol}, etc).
|
||||
|
||||
Memory allocated types must always be kept alive so that the garbage
|
||||
collector does not reclaim them. This involves referencing the object
|
||||
|
|
@ -107,15 +107,15 @@ described below.
|
|||
|
||||
@itemize
|
||||
@item
|
||||
Functions in the Common Lisp (@code{CL}) package are prefixed with the
|
||||
characters @code{cl_}, functions in the System (@code{SI}) package are
|
||||
prefix with @code{si_}, etc, etc.
|
||||
Functions in the Common Lisp (@code{cl}) package are prefixed with the
|
||||
characters @code{cl_}, functions in the System (@code{si}) and
|
||||
Extensions (@code{ext}) package are prefix with @code{si_}, etc, etc.
|
||||
|
||||
@item
|
||||
If a function takes only a fixed number of arguments, it is mapped to a
|
||||
C function with also a fixed number of arguments. For instance,
|
||||
@code{COS} maps to @code{cl_object cl_cos(cl_object)}, which takes a
|
||||
single Lisp object and returns a Lisp object of type @code{FLOAT}.
|
||||
@code{cos} maps to @code{cl_object cl_cos(cl_object)}, which takes a
|
||||
single Lisp object and returns a Lisp object of type @code{float}.
|
||||
|
||||
@item
|
||||
If the function takes a variable number of arguments, its signature
|
||||
|
|
@ -127,9 +127,9 @@ a)}, etc.
|
|||
|
||||
@item
|
||||
Functions return at least one value, which is either the first value
|
||||
output by the function, or @code{NIL}. The extra values may be retrieved
|
||||
output by the function, or @code{nil}. The extra values may be retrieved
|
||||
immediately after the function call using the function
|
||||
@code{ecl_nth_value}.
|
||||
@coderef{ecl_nth_value}.
|
||||
@end itemize
|
||||
|
||||
In addition to the Common Lisp core functions (@code{cl_*}), there exist
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ and the table of known symbols is shown below. Note how some symbols (@code{:cr}
|
|||
|
||||
@subsubsection Sequence Streams
|
||||
|
||||
@lspindex ext:sequence-stream
|
||||
@lspdef ext:sequence-stream
|
||||
@deftp {System Class} ext:sequence-stream
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:sequence-stream, stream, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:sequence-stream}, @code{stream}, @code{t}
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Sequence streams work similar to string streams for vectors. The
|
||||
supplied vectors that the streams read from or write to must have a
|
||||
byte sized element type, i.e. @code{(signed-byte 8)},
|
||||
|
|
@ -134,12 +134,12 @@ vector, whose @code{char-code}s will be equal to the values of the
|
|||
bytes comprising the character in the given external format.
|
||||
@end deftp
|
||||
|
||||
@lspindex ext:make-sequence-input-stream
|
||||
@lspdef ext:make-sequence-input-stream
|
||||
@defun ext:make-sequence-input-stream vector &key (start 0) (end nil) (external-format nil)
|
||||
Create a sequence input stream with the subsequence bounded by
|
||||
@var{start} and @var{end} of the given vector.
|
||||
@end defun
|
||||
@lspindex ext:make-sequence-output-stream
|
||||
@lspdef ext:make-sequence-output-stream
|
||||
@defun ext:make-sequence-output-stream vector &key (external-format nil)
|
||||
Create a sequence output stream.
|
||||
@end defun
|
||||
|
|
@ -161,10 +161,10 @@ CL-USER> *output*
|
|||
|
||||
@subsubsection File Stream Extensions
|
||||
|
||||
@lspindex ext:set-buffering-mode
|
||||
@lspdef ext:set-buffering-mode
|
||||
@defun ext:set-buffering-mode stream mode
|
||||
Control the buffering mode of a stream
|
||||
@subsubheading Synopsis
|
||||
@paragraph Synopsis
|
||||
@table @var
|
||||
@item stream
|
||||
an ANSI stream
|
||||
|
|
@ -173,7 +173,7 @@ one of @code{nil}, @code{:none}, @code{:line}, @code{:line-buffered}, @code{:ful
|
|||
@item returns
|
||||
The supplied stream
|
||||
@end table
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
If @var{mode} is @code{nil} or @code{:none}, @var{stream} will not be
|
||||
buffered, if it is @code{:line} or @code{:line-buffered} resp.
|
||||
@code{:full} or @code{:fully-buffered}, @var{stream} will be line resp.
|
||||
|
|
@ -181,28 +181,28 @@ fully buffered. If the stream does not support buffering, nothing will
|
|||
happen.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:file-stream-fd
|
||||
@lspdef ext:file-stream-fd
|
||||
@defun ext:file-stream-fd file-stream
|
||||
Return the POSIX file descriptor of @var{file-stream} as an integer
|
||||
@end defun
|
||||
|
||||
@subsubsection External Format Extensions
|
||||
|
||||
@lspindex ext:all-encodings
|
||||
@lspdef ext:all-encodings
|
||||
@defun ext:all-encodings
|
||||
Return a list of all supported external formats
|
||||
@end defun
|
||||
|
||||
@lspindex ext:character-coding-error
|
||||
@lspdef ext:character-coding-error
|
||||
@deftp Condition ext:character-coding-error
|
||||
|
||||
Character coding error
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:character-coding-error, error, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:character-coding-error}, @code{error}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Methods
|
||||
@lspindex ext:character-coding-error-external-format
|
||||
@paragraph Methods
|
||||
@lspdef ext:character-coding-error-external-format
|
||||
@defun ext:character-coding-error-external-format condition
|
||||
@table @var
|
||||
@item returns
|
||||
|
|
@ -210,20 +210,20 @@ The external format of @var{condition}
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@subsubheading Description
|
||||
Superclass of @code{ext:character-encoding-error} and @code{ext:character-decoding-error}.
|
||||
@paragraph Description
|
||||
Superclass of @coderef{ext:character-encoding-error} and @coderef{ext:character-decoding-error}.
|
||||
@end deftp
|
||||
|
||||
@lspindex ext:character-encoding-error
|
||||
@lspdef ext:character-encoding-error
|
||||
@deftp Condition ext:character-encoding-error
|
||||
|
||||
Character encoding error
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:character-encoding-error, ext:character-coding-error, error, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:character-encoding-error}, @coderef{ext:character-coding-error}, @code{error}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Methods
|
||||
@lspindex ext:character-encoding-error-code
|
||||
@paragraph Methods
|
||||
@lspdef ext:character-encoding-error-code
|
||||
@defun ext:character-encoding-error-code condition
|
||||
@table @var
|
||||
@item returns
|
||||
|
|
@ -231,22 +231,22 @@ The character code of the character, which can't be encoded
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Condition for characters, which can't be encoded with some external
|
||||
format.
|
||||
@end deftp
|
||||
|
||||
|
||||
@lspindex ext:character-decoding-error
|
||||
@lspdef ext:character-decoding-error
|
||||
@deftp Condition ext:character-decoding-error
|
||||
|
||||
Character decoding error
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:character-decoding-error, ext:character-coding-error, error, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:character-decoding-error}, @coderef{ext:character-coding-error}, @code{error}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Methods
|
||||
@lspindex ext:character-decoding-error-octects
|
||||
@paragraph Methods
|
||||
@lspdef ext:character-decoding-error-octects
|
||||
@defun ext:character-decoding-error-octects condition
|
||||
@table @var
|
||||
@item returns
|
||||
|
|
@ -255,49 +255,49 @@ can't be decoded.
|
|||
@end table
|
||||
@end defun
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Condition for characters, which can't be decoded with some external
|
||||
format.
|
||||
@end deftp
|
||||
|
||||
@lspindex ext:stream-encoding-error
|
||||
@lspdef ext:stream-encoding-error
|
||||
@deftp Condition ext:stream-encoding-error
|
||||
|
||||
Stream encoding error
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:stream-encoding-error, ext:character-encoding-error, ext:character-coding-error, stream-error, error, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:stream-encoding-error}, @coderef{ext:character-encoding-error}, @coderef{ext:character-coding-error}, @code{stream-error}, @code{error}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This condition is signaled when trying to write a character to a
|
||||
stream, which can't be encoded with the streams external format.
|
||||
@end deftp
|
||||
|
||||
|
||||
@lspindex ext:stream-decoding-error
|
||||
@lspdef ext:stream-decoding-error
|
||||
@deftp Condition ext:stream-decoding-error
|
||||
|
||||
Stream decoding error
|
||||
|
||||
@subsubheading Class Precedence List
|
||||
@code{ext:stream-decoding-error, ext:character-decoding-error, ext:character-coding-error, stream-error, error, serious-condition, condition, t}
|
||||
@paragraph Class Precedence List
|
||||
@coderef{ext:stream-decoding-error}, @coderef{ext:character-decoding-error}, @coderef{ext:character-coding-error}, @code{stream-error}, @code{error}, @code{serious-condition}, @code{condition}, @code{t}
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This condition is signaled when trying to read a character from a
|
||||
stream, which can't be decoded with the streams external format.
|
||||
@end deftp
|
||||
|
||||
@lspindex ext:encoding-error
|
||||
@lspdef ext:encoding-error
|
||||
@defun ext:encoding-error stream external-format code
|
||||
Signal a @code{ext:stream-encoding-error} with the given
|
||||
Signal a @coderef{ext:stream-encoding-error} with the given
|
||||
@var{external-format} and @var{code}. Make a restart available so
|
||||
that the error can be ignored or the character can be replaced with a
|
||||
different one.
|
||||
@end defun
|
||||
|
||||
@lspindex ext:decoding-error
|
||||
@lspdef ext:decoding-error
|
||||
@defun ext:decoding-error stream external-format octects
|
||||
Signal a @code{ext:stream-decoding-error} with the given
|
||||
Signal a @coderef{ext:stream-decoding-error} with the given
|
||||
@var{external-format} and @var{octets}. Make a restart available so
|
||||
that the error can be ignored or the octets can be replaced with a
|
||||
character.
|
||||
|
|
@ -322,8 +322,8 @@ Common Lisp and C equivalence
|
|||
@item @clhs{f_file_p.htm,file-length} @tab cl_object cl_file_position(cl_narg narg, cl_object file_stream, ...)
|
||||
@item @clhs{f_file_s.htm,file-position} @tab cl_object cl_file_position(cl_object stream)
|
||||
@item @clhs{f_finish.htm,file-string-length} @tab cl_object cl_file_string_length(cl_object stream, cl_object object)
|
||||
@item @clhs{f_finish.htm,finish-output} @tab cl_object cl_finish_outputt(cl_narg narg, ...)
|
||||
@item @clhs{f_finish.htm,force-output} @tab cl_object cl_force_outputt(cl_narg narg, ...)
|
||||
@item @clhs{f_finish.htm,finish-output} @tab cl_object cl_finish_output(cl_narg narg, ...)
|
||||
@item @clhs{f_finish.htm,force-output} @tab cl_object cl_force_output(cl_narg narg, ...)
|
||||
@item @clhs{f_terpri.htm,fresh-line} @tab cl_object cl_fresh_line(cl_narg narg, ...)
|
||||
@item @clhs{f_get_out.htm,get-output-stream-string} @tab cl_object cl_get_output_stream_string(cl_object string_output_stream)
|
||||
@item @clhs{f_in_stm.htm,input-stream-p} @tab cl_object cl_input_stream_p(cl_object stream)
|
||||
|
|
|
|||
|
|
@ -26,50 +26,46 @@ It is important to remember that strings with unicode characters can only be pri
|
|||
@node Strings - C reference
|
||||
@subsection C reference
|
||||
@subsubsection Base string constructors
|
||||
@cppindex ecl_alloc_adjustable_base_string
|
||||
@cppindex ecl_alloc_adjustable_simple_string
|
||||
@cppindex ecl_make_simple_base_string
|
||||
@cppindex ecl_make_constant_base_string
|
||||
@cppdef ecl_alloc_adjustable_base_string
|
||||
@cppdef ecl_alloc_simple_base_string
|
||||
@cppdef ecl_make_simple_base_string
|
||||
@cppdef ecl_make_constant_base_string
|
||||
|
||||
Building strings of C data
|
||||
|
||||
@subsubheading Functions
|
||||
|
||||
@deftypefun cl_object ecl_alloc_adjustable_base_string (cl_index @var{length});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_alloc_adjustable_simple_string (cl_index @var{length});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_simple_base_string (const char* @var{data}, cl_fixnum @var{length});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_make_constant_base_string (const char* @var{data}, cl_fixnum @var{length});
|
||||
@end deftypefun
|
||||
@deftypefun cl_object ecl_alloc_adjustable_base_string (cl_index length);
|
||||
@deftypefunx cl_object ecl_alloc_simple_base_string (cl_index length);
|
||||
@deftypefunx cl_object ecl_make_simple_base_string (const char* data, cl_fixnum length);
|
||||
@deftypefunx cl_object ecl_make_constant_base_string (const char* data, cl_fixnum length);
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
These are different ways to create a base string, which is a string that holds a small subset of characters, the @code{base-char}, with codes ranging from 0 to 255.
|
||||
|
||||
@code{ecl_alloc_simple_base_string} creates an empty string with that much space for characters and a fixed length. The string does not have a fill pointer and cannot be resized, and the initial data is unspecified
|
||||
@coderef{ecl_alloc_simple_base_string} creates an empty string with that much space for characters and a fixed length. The string does not have a fill pointer and cannot be resized, and the initial data is unspecified
|
||||
|
||||
@code{ecl_alloc_adjustable_base_string} is similar to the previous function, but creates an adjustable string with a fill pointer. This means that the length of the string can be changed and the string itself can be resized to accommodate more data.
|
||||
@coderef{ecl_alloc_adjustable_base_string} is similar to the previous function, but creates an adjustable string with a fill pointer. This means that the length of the string can be changed and the string itself can be resized to accommodate more data.
|
||||
|
||||
The other constructors create strings but use some preexisting data. @code{ecl_make_simple_base_string} creates a string copying the data that the user supplies, and using freshly allocated memory. @code{ecl_make_constant_base_string} on the other hand, does not allocate memory, but simply uses the supplied pointer as buffer for the string. This last function should be used with care, ensuring that the supplied buffer is not deallocated. If the @var{length} argument of these functions is -1, the length is determined by @code{strlen}.
|
||||
The other constructors create strings but use some preexisting data. @coderef{ecl_make_simple_base_string} creates a string copying the data that the user supplies, and using freshly allocated memory. @coderef{ecl_make_constant_base_string} on the other hand, does not allocate memory, but simply uses the supplied pointer as buffer for the string. This last function should be used with care, ensuring that the supplied buffer is not deallocated. If the @var{length} argument of these functions is -1, the length is determined by @code{strlen}.
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection String accessors
|
||||
@cppindex ecl_char
|
||||
@cppindex ecl_char_set
|
||||
@cppdef ecl_char
|
||||
@cppdef ecl_char_set
|
||||
Reading and writing characters into a string
|
||||
|
||||
@subsubheading Functions
|
||||
@deftypefun ecl_character ecl_char (cl_object @var{string}, cl_index @var{index});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ecl_char_set (cl_object @var{string}, cl_index @var{index}, ecl_character @var{c});
|
||||
@end deftypefun
|
||||
@deftypefun ecl_character ecl_char (cl_object string, cl_index index);
|
||||
@deftypefunx ecl_character ecl_char_set (cl_object string, cl_index index, ecl_character c);
|
||||
|
||||
@subsubheading Description
|
||||
Access to string information should be done using these two functions. The first one implements the equivalent of the @code{CHAR} function from Common Lisp, returning the character that is at position @var{index} in the string @var{string}.
|
||||
@paragraph Description
|
||||
Access to string information should be done using these two functions. The first one implements the equivalent of the @code{char} function from Common Lisp, returning the character that is at position @var{index} in the string @var{string}.
|
||||
|
||||
The counterpart of the previous function is @code{ecl_char_set}, which implements @code{(SETF CHAR)} and stores character @var{c} at the position @var{index} in the given string.
|
||||
The counterpart of the previous function is @coderef{ecl_char_set}, which implements @code{(setf char)} and stores character @var{c} at the position @var{index} in the given string.
|
||||
|
||||
Both functions check the type of their arguments and verify that the indices do not exceed the string boundaries. Otherwise they signal a @code{serious-condition}.
|
||||
@end deftypefun
|
||||
|
||||
@subsubsection ANSI dictionary
|
||||
Common Lisp and C equivalence
|
||||
|
|
|
|||
|
|
@ -4,22 +4,21 @@
|
|||
There are no implementation-specific limits on the size or content of symbol names. It is however not allowed to write on the strings which have been passed to @code{#'make-symbol} or returned from @code{#'symbol-name}.
|
||||
|
||||
@subsection C Reference
|
||||
@cppindex ecl_make_keyword
|
||||
@cppindex ecl_make_symbol
|
||||
|
||||
@deftypefun cl_object ecl_make_keyword (char * @var{name});
|
||||
@cppdef ecl_make_keyword
|
||||
@deftypefun cl_object ecl_make_keyword (char *name);
|
||||
Find a lisp keyword
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
|
||||
Many Lisp functions take keyword arguments. When invoking a function with keyword arguments we need keywords, which are a kind of symbols that live in the @code{KEYWORD} package. This function does the task of finding or creating those keywords from C strings.
|
||||
Many Lisp functions take keyword arguments. When invoking a function with keyword arguments we need keywords, which are a kind of symbols that live in the @code{keyword} package. This function does the task of finding or creating those keywords from C strings.
|
||||
|
||||
@itemize
|
||||
@item It is usually safe to store the resulting pointer, because keywords are always referenced by their package and will not be garbage collected (unless of course, you decide to delete it).
|
||||
@item Remember that the case of the string is significant. @code{ecl_make_keyword("TO")} with return @code{:TO}, while @code{ecl_make_keyword("to")} returns a completely different keyword, @code{:|to|}. In short, you usually want to use uppercase.
|
||||
@end itemize
|
||||
|
||||
@subsubheading Example
|
||||
@paragraph Example
|
||||
The following example converts a section of a string to uppercase characters:
|
||||
|
||||
@example
|
||||
|
|
@ -32,11 +31,15 @@ sup = cl_string_upcase(4, s, start, ecl_make_fixnum(2),
|
|||
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun cl_object ecl_make_symbol (const char * @var{name}, const char * @var{package_name});
|
||||
@cppdef ecl_make_symbol
|
||||
@deftypefun cl_object ecl_make_symbol (const char *name, const char *package_name);
|
||||
Find a lisp symbol
|
||||
|
||||
@subsubheading Description
|
||||
This function finds or create a symbol in the given package. First of all, it tries to find the package named by @var{package_name}. If it does not exist, an error is signaled. Then, a symbol with the suppled @var{name} is searched in the given package. If the symbol exists, it is returned. If it does not exist, using @code{INTERN}.
|
||||
@paragraph Description
|
||||
This function finds or create a symbol in the given package. First of
|
||||
all, it tries to find the package named by @var{package_name}. If it
|
||||
does not exist, an error is signaled. Then, a symbol with the supplied
|
||||
@var{name} is created and interned in the given package.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@
|
|||
@lspindex single-float
|
||||
@lspindex double-float
|
||||
|
||||
ECL defines the following additional built-in classes in the @code{CL} package:
|
||||
ECL defines the following additional built-in classes in the @code{cl} package:
|
||||
|
||||
@itemize
|
||||
@item @code{single-float}
|
||||
@item @code{double-float}
|
||||
@item @code{long-float}
|
||||
@end itemize
|
||||
|
||||
@subsection C Reference
|
||||
|
|
|
|||
|
|
@ -152,5 +152,5 @@ make install
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
Library and assets are installed in the @code{ecl-android} directory
|
||||
Library and assets are installed in the "ecl-android" directory
|
||||
and are ready to run on the Android system.
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
@node Embedding ECL - Embedding Reference
|
||||
@subsection Embedding Reference
|
||||
|
||||
@cppindex CL_CATCH_ALL
|
||||
@cppdef CL_CATCH_ALL
|
||||
@defmac CL_CATCH_ALL
|
||||
Create a protected region.
|
||||
|
||||
@subsubheading C Macro
|
||||
@paragraph C Macro
|
||||
@example
|
||||
@verbatim
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
|
|
@ -37,8 +37,8 @@ CL_CATCH_ALL_BEGIN(env) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
This is a set of three macros that create an @code{UNWIND-PROTECT} region that prevents any nonlocal transfer of control to outer loops. In the Lisp speak, the previous code is equivalent to
|
||||
@paragraph Description
|
||||
This is a set of three macros that create an @code{unwind-protect} region that prevents any nonlocal transfer of control to outer loops. In the Lisp speak, the previous code is equivalent to
|
||||
|
||||
@lisp
|
||||
(block nil
|
||||
|
|
@ -49,19 +49,17 @@ This is a set of three macros that create an @code{UNWIND-PROTECT} region that p
|
|||
(return nil)))
|
||||
@end lisp
|
||||
|
||||
As explained in @code{CL_UNWIND_PROTECT},it is normally advisable to set up an unwind-protect frame to avoid the embedded lisp code to perform arbitrary transfers of control.
|
||||
|
||||
@subsubheading See also
|
||||
@code{CL_UNWIND_PROTECT}
|
||||
As explained in @coderef{CL_UNWIND_PROTECT}, it is normally advisable to set up an unwind-protect frame to avoid the embedded lisp code to perform arbitrary transfers of control.
|
||||
|
||||
@seealso{CL_UNWIND_PROTECT}
|
||||
@end defmac
|
||||
|
||||
|
||||
@cppindex CL_UNWIND_PROTECT
|
||||
@cppdef CL_UNWIND_PROTECT
|
||||
@defmac CL_UNWIND_PROTECT
|
||||
Create a protected region.
|
||||
|
||||
@subsubheading C Macro
|
||||
@paragraph C Macro
|
||||
@example
|
||||
@verbatim
|
||||
cl_env_ptr env = ecl_process_env();
|
||||
|
|
@ -85,23 +83,20 @@ CL_UNWIND_PROTECT_BEGIN(env) {
|
|||
@end verbatim
|
||||
@end example
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
When embedding ECL it is normally advisable to set up an @code{unwind-protect} frame to avoid the embedded lisp code to perform arbitrary transfers of control. Furthermore, the unwind protect form will be used in at least in the following occasions:
|
||||
|
||||
@itemize
|
||||
@item In a normal program exit, caused by @code{ext:quit}, ECL unwinds up to the outermost frame, which may be an @code{CL_CATCH_ALL} or @code{CL_UNWIND_PROTECT} macro.
|
||||
@item In a normal program exit, caused by @coderef{ext:quit}, ECL unwinds up to the outermost frame, which may be an @coderef{CL_CATCH_ALL} or @coderef{CL_UNWIND_PROTECT} macro.
|
||||
@end itemize
|
||||
|
||||
Besides this, normal mechanisms for exit, such as @code{ext:quit}, and uncaught exceptions, such as serious signals (@xref{Signals and Interrupts - Synchronous signals}), are best handled using @code{unwind-protect} blocks.
|
||||
|
||||
@subsubheading See also
|
||||
@code{CL_CATCH_ALL}
|
||||
Besides this, normal mechanisms for exit, such as @coderef{ext:quit}, and uncaught exceptions, such as serious signals (@xref{Signals and Interrupts - Synchronous signals}), are best handled using @code{unwind-protect} blocks.
|
||||
|
||||
@seealso CL_CATCH_ALL
|
||||
@end defmac
|
||||
|
||||
|
||||
@cppindex cl_boot
|
||||
@deftypefun int cl_boot (int @var{argc}, char **@var{argv});
|
||||
@cppdef cl_boot
|
||||
@deftypefun int cl_boot (int argc, char **argv);
|
||||
Setup the lisp environment.
|
||||
@table @var
|
||||
@item argc
|
||||
|
|
@ -110,20 +105,21 @@ An integer with the number of arguments to this program.
|
|||
A vector of strings with the arguments to this program.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
This function must be called before any other function from the ECL library, including the creation of any lisp object or evaluating any lisp code. The only exception are @code{ecl_set_option} and @code{ecl_get_option}.
|
||||
@paragraph Description
|
||||
This function must be called before any other function from the ECL library, including the creation of any lisp object or evaluating any lisp code. The only exception are @coderef{ecl_set_option} and @coderef{ecl_get_option}.
|
||||
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex cl_shutdown
|
||||
@cppdef cl_shutdown
|
||||
@deftypefun int cl_shutdown (void);
|
||||
Close the lisp environment.
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This function must be called before exiting a program that uses the ECL environment. It performs some cleaning, including the execution of any finalizers, unloading shared libraries and deleting temporary files that were created by the compiler.
|
||||
@end deftypefun
|
||||
|
||||
@cppdef ecl_set_option
|
||||
@deftypefun void ecl_set_option (int option, cl_fixnum value);
|
||||
Set a boot option.
|
||||
|
||||
|
|
@ -134,7 +130,7 @@ An integer from @ref{tab:boot-options}.
|
|||
A @code{cl_index} value for this option
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This functions sets the value of different options that have to be customized @emph{before} ECL boots. The table of options and default values [@ref{tab:boot-options}] shows that some of them are boolean, and some of them are unsigned integers.
|
||||
|
||||
We distinguish three sets of values. The first set determines whether ECL handles certain exceptions, such as access to forbidden regions of memory, interrupts via , floating point exceptions, etc.
|
||||
|
|
@ -145,14 +141,14 @@ The second set is related to the sizes of different stacks. Currently ECL uses f
|
|||
@caption{Boot options for embedded ECL}
|
||||
@multitable @columnfractions .3 .15 .16 .39
|
||||
@headitem Name @code{(ECL_OPT_*)} @tab Type @tab Default @tab Description
|
||||
@item @code{INCREMENTAL_GC} @tab boolean @tab @code{TRUE} @tab Activate generational garbage collector.
|
||||
@item @code{TRAP_SIGSEGV} @tab boolean @tab @code{TRUE} @tab Capture @code{SIGSEGV} signals.
|
||||
@item @code{TRAP_SIGFPE} @tab boolean @tab @code{TRUE} @tab Capture floating point exceptions.
|
||||
@item @code{TRAP_SIGINT} @tab boolean @tab @code{TRUE} @tab Capture user interrupts.
|
||||
@item @code{TRAP_SIGILL} @tab boolean @tab @code{TRUE} @tab Capture @code{SIGILL} exception.
|
||||
@item @code{TRAP_INTERRUPT_SIGNAL} @tab boolean @tab @code{TRUE} @tab Capture the signal that implements @code{mp:interrupt-process}.
|
||||
@item @code{SIGNAL_HANDLING_THREAD} @tab boolean @tab @code{TRUE} @tab Create a signal to capture and process asynchronous threads (@xref{Signals and Interrupts - Asynchronous signals}).
|
||||
@item @code{BOOTED} @tab boolean @tab @code{TRUE}/@code{FALSE} @tab Has ECL booted (read only).
|
||||
@item @code{INCREMENTAL_GC} @tab boolean @tab TRUE @tab Activate generational garbage collector.
|
||||
@item @code{TRAP_SIGSEGV} @tab boolean @tab TRUE @tab Capture @code{SIGSEGV} signals.
|
||||
@item @code{TRAP_SIGFPE} @tab boolean @tab TRUE @tab Capture floating point exceptions.
|
||||
@item @code{TRAP_SIGINT} @tab boolean @tab TRUE @tab Capture user interrupts.
|
||||
@item @code{TRAP_SIGILL} @tab boolean @tab TRUE @tab Capture @code{SIGILL} exception.
|
||||
@item @code{TRAP_INTERRUPT_SIGNAL} @tab boolean @tab TRUE @tab Capture the signal that implements @coderef{mp:interrupt-process}.
|
||||
@item @code{SIGNAL_HANDLING_THREAD} @tab boolean @tab TRUE @tab Create a signal to capture and process asynchronous threads (@xref{Signals and Interrupts - Asynchronous signals}).
|
||||
@item @code{BOOTED} @tab boolean @tab TRUE/FALSE @tab Has ECL booted (read only).
|
||||
@item @code{BIND_STACK_SIZE} @tab cl_index @tab 8192 @tab Size of stack for binding special variables.
|
||||
@item @code{BIND_STACK_SAFETY_AREA} @tab cl_index @tab 128 @tab
|
||||
@item @code{FRAME_STACK_SIZE} @tab cl_index @tab 2048 @tab Size of stack for nonlocal jumps.
|
||||
|
|
@ -167,59 +163,59 @@ The second set is related to the sizes of different stacks. Currently ECL uses f
|
|||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_get_option
|
||||
@deftypefun cl_fixnum ecl_get_option (int @var{option});
|
||||
@cppdef ecl_get_option
|
||||
@deftypefun cl_fixnum ecl_get_option (int option);
|
||||
Read the value of a boot option.
|
||||
@table @var
|
||||
@item option
|
||||
An integer from @ref{tab:boot-options}.
|
||||
@end table
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This functions reads the value of different options that have to be customized @emph{before} ECL boots. The table of options and default values is @ref{tab:boot-options}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@cppindex ecl_clear_interrupts
|
||||
@cppdef ecl_clear_interrupts
|
||||
@defmac ecl_clear_interrupts ()
|
||||
Clear all pending signals and exceptions.
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This macro clears all pending interrupts.
|
||||
|
||||
@subsubheading See also
|
||||
@code{ecl_disable_interrupts} and @code{ecl_enable_interrupts}.
|
||||
@paragraph See also
|
||||
@coderef{ecl_disable_interrupts} and @coderef{ecl_enable_interrupts}.
|
||||
@end defmac
|
||||
|
||||
|
||||
@cppindex ecl_disable_interrupts
|
||||
@cppdef ecl_disable_interrupts
|
||||
@defmac ecl_disable_interrupts ()
|
||||
Postpone handling of signals and exceptions.
|
||||
|
||||
@subsubheading Description
|
||||
This macro sets a thread-local flag indicating that all received signals should be queued for later processing. Note that it is not possible to execute lisp code while interrupts are disabled in this way. For this purpose, use the @code{ext:without-interrupts} macro. Every call to @code{ecl_disable_interrupts} must be followed by a corresponding call to @code{ecl_enable_interrupts}, else race conditions will appear.
|
||||
@paragraph Description
|
||||
This macro sets a thread-local flag indicating that all received signals should be queued for later processing. Note that it is not possible to execute lisp code while interrupts are disabled in this way. For this purpose, use the @coderef{mp:without-interrupts} macro. Every call to @coderef{ecl_disable_interrupts} must be followed by a corresponding call to @coderef{ecl_enable_interrupts}, else race conditions will appear.
|
||||
|
||||
@subsubheading See also
|
||||
@code{ecl_enable_interrupts} and @code{ecl_clear_interrupts}.
|
||||
@paragraph See also
|
||||
@coderef{ecl_enable_interrupts} and @coderef{ecl_clear_interrupts}.
|
||||
@end defmac
|
||||
|
||||
|
||||
@cppindex ecl_enable_interrupts
|
||||
@cppdef ecl_enable_interrupts
|
||||
@defmac ecl_enable_interrupts();
|
||||
Activate handling of signals and exceptions.
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
This macro sets a thread-local flag indicating that all received signals can be handled. If there are any pending signals, they will be immediately processed.
|
||||
|
||||
@subsubheading See also
|
||||
@code{ecl_disable_interrupts} and @code{ecl_clear_interrupts}.
|
||||
@paragraph See also
|
||||
@coderef{ecl_disable_interrupts} and @coderef{ecl_clear_interrupts}.
|
||||
@end defmac
|
||||
|
||||
@cppindex ECL_WITH_LISP_FPE
|
||||
@cppdef ECL_WITH_LISP_FPE
|
||||
@defmac ECL_WITH_LISP_FPE
|
||||
Execute Lisp code with correct floating point environment
|
||||
|
||||
@subsubheading Description
|
||||
@paragraph Description
|
||||
Unless floating point exceptions are disabled (via the
|
||||
@code{--without-fpe} configure option or @code{ECL_OPT_TRAP_SIGFPE}
|
||||
runtime option), ECL will change the floating point environment when
|
||||
|
|
@ -227,11 +223,11 @@ booting. This macro allows for execution of Lisp code while saving and
|
|||
later restoring the floating point environment of surrounding C code
|
||||
so that changes in the floating point environment don't leak outside.
|
||||
|
||||
@code{ECL_WITH_LISP_FPE} can be also used before ECL has booted or
|
||||
@coderef{ECL_WITH_LISP_FPE} can be also used before ECL has booted or
|
||||
before ECL has been attached to a newly created thread.
|
||||
|
||||
@exindex Safely executing Lisp code with floating point exceptions in embedding program
|
||||
@subsubheading Example
|
||||
@paragraph Example
|
||||
@example
|
||||
@verbatim
|
||||
#include <ecl/ecl.h>
|
||||
|
|
@ -264,7 +260,6 @@ will output
|
|||
inf 0
|
||||
@end verbatim
|
||||
|
||||
@subsubheading See also
|
||||
@code{ext:trap-fpe}
|
||||
@seealso{ext:trap-fpe}
|
||||
|
||||
@end defmac
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ The number in the @ecl{} banner identifies the revision of
|
|||
Unless user specifies @code{--norc} flag when invoking the @ecl{}, it
|
||||
will look for the initialization files @file{~/.ecl} and
|
||||
@file{~/.eclrc}. If he wants to load his own file from the current
|
||||
directory, then he should pass the file path to the @code{-load}
|
||||
directory, then he should pass the file path to the @code{--load}
|
||||
parameter:
|
||||
@example
|
||||
% ecl --norc --load init.lisp
|
||||
|
|
@ -42,7 +42,7 @@ Type :h for Help. Top level.
|
|||
The prompt indicates that @ecl{} is now ready to receive a form from the
|
||||
terminal and to evaluate it.
|
||||
|
||||
Usually, the current package (i.e., the value of @var{*package*}) is the
|
||||
Usually, the current package (i.e., the value of @code{*package*}) is the
|
||||
user package, and the prompt appears as above. If, however, the current
|
||||
package is other than the user package, then the prompt will be prefixed
|
||||
with the package name.
|
||||
|
|
@ -55,7 +55,7 @@ COMMON-LISP> (in-package "SYSTEM")
|
|||
SI>
|
||||
@end example
|
||||
|
||||
To exit from @ecl{}, call the function @code{quit}.
|
||||
To exit from @ecl{}, call the function @coderef{ext:quit}.
|
||||
|
||||
@example
|
||||
> (quit)
|
||||
|
|
@ -110,7 +110,7 @@ Broken at FOO. In: #<process TOP-LEVEL>.
|
|||
|
||||
`@code{>>}' in the last line is the prompt of the break loop. Like in
|
||||
the top-level loop, the prompt will be prefixed by the current package
|
||||
name, if the current package is other than the @code{user} package.
|
||||
name, if the current package is other than the @code{cl-user} package.
|
||||
|
||||
To go back to the top-level loop, type @code{:q}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue