XEmacs 21.2.36 "Notos"
[chise/xemacs-chise.git.1] / man / internals / internals.texi
index f432589..5b8d38e 100644 (file)
@@ -1218,7 +1218,7 @@ name as the value of the Lisp variable @code{top-level}.
 
   When the Lisp initialization code is done, the C code enters the event
 loop, and stays there for the duration of the XEmacs process.  The code
-for the event loop is contained in @file{keyboard.c}, and is called
+for the event loop is contained in @file{cmdloop.c}, and is called
 @code{Fcommand_loop_1()}.  Note that this event loop could very well be
 written in Lisp, and in fact a Lisp version exists; but apparently,
 doing this makes XEmacs run noticeably slower.
@@ -1626,11 +1626,11 @@ stuffs a pointer together with a tag, as follows:
 
 A tag of 00 is used for all pointer object types, a tag of 10 is used
 for characters, and the other two tags 01 and 11 are joined together to
-form the integer object type.  This representation gives us 31 bits
-integers, 30 bits characters and pointers are represented directly
-without any bit masking.  This representation, though, assumes that
-pointers to structs are always aligned to multiples of 4, so the lower 2
-bits are always zero.
+form the integer object type.  This representation gives us 31 bit
+integers and 30 bit characters, while pointers are represented directly
+without any bit masking or shifting.  This representation, though,
+assumes that pointers to structs are always aligned to multiples of 4,
+so the lower 2 bits are always zero.
 
 Lisp objects use the typedef @code{Lisp_Object}, but the actual C type
 used for the Lisp object can vary.  It can be either a simple type
@@ -1641,24 +1641,24 @@ preferable because it ensures that the compiler will actually use a
 machine word to represent the object (some compilers will use more
 general and less efficient code for unions and structs even if they can
 fit in a machine word).  The union type, however, has the advantage of
-stricter type checking (if you accidentally pass an integer where a Lisp
-object is desired, you get a compile error), and it makes it easier to
-decode Lisp objects when debugging.  The choice of which type to use is
-determined by the preprocessor constant @code{USE_UNION_TYPE} which is
-defined via the @code{--use-union-type} option to @code{configure}.
-
-Various macros are used to construct Lisp objects and extract the
-components.  Macros of the form @code{XINT()}, @code{XCHAR()},
-@code{XSTRING()}, @code{XSYMBOL()}, etc. shift out the tag field if
-needed cast it to the appropriate type.  @code{XINT()} needs to be a bit
-tricky so that negative numbers are properly sign-extended.  Since
+stricter type checking.  If you accidentally pass an integer where a Lisp
+object is desired, you get a compile error.  The choice of which type
+to use is determined by the preprocessor constant @code{USE_UNION_TYPE}
+which is defined via the @code{--use-union-type} option to
+@code{configure}.
+
+Various macros are used to convert between Lisp_Objects and the
+corresponding C type.  Macros of the form @code{XINT()}, @code{XCHAR()},
+@code{XSTRING()}, @code{XSYMBOL()}, do any required bit shifting and/or
+masking and cast it to the appropriate type.  @code{XINT()} needs to be
+a bit tricky so that negative numbers are properly sign-extended.  Since
 integers are stored left-shifted, if the right-shift operator does an
 arithmetic shift (i.e. it leaves the most-significant bit as-is rather
 than shifting in a zero, so that it mimics a divide-by-two even for
 negative numbers) the shift to remove the tag bit is enough.  This is
 the case on all the systems we support.
 
-Note that when @code{ERROR_CHECK_TYPECHECK} is defined, the extractor
+Note that when @code{ERROR_CHECK_TYPECHECK} is defined, the converter
 macros become more complicated---they check the tag bits and/or the
 type field in the first four bytes of a record type to ensure that the
 object is really of the correct type.  This is great for catching places
@@ -1668,25 +1668,29 @@ unpredictable (and sometimes not easily traceable) results.
 
 There are similar @code{XSET@var{TYPE}()} macros that construct a Lisp
 object.  These macros are of the form @code{XSET@var{TYPE}
-(@var{lvalue}, @var{result})},
-i.e. they have to be a statement rather than just used in an expression.
-The reason for this is that standard C doesn't let you ``construct'' a
-structure (but GCC does).  Granted, this sometimes isn't too convenient;
-for the case of integers, at least, you can use the function
-@code{make_int()}, which constructs and @emph{returns} an integer
-Lisp object.  Note that the @code{XSET@var{TYPE}()} macros are also
-affected by @code{ERROR_CHECK_TYPECHECK} and make sure that the
-structure is of the right type in the case of record types, where the
-type is contained in the structure.
+(@var{lvalue}, @var{result})}, i.e. they have to be a statement rather
+than just used in an expression.  The reason for this is that standard C
+doesn't let you ``construct'' a structure (but GCC does).  Granted, this
+sometimes isn't too convenient; for the case of integers, at least, you
+can use the function @code{make_int()}, which constructs and
+@emph{returns} an integer Lisp object.  Note that the
+@code{XSET@var{TYPE}()} macros are also affected by
+@code{ERROR_CHECK_TYPECHECK} and make sure that the structure is of the
+right type in the case of record types, where the type is contained in
+the structure.
 
 The C programmer is responsible for @strong{guaranteeing} that a
-Lisp_Object is is the correct type before using the @code{X@var{TYPE}}
+Lisp_Object is the correct type before using the @code{X@var{TYPE}}
 macros.  This is especially important in the case of lists.  Use
 @code{XCAR} and @code{XCDR} if a Lisp_Object is certainly a cons cell,
 else use @code{Fcar()} and @code{Fcdr()}.  Trust other C code, but not
 Lisp code.  On the other hand, if XEmacs has an internal logic error,
-it's better to crash immediately, so sprinkle ``unreachable''
-@code{abort()}s liberally about the source code.
+it's better to crash immediately, so sprinkle @code{assert()}s and
+``unreachable'' @code{abort()}s liberally about the source code.  Where
+performance is an issue, use @code{type_checking_assert},
+@code{bufpos_checking_assert}, and @code{gc_checking_assert}, which do
+nothing unless the corresponding configure error checking flag was
+specified.
 
 @node Rules When Writing New C Code, A Summary of the Various XEmacs Modules, How Lisp Objects Are Represented in C, Top
 @chapter Rules When Writing New C Code
@@ -1740,13 +1744,14 @@ system header files) to ensure that certain tricks played by various
 @file{s/} and @file{m/} files work out correctly.
 
 When including header files, always use angle brackets, not double
-quotes, except when the file to be included is in the same directory as
-the including file.  If either file is a generated file, then that is
-not likely to be the case.  In order to understand why we have this
-rule, imagine what happens when you do a build in the source directory
-using @samp{./configure} and another build in another directory using
-@samp{../work/configure}.  There will be two different @file{config.h}
-files.  Which one will be used if you @samp{#include "config.h"}?
+quotes, except when the file to be included is always in the same
+directory as the including file.  If either file is a generated file,
+then that is not likely to be the case.  In order to understand why we
+have this rule, imagine what happens when you do a build in the source
+directory using @samp{./configure} and another build in another
+directory using @samp{../work/configure}.  There will be two different
+@file{config.h} files.  Which one will be used if you @samp{#include
+"config.h"}?
 
 @strong{All global and static variables that are to be modifiable must
 be declared uninitialized.}  This means that you may not use the
@@ -1791,7 +1796,7 @@ The C source code makes heavy use of C preprocessor macros.  One popular
 macro style is:
 
 @example
-#define FOO(var, value) do @{           \
+#define FOO(var, value) do @{            \
   Lisp_Object FOO_value = (value);      \
   ... /* compute using FOO_value */     \
   (var) = bar;                          \
@@ -2597,13 +2602,19 @@ proceed writing new Mule-aware code.
 @node Techniques for XEmacs Developers,  , Coding for Mule, Rules When Writing New C Code
 @section Techniques for XEmacs Developers
 
+To make a purified XEmacs, do: @code{make puremacs}.
 To make a quantified XEmacs, do: @code{make quantmacs}.
 
-You simply can't dump Quantified and Purified images.  Run the image
-like so:  @code{quantmacs -batch -l loadup.el run-temacs @var{xemacs-args...}}.
+You simply can't dump Quantified and Purified images (unless using the
+portable dumper).  Purify gets confused when xemacs frees memory in one
+process that was allocated in a @emph{different} process on a different
+machine!.  Run it like so:
+@example
+temacs -batch -l loadup.el run-temacs @var{xemacs-args...}
+@end example
 
 Before you go through the trouble, are you compiling with all
-debugging and error-checking off?  If not try that first.  Be warned
+debugging and error-checking off?  If not, try that first.  Be warned
 that while Quantify is directly responsible for quite a few
 optimizations which have been made to XEmacs, doing a run which
 generates results which can be acted upon is not necessarily a trivial
@@ -2642,14 +2653,116 @@ Unfortunately, Emacs Lisp is slow, and is going to stay slow.  Function
 calls in elisp are especially expensive.  Iterating over a long list is
 going to be 30 times faster implemented in C than in Elisp.
 
+Heavily used small code fragments need to be fast.  The traditional way
+to implement such code fragments in C is with macros.  But macros in C
+are known to be broken.
+
+Macro arguments that are repeatedly evaluated may suffer from repeated
+side effects or suboptimal performance.
+
+Variable names used in macros may collide with caller's variables,
+causing (at least) unwanted compiler warnings.
+
+In order to solve these problems, and maintain statement semantics, one
+should use the @code{do @{ ... @} while (0)} trick while trying to
+reference macro arguments exactly once using local variables.
+
+Let's take a look at this poor macro definition:
+
+@example
+#define MARK_OBJECT(obj) \
+  if (!marked_p (obj)) mark_object (obj), did_mark = 1
+@end example
+
+This macro evaluates its argument twice, and also fails if used like this:
+@example
+  if (flag) MARK_OBJECT (obj); else do_something();
+@end example
+
+A much better definition is
+
+@example
+#define MARK_OBJECT(obj) do @{ \
+  Lisp_Object mo_obj = (obj); \
+  if (!marked_p (mo_obj))     \
+    @{                         \
+      mark_object (mo_obj);   \
+      did_mark = 1;           \
+    @}                         \
+@} while (0)
+@end example
+
+Notice the elimination of double evaluation by using the local variable
+with the obscure name.  Writing safe and efficient macros requires great
+care.  The one problem with macros that cannot be portably worked around
+is, since a C block has no value, a macro used as an expression rather
+than a statement cannot use the techniques just described to avoid
+multiple evaluation.
+
+In most cases where a macro has function semantics, an inline function
+is a better implementation technique.  Modern compiler optimizers tend
+to inline functions even if they have no @code{inline} keyword, and
+configure magic ensures that the @code{inline} keyword can be safely
+used as an additional compiler hint.  Inline functions used in a single
+.c files are easy.  The function must already be defined to be
+@code{static}.  Just add another @code{inline} keyword to the
+definition.
+
+@example
+inline static int
+heavily_used_small_function (int arg)
+@{
+  ...
+@}
+@end example
+
+Inline functions in header files are trickier, because we would like to
+make the following optimization if the function is @emph{not} inlined
+(for example, because we're compiling for debugging).  We would like the
+function to be defined externally exactly once, and each calling
+translation unit would create an external reference to the function,
+instead of including a definition of the inline function in the object
+code of every translation unit that uses it.  This optimization is
+currently only available for gcc.  But you don't have to worry about the
+trickiness; just define your inline functions in header files using this
+pattern:
+
+@example
+INLINE_HEADER int
+i_used_to_be_a_crufty_macro_but_look_at_me_now (int arg);
+INLINE_HEADER int
+i_used_to_be_a_crufty_macro_but_look_at_me_now (int arg)
+@{
+  ...
+@}
+@end example
+
+The declaration right before the definition is to prevent warnings when
+compiling with @code{gcc -Wmissing-declarations}.  I consider issuing
+this warning for inline functions a gcc bug, but the gcc maintainers disagree.
+
+Every header which contains inline functions, either directly by using
+@code{INLINE_HEADER} or indirectly by using @code{DECLARE_LRECORD} must
+be added to @file{inline.c}'s includes to make the optimization
+described above work.  (Optimization note: if all INLINE_HEADER
+functions are in fact inlined in all translation units, then the linker
+can just discard @code{inline.o}, since it contains only unreferenced code).
+
 To get started debugging XEmacs, take a look at the @file{.gdbinit} and
-@file{.dbxrc} files in the @file{src} directory.
-@xref{Q2.1.15 - How to Debug an XEmacs problem with a debugger,,,
-xemacs-faq, XEmacs FAQ}.
+@file{.dbxrc} files in the @file{src} directory.  See the section in the
+XEmacs FAQ on How to Debug an XEmacs problem with a debugger.
 
 After making source code changes, run @code{make check} to ensure that
-you haven't introduced any regressions.  If you're feeling ambitious,
-you can try to improve the test suite in @file{tests/automated}.
+you haven't introduced any regressions.  If you want to make xemacs more
+reliable, please improve the test suite in @file{tests/automated}.
+
+Did you make sure you didn't introduce any new compiler warnings?
+
+Before submitting a patch, please try compiling at least once with
+
+@example
+configure --with-mule --with-union-type --error-checking=all
+@end example
 
 Here are things to know when you create a new source file:
 
@@ -2676,23 +2789,6 @@ Header files should @emph{not} include @code{<config.h>} and
 @code{"lisp.h"}.  It is the responsibility of the @file{.c} files that
 use it to do so.
 
-@item
-If the header uses @code{INLINE}, either directly or through
-@code{DECLARE_LRECORD}, then it must be added to @file{inline.c}'s
-includes.
-
-@item
-Try compiling at least once with
-
-@example
-gcc --with-mule --with-union-type --error-checking=all
-@end example
-
-@item
-Did I mention that you should run the test suite?
-@example
-make check
-@end example
 @end itemize
 
 Here is a checklist of things to do when creating a new lisp object type
@@ -2704,17 +2800,20 @@ create @var{foo}.h
 @item
 create @var{foo}.c
 @item
-add definitions of syms_of_@var{foo}, etc. to @var{foo}.c
+add definitions of @code{syms_of_@var{foo}}, etc. to @file{@var{foo}.c}
 @item
-add declarations of syms_of_@var{foo}, etc. to symsinit.h
+add declarations of @code{syms_of_@var{foo}}, etc. to @file{symsinit.h}
 @item
-add calls to syms_of_@var{foo}, etc. to emacs.c(main_1)
+add calls to @code{syms_of_@var{foo}}, etc. to @file{emacs.c}
 @item
-add definitions of macros like CHECK_FOO and FOOP to @var{foo}.h
+add definitions of macros like @code{CHECK_@var{FOO}} and
+@code{@var{FOO}P} to @file{@var{foo}.h}
 @item
-add the new type index to enum lrecord_type
+add the new type index to @code{enum lrecord_type}
 @item
-add DEFINE_LRECORD_IMPLEMENTATION call to @var{foo}.c
+add a DEFINE_LRECORD_IMPLEMENTATION call to @file{@var{foo}.c}
+@item
+add an INIT_LRECORD_IMPLEMENTATION call to @code{syms_of_@var{foo}.c}
 @end enumerate
 
 @node A Summary of the Various XEmacs Modules, Allocation of Objects in XEmacs Lisp, Rules When Writing New C Code, Top
@@ -2811,7 +2910,7 @@ chosen by @file{configure}.
 
 
 @example
-crt0.c
+ecrt0.c
 lastfile.c
 pre-crt0.c
 @end example
@@ -2946,14 +3045,6 @@ provided by the @samp{--error-check-*} configuration options.
 
 
 @example
-prefix-args.c
-@end example
-
-This is actually the source for a small, self-contained program
-used during building.
-
-
-@example
 universe.h
 @end example
 
@@ -2965,7 +3056,6 @@ This is not currently used.
 @section Basic Lisp Modules
 
 @example
-emacsfns.h
 lisp-disunion.h
 lisp-union.h
 lisp.h
@@ -3311,8 +3401,12 @@ Most of this could be implemented in Lisp.
 
 @example
 event-Xt.c
+event-msw.c
 event-stream.c
 event-tty.c
+events-mod.h
+gpmevent.c
+gpmevent.h
 events.c
 events.h
 @end example
@@ -3367,10 +3461,10 @@ relevant keymaps.)
 
 
 @example
-keyboard.c
+cmdloop.c
 @end example
 
-@file{keyboard.c} contains functions that implement the actual editor
+@file{cmdloop.c} contains functions that implement the actual editor
 command loop---i.e. the event loop that cyclically retrieves and
 dispatches events.  This code is also rather tricky, just like
 @file{event-stream.c}.
@@ -3408,13 +3502,31 @@ code is loaded).
 @section Modules for the Basic Displayable Lisp Objects
 
 @example
-device-ns.h
-device-stream.c
-device-stream.h
+console-msw.c
+console-msw.h
+console-stream.c
+console-stream.h
+console-tty.c
+console-tty.h
+console-x.c
+console-x.h
+console.c
+console.h
+@end example
+
+These modules implement the @dfn{console} Lisp object type.  A console
+contains multiple display devices, but only one keyboard and mouse.
+Most of the time, a console will contain exactly one device.
+
+Consoles are the top of a lisp object inclusion hierarchy.  Consoles
+contain devices, which contain frames, which contain windows.
+
+
+
+@example
+device-msw.c
 device-tty.c
-device-tty.h
 device-x.c
-device-x.h
 device.c
 device.h
 @end example
@@ -3435,10 +3547,9 @@ subtypes (X, TTY, NeXTstep, Microsoft Windows, etc.) as devices do.
 
 
 @example
-frame-ns.h
+frame-msw.c
 frame-tty.c
 frame-x.c
-frame-x.h
 frame.c
 frame.h
 @end example
@@ -3490,7 +3601,10 @@ faces.h
 
 @example
 bitmaps.h
-glyphs-ns.h
+glyphs-eimage.c
+glyphs-msw.c
+glyphs-msw.h
+glyphs-widget.c
 glyphs-x.c
 glyphs-x.h
 glyphs.c
@@ -3500,7 +3614,8 @@ glyphs.h
 
 
 @example
-objects-ns.h
+objects-msw.c
+objects-msw.h
 objects-tty.c
 objects-tty.h
 objects-x.c
@@ -3512,13 +3627,18 @@ objects.h
 
 
 @example
+menubar-msw.c
+menubar-msw.h
 menubar-x.c
 menubar.c
+menubar.h
 @end example
 
 
 
 @example
+scrollbar-msw.c
+scrollbar-msw.h
 scrollbar-x.c
 scrollbar-x.h
 scrollbar.c
@@ -3528,6 +3648,7 @@ scrollbar.h
 
 
 @example
+toolbar-msw.c
 toolbar-x.c
 toolbar.c
 toolbar.h
@@ -3554,6 +3675,7 @@ gifalloc.c
 @end example
 
 These modules decode GIF-format image files, for use with glyphs.
+These files were removed due to Unisys patent infringement concerns.
 
 
 
@@ -3562,6 +3684,7 @@ These modules decode GIF-format image files, for use with glyphs.
 
 @example
 redisplay-output.c
+redisplay-msw.c
 redisplay-tty.c
 redisplay-x.c
 redisplay.c
@@ -3656,7 +3779,7 @@ streams and C++ I/O streams.
 Similar to other subsystems in XEmacs, lstreams are separated into
 generic functions and a set of methods for the different types of
 lstreams.  @file{lstream.c} provides implementations of many different
-types of streams; others are provided, e.g., in @file{mule-coding.c}.
+types of streams; others are provided, e.g., in @file{file-coding.c}.
 
 
 
@@ -4121,16 +4244,6 @@ AIX prior to 4.1.
 
 
 
-@example
-msdos.c
-msdos.h
-@end example
-
-These modules are used for MS-DOS support, which does not work in
-XEmacs.
-
-
-
 @node Modules for Interfacing with X Windows, Modules for Internationalization, Modules for Interfacing with the Operating System, A Summary of the Various XEmacs Modules
 @section Modules for Interfacing with X Windows
 
@@ -4198,7 +4311,10 @@ needs to be rewritten.
 
 
 @example
-xselect.c
+select-msw.c
+select-x.c
+select.c
+select.h
 @end example
 
 @cindex selections
@@ -4281,8 +4397,8 @@ mule-canna.c
 mule-ccl.c
 mule-charset.c
 mule-charset.h
-mule-coding.c
-mule-coding.h
+file-coding.c
+file-coding.h
 mule-mcpath.c
 mule-mcpath.h
 mule-wnnfns.c
@@ -4294,13 +4410,13 @@ actually provides a general interface for all sorts of languages, not
 just Asian languages (although they are generally the most complicated
 to support).  This code is still in beta.
 
-@file{mule-charset.*} and @file{mule-coding.*} provide the heart of the
+@file{mule-charset.*} and @file{file-coding.*} provide the heart of the
 XEmacs MULE support.  @file{mule-charset.*} implements the @dfn{charset}
 Lisp object type, which encapsulates a character set (an ordered one- or
 two-dimensional set of characters, such as US ASCII or JISX0208 Japanese
 Kanji).
 
-@file{mule-coding.*} implements the @dfn{coding-system} Lisp object
+@file{file-coding.*} implements the @dfn{coding-system} Lisp object
 type, which encapsulates a method of converting between different
 encodings.  An encoding is a representation of a stream of characters,
 possibly from multiple character sets, using a stream of bytes or words,
@@ -4952,7 +5068,7 @@ For a description about the internals: @xref{lrecords}.
 
 Our next candidates are the other objects that behave quite differently
 than everything else: the strings. They consists of two parts, a
-fixed-size portion (@code{struct Lisp_string}) holding the string's
+fixed-size portion (@code{struct Lisp_String}) holding the string's
 length, its property list and a pointer to the second part, and the
 actual string data, which is stored in string-chars blocks comparable to
 frob blocks. In this block, the data is not only freed, but also a
@@ -5166,7 +5282,9 @@ more defensive but less efficient and is used for error-checking.)
 
   All lrecords have at the beginning of their structure a @code{struct
 lrecord_header}.  This just contains a type number and some flags,
-including the mark bit.  The type number, thru the
+including the mark bit.  All builtin type numbers are defined as
+constants in @code{enum lrecord_type}, to allow the compiler to generate
+more efficient code for @code{@var{type}P}.  The type number, thru the
 @code{lrecord_implementation_table}, gives access to a @code{struct
 lrecord_implementation}, which is a structure containing method pointers
 and such.  There is one of these for each type, and it is a global,
@@ -5201,21 +5319,21 @@ type.
 Whenever you create an lrecord, you need to call either
 @code{DEFINE_LRECORD_IMPLEMENTATION()} or
 @code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()}.  This needs to be
-specified in a C file, at the top level.  What this actually does is
-define and initialize the implementation structure for the lrecord. (And
-possibly declares a function @code{error_check_foo()} that implements
-the @code{XFOO()} macro when error-checking is enabled.)  The arguments
-to the macros are the actual type name (this is used to construct the C
-variable name of the lrecord implementation structure and related
-structures using the @samp{##} macro concatenation operator), a string
-that names the type on the Lisp level (this may not be the same as the C
-type name; typically, the C type name has underscores, while the Lisp
-string has dashes), various method pointers, and the name of the C
-structure that contains the object.  The methods are used to encapsulate
-type-specific information about the object, such as how to print it or
-mark it for garbage collection, so that it's easy to add new object
-types without having to add a specific case for each new type in a bunch
-of different places.
+specified in a @file{.c} file, at the top level.  What this actually
+does is define and initialize the implementation structure for the
+lrecord. (And possibly declares a function @code{error_check_foo()} that
+implements the @code{XFOO()} macro when error-checking is enabled.)  The
+arguments to the macros are the actual type name (this is used to
+construct the C variable name of the lrecord implementation structure
+and related structures using the @samp{##} macro concatenation
+operator), a string that names the type on the Lisp level (this may not
+be the same as the C type name; typically, the C type name has
+underscores, while the Lisp string has dashes), various method pointers,
+and the name of the C structure that contains the object.  The methods
+are used to encapsulate type-specific information about the object, such
+as how to print it or mark it for garbage collection, so that it's easy
+to add new object types without having to add a specific case for each
+new type in a bunch of different places.
 
   The difference between @code{DEFINE_LRECORD_IMPLEMENTATION()} and
 @code{DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION()} is that the former is
@@ -5229,21 +5347,20 @@ to determine the actual size of a particular object of that type.
   For the purpose of keeping allocation statistics, the allocation
 engine keeps a list of all the different types that exist.  Note that,
 since @code{DEFINE_LRECORD_IMPLEMENTATION()} is a macro that is
-specified at top-level, there is no way for it to add to the list of all
-existing types.  What happens instead is that each implementation
-structure contains in it a dynamically assigned number that is
-particular to that type. (Or rather, it contains a pointer to another
-structure that contains this number.  This evasiveness is done so that
-the implementation structure can be declared const.) In the sweep stage
-of garbage collection, each lrecord is examined to see if its
-implementation structure has its dynamically-assigned number set.  If
-not, it must be a new type, and it is added to the list of known types
-and a new number assigned.  The number is used to index into an array
-holding the number of objects of each type and the total memory
-allocated for objects of that type.  The statistics in this array are
-also computed during the sweep stage.  These statistics are returned by
-the call to @code{garbage-collect} and are printed out at the end of the
-loadup phase.
+specified at top-level, there is no way for it to initialize the global
+data structures containing type information, like
+@code{lrecord_implementations_table}.  For this reason a call to
+@code{INIT_LRECORD_IMPLEMENTATION} must be added to the same source file
+containing @code{DEFINE_LRECORD_IMPLEMENTATION}, but instead of to the
+top level, to one of the init functions, typically
+@code{syms_of_@var{foo}.c}.  @code{INIT_LRECORD_IMPLEMENTATION} must be
+called before an object of this type is used.
+
+The type number is also used to index into an array holding the number
+of objects of each type and the total memory allocated for objects of
+that type.  The statistics in this array are computed during the sweep
+stage.  These statistics are returned by the call to
+@code{garbage-collect}.
 
   Note that for every type defined with a @code{DEFINE_LRECORD_*()}
 macro, there needs to be a @code{DECLARE_LRECORD_IMPLEMENTATION()}
@@ -5255,6 +5372,15 @@ included by @file{inline.c}.
 file.  To create one of these, copy an existing model and modify as
 necessary.
 
+  @strong{Please note:} If you define an lrecord in an external
+dynamically-loaded module, you must use @code{DECLARE_EXTERNAL_LRECORD},
+@code{DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION}, and
+@code{DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION} instead of the
+non-EXTERNAL forms. These macros will dynamically add new type numbers
+to the global enum that records them, whereas the non-EXTERNAL forms
+assume that the programmer has already inserted the correct type numbers
+into the enum's code at compile-time.
+
   The various methods in the lrecord implementation structure are:
 
 @enumerate
@@ -5449,16 +5575,15 @@ warning system, when memory gets to 75%, 85%, and 95% full.
 (On some systems, the memory warnings are not functional.)
 
   Allocated memory that is going to be used to make a Lisp object
-is created using @code{allocate_lisp_storage()}.  This calls @code{xmalloc()}
-but also verifies that the pointer to the memory can fit into
-a Lisp word (remember that some bits are taken away for a type
-tag and a mark bit).  If not, an error is issued through @code{memory_full()}.
-@code{allocate_lisp_storage()} is called by @code{alloc_lcrecord()},
-@code{ALLOCATE_FIXED_TYPE()}, and the vector and bit-vector creation
-routines.  These routines also call @code{INCREMENT_CONS_COUNTER()} at the
-appropriate times; this keeps statistics on how much memory is
-allocated, so that garbage-collection can be invoked when the
-threshold is reached.
+is created using @code{allocate_lisp_storage()}.  This just calls
+@code{xmalloc()}.  It used to verify that the pointer to the memory can
+fit into a Lisp word, before the current Lisp object representation was
+introduced.  @code{allocate_lisp_storage()} is called by
+@code{alloc_lcrecord()}, @code{ALLOCATE_FIXED_TYPE()}, and the vector
+and bit-vector creation routines.  These routines also call
+@code{INCREMENT_CONS_COUNTER()} at the appropriate times; this keeps
+statistics on how much memory is allocated, so that garbage-collection
+can be invoked when the threshold is reached.
 
 @node Cons, Vector, Low-level allocation, Allocation of Objects in XEmacs Lisp
 @section Cons
@@ -5688,7 +5813,7 @@ field and a pointer to an associated array of lrecord_description.
 @node Dumping phase, Reloading phase, Data descriptions, Dumping
 @section Dumping phase
 
-Dumping is done by calling the function pdump() (in alloc.c) which is
+Dumping is done by calling the function pdump() (in dumper.c) which is
 invoked from Fdump_emacs (in emacs.c).  This function performs a number
 of tasks.
 
@@ -7024,7 +7149,7 @@ elsewhere.
 buffer positions in them as integers, and every time text is inserted or
 deleted, these positions must be updated.  In order to minimize the
 amount of shuffling that needs to be done, the positions in markers and
-extents (there's one per marker, two per extent) and stored in Meminds.
+extents (there's one per marker, two per extent) are stored in Meminds.
 This means that they only need to be moved when the text is physically
 moved in memory; since the gap structure tries to minimize this, it also
 minimizes the number of marker and extent indices that need to be
@@ -7512,7 +7637,7 @@ this is the code executed to handle any stuff that needs to be done
 other encoded/decoded data has been written out.  This is not used for
 charset CCL programs.
 
-REGISTER: 0..7  -- refered by RRR or rrr
+REGISTER: 0..7  -- referred by RRR or rrr
 
 OPERATOR BIT FIELD (27-bit): XXXXXXXXXXXXXXX RRR TTTTT
         TTTTT (5-bit): operator type
@@ -8649,7 +8774,7 @@ from its corresponding widget_instance by walking the widget_instance
 tree recursively.
 
 This has desirable properties such as lw_modify_all_widgets which is
-called from glyphs-x.c and updates all the properties of a widget
+called from @file{glyphs-x.c} and updates all the properties of a widget
 without having to know what the widget is or what toolkit it is from.
 Unfortunately this also has hairy properties such as making the lwlib
 code quite complex. And of course lwlib has to know at some level what
@@ -8798,4 +8923,3 @@ Not yet documented.
 @c That's all
 
 @bye
-