   Guile Reference Manual Copyright (C) 1996 Free Software Foundation
Copyright (C) 1997 Free Software Foundation
Copyright (C) 2000 Free Software Foundation
Copyright (C) 2001 Free Software Foundation
Copyright (C) 2002 Free Software Foundation

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided that
the entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Free Software Foundation.

Accessing Cell Entries
......................

   For a non-immediate Scheme object X, the object type can be
determined by reading the cell type entry using the `SCM_CELL_TYPE'
macro.  For each different type of cell it is known which cell entries
hold Scheme objects and which cell entries hold raw C data.  To access
the different cell entries appropriately, the following macros are
provided.

 - Macro: scm_t_bits SCM_CELL_WORD (SCM X, unsigned int N)
     Deliver the cell entry N of the heap cell referenced by the
     non-immediate Scheme object X as raw data.  It is illegal, to
     access cell entries that hold Scheme objects by using these
     macros.  For convenience, the following macros are also provided.
        * SCM_CELL_WORD_0 (X) => SCM_CELL_WORD (X, 0)

        * SCM_CELL_WORD_1 (X) => SCM_CELL_WORD (X, 1)

        * ...

        * SCM_CELL_WORD_N (X) => SCM_CELL_WORD (X, N)

 - Macro: SCM SCM_CELL_OBJECT (SCM X, unsigned int N)
     Deliver the cell entry N of the heap cell referenced by the
     non-immediate Scheme object X as a Scheme object.  It is illegal,
     to access cell entries that do not hold Scheme objects by using
     these macros.  For convenience, the following macros are also
     provided.
        * SCM_CELL_OBJECT_0 (X) => SCM_CELL_OBJECT (X, 0)

        * SCM_CELL_OBJECT_1 (X) => SCM_CELL_OBJECT (X, 1)

        * ...

        * SCM_CELL_OBJECT_N (X) => SCM_CELL_OBJECT (X, N)

 - Macro: void SCM_SET_CELL_WORD (SCM X, unsigned int N, scm_t_bits W)
     Write the raw C value W into entry number N of the heap cell
     referenced by the non-immediate Scheme value X.  Values that are
     written into cells this way may only be read from the cells using
     the `SCM_CELL_WORD' macros or, in case cell entry 0 is written,
     using the `SCM_CELL_TYPE' macro.  For the special case of cell
     entry 0 it has to be made sure that W contains a cell type
     information which does not describe a Scheme object.  For
     convenience, the following macros are also provided.
        * SCM_SET_CELL_WORD_0 (X, W) => SCM_SET_CELL_WORD (X, 0, W)

        * SCM_SET_CELL_WORD_1 (X, W) => SCM_SET_CELL_WORD (X, 1, W)

        * ...

        * SCM_SET_CELL_WORD_N (X, W) => SCM_SET_CELL_WORD (X, N, W)

 - Macro: void SCM_SET_CELL_OBJECT (SCM X, unsigned int N, SCM O)
     Write the Scheme object O into entry number N of the heap cell
     referenced by the non-immediate Scheme value X.  Values that are
     written into cells this way may only be read from the cells using
     the `SCM_CELL_OBJECT' macros or, in case cell entry 0 is written,
     using the `SCM_CELL_TYPE' macro.  For the special case of cell
     entry 0 the writing of a Scheme object into this cell is only
     allowed if the cell forms a Scheme pair.  For convenience, the
     following macros are also provided.
        * SCM_SET_CELL_OBJECT_0 (X, O) => SCM_SET_CELL_OBJECT (X, 0, O)

        * SCM_SET_CELL_OBJECT_1 (X, O) => SCM_SET_CELL_OBJECT (X, 1, O)

        * ...

        * SCM_SET_CELL_OBJECT_N (X, O) => SCM_SET_CELL_OBJECT (X, N, O)

Summary:
   * For a non-immediate Scheme object X of unknown type, get the type
     information by using `SCM_CELL_TYPE (X)'.

   * As soon as the cell type information is available, only use the
     appropriate access methods to read and write data to the different
     cell entries.

Basic Rules for Accessing Cell Entries
......................................

   For each cell type it is generally up to the implementation of that
type which of the corresponding cell entries hold Scheme objects and
which hold raw C values.  However, there is one basic rule that has to
be followed: Scheme pairs consist of exactly two cell entries, which
both contain Scheme objects.  Further, a cell which contains a Scheme
object in it first entry has to be a Scheme pair.  In other words, it
is not allowed to store a Scheme object in the first cell entry and a
non Scheme object in the second cell entry.

 - Macro: int SCM_CONSP (SCM X)
     Determine, whether the Scheme object X is a Scheme pair, i.e.
     whether X references a heap cell consisting of exactly two
     entries, where both entries contain a Scheme object.  In this
     case, both entries will have to be accessed using the
     `SCM_CELL_OBJECT' macros.  On the contrary, if the `SCM_CONSP'
     predicate is not fulfilled, the first entry of the Scheme cell is
     guaranteed not to be a Scheme value and thus the first cell entry
     must be accessed using the `SCM_CELL_WORD_0' macro.

Defining New Types (Smobs)
==========================

   "Smobs" are Guile's mechanism for adding new non-immediate types to
the system.(1)  To define a new smob type, the programmer provides
Guile with some essential information about the type -- how to print
it, how to garbage collect it, and so on -- and Guile returns a fresh
type tag for use in the first word of new cells.  The programmer can
then use `scm_c_define_gsubr' to make a set of C functions that create
and operate on these objects visible to Scheme code.

   (You can find a complete version of the example code used in this
section in the Guile distribution, in `doc/example-smob'.  That
directory includes a makefile and a suitable `main' function, so you
can build a complete interactive Guile shell, extended with the
datatypes described here.)

   ---------- Footnotes ----------

   (1) The term "smob" was coined by Aubrey Jaffer, who says it comes
from "small object", referring to the fact that only the CDR and part
of the CAR of a smob's cell are available for use.

Describing a New Type
---------------------

   To define a new type, the programmer must write four functions to
manage instances of the type:

`mark'
     Guile will apply this function to each instance of the new type it
     encounters during garbage collection.  This function is
     responsible for telling the collector about any other
     non-immediate objects the object refers to.  The default smob mark
     function is to not mark any data.  See Garbage Collecting Smobs,
     for more details.

`free'
     Guile will apply this function to each instance of the new type it
     could not find any live pointers to.  The function should release
     all resources held by the object and return the number of bytes
     released.  This is analogous to the Java finalization method- it
     is invoked at an unspecified time (when garbage collection occurs)
     after the object is dead.  The default free function frees the
     smob data (if the size of the struct passed to
     `scm_make_smob_type' is non-zero) using `scm_must_free' and
     returns the size of that struct.  See Garbage Collecting Smobs,
     for more details.

`print'
     Guile will apply this function to each instance of the new type to
     print the value, as for `display' or `write'.  The function should
     write a printed representation of EXP on PORT, in accordance with
     the parameters in PSTATE.  (For more information on print states,
     see Port Data.)  The default print function prints `#<NAME
     ADDRESS>' where `NAME' is the first argument passed to
     `scm_make_smob_type'.

`equalp'
     If Scheme code asks the `equal?' function to compare two instances
     of the same smob type, Guile calls this function.  It should return
     `SCM_BOOL_T' if A and B should be considered `equal?', or
     `SCM_BOOL_F' otherwise.  If `equalp' is `NULL', `equal?' will
     assume that two instances of this type are never `equal?' unless
     they are `eq?'.

   To actually register the new smob type, call `scm_make_smob_type':

 - Function: scm_t_bits scm_make_smob_type (const char *name, size_t
          size)
     This function implements the standard way of adding a new smob
     type, named NAME, with instance size SIZE, to the system.  The
     return value is a tag that is used in creating instances of the
     type.  If SIZE is 0, then no memory will be allocated when
     instances of the smob are created, and nothing will be freed by
     the default free function.  Default values are provided for mark,
     free, print, and, equalp, as described above.  If you want to
     customize any of these functions, the call to `scm_make_smob_type'
     should be immediately followed by calls to one or several of
     `scm_set_smob_mark', `scm_set_smob_free', `scm_set_smob_print',
     and/or `scm_set_smob_equalp'.

   Each of the below `scm_set_smob_XXX' functions registers a smob
special function for a given type.  Each function is intended to be used
only zero or one time per type, and the call should be placed
immediately following the call to `scm_make_smob_type'.

 - Function: void scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM))
     This function sets the smob marking procedure for the smob type
     specified by the tag TC. TC is the tag returned by
     `scm_make_smob_type'.

 - Function: void scm_set_smob_free (scm_t_bits tc, size_t (*free)
          (SCM))
     This function sets the smob freeing procedure for the smob type
     specified by the tag TC. TC is the tag returned by
     `scm_make_smob_type'.

 - Function: void scm_set_smob_print (scm_t_bits tc, int (*print) (SCM,
          SCM, scm_print_state*))
     This function sets the smob printing procedure for the smob type
     specified by the tag TC. TC is the tag returned by
     `scm_make_smob_type'.

 - Function: void scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp)
          (SCM, SCM))
     This function sets the smob equality-testing predicate for the
     smob type specified by the tag TC. TC is the tag returned by
     `scm_make_smob_type'.

   In versions 1.4 and earlier, there was another way of creating smob
types, using `scm_make_smob_type_mfpe'.  This function is now
deprecated and will be removed in a future version of Guile.  You should
use the mechanism described above for new code, and change old code not
to use deprecated features.

   Instead of using `scm_make_smob_type' and calling each of the
individual `scm_set_smob_XXX' functions to register each special
function independently, you could use `scm_make_smob_type_mfpe' to
register all of the special functions at once as you create the smob
type

 - Function: long scm_make_smob_type_mfpe(const char *name, size_t
          size, SCM (*mark) (SCM), size_t (*free) (SCM), int (*print)
          (SCM, SCM, scm_print_state*), SCM (*equalp) (SCM, SCM))
     This function invokes `scm_make_smob_type' on its first two
     arguments to add a new smob type named NAME, with instance size
     SIZE to the system.  It also registers the MARK, FREE, PRINT,
     EQUALP smob special functions for that new type.  Any of these
     parameters can be `NULL' to have that special function use the
     default behavior for guile.  The return value is a tag that is
     used in creating instances of the type.  If SIZE is 0, then no
     memory will be allocated when instances of the smob are created,
     and nothing will be freed by the default free function.

   For example, here is how one might declare and register a new type
representing eight-bit gray-scale images:

     #include <libguile.h>

     static scm_t_bits image_tag;

     void
     init_image_type (void)
     {
       image_tag = scm_make_smob_type ("image", sizeof (struct image));
       scm_set_smob_mark (image_tag, mark_image);
       scm_set_smob_free (image_tag, free_image);
       scm_set_smob_print (image_tag, print_image);
     }

Creating Instances
------------------

   Like other non-immediate types, smobs start with a cell whose first
word contains typing information, and whose remaining words are free
for any use.

   After the header word containing the type code, smobs can have either
one, two or three additional words of data. These words store either a
pointer to the internal C structure holding the smob-specific data, or
the smob data itself.  To create an instance of a smob type following
these standards, you should use `SCM_NEWSMOB', `SCM_NEWSMOB2' or
`SCM_NEWSMOB3':(1)

 - Macro: void SCM_NEWSMOB(SCM value, scm_t_bits tag, void *data)
 - Macro: void SCM_NEWSMOB2(SCM value, scm_t_bits tag, void *data1,
          void *data2)
 - Macro: void SCM_NEWSMOB3(SCM value, scm_t_bits tag, void *data1,
          void *data2, void *data3)
     Make VALUE contain a smob instance of the type with tag TAG and
     smob data DATA (or DATA1, DATA2, and DATA3).  VALUE must be
     previously declared as C type `SCM'.

   Since it is often the case (e.g., in smob constructors) that you will
create a smob instance and return it, there is also a slightly
specialized macro for this situation:

 - Macro: fn_returns SCM_RETURN_NEWSMOB(scm_t_bits tag, void *data)
 - Macro: fn_returns SCM_RETURN_NEWSMOB2(scm_t_bits tag, void *data1,
          void *data2)
 - Macro: fn_returns SCM_RETURN_NEWSMOB3(scm_t_bits tag, void *data1,
          void *data2, void *data3)
     This macro expands to a block of code that creates a smob instance
     of the type with tag TAG and smob data DATA (or DATA1, DATA2, and
     DATA3), and causes the surrounding function to return that `SCM'
     value.  It should be the last piece of code in a block.

   Guile provides the following functions for managing memory, which are
often helpful when implementing smobs:

 - Function: char * scm_must_malloc (size_t LEN, char *WHAT)
     Allocate LEN bytes of memory, using `malloc', and return a pointer
     to them.

     If there is not enough memory available, invoke the garbage
     collector, and try once more.  If there is still not enough,
     signal an error, reporting that we could not allocate WHAT.

     This function also helps maintain statistics about the size of the
     heap.

 - Function: char * scm_must_realloc (char *ADDR, size_t OLEN, size_t
          LEN, char *WHAT)
     Resize (and possibly relocate) the block of memory at ADDR, to
     have a size of LEN bytes, by calling `realloc'.  Return a pointer
     to the new block.

     If there is not enough memory available, invoke the garbage
     collector, and try once more.  If there is still not enough,
     signal an error, reporting that we could not allocate WHAT.

     The value OLEN should be the old size of the block of memory at
     ADDR; it is only used for keeping statistics on the size of the
     heap.

 - Function: void scm_must_free (char *ADDR)
     Free the block of memory at ADDR, using `free'.  If ADDR is zero,
     signal an error, complaining of an attempt to free something that
     is already free.

     This does no record-keeping; instead, the smob's `free' function
     must take care of that.

     This function isn't usually sufficiently different from the usual
     `free' function to be worth using.

   Continuing the above example, if the global variable `image_tag'
contains a tag returned by `scm_make_smob_type', here is how we could
construct a smob whose CDR contains a pointer to a freshly allocated
`struct image':

     struct image {
       int width, height;
       char *pixels;

       /* The name of this image */
       SCM name;

       /* A function to call when this image is
          modified, e.g., to update the screen,
          or SCM_BOOL_F if no action necessary */
       SCM update_func;
     };

     SCM
     make_image (SCM name, SCM s_width, SCM s_height)
     {
       struct image *image;
       int width, height;

       SCM_ASSERT (SCM_STRINGP (name), name, SCM_ARG1, "make-image");
       SCM_ASSERT (SCM_INUMP (s_width),  s_width,  SCM_ARG2, "make-image");
       SCM_ASSERT (SCM_INUMP (s_height), s_height, SCM_ARG3, "make-image");

       width = SCM_INUM (s_width);
       height = SCM_INUM (s_height);

       image = (struct image *) scm_must_malloc (sizeof (struct image), "image");
       image->width = width;
       image->height = height;
       image->pixels = scm_must_malloc (width * height, "image pixels");
       image->name = name;
       image->update_func = SCM_BOOL_F;

       SCM_RETURN_NEWSMOB (image_tag, image);
     }

   ---------- Footnotes ----------

   (1) The `SCM_NEWSMOB2' and `SCM_NEWSMOB3' variants will allocate
double cells and thus use twice as much memory as smobs created by
`SCM_NEWSMOB'.

Type checking
-------------

   Functions that operate on smobs should aggressively check the types
of their arguments, to avoid misinterpreting some other datatype as a
smob, and perhaps causing a segmentation fault.  Fortunately, this is
pretty simple to do.  The function need only verify that its argument
is a non-immediate, whose first word is the type tag returned by
`scm_make_smob_type'.

   For example, here is a simple function that operates on an image
smob, and checks the type of its argument.  We also present an expanded
version of the `init_image_type' function, to make `clear_image' and
the image constructor function `make_image' visible to Scheme code.

     SCM
     clear_image (SCM image_smob)
     {
       int area;
       struct image *image;

       SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
                   image_smob, SCM_ARG1, "clear-image");

       image = (struct image *) SCM_SMOB_DATA (image_smob);
       area = image->width * image->height;
       memset (image->pixels, 0, area);

       /* Invoke the image's update function.  */
       if (image->update_func != SCM_BOOL_F)
         scm_apply (image->update_func, SCM_EOL, SCM_EOL);

       return SCM_UNSPECIFIED;
     }

     void
     init_image_type (void)
     {
       image_tag = scm_make_smob_type ("image", sizeof (struct image));
       scm_set_smob_mark (image_tag, mark_image);
       scm_set_smob_free (image_tag, free_image);
       scm_set_smob_print (image_tag, print_image);

       scm_c_define_gsubr ("clear-image", 1, 0, 0, clear_image);
       scm_c_define_gsubr ("make-image", 3, 0, 0, make_image);
     }

Garbage Collecting Smobs
------------------------

   Once a smob has been released to the tender mercies of the Scheme
system, it must be prepared to survive garbage collection.  Guile calls
the `mark' and `free' functions of the `scm_smobfuns' structure to
manage this.

   As described before (see Conservative GC), every object in the
Scheme system has a "mark bit", which the garbage collector uses to
tell live objects from dead ones.  When collection starts, every
object's mark bit is clear.  The collector traces pointers through the
heap, starting from objects known to be live, and sets the mark bit on
each object it encounters.  When it can find no more unmarked objects,
the collector walks all objects, live and dead, frees those whose mark
bits are still clear, and clears the mark bit on the others.

   The two main portions of the collection are called the "mark phase",
during which the collector marks live objects, and the "sweep phase",
during which the collector frees all unmarked objects.

   The mark bit of a smob lives in a special memory region.  When the
collector encounters a smob, it sets the smob's mark bit, and uses the
smob's type tag to find the appropriate `mark' function for that smob:
the one listed in that smob's `scm_smobfuns' structure.  It then calls
the `mark' function, passing it the smob as its only argument.

   The `mark' function is responsible for marking any other Scheme
objects the smob refers to.  If it does not do so, the objects' mark
bits will still be clear when the collector begins to sweep, and the
collector will free them.  If this occurs, it will probably break, or at
least confuse, any code operating on the smob; the smob's `SCM' values
will have become dangling references.

   To mark an arbitrary Scheme object, the `mark' function may call
this function:

 - Function: void scm_gc_mark (SCM X)
     Mark the object X, and recurse on any objects X refers to.  If X's
     mark bit is already set, return immediately.

   Thus, here is how we might write the `mark' function for the image
smob type discussed above:

     SCM
     mark_image (SCM image_smob)
     {
       /* Mark the image's name and update function.  */
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);

       scm_gc_mark (image->name);
       scm_gc_mark (image->update_func);

       return SCM_BOOL_F;
     }

   Note that, even though the image's `update_func' could be an
arbitrarily complex structure (representing a procedure and any values
enclosed in its environment), `scm_gc_mark' will recurse as necessary
to mark all its components.  Because `scm_gc_mark' sets an object's
mark bit before it recurses, it is not confused by circular structures.

   As an optimization, the collector will mark whatever value is
returned by the `mark' function; this helps limit depth of recursion
during the mark phase.  Thus, the code above could also be written as:
     SCM
     mark_image (SCM image_smob)
     {
       /* Mark the image's name and update function.  */
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);

       scm_gc_mark (image->name);
       return image->update_func;
     }

   Finally, when the collector encounters an unmarked smob during the
sweep phase, it uses the smob's tag to find the appropriate `free'
function for the smob.  It then calls the function, passing it the smob
as its only argument.

   The `free' function must release any resources used by the smob.
However, it need not free objects managed by the collector; the
collector will take care of them.  The return type of the `free'
function should be `size_t', an unsigned integral type; the `free'
function should return the number of bytes released, to help the
collector maintain statistics on the size of the heap.

   Here is how we might write the `free' function for the image smob
type:
     size_t
     free_image (SCM image_smob)
     {
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
       size_t size = image->width * image->height + sizeof (*image);

       free (image->pixels);
       free (image);

       return size;
     }

   During the sweep phase, the garbage collector will clear the mark
bits on all live objects.  The code which implements a smob need not do
this itself.

   There is no way for smob code to be notified when collection is
complete.

   It is usually a good idea to minimize the amount of processing done
during garbage collection; keep `mark' and `free' functions very
simple.  Since collections occur at unpredictable times, it is easy for
any unusual activity to interfere with normal code.

A Common Mistake In Allocating Smobs
------------------------------------

   When constructing new objects, you must be careful that the garbage
collector can always find any new objects you allocate.  For example,
suppose we wrote the `make_image' function this way:

     SCM
     make_image (SCM name, SCM s_width, SCM s_height)
     {
       struct image *image;
       SCM image_smob;
       int width, height;

       SCM_ASSERT (SCM_STRINGP (name), name, SCM_ARG1, "make-image");
       SCM_ASSERT (SCM_INUMP (s_width),  s_width,  SCM_ARG2, "make-image");
       SCM_ASSERT (SCM_INUMP (s_height), s_height, SCM_ARG3, "make-image");

       width = SCM_INUM (s_width);
       height = SCM_INUM (s_height);

       image = (struct image *) scm_must_malloc (sizeof (struct image), "image");
       image->width = width;
       image->height = height;
       image->pixels = scm_must_malloc (width * height, "image pixels");

       /* THESE TWO LINES HAVE CHANGED: */
       image->name = scm_string_copy (name);
       image->update_func = scm_c_define_gsubr (...);

       SCM_NEWCELL (image_smob);
       SCM_SET_CELL_WORD_1 (image_smob, image);
       SCM_SET_CELL_TYPE (image_smob, image_tag);

       return image_smob;
     }

   This code is incorrect.  The calls to `scm_string_copy' and
`scm_c_define_gsubr' allocate fresh objects.  Allocating any new object
may cause the garbage collector to run.  If `scm_c_define_gsubr'
invokes a collection, the garbage collector has no way to discover that
`image->name' points to the new string object; the `image' structure is
not yet part of any Scheme object, so the garbage collector will not
traverse it.  Since the garbage collector cannot find any references to
the new string object, it will free it, leaving `image' pointing to a
dead object.

   A correct implementation might say, instead:

       image->name = SCM_BOOL_F;
       image->update_func = SCM_BOOL_F;

       SCM_NEWCELL (image_smob);
       SCM_SET_CELL_WORD_1 (image_smob, image);
       SCM_SET_CELL_TYPE (image_smob, image_tag);

       image->name = scm_string_copy (name);
       image->update_func = scm_c_define_gsubr (...);

       return image_smob;

   Now, by the time we allocate the new string and function objects,
`image_smob' points to `image'.  If the garbage collector scans the
stack, it will find a reference to `image_smob' and traverse `image',
so any objects `image' points to will be preserved.

Garbage Collecting Simple Smobs
-------------------------------

   It is often useful to define very simple smob types -- smobs which
have no data to mark, other than the cell itself, or smobs whose first
data word is simply an ordinary Scheme object, to be marked recursively.
Guile provides some functions to handle these common cases; you can use
this function as your smob type's `mark' function, if your smob's
structure is simple enough.

   If the smob refers to no other Scheme objects, then no action is
necessary; the garbage collector has already marked the smob cell
itself.  In that case, you can use zero as your mark function.

 - Function: SCM scm_markcdr (SCM X)
     Mark the references in the smob X, assuming that X's first data
     word contains an ordinary Scheme object, and X refers to no other
     objects.  This function simply returns X's first data word.

     This is only useful for simple smobs created by `SCM_NEWSMOB' or
     `SCM_RETURN_NEWSMOB', not for smobs allocated as double cells.

 - Function: size_t scm_free0 (SCM X)
     Do nothing; return zero.  This function is appropriate for smobs
     that use either zero or `scm_markcdr' as their marking functions,
     and refer to no heap storage, including memory managed by `malloc',
     other than the smob's header cell.

     This function should not be needed anymore, because simply passing
     `NULL' as the free function does the same.

A Complete Example
------------------

   Here is the complete text of the implementation of the image
datatype, as presented in the sections above.  We also provide a
definition for the smob's `print' function, and make some objects and
functions static, to clarify exactly what the surrounding code is using.

   As mentioned above, you can find this code in the Guile
distribution, in `doc/example-smob'.  That directory includes a
makefile and a suitable `main' function, so you can build a complete
interactive Guile shell, extended with the datatypes described here.)

     /* file "image-type.c" */

     #include <stdlib.h>
     #include <libguile.h>

     static scm_t_bits image_tag;

     struct image {
       int width, height;
       char *pixels;

       /* The name of this image */
       SCM name;

       /* A function to call when this image is
          modified, e.g., to update the screen,
          or SCM_BOOL_F if no action necessary */
       SCM update_func;
     };

     static SCM
     make_image (SCM name, SCM s_width, SCM s_height)
     {
       struct image *image;
       int width, height;

       SCM_ASSERT (SCM_STRINGP (name), name, SCM_ARG1, "make-image");
       SCM_ASSERT (SCM_INUMP (s_width),  s_width,  SCM_ARG2, "make-image");
       SCM_ASSERT (SCM_INUMP (s_height), s_height, SCM_ARG3, "make-image");

       width = SCM_INUM (s_width);
       height = SCM_INUM (s_height);

       image = (struct image *) scm_must_malloc (sizeof (struct image), "image");
       image->width = width;
       image->height = height;
       image->pixels = scm_must_malloc (width * height, "image pixels");
       image->name = name;
       image->update_func = SCM_BOOL_F;

       SCM_RETURN_NEWSMOB (image_tag, image);
     }

     static SCM
     clear_image (SCM image_smob)
     {
       int area;
       struct image *image;

       SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
                   image_smob, SCM_ARG1, "clear-image");

       image = (struct image *) SCM_SMOB_DATA (image_smob);
       area = image->width * image->height;
       memset (image->pixels, 0, area);

       /* Invoke the image's update function.  */
       if (image->update_func != SCM_BOOL_F)
         scm_apply (image->update_func, SCM_EOL, SCM_EOL);

       return SCM_UNSPECIFIED;
     }

     static SCM
     mark_image (SCM image_smob)
     {
       /* Mark the image's name and update function.  */
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);

       scm_gc_mark (image->name);
       return image->update_func;
     }

     static size_t
     free_image (SCM image_smob)
     {
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
       size_t size = image->width * image->height + sizeof (struct image);

       free (image->pixels);
       free (image);

       return size;
     }

     static int
     print_image (SCM image_smob, SCM port, scm_print_state *pstate)
     {
       struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);

       scm_puts ("#<image ", port);
       scm_display (image->name, port);
       scm_puts (">", port);

       /* non-zero means success */
       return 1;
     }

     void
     init_image_type (void)
     {
       image_tag = scm_make_smob_type ("image", sizeof (struct image));
       scm_set_smob_mark (image_tag, mark_image);
       scm_set_smob_free (image_tag, free_image);
       scm_set_smob_print (image_tag, print_image);

       scm_c_define_gsubr ("clear-image", 1, 0, 0, clear_image);
       scm_c_define_gsubr ("make-image", 3, 0, 0, make_image);
     }

   Here is a sample build and interaction with the code from the
`example-smob' directory, on the author's machine:

     zwingli:example-smob$ make CC=gcc
     gcc `guile-config compile`   -c image-type.c -o image-type.o
     gcc `guile-config compile`   -c myguile.c -o myguile.o
     gcc image-type.o myguile.o `guile-config link` -o myguile
     zwingli:example-smob$ ./myguile
     guile> make-image
     #<primitive-procedure make-image>
     guile> (define i (make-image "Whistler's Mother" 100 100))
     guile> i
     #<image Whistler's Mother>
     guile> (clear-image i)
     guile> (clear-image 4)
     ERROR: In procedure clear-image in expression (clear-image 4):
     ERROR: Wrong type argument in position 1: 4
     ABORT: (wrong-type-arg)

     Type "(backtrace)" to get more information.
     guile>

GH: A Portable C to Scheme Interface
************************************

   This chapter shows how to use the GH interface to call Guile from
your application's C code, and to add new Scheme level procedures to
Guile whose behaviour is specified by application specific code written
in C.

   Note, however, that the GH interface is now deprecated, and
developers are encouraged to switch to using the scm interface instead.
Therefore, for each GH feature, this chapter should also document how
to achieve the same result using the scm interface.

Why the GH Interface is Now Deprecated
======================================

   Historically, the GH interface was the product of a practical problem
and a neat idea.  The practical problem was that the interface of the
`scm_' functions with which Guile itself was written (inherited from
Aubrey Jaffer's SCM) was so closely tied to the (rather arcane) details
of the internal data representation that it was extremely difficult to
write a Guile extension using these functions.  The neat idea was to
define a high level language extension interface in such a way that
other extension language projects, not just Guile, would be able to
provide an implementation of that interface; then applications using
this interface could be compiled with whichever of the various
available implementations they chose.  So the GH interface was created,
and advertised both as the recommended interface for application
developers wishing to use Guile, and as a portable high level interface
that could theoretically be implemented by other extension language
projects.

   Time passed, and various things changed.  Crucially, an enormous
number of improvements were made to the `scm_' interface that Guile
itself uses in its implementation, with the result that it is now both
easy and comfortable to write a Guile extension with this interface.
At the same time, the contents of the GH interface were somewhat
neglected by the core Guile developers, such that some key operations
-- such as smob creation and management -- are simply not possible
using GH alone.  Finally, the idea of multiple implementations of the
GH interface did not really crystallize (apart, I believe, from a short
lived implementation by the MzScheme project).

   For all these reasons, the Guile developers have decided to deprecate
the GH interface -- which means that support for GH will be completely
removed after the next few releases -- and to focus only on the `scm_'
interface, with additions to ensure that it is as easy to use in all
respects as GH was.

   It remains an open question whether a deep kind of interface
portability would be useful for extension language-based applications,
and it may still be an interesting project to attempt to define a
corresponding GH-like interface, but the Guile developers no longer
plan to try to do this as part of the core Guile project.

gh preliminaries
================

   To use gh, you must have the following toward the beginning of your C
source:
     #include <guile/gh.h>

   When you link, you will have to add at least `-lguile' to the list
of libraries.  If you are using more of Guile than the basic Scheme
interpreter, you will have to add more libraries.

Data types and constants defined by gh
======================================

   The following C constants and data types are defined in gh:

   `SCM' is a C data type used to store all Scheme data, no matter what
the Scheme type.  Values are converted between C data types and the SCM
type with utility functions described below (see Converting data between C and Scheme).
[FIXME: put in references to Jim's essay and
so forth.]

 - Constant: SCM_BOOL_T
 - Constant: SCM_BOOL_F
     The _Scheme_ values returned by many boolean procedures in
     libguile.

     This can cause confusion because they are different from 0 and 1.
     In testing a boolean function in libguile programming, you must
     always make sure that you check the spec: `gh_' and `scm_'
     functions will usually return `SCM_BOOL_T' and `SCM_BOOL_F', but
     other C functions usually can be tested against 0 and 1, so
     programmers' fingers tend to just type `if (boolean_function()) {
     ... }'

 - Constant: SCM_UNSPECIFIED
     This is a SCM value that is not the same as any legal Scheme
     value.  It is the value that a Scheme function returns when its
     specification says that its return value is unspecified.

 - Constant: SCM_UNDEFINED
     This is another SCM value that is not the same as any legal Scheme
     value.  It is the value used to mark variables that do not yet
     have a value, and it is also used in C to terminate functions with
     variable numbers of arguments, such as `gh_list()'.

Starting and controlling the interpreter
========================================

   In almost every case, your first `gh_' call will be:

 - Function: void gh_enter (int ARGC, char *ARGV[], void (*MAIN_PROG)())
     Starts up a Scheme interpreter with all the builtin Scheme
     primitives.  `gh_enter()' never exits, and the user's code should
     all be in the `MAIN_PROG()' function.  `argc' and `argv' will be
     passed to MAIN_PROG.

      - Function: void main_prog (int ARGC, char *ARGV[])
          This is the user's main program.  It will be invoked by
          `gh_enter()' after Guile has been started up.

     Note that you can use `gh_repl' inside `gh_enter' (in other words,
     inside the code for `main-prog') if you want the program to be
     controlled by a Scheme read-eval-print loop.

   A convenience routine which enters the Guile interpreter with the
standard Guile read-eval-print loop ("REPL") is:

 - Function: void gh_repl (int ARGC, char *ARGV[])
     Enters the Scheme interpreter giving control to the Scheme REPL.
     Arguments are processed as if the Guile program `guile' were being
     invoked.

     Note that `gh_repl' should be used _inside_ `gh_enter', since any
     Guile interpreter calls are meaningless unless they happen in the
     context of the interpreter.

     Also note that when you use `gh_repl', your program will be
     controlled by Guile's REPL (which is written in Scheme and has many
     useful features).  Use straight C code inside `gh_enter' if you
     want to maintain execution control in your C program.

   You will typically use `gh_enter' and `gh_repl' when you want a
Guile interpreter enhanced by your own libraries, but otherwise quite
normal.  For example, to build a Guile-derived program that includes
some random number routines "GSL" (GNU Scientific Library), you would
write a C program that looks like this:

     #include <guile/gh.h>
     #include <gsl_ran.h>

     /* random number suite */
     SCM gw_ran_seed(SCM s)
     {
       gsl_ran_seed(gh_scm2int(s));
       return SCM_UNSPECIFIED;
     }

     SCM gw_ran_random()
     {
       SCM x;

       x = gh_ulong2scm(gsl_ran_random());
       return x;
     }

     SCM gw_ran_uniform()
     {
       SCM x;

       x = gh_double2scm(gsl_ran_uniform());
       return x;
     }
     SCM gw_ran_max()
     {
       return gh_double2scm(gsl_ran_max());
     }

     void
     init_gsl()
     {
       /* random number suite */
       gh_new_procedure("gsl-ran-seed", gw_ran_seed, 1, 0, 0);
       gh_new_procedure("gsl-ran-random", gw_ran_random, 0, 0, 0);
       gh_new_procedure("gsl-ran-uniform", gw_ran_uniform, 0, 0, 0);
       gh_new_procedure("gsl-ran-max", gw_ran_max, 0, 0, 0);
     }

     void
     main_prog (int argc, char *argv[])
     {
       init_gsl();

       gh_repl(argc, argv);
     }

     int
     main (int argc, char *argv[])
     {
       gh_enter (argc, argv, main_prog);
     }

   Then, supposing the C program is in `guile-gsl.c', you could compile
it with `gcc -o guile-gsl guile-gsl.c -lguile -lgsl'.

   The resulting program `guile-gsl' would have new primitive
procedures `gsl-ran-random', `gsl-ran-gaussian' and so forth.

Error messages
==============

   [FIXME: need to fill this based on Jim's new mechanism]

Executing Scheme code
=====================

   Once you have an interpreter running, you can ask it to evaluate
Scheme code.  There are two calls that implement this:

 - Function: SCM gh_eval_str (char *SCHEME_CODE)
     This asks the interpreter to evaluate a single string of Scheme
     code, and returns the result of the last expression evaluated.

     Note that the line of code in SCHEME_CODE must be a well formed
     Scheme expression.  If you have many lines of code before you
     balance parentheses, you must either concatenate them into one
     string, or use `gh_eval_file()'.

 - Function: SCM gh_eval_file (char *FNAME)
 - Function: SCM gh_load (char *FNAME)
     `gh_eval_file' is completely analogous to `gh_eval_str()', except
     that a whole file is evaluated instead of a string.
     `gh_eval_file' returns `SCM_UNSPECIFIED'.

     `gh_load' is identical to `gh_eval_file' (it's a macro that calls
     `gh_eval_file' on its argument).  It is provided to start making
     the `gh_' interface match the R5RS Scheme procedures closely.

Defining new Scheme procedures in C
===================================

   The real interface between C and Scheme comes when you can write new
Scheme procedures in C.  This is done through the routine

 - Libguile high: SCM gh_new_procedure (char *PROC_NAME, SCM (*FN)(),
          int N_REQUIRED_ARGS, int N_OPTIONAL_ARGS, int RESTP)
     `gh_new_procedure' defines a new Scheme procedure.  Its Scheme name
     will be PROC_NAME, it will be implemented by the C function
     (*FN)(), it will take at least N_REQUIRED_ARGS arguments, and at
     most N_OPTIONAL_ARGS extra arguments.

     When the RESTP parameter is 1, the procedure takes a final
     argument: a list of remaining parameters.

     `gh_new_procedure' returns an SCM value representing the procedure.

     The C function FN should have the form

      - Libguile high: SCM fn (SCM REQ1, SCM REQ2, ..., SCM OPT1, SCM
               OPT2, ..., SCM REST_ARGS)
          The arguments are all passed as SCM values, so the user will
          have to use the conversion functions to convert to standard C
          types.

          Examples of C functions used as new Scheme primitives can be
          found in the sample programs `learn0' and `learn1'.

   *Rationale:* this is the correct way to define new Scheme procedures
in C.  The ugly mess of arguments is required because of how C handles
procedures with variable numbers of arguments.

   *Note:* what about documentation strings?

   There are several important considerations to be made when writing
the C routine `(*fn)()'.

   First of all the C routine has to return type `SCM'.

   Second, all arguments passed to the C function will be of type `SCM'.

   Third: the C routine is now subject to Scheme flow control, which
means that it could be interrupted at any point, and then reentered.
This means that you have to be very careful with operations such as
allocating memory, modifying static data ...

   Fourth: to get around the latter issue, you can use `GH_DEFER_INTS'
and `GH_ALLOW_INTS'.

 - Macro: GH_DEFER_INTS
 - Macro: GH_ALLOW_INTS
     These macros disable and re-enable Scheme's flow control.  They

Converting data between C and Scheme
====================================

   Guile provides mechanisms to convert data between C and Scheme.  This
allows new builtin procedures to understand their arguments (which are
of type `SCM') and return values of type `SCM'.

C to Scheme
-----------

 - Function: SCM gh_bool2scm (int X)
     Returns `#f' if X is zero, `#t' otherwise.

 - Function: SCM gh_ulong2scm (unsigned long X)
 - Function: SCM gh_long2scm (long X)
 - Function: SCM gh_double2scm (double X)
 - Function: SCM gh_char2scm (char X)
     Returns a Scheme object with the value of the C quantity X.

 - Function: SCM gh_str2scm (char *S, int LEN)
     Returns a new Scheme string with the (not necessarily
     null-terminated) C array S data.

 - Function: SCM gh_str02scm (char *S)
     Returns a new Scheme string with the null-terminated C string S
     data.

 - Function: SCM gh_set_substr (char *SRC, SCM DST, int START, int LEN)
     Copy LEN characters at SRC into the _existing_ Scheme string DST,
     starting at START.  START is an index into DST; zero means the
     beginning of the string.

     If START + LEN is off the end of DST, signal an out-of-range error.

 - Function: SCM gh_symbol2scm (char *NAME)
     Given a null-terminated string NAME, return the symbol with that
     name.

 - Function: SCM gh_ints2scm (int *DPTR, int N)
 - Function: SCM gh_doubles2scm (double *DPTR, int N)
     Make a scheme vector containing the N ints or doubles at memory
     location DPTR.

 - Function: SCM gh_chars2byvect (char *DPTR, int N)
 - Function: SCM gh_shorts2svect (short *DPTR, int N)
 - Function: SCM gh_longs2ivect (long *DPTR, int N)
 - Function: SCM gh_ulongs2uvect (ulong *DPTR, int N)
 - Function: SCM gh_floats2fvect (float *DPTR, int N)
 - Function: SCM gh_doubles2dvect (double *DPTR, int N)
     Make a scheme uniform vector containing the N chars, shorts,
     longs, unsigned longs, floats or doubles at memory location DPTR.