Next: Writing Good Comments, Previous: General Coding Rules, Up: Rules When Writing New C Code [Contents][Index]
Lisp primitives are Lisp functions implemented in C. The details of interfacing the C function so that Lisp can call it are handled by a few C macros. The only way to really understand how to write new C code is to read the source, but we can explain some things here.
An example of a special form is the definition of prog1
, from
eval.c. (An ordinary function would have the same general
appearance.)
DEFUN ("prog1", Fprog1, 1, UNEVALLED, 0, /* Similar to `progn', but the value of the first form is returned. \(prog1 FIRST BODY...): All the arguments are evaluated sequentially. The value of FIRST is saved during evaluation of the remaining args, whose values are discarded. */ (args)) { /* This function can GC */ REGISTER Lisp_Object val, form, tail; struct gcpro gcpro1; val = Feval (XCAR (args)); GCPRO1 (val); LIST_LOOP_3 (form, XCDR (args), tail) Feval (form); UNGCPRO; return val; }
Let’s start with a precise explanation of the arguments to the
DEFUN
macro. Here is a template for them:
DEFUN (lname, fname, min_args, max_args, interactive, /* docstring */ (arglist))
This string is the name of the Lisp symbol to define as the function
name; in the example above, it is "prog1"
.
This is the C function name for this function. This is the name that is
used in C code for calling the function. The name is, by convention,
‘F’ prepended to the Lisp name, with all dashes (‘-’) in the
Lisp name changed to underscores. Thus, to call this function from C
code, call Fprog1
. Remember that the arguments are of type
Lisp_Object
; various macros and functions for creating values of
type Lisp_Object
are declared in the file lisp.h.
Primitives whose names are special characters (e.g. +
or
<
) are named by spelling out, in some fashion, the special
character: e.g. Fplus()
or Flss()
. Primitives whose names
begin with normal alphanumeric characters but also contain special
characters are spelled out in some creative way, e.g. let*
becomes FletX()
.
Each function also has an associated structure that holds the data for
the subr object that represents the function in Lisp. This structure
conveys the Lisp symbol name to the initialization routine that will
create the symbol and store the subr object as its definition. The C
variable name of this structure is always ‘S’ prepended to the
fname. You hardly ever need to be aware of the existence of this
structure, since DEFUN
plus DEFSUBR
takes care of all the
details.
This is the minimum number of arguments that the function requires. The
function prog1
allows a minimum of one argument.
This is the maximum number of arguments that the function accepts, if
there is a fixed maximum. Alternatively, it can be UNEVALLED
,
indicating a special form that receives unevaluated arguments, or
MANY
, indicating an unlimited number of evaluated arguments (the
C equivalent of &rest
). Both UNEVALLED
and MANY
are macros. If max_args is a number, it may not be less than
min_args and it may not be greater than 8. (If you need to add a
function with more than 8 arguments, use the MANY
form. Resist
the urge to edit the definition of DEFUN
in lisp.h. If
you do it anyways, make sure to also add another clause to the switch
statement in primitive_funcall().
)
This is an interactive specification, a string such as might be used as
the argument of interactive
in a Lisp function. In the case of
prog1
, it is 0 (a null pointer), indicating that prog1
cannot be called interactively. A value of ""
indicates a
function that should receive no arguments when called interactively.
This is the documentation string. It is written just like a documentation string for a function defined in Lisp; in particular, the first line should be a single sentence. Note how the documentation string is enclosed in a comment, none of the documentation is placed on the same lines as the comment-start and comment-end characters, and the comment-start characters are on the same line as the interactive specification. make-docfile, which scans the C files for documentation strings, is very particular about what it looks for, and will not properly extract the doc string if it’s not in this exact format.
In order to make both etags and make-docfile happy, make
sure that the DEFUN
line contains the lname and
fname, and that the comment-start characters for the doc string
are on the same line as the interactive specification, and put a newline
directly after them (and before the comment-end characters).
This is the comma-separated list of arguments to the C function. For a
function with a fixed maximum number of arguments, provide a C argument
for each Lisp argument. In this case, unlike regular C functions, the
types of the arguments are not declared; they are simply always of type
Lisp_Object
.
The names of the C arguments will be used as the names of the arguments
to the Lisp primitive as displayed in its documentation, modulo the same
concerns described above for F...
names (in particular,
underscores in the C arguments become dashes in the Lisp arguments).
There is one additional kludge: A trailing ‘_’ on the C argument is
discarded when forming the Lisp argument. This allows C language
reserved words (like default
) or global symbols (like
dirname
) to be used as argument names without compiler warnings
or errors.
A Lisp function with max_args = UNEVALLED
is a
special form; its arguments are not evaluated. Instead it
receives one argument of type Lisp_Object
, a (Lisp) list of the
unevaluated arguments, conventionally named (args)
.
When a Lisp function has no upper limit on the number of arguments,
specify max_args = MANY
. In this case its implementation in
C actually receives exactly two arguments: the number of Lisp arguments
(an int
) and the address of a block containing their values (a
Lisp_Object *
). In this case only are the C types specified
in the arglist: (int nargs, Lisp_Object *args)
.
Within the function Fprog1
itself, note the use of the macros
GCPRO1
and UNGCPRO
. GCPRO1
is used to “protect”
a variable from garbage collection—to inform the garbage collector
that it must look in that variable and regard the object pointed at by
its contents as an accessible object. This is necessary whenever you
call Feval
or anything that can directly or indirectly call
Feval
(this includes the QUIT
macro!). At such a time,
any Lisp object that you intend to refer to again must be protected
somehow. UNGCPRO
cancels the protection of the variables that
are protected in the current function. It is necessary to do this
explicitly.
The macro GCPRO1
protects just one local variable. If you want
to protect two, use GCPRO2
instead; repeating GCPRO1
will
not work. Macros GCPRO3
and GCPRO4
also exist.
These macros implicitly use local variables such as gcpro1
; you
must declare these explicitly, with type struct gcpro
. Thus, if
you use GCPRO2
, you must declare gcpro1
and gcpro2
.
Note also that the general rule is caller-protects; i.e. you are only responsible for protecting those Lisp objects that you create. Any objects passed to you as arguments should have been protected by whoever created them, so you don’t in general have to protect them.
In particular, the arguments to any Lisp primitive are always
automatically GCPRO
ed, when called “normally” from Lisp code or
bytecode. So only a few Lisp primitives that are called frequently from
C code, such as Fprogn
protect their arguments as a service to
their caller. You don’t need to protect your arguments when writing a
new DEFUN
.
GCPRO
ing is perhaps the trickiest and most error-prone part of
SXEmacs coding. It is extremely important that you get this
right and use a great deal of discipline when writing this code.
See GCPRO
ing, for full details on how to do this.
What DEFUN
actually does is declare a global structure of type
Lisp_Subr
whose name begins with capital ‘SF’ and which
contains information about the primitive (e.g. a pointer to the
function, its minimum and maximum allowed arguments, a string describing
its Lisp name); DEFUN
then begins a normal C function declaration
using the F...
name. The Lisp subr object that is the function
definition of a primitive (i.e. the object in the function slot of the
symbol that names the primitive) actually points to this ‘SF’
structure; when Feval
encounters a subr, it looks in the
structure to find out how to call the C function.
Defining the C function is not enough to make a Lisp primitive available; you must also create the Lisp symbol for the primitive (the symbol is interned; see Obarrays) and store a suitable subr object in its function cell. (If you don’t do this, the primitive won’t be seen by Lisp code.) The code looks like this:
DEFSUBR (fname);
Here fname is the same name you used as the second argument to
DEFUN
.
This call to DEFSUBR
should go in the syms_of_*()
function
at the end of the module. If no such function exists, create it and
make sure to also declare it in symsinit.h and call it from the
appropriate spot in main()
. See General Coding Rules.
Note that C code cannot call functions by name unless they are defined
in C. The way to call a function written in Lisp from C is to use
Ffuncall
, which embodies the Lisp function funcall
. Since
the Lisp function funcall
accepts an unlimited number of
arguments, in C it takes two: the number of Lisp-level arguments, and a
one-dimensional array containing their values. The first Lisp-level
argument is the Lisp function to call, and the rest are the arguments to
pass to it. Since Ffuncall
can call the evaluator, you must
protect pointers from garbage collection around the call to
Ffuncall
. (However, Ffuncall
explicitly protects all of
its parameters, so you don’t have to protect any pointers passed as
parameters to it.)
The C functions call0
, call1
, call2
, and so on,
provide handy ways to call a Lisp function conveniently with a fixed
number of arguments. They work by calling Ffuncall
.
eval.c is a very good file to look through for examples; lisp.h contains the definitions for important macros and functions.
Next: Writing Good Comments, Previous: General Coding Rules, Up: Rules When Writing New C Code [Contents][Index]