]> git.eshelyaron.com Git - emacs.git/commitdiff
Stop assuming interval pointers and lisp objects can be distinguished by
authorKen Raeburn <raeburn@raeburn.org>
Wed, 29 Mar 2000 22:14:34 +0000 (22:14 +0000)
committerKen Raeburn <raeburn@raeburn.org>
Wed, 29 Mar 2000 22:14:34 +0000 (22:14 +0000)
inspection.  Beginnings of support for expensive internal consistency checks.

* config.in (ENABLE_CHECKING): Undef.

* lisp.h (struct interval): Replace "parent" field with a union of interval
pointer and Lisp_Object; add new bitfield to use as discriminant.  Change other
flag fields to bitfields.
(CHECK): New macro for consistency checking.  If ENABLE_CHECKING is defined and
the supplied test fails, print a message and abort.
(eassert): New macro.  Use CHECK to provide an assert-like facility.

* intervals.h (NULL_INTERVAL_P): Now applies only to real interval pointers;
abort if the value looks like a lisp object.
(NULL_INTERVAL_P, NULL_PARENT, HAS_PARENT, HAS_OBJECT, SET_PARENT, SET_OBJECT,
INTERVAL_PARENT, GET_INTERVAL_OBJECT, COPY_PARENT): Modify for new interval
parent definition.

* alloc.c (mark_interval_tree, MARK_INTERVAL_TREE, UNMARK_BALANCE_INTERVALS):
Update references that need an addressable lisp object in the interval
structure.
(die): New function.
(suppress_checking): New variable.

* intervals.c (interval_start_pos): Just return 0 if there's no parent object.

src/ChangeLog
src/alloc.c
src/config.in
src/intervals.c
src/intervals.h
src/lisp.h

index 2232594d3b201d394deca3bfd40771a7262e611b..cf1050bb1ea0648d5dd8f7b9e9e7cb07cef2fcc3 100644 (file)
@@ -1,3 +1,31 @@
+2000-03-29  Ken Raeburn  <raeburn@gnu.org>
+
+       * config.in (ENABLE_CHECKING): Undef.
+
+       * lisp.h (struct interval): Replace "parent" field with a union of
+       interval pointer and Lisp_Object; add new bitfield to use as
+       discriminant.  Change other flag fields to bitfields.
+       (CHECK): New macro for consistency checking.  If ENABLE_CHECKING
+       is defined and the supplied test fails, print a message and
+       abort.
+       (eassert): New macro.  Use CHECK to provide an assert-like
+       facility.
+
+       * intervals.h (NULL_INTERVAL_P): Now applies only to real interval
+       pointers; abort if the value looks like a lisp object.
+       (NULL_INTERVAL_P, NULL_PARENT, HAS_PARENT, HAS_OBJECT, SET_PARENT,
+       SET_OBJECT, INTERVAL_PARENT, GET_INTERVAL_OBJECT, COPY_PARENT):
+       Modify for new interval parent definition.
+
+       * alloc.c (mark_interval_tree, MARK_INTERVAL_TREE,
+       UNMARK_BALANCE_INTERVALS): Update references that need an
+       addressable lisp object in the interval structure.
+       (die): New function.
+       (suppress_checking): New variable.
+
+       * intervals.c (interval_start_pos): Just return 0 if there's no
+       parent object.
+
 2000-03-29  Gerd Moellmann  <gerd@gnu.org>
 
        * lread.c (read1): Accept `.' (period) as symbol start like in CL
index d7e4214c6c43610b5390a7b10786a6adc2a5e79f..3b5d0e57ace1801f916324cd3d920f909ecf3a3e 100644 (file)
@@ -766,7 +766,7 @@ mark_interval_tree (tree)
 
   /* XMARK expands to an assignment; the LHS of an assignment can't be
      a cast.  */
-  XMARK (* (Lisp_Object *) &tree->parent);
+  XMARK (tree->up.obj);
 
   traverse_intervals (tree, 1, 0, mark_interval, Qnil);
 }
@@ -777,7 +777,7 @@ mark_interval_tree (tree)
 #define MARK_INTERVAL_TREE(i)                          \
   do {                                                 \
     if (!NULL_INTERVAL_P (i)                           \
-       && ! XMARKBIT (*(Lisp_Object *) &i->parent))    \
+       && ! XMARKBIT (i->up.obj))                      \
       mark_interval_tree (i);                          \
   } while (0)
 
@@ -790,7 +790,7 @@ mark_interval_tree (tree)
   do {                                                 \
    if (! NULL_INTERVAL_P (i))                          \
      {                                                 \
-       XUNMARK (* (Lisp_Object *) (&(i)->parent));     \
+       XUNMARK ((i)->up.obj);                          \
        (i) = balance_intervals (i);                    \
      }                                                 \
   } while (0)
@@ -4649,6 +4649,18 @@ Frames, windows, buffers, and subprocesses count as vectors\n\
 
   return Flist (8, consed);
 }
+
+int suppress_checking;
+void
+die (msg, file, line)
+     const char *msg;
+     const char *file;
+     int line;
+{
+  fprintf (stderr, "\r\nEmacs fatal error: %s:%d: %s\r\n",
+          file, line, msg);
+  abort ();
+}
 \f
 /* Initialization */
 
index 9fb464e6f7ba72a08f26c625d3dfc2d569ad60a3..511919aa3e8fb5483bf583dcdd8c9e3f2e9d92f6 100644 (file)
@@ -504,3 +504,6 @@ extern char *getenv ();
 #if defined HAVE_X11R6 && !defined INHIBIT_X11R6_XIM
 #define HAVE_X11R6_XIM
 #endif
+
+/* Should we enable expensive run-time checking of data types?  */
+#undef ENABLE_CHECKING
index 2a03abbb7629f4a0bb8dfb773c210eb5ecd78755..f925d222db2df26209d0bcc8737ae250b976f74a 100644 (file)
@@ -570,6 +570,8 @@ interval_start_pos (source)
   if (NULL_INTERVAL_P (source))
     return 0;
 
+  if (! INTERVAL_HAS_OBJECT (source))
+    return 0;
   GET_INTERVAL_OBJECT (parent, source);
   if (BUFFERP (parent))
     return BUF_BEG (XBUFFER (parent));
index eb50d723784581ce8cb060f3ef0c0bd66d2667f5..5db02e78629406c19e733a35665ed8e0978f2a43 100644 (file)
@@ -43,7 +43,8 @@ Boston, MA 02111-1307, USA.  */
 #define INT_LISPLIKE(i) (BUFFERP ((Lisp_Object){(EMACS_INT)(i)}) \
                         || STRINGP ((Lisp_Object){(EMACS_INT)(i)}))
 #endif
-#define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL || INT_LISPLIKE (i))
+#define NULL_INTERVAL_P(i) (CHECK(!INT_LISPLIKE(i),"non-interval"),(i) == NULL_INTERVAL)
+/* old #define NULL_INTERVAL_P(i) ((i) == NULL_INTERVAL || INT_LISPLIKE (i)) */
 
 /* True if this interval has no right child. */
 #define NULL_RIGHT_CHILD(i) ((i)->right == NULL_INTERVAL)
@@ -52,7 +53,7 @@ Boston, MA 02111-1307, USA.  */
 #define NULL_LEFT_CHILD(i) ((i)->left == NULL_INTERVAL)
 
 /* True if this interval has no parent. */
-#define NULL_PARENT(i) (NULL_INTERVAL_P ((i)->parent))
+#define NULL_PARENT(i) ((i)->up_obj || (i)->up.interval == 0)
 
 /* True if this interval is the left child of some other interval. */
 #define AM_LEFT_CHILD(i) (! NULL_PARENT (i) \
@@ -104,24 +105,24 @@ Boston, MA 02111-1307, USA.  */
 
 /* Test what type of parent we have.  Three possibilities: another
    interval, a buffer or string object, or NULL_INTERVAL.  */
-#define INTERVAL_HAS_PARENT(i) ((i)->parent && ! INT_LISPLIKE ((i)->parent))
-#define INTERVAL_HAS_OBJECT(i) ((i)->parent &&   INT_LISPLIKE ((i)->parent))
+#define INTERVAL_HAS_PARENT(i) ((i)->up_obj == 0 && (i)->up.interval != 0)
+#define INTERVAL_HAS_OBJECT(i) ((i)->up_obj)
 
 /* Set/get parent of an interval.
 
    The choice of macros is dependent on the type needed.  Don't add
    casts to get around this, it will break some development work in
    progress.  */
-#define SET_INTERVAL_PARENT(i,p) ((i)->parent = (p))
-#define SET_INTERVAL_OBJECT(i,o) ((i)->parent = (INTERVAL) XFASTINT (o))
-#define INTERVAL_PARENT(i) ((i)->parent)
+#define SET_INTERVAL_PARENT(i,p) (eassert (!BUFFERP ((Lisp_Object)(p)) && !STRINGP ((Lisp_Object)(p))),(i)->up_obj = 0, (i)->up.interval = (p))
+#define SET_INTERVAL_OBJECT(i,o) (eassert ((o) != 0), eassert (BUFFERP (o) || STRINGP (o)),(i)->up_obj = 1, (i)->up.obj = (o))
+#define INTERVAL_PARENT(i) (eassert((i) != 0 && (i)->up_obj == 0),(i)->up.interval)
 /* Because XSETFASTINT has to be used, this can't simply be
    value-returning.  */
-#define GET_INTERVAL_OBJECT(d,s) XSETFASTINT((d), (EMACS_INT) (s)->parent)
+#define GET_INTERVAL_OBJECT(d,s) (eassert((s)->up_obj == 1),XSETFASTINT ((d), (s)->up.obj))
 
 /* Make the parent of D be whatever the parent of S is, regardless of
    type.  This is used when balancing an interval tree.  */
-#define COPY_INTERVAL_PARENT(d,s) ((d)->parent = (s)->parent)
+#define COPY_INTERVAL_PARENT(d,s) ((d)->up = (s)->up, (d)->up_obj = (s)->up_obj)
 
 /* Get the parent interval, if any, otherwise a null pointer.  Useful
    for walking up to the root in a "for" loop; use this to get the
index af1ddb7a460693095990e9d4aa53d4e344646421..0e1cfff61abb7cfd94462d1b0bda7a6fc69fab6b 100644 (file)
@@ -46,6 +46,23 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #endif
 
+/* Extra internal type checking?  */
+extern int suppress_checking;
+#ifdef ENABLE_CHECKING
+extern void die P_((const char *, const char *, int));
+#define CHECK(check,msg) ((check || suppress_checking ? 0 : die (msg, __FILE__, __LINE__)), 0)
+#else
+/* Produce same side effects and result, but don't complain.  */
+#define CHECK(check,msg) ((check),0)
+#endif
+/* Define an Emacs version of "assert", since some system ones are
+   flaky.  */
+#if defined (__GNUC__) && __GNUC__ >= 2 && defined (__STDC__)
+#define eassert(cond) CHECK(cond,"assertion failed: " #cond)
+#else
+#define eassert(cond) CHECK(cond,"assertion failed")
+#endif
+
 /* Define the fundamental Lisp data structures.  */
 
 /* This is the set of Lisp data types.  */
@@ -494,17 +511,22 @@ struct interval
      You'd think we could store this information in the parent object
      somewhere (after all, that should be visited once and then
      ignored too, right?), but strings are GC'd strangely.  */
-  struct interval *parent;
+  union
+  {
+    struct interval *interval;
+    Lisp_Object obj;
+  } up;
+  unsigned int up_obj : 1;
 
   /* The remaining components are `properties' of the interval.
      The first four are duplicates for things which can be on the list,
      for purposes of speed.  */
 
-  unsigned char write_protect;     /* Non-zero means can't modify.  */
-  unsigned char visible;           /* Zero means don't display.  */
-  unsigned char front_sticky;      /* Non-zero means text inserted just
+  unsigned int write_protect : 1;    /* Non-zero means can't modify.  */
+  unsigned int visible : 1;        /* Zero means don't display.  */
+  unsigned int front_sticky : 1;    /* Non-zero means text inserted just
                                       before this interval goes into it.  */
-  unsigned char rear_sticky;       /* Likewise for just after it.  */
+  unsigned int rear_sticky : 1;            /* Likewise for just after it.  */
 
   /* Properties of this interval.
      The mark bit on this field says whether this particular interval