emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 682b068ba7: Merge remote-tracking branch 'origin/scratch/noverlay


From: Stefan Monnier
Subject: master 682b068ba7: Merge remote-tracking branch 'origin/scratch/noverlay'
Date: Thu, 17 Nov 2022 18:52:54 -0500 (EST)

branch: master
commit 682b068ba712075cea34d8bc790620ba82169d6c
Merge: 17889dd828 091e0f04ff
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    Merge remote-tracking branch 'origin/scratch/noverlay'
---
 src/alloc.c  |   5 -
 src/buffer.c |  12 +-
 src/emacs.c  |   3 -
 src/eval.c   |   1 -
 src/itree.c  | 432 +++++++++++++++++++++++++++--------------------------------
 src/itree.h  |  55 ++++----
 src/xdisp.c  |  10 +-
 7 files changed, 230 insertions(+), 288 deletions(-)

diff --git a/src/alloc.c b/src/alloc.c
index 6862cf916f..b9d12dff7e 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6279,11 +6279,6 @@ garbage_collect (void)
   image_prune_animation_caches (false);
 #endif
 
-  /* ELisp code run by `gc-post-hook' could result in itree iteration,
-     which must not happen while the itree is already busy.  See
-     bug#58639.  */
-  eassert (!itree_iterator_busy_p ());
-
   if (!NILP (Vpost_gc_hook))
     {
       specpdl_ref gc_count = inhibit_garbage_collection ();
diff --git a/src/buffer.c b/src/buffer.c
index 9be2c4a970..4da5b451d0 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2985,17 +2985,13 @@ overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
       if (node->begin > end)
         {
           next = min (next, node->begin);
-          ITREE_FOREACH_ABORT ();
           break;
         }
       else if (node->begin == end)
         {
           next = node->begin;
           if ((! empty || end < ZV) && beg < end)
-            {
-              ITREE_FOREACH_ABORT ();
-              break;
-            }
+            break;
           if (empty && node->begin != node->end)
             continue;
         }
@@ -3050,7 +3046,6 @@ next_overlay_change (ptrdiff_t pos)
              of pos, because the search is limited to [pos,next) . */
           eassert (node->begin < next);
           next = node->begin;
-          ITREE_FOREACH_ABORT ();
           break;
         }
       else if (node->begin < node->end && node->end < next)
@@ -3155,10 +3150,7 @@ overlay_touches_p (ptrdiff_t pos)
      pos. */
   ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING)
     if (node->begin == pos || node->end == pos)
-      {
-        ITREE_FOREACH_ABORT ();
-        return true;
-      }
+      return true;
   return false;
 }
 
diff --git a/src/emacs.c b/src/emacs.c
index c4c8bfc82f..85102acd28 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1932,7 +1932,6 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
   running_asynch_code = 0;
   init_random ();
   init_xfaces ();
-  init_itree ();
 
 #if defined HAVE_JSON && !defined WINDOWSNT
   init_json ();
@@ -3105,8 +3104,6 @@ You must run Emacs in batch mode in order to dump it.  */)
   gflags.will_dump_with_unexec_ = false;
   gflags.dumped_with_unexec_ = true;
 
-  forget_itree ();
-
   alloc_unexec_pre ();
 
   unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
diff --git a/src/eval.c b/src/eval.c
index ea23829948..78e606267f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1716,7 +1716,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
   Lisp_Object clause = Qnil;
   struct handler *h;
 
-  eassert (!itree_iterator_busy_p ());
   if (gc_in_progress || waiting_for_input)
     emacs_abort ();
 
diff --git a/src/itree.c b/src/itree.c
index 3b219d958a..7bf3b9507b 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -131,33 +131,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
  * | Stack
  * +=======================================================================+ */
 
-typedef uintptr_t nodeptr_and_flag;
-
-static inline nodeptr_and_flag
-make_nav (struct itree_node *ptr, bool flag)
-{
-  uintptr_t v = (uintptr_t) ptr;
-  /* We assume alignment imposes the LSB is clear for us to use it.  */
-  eassert (!(v & 1));
-  return v | !!flag;
-}
-
-static inline struct itree_node *
-nav_nodeptr (nodeptr_and_flag nav)
-{
-  return (struct itree_node *) (nav & (~(uintptr_t)1));
-}
-
-static inline bool
-nav_flag (nodeptr_and_flag nav)
-{
-  return (bool) (nav & 1);
-}
-
 /* Simple dynamic array. */
 struct itree_stack
 {
-  nodeptr_and_flag *nodes;
+  struct itree_node **nodes;
   size_t size;
   size_t length;
 };
@@ -184,12 +161,6 @@ itree_stack_destroy (struct itree_stack *stack)
   xfree (stack);
 }
 
-static void
-itree_stack_clear (struct itree_stack *stack)
-{
-  stack->length = 0;
-}
-
 static inline void
 itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements)
 {
@@ -204,104 +175,32 @@ itree_stack_ensure_space (struct itree_stack *stack, 
uintmax_t nelements)
 /* Push NODE on the STACK, while settings its visited flag to FLAG. */
 
 static inline void
-itree_stack_push_flagged (struct itree_stack *stack,
-                            struct itree_node *node, bool flag)
+itree_stack_push (struct itree_stack *stack, struct itree_node *node)
 {
   eassert (node);
-
-  /* FIXME: While the stack used in the iterator is bounded by the tree
-     depth and could be easily pre-allocated to a large enough size to avoid
-     this "ensure" check, `itree_stack_push` is also used elsewhere to
-     simply collect some subset of the overlays, where it's only bounded by
-     the total number of overlays in the buffer (which can be large and thus
-     preferably not pre-allocated needlessly).  */
   itree_stack_ensure_space (stack, stack->length + 1);
 
-  stack->nodes[stack->length] = make_nav (node, flag);
+  stack->nodes[stack->length] = node;
   stack->length++;
 }
 
-static inline void
-itree_stack_push (struct itree_stack *stack, struct itree_node *node)
-{
-  itree_stack_push_flagged (stack, node, false);
-}
-
-static inline nodeptr_and_flag
+static inline struct itree_node *
 itree_stack_pop (struct itree_stack *stack)
 {
   if (stack->length == 0)
-    return make_nav (NULL, false);
+    return NULL;
   return stack->nodes[--stack->length];
 }
 
 
 /* +-----------------------------------------------------------------------+ */
 
-/* State used when iterating interval. */
-struct itree_iterator
-{
-  struct itree_stack *stack;
-  ptrdiff_t begin;
-  ptrdiff_t end;
-
-  /* A copy of the tree's `otick`.  */
-  uintmax_t otick;
-  enum itree_order order;
-  bool running;
-  const char *file;
-  int line;
-};
-
-/* Ideally, every iteration would use its own `iter` object, so we could
-   have several iterations active at the same time.  In practice, iterations
-   are limited by the fact we don't allow modifying the tree at the same
-   time, making the use of nested iterations quite rare anyway.
-   So we just use a single global iterator instead for now.  */
-static struct itree_iterator *iter = NULL;
-
 static int
 itree_max_height (const struct itree_tree *tree)
 {
   return 2 * log (tree->size + 1) / log (2) + 0.5;
 }
 
-/* Allocate a new iterator for TREE. */
-
-static struct itree_iterator *
-itree_iterator_create (struct itree_tree *tree)
-{
-  struct itree_iterator *g = xmalloc (sizeof *g);
-  /* 19 here just avoids starting with a silly-small stack.
-     FIXME: Since this stack only needs to be about 2*max_depth
-     in the worst case, we could completely pre-allocate it to something
-     like word-bit-size * 2 and then never worry about growing it.  */
-  const int size = (tree ? itree_max_height (tree) : 19) + 1;
-
-  g->stack = itree_stack_create (size);
-  g->running = false;
-  g->begin = 0;
-  g->end = 0;
-  g->file = NULL;
-  g->line = 0;
-  return g;
-}
-
-void
-init_itree (void)
-{
-  eassert (!iter);
-  iter = itree_iterator_create (NULL);
-}
-
-#ifdef HAVE_UNEXEC
-void
-forget_itree (void)
-{
-  iter = NULL;
-}
-#endif
-
 struct check_subtree_result
 {
   /* Node count of the tree.  */
@@ -869,14 +768,11 @@ itree_node_set_region (struct itree_tree *tree,
 static bool
 itree_contains (struct itree_tree *tree, struct itree_node *node)
 {
-  eassert (iter && node);
+  eassert (node);
   struct itree_node *other;
   ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING)
     if (other == node)
-      {
-       ITREE_FOREACH_ABORT ();
-       return true;
-      }
+      return true;
 
   return false;
 }
@@ -1138,52 +1034,6 @@ itree_remove (struct itree_tree *tree, struct itree_node 
*node)
   return node;
 }
 
-bool
-itree_iterator_busy_p (void)
-{
-  return (iter && iter->running);
-}
-
-/* Start a iterator enumerating all intervals in [BEGIN,END) in the
-   given ORDER.  Only one iterator per tree can be running at any time.  */
-
-struct itree_iterator *
-itree_iterator_start (struct itree_tree *tree, ptrdiff_t begin,
-                     ptrdiff_t end, enum itree_order order,
-                     const char *file, int line)
-{
-  eassert (iter);
-  if (iter->running)
-    {
-      fprintf (stderr,
-              "Detected nested iteration!\nOuter: %s:%d\nInner: %s:%d\n",
-              iter->file, iter->line, file, line);
-      emacs_abort ();
-    }
-  iter->begin = begin;
-  iter->end = end;
-  iter->otick = tree->otick;
-  iter->order = order;
-  itree_stack_clear (iter->stack);
-  if (begin <= end && tree->root != NULL)
-    itree_stack_push_flagged (iter->stack, tree->root, false);
-  iter->file = file;
-  iter->line = line;
-  iter->running = true;
-  /* itree_stack_ensure_space (iter->stack,
-                                 2 * itree_max_height (tree)); */
-  return iter;
-}
-
-/* Stop using the iterator. */
-
-void
-itree_iterator_finish (struct itree_iterator *iter)
-{
-  eassert (iter && iter->running);
-  iter->running = false;
-}
-
 
 /* +=======================================================================+
  * | Insert/Delete Gaps
@@ -1214,6 +1064,7 @@ itree_insert_gap (struct itree_tree *tree,
   struct itree_node *node = NULL;
   if (!before_markers)
     {
+      /* Actually any order would do.  */
       ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER)
        {
          if (node->begin == pos && node->front_advance
@@ -1225,7 +1076,7 @@ itree_insert_gap (struct itree_tree *tree,
        }
     }
   for (size_t i = 0; i < saved->length; ++i)
-    itree_remove (tree, nav_nodeptr (saved->nodes[i]));
+    itree_remove (tree, saved->nodes[i]);
 
   /* We can't use an iterator here, because we can't effectively
      narrow AND shift some subtree at the same time.  */
@@ -1234,9 +1085,7 @@ itree_insert_gap (struct itree_tree *tree,
       const int size = itree_max_height (tree) + 1;
       struct itree_stack *stack = itree_stack_create (size);
       itree_stack_push (stack, tree->root);
-      nodeptr_and_flag nav;
-      while ((nav = itree_stack_pop (stack),
-             node = nav_nodeptr (nav)))
+      while ((node = itree_stack_pop (stack)))
        {
          /* Process in pre-order. */
          itree_inherit_offset (tree->otick, node);
@@ -1273,9 +1122,7 @@ itree_insert_gap (struct itree_tree *tree,
 
   /* Reinsert nodes starting at POS having front-advance.  */
   uintmax_t notick = tree->otick;
-  nodeptr_and_flag nav;
-  while ((nav = itree_stack_pop (saved),
-         node = nav_nodeptr (nav)))
+  while ((node = itree_stack_pop (saved)))
     {
       eassert (node->otick == ootick);
       eassert (node->begin == pos);
@@ -1308,10 +1155,8 @@ itree_delete_gap (struct itree_tree *tree,
   struct itree_node *node;
 
   itree_stack_push (stack, tree->root);
-  nodeptr_and_flag nav;
-  while ((nav = itree_stack_pop (stack)))
+  while ((node = itree_stack_pop (stack)))
     {
-      node = nav_nodeptr (nav);
       itree_inherit_offset (tree->otick, node);
       if (pos > node->limit)
        continue;
@@ -1357,80 +1202,205 @@ itree_delete_gap (struct itree_tree *tree,
 
 static inline bool
 itree_node_intersects (const struct itree_node *node,
-                         ptrdiff_t begin, ptrdiff_t end)
+                      ptrdiff_t begin, ptrdiff_t end)
 {
   return (begin < node->end && node->begin < end)
     || (node->begin == node->end && begin == node->begin);
 }
 
-/* Return the next node of the iterator in the order given when it was
-   started; or NULL if there are no more nodes. */
+/* Return the "next" node in the current traversal order.
 
-struct itree_node *
-itree_iterator_next (struct itree_iterator *g)
-{
-  eassert (g && g->running);
+   Note that this should return all the nodes that we need to traverse
+   in order to traverse the nodes selected by the current narrowing (i.e.
+   `ITER->begin..ITER->end`) so it will also return some nodes which aren't in
+   that narrowing simply because they may have children which are.
 
-  struct itree_node *const null = NULL;
-  struct itree_node *node;
+   The code itself is very unsatifactory because the code of each one
+   of the supported traversals seems completely different from the others.
+   If someone knows how to make it more uniform and "obviously correct",
+   please make yourself heard.  */
 
-  /* The `visited` flag stored in each node is used here (and only here):
-     We keep a "workstack" of nodes we need to consider.  This stack
-     consist of nodes of two types: nodes that we have decided
-     should be returned by the iterator, and nodes which we may
-     need to consider (including checking their children).
-     We start an iteration with a stack containing just the root
-     node marked as "not visited" which means that it (and its children)
-     needs to be considered but we haven't yet decided whether it's included
-     in the iterator's output.  */
-
-  do
+static struct itree_node *
+itree_iter_next_in_subtree (struct itree_node *node,
+                            struct itree_iterator *iter)
+{
+  struct itree_node *next;
+  switch (iter->order)
     {
-      nodeptr_and_flag nav;
-      bool visited;
-      while ((nav = itree_stack_pop (g->stack),
-             node = nav_nodeptr (nav),
-             visited = nav_flag (nav),
-             node && !visited))
-       {
-         struct itree_node *const left = node->left;
-         struct itree_node *const right = node->right;
+    case ITREE_ASCENDING:
+      next = node->right;
+      if (!next)
+        {
+          while ((next = node->parent)
+                 && next->right == node)
+            node = next;
+          if (!next)
+            return NULL;   /* No more nodes to visit. */
+          node = next;
+        }
+      else
+        {
+          node = next;
+          itree_inherit_offset (iter->otick, node);
+          while ((next = node->left)
+                 && (itree_inherit_offset (iter->otick, next),
+                     iter->begin <= next->limit))
+            node = next;
+        }
+      if (node->begin > iter->end)
+        return NULL;  /* No more nodes within begin..end.  */
+      return node;
+
+    case ITREE_DESCENDING:
+      next = node->left;
+      if (!next
+          || (itree_inherit_offset (iter->otick, next),
+              next->limit < iter->begin))
+        {
+          while ((next = node->parent)
+                 && next->left == node)
+            node = next;
+          if (!next)
+            return NULL;   /* No more nodes to visit. */
+          node = next;
+        }
+      else
+        {
+          node = next;
+          while (node->begin <= iter->end
+                 && (next = node->right))
+            {
+              itree_inherit_offset (iter->otick, next),
+              node = next;
+            }
+        }
+      return node;
+
+    case ITREE_PRE_ORDER:
+      next = node->left;
+      if (next
+          && (itree_inherit_offset (iter->otick, next),
+              !(next->limit < iter->begin)))
+        return next;
+      next = node->right;
+      if (node->begin <= iter->end && next)
+        {
+          itree_inherit_offset (iter->otick, next);
+          return next;
+        }
+      while ((next = node->parent))
+        {
+          if (next->right == node)
+            node = next;
+          else
+            {
+              eassert (next->left == node);
+              node = next;
+              next = node->right;
+              if (node->begin <= iter->end && next)
+                {
+                  itree_inherit_offset (iter->otick, next);
+                  return next;
+                }
+            }
+          }
+      return NULL;
+
+    case ITREE_POST_ORDER:
+      next = node->parent;
+      if (!next || next->right == node)
+        return next;
+      eassert (next->left == node);
+      node = next;
+      next = node->right;
+      if (!(node->begin <= iter->end && next))
+        return node;
+      node = next;
+      itree_inherit_offset (iter->otick, node);
+      while (((next = node->left)
+              && (itree_inherit_offset (iter->otick, next),
+                  iter->begin <= next->limit))
+             || (node->begin <= iter->end
+                 && (next = node->right)
+                 && (itree_inherit_offset (iter->otick, next), true)))
+        node = next;
+      return node;
+
+    default:
+    emacs_abort ();
+    }
+}
 
-         itree_inherit_offset (g->otick, node);
-         eassert (itree_limit_is_stable (node));
-         switch (g->order)
-           {
-           case ITREE_ASCENDING:
-             if (right != null && node->begin <= g->end)
-               itree_stack_push_flagged (g->stack, right, false);
-             if (itree_node_intersects (node, g->begin, g->end))
-               itree_stack_push_flagged (g->stack, node, true);
-             /* Node's children may still be off-set and we need to add it.  */
-             if (left != null && g->begin <= left->limit + left->offset)
-               itree_stack_push_flagged (g->stack, left, false);
-             break;
-           case ITREE_DESCENDING:
-             if (left != null && g->begin <= left->limit + left->offset)
-               itree_stack_push_flagged (g->stack, left, false);
-             if (itree_node_intersects (node, g->begin, g->end))
-               itree_stack_push_flagged (g->stack, node, true);
-             if (right != null && node->begin <= g->end)
-               itree_stack_push_flagged (g->stack, right, false);
-             break;
-           case ITREE_PRE_ORDER:
-             if (right != null && node->begin <= g->end)
-               itree_stack_push_flagged (g->stack, right, false);
-             if (left != null && g->begin <= left->limit + left->offset)
-               itree_stack_push_flagged (g->stack, left, false);
-             if (itree_node_intersects (node, g->begin, g->end))
-               itree_stack_push_flagged (g->stack, node, true);
-             break;
-           }
-       }
-      /* Node may have been invalidated by itree_iterator_narrow
-        after it was pushed: Check if it still intersects. */
-    } while (node && ! itree_node_intersects (node, g->begin, g->end));
+static struct itree_node *
+itree_iterator_first_node (struct itree_tree *tree,
+                           struct itree_iterator *iter)
+{
+  struct itree_node *node = tree->root;
+  if (node)
+    {
+      struct itree_node dummy;
+      dummy.left = NULL;
+      dummy.parent = NULL;
+      dummy.right = NULL;
+      itree_inherit_offset (iter->otick, node);
+      switch (iter->order)
+        {
+        case ITREE_ASCENDING:
+          dummy.right = node;
+          dummy.begin = PTRDIFF_MIN;
+          node = itree_iter_next_in_subtree (&dummy, iter);
+          break;
+
+        case ITREE_DESCENDING:
+          dummy.left = node;
+          node = itree_iter_next_in_subtree (&dummy, iter);
+          break;
+
+        case ITREE_PRE_ORDER:
+          break;
+
+        case ITREE_POST_ORDER:
+          dummy.parent = &dummy;
+          dummy.left = &dummy;
+          dummy.right = node;
+          dummy.begin = PTRDIFF_MIN;
+          node = itree_iter_next_in_subtree (&dummy, iter);
+          break;
+        default:
+          emacs_abort ();
+        }
+    }
+  return node;
+}
+
+/* Start a iterator enumerating all intervals in [BEGIN,END) in the
+   given ORDER.  */
 
+struct itree_iterator *
+itree_iterator_start (struct itree_iterator *iter,
+                     struct itree_tree *tree,
+                     ptrdiff_t begin, ptrdiff_t end, enum itree_order order)
+{
+  eassert (iter);
+  iter->begin = begin;
+  iter->end = end;
+  iter->otick = tree->otick;
+  iter->order = order;
+  iter->node = itree_iterator_first_node (tree, iter);
+  return iter;
+}
+
+struct itree_node *
+itree_iterator_next (struct itree_iterator *iter)
+{
+  struct itree_node *node = iter->node;
+  while (node
+         && !itree_node_intersects (node, iter->begin, iter->end))
+    {
+      node = itree_iter_next_in_subtree (node, iter);
+      eassert (itree_limit_is_stable (node));
+    }
+  iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL;
   return node;
 }
 
@@ -1441,7 +1411,7 @@ void
 itree_iterator_narrow (struct itree_iterator *g,
                       ptrdiff_t begin, ptrdiff_t end)
 {
-  eassert (g && g->running);
+  eassert (g);
   eassert (begin >= g->begin);
   eassert (end <= g->end);
   g->begin = max (begin, g->begin);
diff --git a/src/itree.h b/src/itree.h
index 10ee0897c3..291fa53fd3 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -104,12 +104,9 @@ enum itree_order
     ITREE_ASCENDING,
     ITREE_DESCENDING,
     ITREE_PRE_ORDER,
+    ITREE_POST_ORDER,
   };
 
-extern void init_itree (void);
-#ifdef HAVE_UNEXEC
-extern void forget_itree (void);
-#endif
 extern void itree_node_init (struct itree_node *, bool, bool, Lisp_Object);
 extern ptrdiff_t itree_node_begin (struct itree_tree *, struct itree_node *);
 extern ptrdiff_t itree_node_end (struct itree_tree *, struct itree_node *);
@@ -128,20 +125,28 @@ extern void itree_delete_gap (struct itree_tree *, 
ptrdiff_t, ptrdiff_t);
 
 /* Iteration functions.  Almost all code should use ITREE_FOREACH
    instead.  */
-extern bool itree_iterator_busy_p (void);
-extern struct itree_iterator *itree_iterator_start (struct itree_tree *,
+extern struct itree_iterator *itree_iterator_start (struct itree_iterator *,
+                                                   struct itree_tree *,
                                                    ptrdiff_t,
                                                    ptrdiff_t,
-                                                   enum itree_order,
-                                                   const char *, int);
+                                                   enum itree_order);
 extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t,
                                   ptrdiff_t);
-extern void itree_iterator_finish (struct itree_iterator *);
 extern struct itree_node *itree_iterator_next (struct itree_iterator *);
 
+/* State used when iterating interval. */
+struct itree_iterator
+  {
+    struct itree_node *node;
+    ptrdiff_t begin;
+    ptrdiff_t end;
+    uintmax_t otick;    /* A copy of the tree's `otick`.  */
+    enum itree_order order;
+  };
+
 /* Iterate over the intervals between BEG and END in the tree T.
    N will hold successive nodes.  ORDER can be one of : `ASCENDING`,
-   `DESCENDING`, or `PRE_ORDER`.
+   `DESCENDING`, `POST_ORDER`, or `PRE_ORDER`.
    It should be used as:
 
       ITREE_FOREACH (n, t, beg, end, order)
@@ -152,33 +157,23 @@ extern struct itree_node *itree_iterator_next (struct 
itree_iterator *);
    BEWARE:
    - The expression T may be evaluated more than once, so make sure
      it is cheap and pure.
-   - Only a single iteration can happen at a time, so make sure none of the
-     code within the loop can start another tree iteration, i.e. it shouldn't
-     be able to run ELisp code, nor GC since GC can run ELisp by way
-     of `post-gc-hook`.
-   - If you need to exit the loop early, you *have* to call `ITREE_ABORT`
-     just before exiting (e.g. with `break` or `return`).
-   - Non-local exits are not supported within the body of the loop.
    - Don't modify the tree during the iteration.
  */
 #define ITREE_FOREACH(n, t, beg, end, order)                        \
-  /* FIXME: We'd want to declare `x` right here, but I can't figure out
+  /* FIXME: We'd want to declare `n` right here, but I can't figure out
      how to make that work here: the `for` syntax only allows a single
      clause for the var declarations where we need 2 different types.
      We could use the `struct {foo x; bar y; } p;` trick to declare two
      vars `p.x` and `p.y` of unrelated types, but then none of the names
-     of the vars matches the `n` we receive :-(.  */                \
-  if (!t)                                                           \
-    { }                                                             \
-  else                                                              \
-    for (struct itree_iterator *itree_iter_                         \
-            = itree_iterator_start (t, beg, end, ITREE_##order,     \
-                                        __FILE__, __LINE__);        \
-          ((n = itree_iterator_next (itree_iter_))                  \
-           || (itree_iterator_finish (itree_iter_), false));)
-
-#define ITREE_FOREACH_ABORT() \
-  itree_iterator_finish (itree_iter_)
+     of the vars matches the `n` we receive :-(.  */             \
+  if (!t)                                                        \
+    { }                                                          \
+  else                                                           \
+    for (struct itree_iterator itree_local_iter_,                \
+                               *itree_iter_                      \
+            = itree_iterator_start (&itree_local_iter_,          \
+                                    t, beg, end, ITREE_##order); \
+          ((n = itree_iterator_next (itree_iter_)));)
 
 #define ITREE_FOREACH_NARROW(beg, end) \
   itree_iterator_narrow (itree_iter_, beg, end)
diff --git a/src/xdisp.c b/src/xdisp.c
index 3b4f0b3956..f8fc0f5787 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -7044,17 +7044,11 @@ strings_with_newlines (ptrdiff_t startpos, ptrdiff_t 
endpos, struct window *w)
       str = Foverlay_get (overlay, Qbefore_string);
       if (STRINGP (str) && SCHARS (str)
          && memchr (SDATA (str), '\n', SBYTES (str)))
-       {
-         ITREE_FOREACH_ABORT ();
-         return true;
-       }
+       return true;
       str = Foverlay_get (overlay, Qafter_string);
       if (STRINGP (str) && SCHARS (str)
          && memchr (SDATA (str), '\n', SBYTES (str)))
-       {
-         ITREE_FOREACH_ABORT ();
-         return true;
-       }
+       return true;
     }
 
   /* Check for 'display' properties whose values include strings.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]