elisp: Writing Emacs Primitives

 
 E.7 Writing Emacs Primitives
 ============================
 
 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 ‘or’, from
 ‘eval.c’.  (An ordinary function would have the same general
 appearance.)
 
      DEFUN ("or", For, Sor, 0, UNEVALLED, 0,
        doc: /* Eval args until one of them yields non-nil, then return
      that value.
      The remaining args are not evalled at all.
      If all args return nil, return nil.
      usage: (or CONDITIONS...)  */)
        (Lisp_Object args)
      {
        Lisp_Object val = Qnil;
 
        while (CONSP (args))
          {
            val = eval_sub (XCAR (args));
            if (!NILP (val))
              break;
            args = XCDR (args);
            QUIT;
          }
 
        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, SNAME, MIN, MAX, INTERACTIVE, DOC)
 
 LNAME
      This is the name of the Lisp symbol to define as the function name;
      in the example above, it is ‘or’.
 
 FNAME
      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 ‘For’.
 
 SNAME
      This is a C variable name to use for a 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.  By convention, this name is always FNAME with ‘F’
      replaced with ‘S’.
 
 MIN
      This is the minimum number of arguments that the function requires.
      The function ‘or’ allows a minimum of zero arguments.
 
 MAX
      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
      equivalent of ‘&rest’).  Both ‘UNEVALLED’ and ‘MANY’ are macros.
      If MAX is a number, it must be more than MIN but less than 8.
 
 INTERACTIVE
      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 ‘or’, it is 0 (a null pointer), indicating that ‘or’ cannot
      be called interactively.  A value of ‘""’ indicates a function that
      should receive no arguments when called interactively.  If the
      value begins with a ‘"(’, the string is evaluated as a Lisp form.
      For example:
 
           DEFUN ("foo", Ffoo, Sfoo, 0, UNEVALLED,
                  "(list (read-char-by-name \"Insert character: \")\
                         (prefix-numeric-value current-prefix-arg)\
                         t))",
             doc: /* ... /*)
 
 DOC
      This is the documentation string.  It uses C comment syntax rather
      than C string syntax because comment syntax requires nothing
      special to include multiple lines.  The ‘doc:’ identifies the
      comment that follows as the documentation string.  The ‘/*’ and
      ‘*/’ delimiters that begin and end the comment are not part of the
      documentation string.
 
      If the last line of the documentation string begins with the
      keyword ‘usage:’, the rest of the line is treated as the argument
      list for documentation purposes.  This way, you can use different
      argument names in the documentation string from the ones used in
      the C code.  ‘usage:’ is required if the function has an unlimited
      number of arguments.
 
      All the usual rules for documentation strings in Lisp code (See
      Documentation Tips) apply to C code documentation strings too.
 
    After the call to the ‘DEFUN’ macro, you must write the argument list
 for the C function, including the types for the arguments.  If the
 primitive accepts a fixed maximum number of Lisp arguments, there must
 be one C argument for each Lisp argument, and each argument must be of
 type ‘Lisp_Object’.  (Various macros and functions for creating values
 of type ‘Lisp_Object’ are declared in the file ‘lisp.h’.)  If the
 primitive has no upper limit on the number of Lisp arguments, it must
 have exactly two C arguments: the first is the number of Lisp arguments,
 and the second is the address of a block containing their values.  These
 have types ‘int’ and ‘Lisp_Object *’ respectively.  Since ‘Lisp_Object’
 can hold any Lisp object of any data type, you can determine the actual
 data type only at run time; so if you want a primitive to accept only a
 certain type of argument, you must check the type explicitly using a
 suitable predicate (SeeType Predicates).
 
    Within the function ‘For’ itself, the local variable ‘args’ refers to
 objects controlled by Emacs’s stack-marking garbage collector.  Although
 the garbage collector does not reclaim objects reachable from C
 ‘Lisp_Object’ stack variables, it may move non-object components of an
 object, such as string contents; so functions that access non-object
 components must take care to refetch their addresses after performing
 Lisp evaluation.  Lisp evaluation can occur via calls to ‘eval_sub’ or
 ‘Feval’, either directly or indirectly.
 
    Note the call to the ‘QUIT’ macro inside the loop: this macro checks
 whether the user pressed ‘C-g’, and if so, aborts the processing.  You
 should do that in any loop that can potentially require a large number
 of iterations; in this case, the list of arguments could be very long.
 This increases Emacs responsiveness and improves user experience.
 
    You must not use C initializers for static or global variables unless
 the variables are never written once Emacs is dumped.  These variables
 with initializers are allocated in an area of memory that becomes
 read-only (on certain operating systems) as a result of dumping Emacs.
 SeePure Storage.
 
    Defining the C function is not enough to make a Lisp primitive
 available; you must also create the Lisp symbol for the primitive and
 store a suitable subr object in its function cell.  The code looks like
 this:
 
      defsubr (&SNAME);
 
 Here SNAME is the name you used as the third argument to ‘DEFUN’.
 
    If you add a new primitive to a file that already has Lisp primitives
 defined in it, find the function (near the end of the file) named
 ‘syms_of_SOMETHING’, and add the call to ‘defsubr’ there.  If the file
 doesn’t have this function, or if you create a new file, add to it a
 ‘syms_of_FILENAME’ (e.g., ‘syms_of_myfile’).  Then find the spot in
 ‘emacs.c’ where all of these functions are called, and add a call to
 ‘syms_of_FILENAME’ there.
 
    The function ‘syms_of_FILENAME’ is also the place to define any C
 variables that are to be visible as Lisp variables.  ‘DEFVAR_LISP’ makes
 a C variable of type ‘Lisp_Object’ visible in Lisp.  ‘DEFVAR_INT’ makes
 a C variable of type ‘int’ visible in Lisp with a value that is always
 an integer.  ‘DEFVAR_BOOL’ makes a C variable of type ‘int’ visible in
 Lisp with a value that is either ‘t’ or ‘nil’.  Note that variables
 defined with ‘DEFVAR_BOOL’ are automatically added to the list
 ‘byte-boolean-vars’ used by the byte compiler.
 
    If you want to make a Lisp variables that is defined in C behave like
 one declared with ‘defcustom’, add an appropriate entry to
 ‘cus-start.el’.
 
    If you define a file-scope C variable of type ‘Lisp_Object’, you must
 protect it from garbage-collection by calling ‘staticpro’ in
 ‘syms_of_FILENAME’, like this:
 
      staticpro (&VARIABLE);
 
    Here is another example function, with more complicated arguments.
 This comes from the code in ‘window.c’, and it demonstrates the use of
 macros and functions to manipulate Lisp objects.
 
      DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
        Scoordinates_in_window_p, 2, 2, 0,
        doc: /* Return non-nil if COORDINATES are in WINDOW.
        ...
        or `right-margin' is returned.  */)
        (register Lisp_Object coordinates, Lisp_Object window)
      {
        struct window *w;
        struct frame *f;
        int x, y;
        Lisp_Object lx, ly;
 
        CHECK_LIVE_WINDOW (window);
        w = XWINDOW (window);
        f = XFRAME (w->frame);
        CHECK_CONS (coordinates);
        lx = Fcar (coordinates);
        ly = Fcdr (coordinates);
        CHECK_NUMBER_OR_FLOAT (lx);
        CHECK_NUMBER_OR_FLOAT (ly);
        x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH(f);
        y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH(f);
 
        switch (coordinates_in_window (w, x, y))
          {
          case ON_NOTHING:            /* NOT in window at all.  */
            return Qnil;
 
          ...
 
          case ON_MODE_LINE:          /* In mode line of window.  */
            return Qmode_line;
 
          ...
 
          case ON_SCROLL_BAR:         /* On scroll-bar of window.  */
            /* Historically we are supposed to return nil in this case.  */
            return Qnil;
 
          default:
            abort ();
          }
      }
 
    Note that C code cannot call functions by name unless they are
 defined in C.  The way to call a function written in Lisp 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.
 
    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 some important macros and functions.
 
    If you define a function which is side-effect free, update the code
 in ‘byte-opt.el’ that binds ‘side-effect-free-fns’ and
 ‘side-effect-and-error-free-fns’ so that the compiler optimizer knows
 about it.