* scheme-data.texi (Arithmetic): Documented the arithmetic
[bpt/guile.git] / doc / data-rep.texi
index c6cd9ad..9b7b879 100644 (file)
-\input texinfo
-@c -*-texinfo-*-
-@c %**start of header
-@setfilename data-rep.info
-@settitle Data Representation in Guile
-@c %**end of header
-
-@include version.texi
-
-@dircategory Scheme Programming
-@direntry
-* data-rep: (data-rep).  Data Representation in Guile --- how to use
+@c essay \input texinfo
+@c essay @c -*-texinfo-*-
+@c essay @c %**start of header
+@c essay @setfilename data-rep.info
+@c essay @settitle Data Representation in Guile
+@c essay @c %**end of header
+
+@c essay @include version.texi
+
+@c essay @dircategory The Algorithmic Language Scheme
+@c essay @direntry
+@c essay * data-rep: (data-rep).  Data Representation in Guile --- how to use
                          Guile objects in your C code.
-@end direntry
-
-@setchapternewpage off
-
-@ifinfo
-Data Representation in Guile
-
-Copyright (C) 1998 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.
-
-@ignore
-Permission is granted to process this file through TeX and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
-@end ignore
-
-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.
-@end ifinfo
-
-@titlepage
-@sp 10
-@comment The title is printed in a large font.
-@title Data Representation in Guile
-@subtitle $Id: data-rep.texi,v 1.1 1998-10-07 07:37:16 jimb Exp $
-@subtitle For use with Guile @value{VERSION}
-@author Jim Blandy
-@author Free Software Foundation
-@author @email{jimb@@red-bean.com}
-@c The following two commands start the copyright page.
-@page
-@vskip 0pt plus 1filll
-@vskip 0pt plus 1filll
-Copyright @copyright{} 1998 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.
+@c essay @end direntry
+
+@c essay @setchapternewpage off
+
+@c essay @ifinfo
+@c essay Data Representation in Guile
+
+@c essay Copyright (C) 1998, 1999, 2000 Free Software Foundation
+
+@c essay Permission is granted to make and distribute verbatim copies of
+@c essay this manual provided the copyright notice and this permission notice
+@c essay are preserved on all copies.
+
+@c essay @ignore
+@c essay Permission is granted to process this file through TeX and print the
+@c essay results, provided the printed document carries copying permission
+@c essay notice identical to this one except for the removal of this paragraph
+@c essay (this paragraph not being relevant to the printed manual).
+@c essay @end ignore
+
+@c essay Permission is granted to copy and distribute modified versions of this
+@c essay manual under the conditions for verbatim copying, provided that the entire
+@c essay resulting derived work is distributed under the terms of a permission
+@c essay notice identical to this one.
+
+@c essay Permission is granted to copy and distribute translations of this manual
+@c essay into another language, under the above conditions for modified versions,
+@c essay except that this permission notice may be stated in a translation approved
+@c essay by the Free Software Foundation.
+@c essay @end ifinfo
+
+@c essay @titlepage
+@c essay @sp 10
+@c essay @comment The title is printed in a large font.
+@c essay @title Data Representation in Guile
+@c essay @subtitle $Id: data-rep.texi,v 1.17 2001-03-09 08:21:59 ossau Exp $
+@c essay @subtitle For use with Guile @value{VERSION}
+@c essay @author Jim Blandy
+@c essay @author Free Software Foundation
+@c essay @author @email{jimb@@red-bean.com}
+@c essay @c The following two commands start the copyright page.
+@c essay @page
+@c essay @vskip 0pt plus 1filll
+@c essay @vskip 0pt plus 1filll
+@c essay Copyright @copyright{} 1998 Free Software Foundation
+
+@c essay Permission is granted to make and distribute verbatim copies of
+@c essay this manual provided the copyright notice and this permission notice
+@c essay are preserved on all copies.
+
+@c essay Permission is granted to copy and distribute modified versions of this
+@c essay manual under the conditions for verbatim copying, provided that the entire
+@c essay resulting derived work is distributed under the terms of a permission
+@c essay notice identical to this one.
+
+@c essay Permission is granted to copy and distribute translations of this manual
+@c essay into another language, under the above conditions for modified versions,
+@c essay except that this permission notice may be stated in a translation approved
+@c essay by Free Software Foundation.
+@c essay @end titlepage
+
+@c essay @c @smallbook
+@c essay @c @finalout
+@c essay @headings double
+
+
+@c essay @node Top, Data Representation in Scheme, (dir), (dir)
+@c essay @top Data Representation in Guile
+
+@c essay @ifinfo
+@c essay This essay is meant to provide the background necessary to read and
+@c essay write C code that manipulates Scheme values in a way that conforms to
+@c essay libguile's interface.  If you would like to write or maintain a
+@c essay Guile-based application in C or C++, this is the first information you
+@c essay need.
+
+@c essay In order to make sense of Guile's @code{SCM_} functions, or read
+@c essay libguile's source code, it's essential to have a good grasp of how Guile
+@c essay actually represents Scheme values.  Otherwise, a lot of the code, and
+@c essay the conventions it follows, won't make very much sense.
+
+@c essay We assume you know both C and Scheme, but we do not assume you are
+@c essay familiar with Guile's C interface.
+@c essay @end ifinfo
 
-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 Free Software Foundation.
-@end titlepage
-
-@c @smallbook
-@c @finalout
-@headings double
+@page
+@node Data Representation
+@chapter Data Representation in Guile
 
+@strong{by Jim Blandy}
 
-@node Top, Data Representation in Scheme, (dir), (dir)
-@top Data Representation in Guile
+[Due to the rather non-orthogonal and performance-oriented nature of the
+SCM interface, you need to understand SCM internals *before* you can use
+the SCM API.  That's why this chapter comes first.]
 
-@ifinfo
-This essay is meant to provide the background necessary to read and
-write C code that manipulates Scheme values in a way that conforms to
-libguile's interface.  If you would like to write or maintain a
-Guile-based application, this is the first information you need.
+[NOTE: this is Jim Blandy's essay almost entirely unmodified.  It has to
+be adapted to fit this manual smoothly.]
 
 In order to make sense of Guile's SCM_ functions, or read libguile's
 source code, it's essential to have a good grasp of how Guile actually
 represents Scheme values.  Otherwise, a lot of the code, and the
-conventions it follows, won't make very much sense.
+conventions it follows, won't make very much sense.  This essay is meant
+to provide the background necessary to read and write C code that
+manipulates Scheme values in a way that is compatible with libguile.
 
 We assume you know both C and Scheme, but we do not assume you are
-familiar with Guile's C interface.
-@end ifinfo
+familiar with Guile's implementation.
 
 @menu
 * Data Representation in Scheme::       Why things aren't just totally
@@ -105,14 +130,15 @@ familiar with Guile's C interface.
                                         application-specific datatypes.
 @end menu
 
-@node Data Representation in Scheme, How Guile does it, Top, Top
+@node Data Representation in Scheme
 @section Data Representation in Scheme
 
 Scheme is a latently-typed language; this means that the system cannot,
 in general, determine the type of a given expression at compile time.
 Types only become apparent at run time.  Variables do not have fixed
 types; a variable may hold a pair at one point, an integer at the next,
-and a thousand-element vector later.  Instead, values have fixed types.
+and a thousand-element vector later.  Instead, values, not variables,
+have fixed types.
 
 In order to implement standard Scheme functions like @code{pair?} and
 @code{string?} and provide garbage collection, the representation of
@@ -141,7 +167,7 @@ does it}.
 * Guile Is Hairier::            
 @end menu
 
-@node A Simple Representation, Faster Integers, Data Representation in Scheme, Data Representation in Scheme
+@node A Simple Representation
 @subsection A Simple Representation
 
 The simplest way to meet the above requirements in C would be to
@@ -185,7 +211,7 @@ semantics.  If @var{x} is an @code{SCM} value:
 @end itemize
 
 
-@node Faster Integers, Cheaper Pairs, A Simple Representation, Data Representation in Scheme
+@node Faster Integers
 @subsection Faster Integers
 
 Unfortunately, the above representation has a serious disadvantage.  In
@@ -280,7 +306,7 @@ but this essay isn't about bit-twiddling.  (Hint: what if pointers had
 @code{01} in their least significant bits, and integers had @code{00}?)
 
 
-@node Cheaper Pairs, Guile Is Hairier, Faster Integers, Data Representation in Scheme
+@node Cheaper Pairs
 @subsection Cheaper Pairs
 
 However, there is yet another issue to confront.  Most Scheme heaps
@@ -378,7 +404,7 @@ are referencing, making a modified pointer as fast to use as an
 unmodified pointer.
 
 
-@node Guile Is Hairier,  , Cheaper Pairs, Data Representation in Scheme
+@node Guile Is Hairier
 @subsection Guile Is Hairier
 
 We originally started with a very simple typing system --- each object
@@ -394,7 +420,7 @@ significant loss of efficiency, but the simplified system would still be
 more complex than what we've presented above.
 
 
-@node How Guile does it, Defining New Types (Smobs), Data Representation in Scheme, Top
+@node How Guile does it
 @section How Guile does it
 
 Here we present the specifics of how Guile represents its data.  We
@@ -406,14 +432,14 @@ everything one need know to use Guile's data.
 
 @menu
 * General Rules::               
-* Garbage Collection::          
+* Conservative GC::          
 * Immediates vs. Non-immediates::  
 * Immediate Datatypes::         
 * Non-immediate Datatypes::     
 * Signalling Type Errors::      
 @end menu
 
-@node General Rules, Garbage Collection, How Guile does it, How Guile does it
+@node General Rules
 @subsection General Rules
 
 Any code which operates on Guile datatypes must @code{#include} the
@@ -444,8 +470,8 @@ boolean value have names starting with @code{SCM_N}.  For example,
 @emph{not} a pair object (a @code{CONS}).
 
 
-@node Garbage Collection, Immediates vs. Non-immediates, General Rules, How Guile does it
-@subsection Garbage Collection
+@node Conservative GC
+@subsection Conservative Garbage Collection
 
 Aside from the latent typing, the major source of constraints on a
 Scheme implementation's data representation is the garbage collector.
@@ -491,7 +517,7 @@ problem.  The alternative, an explicitly maintained list of local
 variable addresses, is effectively much less reliable, due to programmer
 error.
 
-To accomodate this technique, data must be represented so that the
+To accommodate this technique, data must be represented so that the
 collector can accurately determine whether a given stack word is a
 pointer or not.  Guile does this as follows:
 @itemize @bullet
@@ -528,7 +554,7 @@ many pieces of code, it is enough for the collector to find the cell,
 and then use the cell's type to find more pointers to trace.
 
 
-@node Immediates vs. Non-immediates, Immediate Datatypes, Garbage Collection, How Guile does it
+@node Immediates vs. Non-immediates
 @subsection Immediates vs. Non-immediates
 
 Guile classifies Scheme objects into two kinds: those that fit entirely
@@ -569,7 +595,7 @@ from this weakness.
 @end deftypefn
 
 
-@node Immediate Datatypes, Non-immediate Datatypes, Immediates vs. Non-immediates, How Guile does it
+@node Immediate Datatypes
 @subsection Immediate Datatypes
 
 The following datatypes are immediate values; that is, they fit entirely
@@ -586,13 +612,13 @@ before applying them.
 
 
 @menu
-* Integers::                    
-* Characters::                  
-* Booleans::                    
+* Integer Data::                    
+* Character Data::                  
+* Boolean Data::                    
 * Unique Values::               
 @end menu
 
-@node Integers, Characters, Immediate Datatypes, Immediate Datatypes
+@node Integer Data
 @subsubsection Integers
 
 Here are functions for operating on small integers, that fit within an
@@ -625,27 +651,27 @@ This function does not check for overflow.
 @end deftypefn
 
 
-@node Characters, Booleans, Integers, Immediate Datatypes
+@node Character Data
 @subsubsection Characters
 
 Here are functions for operating on characters.
 
-@deftypefn Macro int SCM_ICHRP (SCM @var{x})
+@deftypefn Macro int SCM_CHARP (SCM @var{x})
 Return non-zero iff @var{x} is a character value.
 @end deftypefn
 
-@deftypefn Macro {unsigned int} SCM_ICHR (SCM @var{x})
+@deftypefn Macro {unsigned int} SCM_CHAR (SCM @var{x})
 Return the value of @code{x} as a C character.  If @var{x} is not a
 Scheme character, the result is undefined.
 @end deftypefn
 
-@deftypefn Macro SCM SCM_MAKICHR (SCM @var{c})
+@deftypefn Macro SCM SCM_MAKE_CHAR (int @var{c})
 Given a C character @var{c}, return its representation as a Scheme
 character value.
 @end deftypefn
 
 
-@node Booleans, Unique Values, Characters, Immediate Datatypes
+@node Boolean Data
 @subsubsection Booleans
 
 Here are functions and macros for operating on booleans.
@@ -668,7 +694,7 @@ Scheme boolean, the result is undefined.
 @end deftypefn
 
 
-@node Unique Values,  , Booleans, Immediate Datatypes
+@node Unique Values
 @subsubsection Unique Values
 
 The immediate values that are neither small integers, characters, nor
@@ -713,7 +739,7 @@ symbol's value to see if it has a binding as a global variable.
 @end deftypefn
 
 
-@node Non-immediate Datatypes, Signalling Type Errors, Immediate Datatypes, How Guile does it
+@node Non-immediate Datatypes
 @subsection Non-immediate Datatypes 
 
 A non-immediate datatype is one which lives in the heap, either because
@@ -736,18 +762,18 @@ corrupted.
 @menu
 * Non-immediate Type Predicates::  Special rules for using the type
                                         predicates described here.
-* Pairs::                       
-* Vectors::                     
+* Pair Data::                       
+* Vector Data::                     
 * Procedures::                  
 * Closures::                    
 * Subrs::                       
-* Ports::                       
+* Port Data::                       
 @end menu
 
-@node Non-immediate Type Predicates, Pairs, Non-immediate Datatypes, Non-immediate Datatypes
+@node Non-immediate Type Predicates
 @subsubsection Non-immediate Type Predicates
 
-As mentioned in @ref{Garbage Collection}, all non-immediate objects
+As mentioned in @ref{Conservative GC}, all non-immediate objects
 start with a @dfn{cell}, or a pair of words.  Furthermore, all type
 information that distinguishes one kind of non-immediate from another is
 stored in the cell.  The type information in the @code{SCM} value
@@ -765,7 +791,7 @@ SCM_NIMP (@var{x}) && SCM_CONSP (@var{x})
 @end example
 
 
-@node Pairs, Vectors, Non-immediate Type Predicates, Non-immediate Datatypes
+@node Pair Data
 @subsubsection Pairs
 
 Pairs are the essential building block of list structure in Scheme.  A
@@ -850,7 +876,7 @@ Return the @sc{car} of the @sc{car} of @var{cell}, the @sc{car} of the
 @end deftypefn
 
 
-@node Vectors, Procedures, Pairs, Non-immediate Datatypes
+@node Vector Data
 @subsubsection Vectors, Strings, and Symbols
 
 Vectors, strings, and symbols have some properties in common.  They all
@@ -897,7 +923,7 @@ There are also a few magic values stuffed into memory before a symbol's
 characters, but you don't want to know about those.  What cruft!
 
 
-@node Procedures, Closures, Vectors, Non-immediate Datatypes
+@node Procedures
 @subsubsection Procedures
 
 Guile provides two kinds of procedures: @dfn{closures}, which are the
@@ -914,7 +940,7 @@ any sort.  Otherwise, return @code{SCM_BOOL_F}.
 @end deftypefun
 
 
-@node Closures, Subrs, Procedures, Non-immediate Datatypes
+@node Closures
 @subsubsection Closures
 
 [FIXME: this needs to be further subbed, but texinfo has no subsubsub]
@@ -963,7 +989,7 @@ connected with the interpreter's implementation.
 @end deftypefn
 
 
-@node Subrs, Ports, Closures, Non-immediate Datatypes
+@node Subrs
 @subsubsection Subrs
 
 [FIXME: this needs to be further subbed, but texinfo has no subsubsub]
@@ -1014,13 +1040,13 @@ object instead of a subr object.
 @end deftypefun
 
 
-@node Ports,  , Subrs, Non-immediate Datatypes
+@node Port Data
 @subsubsection Ports
 
 Haven't written this yet, 'cos I don't understand ports yet.
 
 
-@node Signalling Type Errors,  , Non-immediate Datatypes, How Guile does it
+@node Signalling Type Errors
 @subsection Signalling Type Errors
 
 Every function visible at the Scheme level should aggressively check the
@@ -1075,13 +1101,8 @@ naming the function.  Usually, Guile catches these errors before ever
 invoking the subr, so we don't run into these problems.
 @end deftypefn
 
-@deftypefn Macro int SCM_OUTOFRANGE
-Signal an error complaining that @var{obj} is ``out of range'' for
-@var{subr}.
-@end deftypefn
-
 
-@node Defining New Types (Smobs),  , How Guile does it, Top
+@node Defining New Types (Smobs)
 @section Defining New Types (Smobs)
 
 @dfn{Smobs} are Guile's mechanism for adding new non-immediate types to
@@ -1090,76 +1111,132 @@ says it comes from ``small object'', referring to the fact that only the
 @sc{cdr} and part of the @sc{car} of a smob's cell are available for
 use.}  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, @i{et cetera} --- and Guile returns a fresh type tag for
+garbage collect it, and so on --- and Guile returns a fresh type tag for
 use in the @sc{car} of new cells.  The programmer can then use
-@code{scm_make_gsubr} to publish a set of C functions to the Scheme
-world that create and operate on these objects.
+@code{scm_make_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 @file{doc/example-smob}.  That
+directory includes a makefile and a suitable @code{main} function, so
+you can build a complete interactive Guile shell, extended with the
+datatypes described here.)
 
 @menu
 * Describing a New Type::       
 * Creating Instances::          
 * Typechecking::                
 * Garbage Collecting Smobs::    
+* A Common Mistake In Allocating Smobs::  
 * Garbage Collecting Simple Smobs::  
 * A Complete Example::          
 @end menu
 
-@node Describing a New Type, Creating Instances, Defining New Types (Smobs), Defining New Types (Smobs)
+@node Describing a New Type
 @subsection Describing a New Type
 
-To define a new type, the programmer must fill in an @code{scm_smobfuns}
-structure with functions to manage instances of the type.  Here is the
-definition of the structure:
-
-@example
-typedef struct scm_smobfuns
-@{
-  SCM       (*mark) (SCM @var{obj});
-  scm_sizet (*free) (SCM @var{obj});
-  int       (*print) (SCM @var{obj},
-                      SCM @var{port},
-                      scm_print_state *@var{pstate});
-  SCM       (*equalp) (SCM @var{a}, SCM @var{b});
-@} scm_smobfuns;
-@end example
+To define a new type, the programmer must write four functions to
+manage instances of the type:
 
 @table @code
 @item 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.  @xref{Garbage Collecting Smobs}, for more details.
+refers to.  The default smob mark function is to not mark any data.
+@xref{Garbage Collecting Smobs}, for more details.
 
 @item 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.
-@xref{Garbage Collecting Smobs}, for more details.
+resources held by the object and return the number of bytes released.
+This is analagous 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 @code{scm_make_smob_type} or @code{scm_make_smob_type_mfpe} is
+non-zero) using @code{scm_must_free} and returns the size of that
+struct.  @xref{Garbage Collecting Smobs}, for more details.
 
 @item print
+@c GJB:FIXME:: @var{exp} and @var{port} need to refer to a prototype of 
+@c the print function.... where is that, or where should it go?
 Guile will apply this function to each instance of the new type to print
 the value, as for @code{display} or @code{write}.  The function should
 write a printed representation of @var{exp} on @var{port}, in accordance
 with the parameters in @var{pstate}.  (For more information on print
-states, see @ref{Ports}.)
+states, see @ref{Port Data}.)  The default print function prints @code{#<NAME ADDRESS>} 
+where @code{NAME} is the first argument passed to @code{scm_make_smob_type} or 
+@code{scm_make_smob_type_mfpe}.
 
 @item equalp
 If Scheme code asks the @code{equal?} function to compare two instances
 of the same smob type, Guile calls this function.  It should return
 @code{SCM_BOOL_T} if @var{a} and @var{b} should be considered
 @code{equal?}, or @code{SCM_BOOL_F} otherwise.  If @code{equalp} is
-zero, @code{equal?} will assume that two instances of this type are
+@code{NULL}, @code{equal?} will assume that two instances of this type are
 never @code{equal?} unless they are @code{eq?}.
 
 @end table
 
-Once you have built a @code{scm_smobfuns} structure, you can call the
-@code{scm_newsmob} function to add the type to the system.
+To actually register the new smob type, call @code{scm_make_smob_type}:
+
+@deftypefun long scm_make_smob_type (const char *name, scm_sizet size)
+This function implements the standard way of adding a new smob type,
+named @var{name}, with instance size @var{size}, to the system.  The
+return value is a tag that is used in creating instances of the type.
+If @var{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 @code{scm_make_smob_type} should be immediately
+followed by calls to one or several of @code{scm_set_smob_mark},
+@code{scm_set_smob_free}, @code{scm_set_smob_print}, and/or
+@code{scm_set_smob_equalp}.
+@end deftypefun
 
-@deftypefun long scm_newsmob (scm_smobfuns *@var{funs})
-This function adds the type described by @var{funs} to the system.  The
-return value is a tag, used in creating instances of the type.
+Each of the below @code{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 @code{scm_make_smob_type}.
+
+@deftypefun void scm_set_smob_mark (long tc, SCM (*mark) (SCM))
+This function sets the smob marking procedure for the smob type specified by
+the tag @var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}.
+@end deftypefun
+
+@deftypefun void scm_set_smob_free (long tc, scm_sizet (*free) (SCM))
+This function sets the smob freeing procedure for the smob type specified by
+the tag @var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}.
+@end deftypefun
+
+@deftypefun void scm_set_smob_print (long tc, int (*print) (SCM,SCM,scm_print_state*))
+This function sets the smob printing procedure for the smob type specified by
+the tag @var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}.
+@end deftypefun
+
+@deftypefun void scm_set_smob_equalp (long tc, SCM (*equalp) (SCM,SCM))
+This function sets the smob equality-testing predicate for the smob type specified by
+the tag @var{tc}. @var{tc} is the tag returned by @code{scm_make_smob_type}.
+@end deftypefun
+
+Instead of using @code{scm_make_smob_type} and calling each of the
+individual @code{scm_set_smob_XXX} functions to register each special
+function independently, you can use @code{scm_make_smob_type_mfpe} to
+register all of the special functions at once as you create the smob
+type@footnote{Warning: There is an ongoing discussion among the developers which
+may result in deprecating @code{scm_make_smob_type_mfpe} in next release
+of Guile.}:
+
+@deftypefun long scm_make_smob_type_mfpe(const char *name, scm_sizet size, SCM (*mark) (SCM), scm_sizet (*free) (SCM), int (*print) (SCM, SCM, scm_print_state*), SCM (*equalp) (SCM, SCM))
+This function invokes @code{scm_make_smob_type} on its first two arguments
+to add a new smob type named @var{name}, with instance size @var{size} to the system.  
+It also registers the @var{mark}, @var{free}, @var{print}, @var{equalp} smob
+special functions for that new type.  Any of these parameters can be @code{NULL}
+to have that special function use the default behaviour for guile.
+The return value is a tag that is used in creating instances of the type.  If @var{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.
 @end deftypefun
 
 For example, here is how one might declare and register a new type
@@ -1167,28 +1244,43 @@ representing eight-bit grayscale images:
 @example
 #include <libguile.h>
 
-scm_smobfuns image_funs = @{
-  mark_image, free_image, print_image, 0
-@};
-
 long image_tag;
 
 void
 init_image_type ()
 @{
-  image_tag = scm_newsmob (&image_funs);
+  image_tag = scm_make_smob_type_mfpe ("image",sizeof(struct image),
+                                      mark_image, free_image, print_image, NULL);
 @}
 @end example
 
 
-@node Creating Instances, Typechecking, Describing a New Type, Defining New Types (Smobs)
+@node Creating Instances
 @subsection Creating Instances
 
 Like other non-immediate types, smobs start with a cell whose @sc{car}
-contains typing information, and whose @code{cdr} is free for any use.
-To create an instance of a smob type, you must allocate a fresh cell, by
-calling @code{SCM_NEWCELL}, and store the tag returned by
-@code{scm_smobfuns} in its car.
+contains typing information, and whose @code{cdr} is free for any use.  For smobs,
+the @code{cdr} stores a pointer to the internal C structure holding the 
+smob-specific data.
+To create an instance of a smob type following these standards, you should
+use @code{SCM_NEWSMOB}:
+
+@deftypefn Macro void SCM_NEWSMOB(SCM value,long tag,void *data)
+Make @var{value} contain a smob instance of the type with tag @var{tag}
+and smob data @var{data}.  @var{value} must be previously declared
+as C type @code{SCM}.
+@end deftypefn
+
+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:
+
+@deftypefn Macro fn_returns SCM_RETURN_NEWSMOB(long tab, void *data)
+This macro expands to a block of code that creates a smob instance of
+the type with tag @var{tag} and smob data @var{data}, and returns
+that @code{SCM} value.  It should be the last piece of code in 
+a block.
+@end deftypefn
 
 Guile provides the following functions for managing memory, which are
 often helpful when implementing smobs:
@@ -1251,28 +1343,32 @@ struct image @{
 @};
 
 SCM
-create_image (SCM name, int width, int height)
+make_image (SCM name, SCM s_width, SCM s_height)
 @{
   struct image *image;
-  SCM image_smob;
+  int width, height;
 
-  image = (struct image *) scm_must_malloc (sizeof (*image), "image");
+  SCM_ASSERT (SCM_NIMP (name) && 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_NEWCELL (image_smob);
-  SCM_SETCAR (image_smob, image_tag);
-  SCM_SETCDR (image_smob, image);
-
-  return image_smob;
+  SCM_RETURN_NEWSMOB (image_tag, image);
 @}
 @end example
 
 
-@node Typechecking, Garbage Collecting Smobs, Creating Instances, Defining New Types (Smobs)
+@node Typechecking
 @subsection Typechecking
 
 Functions that operate on smobs should aggressively check the types of
@@ -1284,8 +1380,9 @@ non-immediate, whose @sc{car} is the type tag returned by
 
 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 @code{init_image_type} function, to make clear_image
-available to the Scheme level.
+version of the @code{init_image_type} function, to make
+@code{clear_image} and the image constructor function @code{make_image}
+visible to Scheme code.
 @example
 SCM
 clear_image (SCM image_smob)
@@ -1293,11 +1390,10 @@ clear_image (SCM image_smob)
   int area;
   struct image *image;
 
-  SCM_ASSERT ((SCM_NIMP (image_smob)
-               && SCM_CAR (image_smob) == image_tag),
+  SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
               image_smob, SCM_ARG1, "clear-image");
 
-  image = (struct image *) SCM_CDR (image_smob);
+  image = (struct image *) SCM_SMOB_DATA (image_smob);
   area = image->width * image->height;
   memset (image->pixels, 0, area);
 
@@ -1313,6 +1409,8 @@ void
 init_image_type ()
 @{
   image_tag = scm_newsmob (&image_funs);
+
+  scm_make_gsubr ("make-image", 3, 0, 0, make_image);
   scm_make_gsubr ("clear-image", 1, 0, 0, clear_image);
 @}
 @end example
@@ -1321,8 +1419,9 @@ Note that checking types is a little more complicated during garbage
 collection; see the description of @code{SCM_GCTYP16} in @ref{Garbage
 Collecting Smobs}.
 
+@c GJB:FIXME:: should talk about guile-snarf somewhere!
 
-@node Garbage Collecting Smobs, Garbage Collecting Simple Smobs, Typechecking, Defining New Types (Smobs)
+@node Garbage Collecting Smobs
 @subsection Garbage Collecting Smobs
 
 Once a smob has been released to the tender mercies of the Scheme
@@ -1330,7 +1429,7 @@ system, it must be prepared to survive garbage collection.  Guile calls
 the @code{mark} and @code{free} functions of the @code{scm_smobfuns}
 structure to manage this.
 
-As described before (@pxref{Garbage Collection}), every object in the
+As described before (@pxref{Conservative GC}), every object in the
 Scheme system has a @dfn{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
@@ -1350,7 +1449,7 @@ function for that smob: the one listed in that smob's
 @code{scm_smobfuns} structure.  It then calls the @code{mark} function,
 passing it the smob as its only argument.
 
-The @code{mark} function's is responsible for marking any other Scheme
+The @code{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
@@ -1373,7 +1472,7 @@ SCM
 mark_image (SCM image_smob)
 @{
   /* Mark the image's name and update function.  */
-  struct image *image = (struct image *) SCM_CDR (image_smob);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
   scm_gc_mark (image->name);
   scm_gc_mark (image->update_func);
@@ -1399,7 +1498,7 @@ SCM
 mark_image (SCM image_smob)
 @{
   /* Mark the image's name and update function.  */
-  struct image *image = (struct image *) SCM_CDR (image_smob);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
   scm_gc_mark (image->name);
   return image->update_func;
@@ -1426,7 +1525,7 @@ type:
 scm_sizet
 free_image (SCM image_smob)
 @{
-  struct image *image = (struct image *) SCM_CDR (image_smob);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
   scm_sizet size = image->width * image->height + sizeof (*image);
 
   free (image->pixels);
@@ -1463,13 +1562,87 @@ very simple.  Since collections occur at unpredictable times, it is easy
 for any unusual activity to interfere with normal code.
 
 
-@node Garbage Collecting Simple Smobs, A Complete Example, Garbage Collecting Smobs, Defining New Types (Smobs)
+@node A Common Mistake In Allocating Smobs, Garbage Collecting Simple Smobs, Garbage Collecting Smobs, Defining New Types (Smobs)
+@subsection 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 @code{make_image} function this way:
+
+@example
+SCM
+make_image (SCM name, SCM s_width, SCM s_height)
+@{
+  struct image *image;
+  SCM image_smob;
+  int width, height;
+
+  SCM_ASSERT (SCM_NIMP (name) && 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_make_gsubr (@dots{});
+
+  SCM_NEWCELL (image_smob);
+  SCM_SETCDR (image_smob, image);
+  SCM_SETCAR (image_smob, image_tag);
+
+  return image_smob;
+@}
+@end example
+
+This code is incorrect.  The calls to @code{scm_string_copy} and
+@code{scm_make_gsubr} allocate fresh objects.  Allocating any new object
+may cause the garbage collector to run.  If @code{scm_make_gsubr}
+invokes a collection, the garbage collector has no way to discover that
+@code{image->name} points to the new string object; the @code{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
+@code{image} pointing to a dead object.
+
+A correct implementation might say, instead:
+@example
+  image->name = SCM_BOOL_F;
+  image->update_func = SCM_BOOL_F;
+
+  SCM_NEWCELL (image_smob);
+  SCM_SETCDR (image_smob, image);
+  SCM_SETCAR (image_smob, image_tag);
+
+  image->name = scm_string_copy (name);
+  image->update_func = scm_make_gsubr (@dots{});
+
+  return image_smob;
+@end example
+
+Now, by the time we allocate the new string and function objects,
+@code{image_smob} points to @code{image}.  If the garbage collector
+scans the stack, it will find a reference to @code{image_smob} and
+traverse @code{image}, so any objects @code{image} points to will be
+preserved.
+
+
+@node Garbage Collecting Simple Smobs, A Complete Example, A Common Mistake In Allocating Smobs, Defining New Types (Smobs)
 @subsection 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 @sc{cdr} is
 simply an ordinary Scheme object, to be marked recursively.  Guile
-provides some functions to handle these common cases.
+provides some functions to handle these common cases; you can use these
+functions as your smob type's @code{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
@@ -1489,18 +1662,26 @@ other than the smob's header cell.
 @end deftypefun
 
 
-@node A Complete Example,  , Garbage Collecting Simple Smobs, Defining New Types (Smobs)
+@node A Complete Example
 @subsection 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 @code{print} function.
+the smob's @code{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
+@file{doc/example-smob}.  That directory includes a makefile and a
+suitable @code{main} function, so you can build a complete interactive
+Guile shell, extended with the datatypes described here.)
 
 @example
+/* file "image-type.c" */
+
 #include <stdlib.h>
 #include <libguile.h>
 
-long image_tag;
+static long image_tag;
 
 struct image @{
   int width, height;
@@ -1515,39 +1696,43 @@ struct image @{
   SCM update_func;
 @};
 
-
-SCM
-create_image (SCM name, int width, int height)
+static SCM
+make_image (SCM name, SCM s_width, SCM s_height)
 @{
   struct image *image;
   SCM image_smob;
+  int width, height;
 
-  image = (struct image *) scm_must_malloc (sizeof (*image), "image");
+  SCM_ASSERT (SCM_NIMP (name) && 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_NEWCELL (image_smob);
-  SCM_SETCDR (image_smob, image);
-  SCM_SETCAR (image_smob, image_tag);
+  SCM_NEWSMOB (image_smob, image_tag, image);
 
   return image_smob;
 @}
 
-
-SCM
+static SCM
 clear_image (SCM image_smob)
 @{
   int area;
   struct image *image;
 
-  SCM_ASSERT ((SCM_NIMP (image_smob)
-               && SCM_CAR (image_smob) == image_tag),
+  SCM_ASSERT (SCM_SMOB_PREDICATE (image_tag, image_smob),
               image_smob, SCM_ARG1, "clear-image");
 
-  image = (struct image *) SCM_CDR (image_smob);
+  image = (struct image *) SCM_SMOB_DATA (image_smob);
   area = image->width * image->height;
   memset (image->pixels, 0, area);
 
@@ -1558,22 +1743,20 @@ clear_image (SCM image_smob)
   return SCM_UNSPECIFIED;
 @}
 
-
-SCM
+static SCM
 mark_image (SCM image_smob)
 @{
-  struct image *image = (struct image *) SCM_CDR (image_smob);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
   scm_gc_mark (image->name);
   return image->update_func;
 @}
 
-
-scm_sizet
+static scm_sizet
 free_image (SCM image_smob)
 @{
-  struct image *image = (struct image *) SCM_CDR (image_smob);
-  scm_sizet size = image->width * image->height + sizeof (*image);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
+  scm_sizet size = image->width * image->height + sizeof (struct image);
 
   free (image->pixels);
   free (image);
@@ -1581,31 +1764,55 @@ free_image (SCM image_smob)
   return size;
 @}
 
-
-int
-print_image (SCM obj, SCM port, scm_print_state *pstate)
+static int
+print_image (SCM image_smob, SCM port, scm_print_state *pstate)
 @{
-  struct image *image = (struct image *) SCM_CDR (image_smob);
+  struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
 
-  scm_gen_puts (scm_regular_string, "#<image ", port);
+  scm_puts ("#<image ", port);
   scm_display (image->name, port);
-  scm_gen_puts (scm_regular_string, ">", port);
+  scm_puts (">", port);
 
   /* non-zero means success */
   return 1;
 @}
 
-scm_smobfuns image_funs = @{
+static scm_smobfuns image_funs = @{
   mark_image, free_image, print_image, 0
 @};
 
-
 void
 init_image_type ()
 @{
   image_tag = scm_newsmob (&image_funs);
+
   scm_make_gsubr ("clear-image", 1, 0, 0, clear_image);
+  scm_make_gsubr ("make-image", 3, 0, 0, make_image);
 @}
 @end example
 
-@bye
+Here is a sample build and interaction with the code from the
+@file{example-smob} directory, on the author's machine:
+
+@example
+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> 
+@end example
+
+@c essay @bye