Next: General Coding Rules, Up: Rules When Writing New C Code [Contents][Index]
Of course the low-level implementation language of SXEmacs is C, but much of that uses the Lisp engine to do its work. However, because the code is “inside” of the protective containment shell around the “reactor core,” you’ll see lots of complex “plumbing” needed to do the work and “safety mechanisms,” whose failure results in a meltdown. This section provides a quick overview (or review) of the various components of the implementation of Lisp objects.
Two typographic conventions help to identify C objects that implement Lisp objects. The first is that capitalized identifiers, especially beginning with the letters ‘Q’, ‘V’, ‘F’, and ‘S’, for C variables and functions, and C macros with beginning with the letter ‘X’, are used to implement Lisp. The second is that where Lisp uses the hyphen ‘-’ in symbol names, the corresponding C identifiers use the underscore ‘_’. Of course, since SXEmacs Lisp contains interfaces to many external libraries, those external names will follow the coding conventions their authors chose, and may overlap the “SXEmacs name space.” However these cases are usually pretty obvious.
All Lisp objects are handled indirectly. The Lisp_Object
type is usually a pointer to a structure, except for a very small number
of types with immediate representations (currently characters and
integers). However, these types cannot be directly operated on in C
code, either, so they can also be considered indirect. Types that do
not have an immediate representation always have a C typedef
Lisp_type
for a corresponding structure.
In older code, it was common practice to pass around pointers to
Lisp_type
, but this is now deprecated in favor of using
Lisp_Object
for all function arguments and return values that are
Lisp objects. The Xtype
macro is used to extract the
pointer and cast it to (Lisp_type *)
for the desired type.
Convention: macros whose names begin with ‘X’ operate on
Lisp_Object
s and do no type-checking. Many such macros are type
extractors, but others implement Lisp operations in C (e.g.,
XCAR
implements the Lisp car
function). These are unsafe,
and must only be used where types of all data have already been checked.
Such macros are only applied to Lisp_Object
s. In internal
implementations where the pointer has already been converted, the
structure is operated on directly using the C ->
member access
operator.
The typeP
, CHECK_type
, and
CONCHECK_type
macros are used to test types. The first
returns a Boolean value, and the latter signal errors. (The
‘CONCHECK’ variety allows execution to be CONtinued under some
circumstances, thus the name.) Functions which expect to be passed user
data invariably call ‘CHECK’ macros on arguments.
There are many types of specialized Lisp objects implemented in C, but the most pervasive type is the symbol. Symbols are used as identifiers, variables, and functions.
Convention: Global variables whose names begin with ‘Q’
are constants whose value is a symbol. The name of the variable should
be derived from the name of the symbol using the same rules as for Lisp
primitives. Such variables allow the C code to check whether a
particular Lisp_Object
is equal to a given symbol. Symbols are
Lisp objects, so these variables may be passed to Lisp primitives. (An
alternative to the use of ‘Q...’ variables is to call the
intern
function at initialization in the
vars_of_module
function, which is hardly less efficient.)
Convention: Global variables whose names begin with ‘V’
are variables that contain Lisp objects. The convention here is that
all global variables of type Lisp_Object
begin with ‘V’, and
no others do (not even integer and boolean variables that have Lisp
equivalents). Most of the time, these variables have equivalents in
Lisp, which are defined via the ‘DEFVAR’ family of macros, but some
don’t. Since the variable’s value is a Lisp_Object
, it can be
passed to Lisp primitives.
The implementation of Lisp primitives is more complex.
Convention: Global variables with names beginning with ‘S’
contain a structure that allows the Lisp engine to identify and call a C
function. In modern versions of SXEmacs, these identifiers are almost
always completely hidden in the DEFUN
and SUBR
macros, but
you will encounter them if you look at very old versions of SXEmacs or at
GNU Emacs. Convention: Functions with names beginning with
‘F’ implement Lisp primitives. Of course all their arguments and
their return values must be Lisp_Objects. (This is hidden in the
DEFUN
macro.)
Next: General Coding Rules, Up: Rules When Writing New C Code [Contents][Index]