XEmacs 21.2.46 "Urania".
[chise/xemacs-chise.git-] / info / internals.info-2
index e8fe7d4..805e7ef 100644 (file)
@@ -410,11 +410,11 @@ representation 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 `Lisp_Object', but the actual C type
 used for the Lisp object can vary.  It can be either a simple type
@@ -425,24 +425,23 @@ 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
+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 `USE_UNION_TYPE' which is
 defined via the `--use-union-type' option to `configure'.
 
-   Various macros are used to construct Lisp objects and extract the
-components.  Macros of the form `XINT()', `XCHAR()', `XSTRING()',
-`XSYMBOL()', etc. shift out the tag field if needed cast it to the
-appropriate type.  `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 `ERROR_CHECK_TYPECHECK' is defined, the extractor
+   Various macros are used to convert between Lisp_Objects and the
+corresponding C type.  Macros of the form `XINT()', `XCHAR()',
+`XSTRING()', `XSYMBOL()', do any required bit shifting and/or masking
+and cast it to the appropriate type.  `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 `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
@@ -454,22 +453,24 @@ unpredictable (and sometimes not easily traceable) results.
 These macros are of the form `XSETTYPE (LVALUE, 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
-`make_int()', which constructs and _returns_ an integer Lisp object.
-Note that the `XSETTYPE()' macros are also affected by
+structure (but GCC does).  Granted, this sometimes isn't too
+convenient; for the case of integers, at least, you can use the
+function `make_int()', which constructs and _returns_ an integer Lisp
+object.  Note that the `XSETTYPE()' macros are also affected by
 `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 *guaranteeing* that a
-Lisp_Object is is the correct type before using the `XTYPE' macros.
-This is especially important in the case of lists.  Use `XCAR' and
-`XCDR' if a Lisp_Object is certainly a cons cell, else use `Fcar()' and
-`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" `abort()'s liberally about the
-source code.
+Lisp_Object is the correct type before using the `XTYPE' macros.  This
+is especially important in the case of lists.  Use `XCAR' and `XCDR' if
+a Lisp_Object is certainly a cons cell, else use `Fcar()' and `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 `assert()'s and "unreachable" `abort()'s liberally about the
+source code.  Where performance is an issue, use `type_checking_assert',
+`bufpos_checking_assert', and `gc_checking_assert', which do nothing
+unless the corresponding configure error checking flag was specified.
 
 \1f
 File: internals.info,  Node: Rules When Writing New C Code,  Next: A Summary of the Various XEmacs Modules,  Prev: How Lisp Objects Are Represented in C,  Up: Top
@@ -488,12 +489,14 @@ situations, often in code far away from where the actual breakage is.
 
 * General Coding Rules::
 * Writing Lisp Primitives::
+* Writing Good Comments::
 * Adding Global Lisp Variables::
+* Proper Use of Unsigned Types::
 * Coding for Mule::
 * Techniques for XEmacs Developers::
 
 \1f
-File: internals.info,  Node: General Coding Rules,  Next: Writing Lisp Primitives,  Prev: Rules When Writing New C Code,  Up: Rules When Writing New C Code
+File: internals.info,  Node: General Coding Rules,  Next: Writing Lisp Primitives,  Up: Rules When Writing New C Code
 
 General Coding Rules
 ====================
@@ -506,21 +509,6 @@ been found by compiling with C++.  The ability to use both C and C++
 tools means that a greater variety of development tools are available to
 the developer.
 
-   Almost every module contains a `syms_of_*()' function and a
-`vars_of_*()' function.  The former declares any Lisp primitives you
-have defined and defines any symbols you will be using.  The latter
-declares any global Lisp variables you have added and initializes global
-C variables in the module.  For each such function, declare it in
-`symsinit.h' and make sure it's called in the appropriate place in
-`emacs.c'.  *Important*: There are stringent requirements on exactly
-what can go into these functions.  See the comment in `emacs.c'.  The
-reason for this is to avoid obscure unwanted interactions during
-initialization.  If you don't follow these rules, you'll be sorry!  If
-you want to do anything that isn't allowed, create a
-`complex_vars_of_*()' function for it.  Doing this is tricky, though:
-You have to make sure your function is called at the right time so that
-all the initialization dependencies work out.
-
    Every module includes `<config.h>' (angle brackets so that
 `--srcdir' works correctly; `config.h' may or may not be in the same
 directory as the C sources) and `lisp.h'.  `config.h' must always be
@@ -529,13 +517,30 @@ to ensure that certain tricks played by various `s/' and `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 `./configure' and another build in another directory using
-`../work/configure'.  There will be two different `config.h' files.
-Which one will be used if you `#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 `./configure' and another build in another directory
+using `../work/configure'.  There will be two different `config.h'
+files.  Which one will be used if you `#include "config.h"'?
+
+   Almost every module contains a `syms_of_*()' function and a
+`vars_of_*()' function.  The former declares any Lisp primitives you
+have defined and defines any symbols you will be using.  The latter
+declares any global Lisp variables you have added and initializes global
+C variables in the module.  *Important*: There are stringent
+requirements on exactly what can go into these functions.  See the
+comment in `emacs.c'.  The reason for this is to avoid obscure unwanted
+interactions during initialization.  If you don't follow these rules,
+you'll be sorry!  If you want to do anything that isn't allowed, create
+a `complex_vars_of_*()' function for it.  Doing this is tricky, though:
+you have to make sure your function is called at the right time so that
+all the initialization dependencies work out.
+
+   Declare each function of these kinds in `symsinit.h'.  Make sure
+it's called in the appropriate place in `emacs.c'.  You never need to
+include `symsinit.h' directly, because it is included by `lisp.h'.
 
    *All global and static variables that are to be modifiable must be
 declared uninitialized.*  This means that you may not use the "declare
@@ -574,7 +579,7 @@ them.  This awful kludge has been removed in XEmacs because
    The C source code makes heavy use of C preprocessor macros.  One
 popular macro style is:
 
-     #define FOO(var, value) do {           \
+     #define FOO(var, value) do {            \
        Lisp_Object FOO_value = (value);      \
        ... /* compute using FOO_value */     \
        (var) = bar;                          \
@@ -589,9 +594,9 @@ copying a supplied argument into a local variable, so that
    Lisp lists are popular data structures in the C code as well as in
 Elisp.  There are two sets of macros that iterate over lists.
 `EXTERNAL_LIST_LOOP_N' should be used when the list has been supplied
-by the user, and cannot be trusted to be acyclic and nil-terminated.  A
-`malformed-list' or `circular-list' error will be generated if the list
-being iterated over is not entirely kosher.  `LIST_LOOP_N', on the
+by the user, and cannot be trusted to be acyclic and `nil'-terminated.
+A `malformed-list' or `circular-list' error will be generated if the
+list being iterated over is not entirely kosher.  `LIST_LOOP_N', on the
 other hand, is faster and less safe, and can be used only on trusted
 lists.
 
@@ -602,7 +607,7 @@ macros `EXTERNAL_LIST_LOOP_DELETE_IF' and `LIST_LOOP_DELETE_IF' delete
 elements from a lisp list satisfying some predicate.
 
 \1f
-File: internals.info,  Node: Writing Lisp Primitives,  Next: Adding Global Lisp Variables,  Prev: General Coding Rules,  Up: Rules When Writing New C Code
+File: internals.info,  Node: Writing Lisp Primitives,  Next: Writing Good Comments,  Prev: General Coding Rules,  Up: Rules When Writing New C Code
 
 Writing Lisp Primitives
 =======================
@@ -832,7 +837,70 @@ arguments.  They work by calling `Ffuncall'.
 contains the definitions for important macros and functions.
 
 \1f
-File: internals.info,  Node: Adding Global Lisp Variables,  Next: Coding for Mule,  Prev: Writing Lisp Primitives,  Up: Rules When Writing New C Code
+File: internals.info,  Node: Writing Good Comments,  Next: Adding Global Lisp Variables,  Prev: Writing Lisp Primitives,  Up: Rules When Writing New C Code
+
+Writing Good Comments
+=====================
+
+   Comments are a lifeline for programmers trying to understand tricky
+code.  In general, the less obvious it is what you are doing, the more
+you need a comment, and the more detailed it needs to be.  You should
+always be on guard when you're writing code for stuff that's tricky, and
+should constantly be putting yourself in someone else's shoes and asking
+if that person could figure out without much difficulty what's going
+on. (Assume they are a competent programmer who understands the
+essentials of how the XEmacs code is structured but doesn't know much
+about the module you're working on or any algorithms you're using.) If
+you're not sure whether they would be able to, add a comment.  Always
+err on the side of more comments, rather than less.
+
+   Generally, when making comments, there is no need to attribute them
+with your name or initials.  This especially goes for small,
+easy-to-understand, non-opinionated ones.  Also, comments indicating
+where, when, and by whom a file was changed are _strongly_ discouraged,
+and in general will be removed as they are discovered.  This is exactly
+what `ChangeLogs' are there for.  However, it can occasionally be
+useful to mark exactly where (but not when or by whom) changes are
+made, particularly when making small changes to a file imported from
+elsewhere.  These marks help when later on a newer version of the file
+is imported and the changes need to be merged. (If everything were
+always kept in CVS, there would be no need for this.  But in practice,
+this often doesn't happen, or the CVS repository is later on lost or
+unavailable to the person doing the update.)
+
+   When putting in an explicit opinion in a comment, you should
+_always_ attribute it with your name, and optionally the date.  This
+also goes for long, complex comments explaining in detail the workings
+of something - by putting your name there, you make it possible for
+someone who has questions about how that thing works to determine who
+wrote the comment so they can write to them.  Preferably, use your
+actual name and not your initials, unless your initials are generally
+recognized (e.g. `jwz').  You can use only your first name if it's
+obvious who you are; otherwise, give first and last name.  If you're
+not a regular contributor, you might consider putting your email
+address in - it may be in the ChangeLog, but after awhile ChangeLogs
+have a tendency of disappearing or getting muddled. (E.g. your comment
+may get copied somewhere else or even into another program, and
+tracking down the proper ChangeLog may be very difficult.)
+
+   If you come across an opinion that is not or no longer valid, or you
+come across any comment that no longer applies but you want to keep it
+around, enclose it in `[[ ' and ` ]]' marks and add a comment
+afterwards explaining why the preceding comment is no longer valid.  Put
+your name on this comment, as explained above.
+
+   Just as comments are a lifeline to programmers, incorrect comments
+are death.  If you come across an incorrect comment, *immediately*
+correct it or flag it as incorrect, as described in the previous
+paragraph.  Whenever you work on a section of code, _always_ make sure
+to update any comments to be correct - or, at the very least, flag them
+as incorrect.
+
+   To indicate a "todo" or other problem, use four pound signs - i.e.
+`####'.
+
+\1f
+File: internals.info,  Node: Adding Global Lisp Variables,  Next: Proper Use of Unsigned Types,  Prev: Writing Good Comments,  Up: Rules When Writing New C Code
 
 Adding Global Lisp Variables
 ============================
@@ -895,7 +963,36 @@ and you will be the one who's unhappy when you can't figure out how
 your variable got overwritten.
 
 \1f
-File: internals.info,  Node: Coding for Mule,  Next: Techniques for XEmacs Developers,  Prev: Adding Global Lisp Variables,  Up: Rules When Writing New C Code
+File: internals.info,  Node: Proper Use of Unsigned Types,  Next: Coding for Mule,  Prev: Adding Global Lisp Variables,  Up: Rules When Writing New C Code
+
+Proper Use of Unsigned Types
+============================
+
+   Avoid using `unsigned int' and `unsigned long' whenever possible.
+Unsigned types are viral - any arithmetic or comparisons involving
+mixed signed and unsigned types are automatically converted to
+unsigned, which is almost certainly not what you want.  Many subtle and
+hard-to-find bugs are created by careless use of unsigned types.  In
+general, you should almost _never_ use an unsigned type to hold a
+regular quantity of any sort.  The only exceptions are
+
+  1. When there's a reasonable possibility you will actually need all
+     32 or 64 bits to store the quantity.
+
+  2. When calling existing API's that require unsigned types.  In this
+     case, you should still do all manipulation using signed types, and
+     do the conversion at the very threshold of the API call.
+
+  3. In existing code that you don't want to modify because you don't
+     maintain it.
+
+  4. In bit-field structures.
+
+   Other reasonable uses of `unsigned int' and `unsigned long' are
+representing non-quantities - e.g. bit-oriented flags and such.
+
+\1f
+File: internals.info,  Node: Coding for Mule,  Next: Techniques for XEmacs Developers,  Prev: Proper Use of Unsigned Types,  Up: Rules When Writing New C Code
 
 Coding for Mule
 ===============
@@ -920,7 +1017,7 @@ of code generalization for future I18N work.
 * An Example of Mule-Aware Code::
 
 \1f
-File: internals.info,  Node: Character-Related Data Types,  Next: Working With Character and Byte Positions,  Prev: Coding for Mule,  Up: Coding for Mule
+File: internals.info,  Node: Character-Related Data Types,  Next: Working With Character and Byte Positions,  Up: Coding for Mule
 
 Character-Related Data Types
 ----------------------------
@@ -990,102 +1087,3 @@ glance at the declaration can tell the intended use of the variable.
      is the distance between two `Extbyte's.  Extbytes and Extcounts
      are not all that frequent in XEmacs code.
 
-\1f
-File: internals.info,  Node: Working With Character and Byte Positions,  Next: Conversion to and from External Data,  Prev: Character-Related Data Types,  Up: Coding for Mule
-
-Working With Character and Byte Positions
------------------------------------------
-
-   Now that we have defined the basic character-related types, we can
-look at the macros and functions designed for work with them and for
-conversion between them.  Most of these macros are defined in
-`buffer.h', and we don't discuss all of them here, but only the most
-important ones.  Examining the existing code is the best way to learn
-about them.
-
-`MAX_EMCHAR_LEN'
-     This preprocessor constant is the maximum number of buffer bytes to
-     represent an Emacs character in the variable width internal
-     encoding.  It is useful when allocating temporary strings to keep
-     a known number of characters.  For instance:
-
-          {
-            Charcount cclen;
-            ...
-            {
-              /* Allocate place for CCLEN characters. */
-              Bufbyte *buf = (Bufbyte *)alloca (cclen * MAX_EMCHAR_LEN);
-          ...
-
-     If you followed the previous section, you can guess that,
-     logically, multiplying a `Charcount' value with `MAX_EMCHAR_LEN'
-     produces a `Bytecount' value.
-
-     In the current Mule implementation, `MAX_EMCHAR_LEN' equals 4.
-     Without Mule, it is 1.
-
-`charptr_emchar'
-`set_charptr_emchar'
-     The `charptr_emchar' macro takes a `Bufbyte' pointer and returns
-     the `Emchar' stored at that position.  If it were a function, its
-     prototype would be:
-
-          Emchar charptr_emchar (Bufbyte *p);
-
-     `set_charptr_emchar' stores an `Emchar' to the specified byte
-     position.  It returns the number of bytes stored:
-
-          Bytecount set_charptr_emchar (Bufbyte *p, Emchar c);
-
-     It is important to note that `set_charptr_emchar' is safe only for
-     appending a character at the end of a buffer, not for overwriting a
-     character in the middle.  This is because the width of characters
-     varies, and `set_charptr_emchar' cannot resize the string if it
-     writes, say, a two-byte character where a single-byte character
-     used to reside.
-
-     A typical use of `set_charptr_emchar' can be demonstrated by this
-     example, which copies characters from buffer BUF to a temporary
-     string of Bufbytes.
-
-          {
-            Bufpos pos;
-            for (pos = beg; pos < end; pos++)
-              {
-                Emchar c = BUF_FETCH_CHAR (buf, pos);
-                p += set_charptr_emchar (buf, c);
-              }
-          }
-
-     Note how `set_charptr_emchar' is used to store the `Emchar' and
-     increment the counter, at the same time.
-
-`INC_CHARPTR'
-`DEC_CHARPTR'
-     These two macros increment and decrement a `Bufbyte' pointer,
-     respectively.  They will adjust the pointer by the appropriate
-     number of bytes according to the byte length of the character
-     stored there.  Both macros assume that the memory address is
-     located at the beginning of a valid character.
-
-     Without Mule support, `INC_CHARPTR (p)' and `DEC_CHARPTR (p)'
-     simply expand to `p++' and `p--', respectively.
-
-`bytecount_to_charcount'
-     Given a pointer to a text string and a length in bytes, return the
-     equivalent length in characters.
-
-          Charcount bytecount_to_charcount (Bufbyte *p, Bytecount bc);
-
-`charcount_to_bytecount'
-     Given a pointer to a text string and a length in characters,
-     return the equivalent length in bytes.
-
-          Bytecount charcount_to_bytecount (Bufbyte *p, Charcount cc);
-
-`charptr_n_addr'
-     Return a pointer to the beginning of the character offset CC (in
-     characters) from P.
-
-          Bufbyte *charptr_n_addr (Bufbyte *p, Charcount cc);
-