diff options
| author | Stefan Monnier | 2022-11-17 18:09:37 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2022-11-17 18:09:37 -0500 |
| commit | 091e0f04ffe494ee4cddb67670f0c495a7c9b691 (patch) | |
| tree | 3e93d67eed88aeea94cc78951e987fedffd7d8ea | |
| parent | fb7f1864da4aa4c09756cfe47db6c56b4e87bd14 (diff) | |
| download | emacs-scratch/noverlay.tar.gz emacs-scratch/noverlay.zip | |
itree.c: Get rid of the old iterator codescratch/noverlay
Only use the new iterator which relies on a fixed size (and small)
state in the iterator.
This makes non-local exits safe within ITREE_FOREACH loops.
* src/itree.c (make_nav, nav_nodeptr, nav_flag, itree_stack_clear)
(itree_stack_push_flagged): Delete functions.
(nodeptr_and_flag): Delete type.
(struct itree_stack): Make the array hold plain pointers instead.
(itree_stack_push): Inline the former code of `itree_stack_push_flagged`.
(itree_stack_pop): Change return type.
(itree_contains): Don't call `ITREE_FOREACH_ABORT` any more.
(itree_insert_gap): Simplify access to the stack of nodes.
(itree_delete_gap, itree_insert_gap): Adjust code to new return type of
`itree_stack_pop`.
(itree_iterator_finish): Delete function.
(itree_iterator_start): Don't setup the `stack` field any more.
(itree_iterator_next): Delete function.
(itree_iter_next): Rename to `itree_iterator_next` and make it non-static.
(itree_iterator_narrow): Don't check the `running` flag any more.
* src/itree.h (itree_iterator_finish): Remove declaration.
(struct itree_iterator): Remove the `stack` and `running` fields.
(ITREE_FOREACH_ABORT): Delete macro.
(ITREE_FOREACH): Don't call `itree_iterator_finish` any more.
* src/xdisp.c (strings_with_newlines):
* src/buffer.c (overlays_in, next_overlay_change, overlay_touches_p):
Don't call `ITREE_FOREACH_ABORT` any more.
| -rw-r--r-- | src/buffer.c | 12 | ||||
| -rw-r--r-- | src/itree.c | 199 | ||||
| -rw-r--r-- | src/itree.h | 16 | ||||
| -rw-r--r-- | src/xdisp.c | 10 |
4 files changed, 23 insertions, 214 deletions
diff --git a/src/buffer.c b/src/buffer.c index 9be2c4a970e..4da5b451d0f 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -2985,17 +2985,13 @@ overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend, | |||
| 2985 | if (node->begin > end) | 2985 | if (node->begin > end) |
| 2986 | { | 2986 | { |
| 2987 | next = min (next, node->begin); | 2987 | next = min (next, node->begin); |
| 2988 | ITREE_FOREACH_ABORT (); | ||
| 2989 | break; | 2988 | break; |
| 2990 | } | 2989 | } |
| 2991 | else if (node->begin == end) | 2990 | else if (node->begin == end) |
| 2992 | { | 2991 | { |
| 2993 | next = node->begin; | 2992 | next = node->begin; |
| 2994 | if ((! empty || end < ZV) && beg < end) | 2993 | if ((! empty || end < ZV) && beg < end) |
| 2995 | { | 2994 | break; |
| 2996 | ITREE_FOREACH_ABORT (); | ||
| 2997 | break; | ||
| 2998 | } | ||
| 2999 | if (empty && node->begin != node->end) | 2995 | if (empty && node->begin != node->end) |
| 3000 | continue; | 2996 | continue; |
| 3001 | } | 2997 | } |
| @@ -3050,7 +3046,6 @@ next_overlay_change (ptrdiff_t pos) | |||
| 3050 | of pos, because the search is limited to [pos,next) . */ | 3046 | of pos, because the search is limited to [pos,next) . */ |
| 3051 | eassert (node->begin < next); | 3047 | eassert (node->begin < next); |
| 3052 | next = node->begin; | 3048 | next = node->begin; |
| 3053 | ITREE_FOREACH_ABORT (); | ||
| 3054 | break; | 3049 | break; |
| 3055 | } | 3050 | } |
| 3056 | else if (node->begin < node->end && node->end < next) | 3051 | else if (node->begin < node->end && node->end < next) |
| @@ -3155,10 +3150,7 @@ overlay_touches_p (ptrdiff_t pos) | |||
| 3155 | pos. */ | 3150 | pos. */ |
| 3156 | ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING) | 3151 | ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING) |
| 3157 | if (node->begin == pos || node->end == pos) | 3152 | if (node->begin == pos || node->end == pos) |
| 3158 | { | 3153 | return true; |
| 3159 | ITREE_FOREACH_ABORT (); | ||
| 3160 | return true; | ||
| 3161 | } | ||
| 3162 | return false; | 3154 | return false; |
| 3163 | } | 3155 | } |
| 3164 | 3156 | ||
diff --git a/src/itree.c b/src/itree.c index 9e60071980d..e4d5fb304b7 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/>. */ | |||
| 131 | * | Stack | 131 | * | Stack |
| 132 | * +=======================================================================+ */ | 132 | * +=======================================================================+ */ |
| 133 | 133 | ||
| 134 | typedef uintptr_t nodeptr_and_flag; | ||
| 135 | |||
| 136 | static inline nodeptr_and_flag | ||
| 137 | make_nav (struct itree_node *ptr, bool flag) | ||
| 138 | { | ||
| 139 | uintptr_t v = (uintptr_t) ptr; | ||
| 140 | /* We assume alignment imposes the LSB is clear for us to use it. */ | ||
| 141 | eassert (!(v & 1)); | ||
| 142 | return v | !!flag; | ||
| 143 | } | ||
| 144 | |||
| 145 | static inline struct itree_node * | ||
| 146 | nav_nodeptr (nodeptr_and_flag nav) | ||
| 147 | { | ||
| 148 | return (struct itree_node *) (nav & (~(uintptr_t)1)); | ||
| 149 | } | ||
| 150 | |||
| 151 | static inline bool | ||
| 152 | nav_flag (nodeptr_and_flag nav) | ||
| 153 | { | ||
| 154 | return (bool) (nav & 1); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* Simple dynamic array. */ | 134 | /* Simple dynamic array. */ |
| 158 | struct itree_stack | 135 | struct itree_stack |
| 159 | { | 136 | { |
| 160 | nodeptr_and_flag *nodes; | 137 | struct itree_node **nodes; |
| 161 | size_t size; | 138 | size_t size; |
| 162 | size_t length; | 139 | size_t length; |
| 163 | }; | 140 | }; |
| @@ -184,12 +161,6 @@ itree_stack_destroy (struct itree_stack *stack) | |||
| 184 | xfree (stack); | 161 | xfree (stack); |
| 185 | } | 162 | } |
| 186 | 163 | ||
| 187 | static void | ||
| 188 | itree_stack_clear (struct itree_stack *stack) | ||
| 189 | { | ||
| 190 | stack->length = 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static inline void | 164 | static inline void |
| 194 | itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) | 165 | itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) |
| 195 | { | 166 | { |
| @@ -204,34 +175,20 @@ itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements) | |||
| 204 | /* Push NODE on the STACK, while settings its visited flag to FLAG. */ | 175 | /* Push NODE on the STACK, while settings its visited flag to FLAG. */ |
| 205 | 176 | ||
| 206 | static inline void | 177 | static inline void |
| 207 | itree_stack_push_flagged (struct itree_stack *stack, | 178 | itree_stack_push (struct itree_stack *stack, struct itree_node *node) |
| 208 | struct itree_node *node, bool flag) | ||
| 209 | { | 179 | { |
| 210 | eassert (node); | 180 | eassert (node); |
| 211 | |||
| 212 | /* FIXME: While the stack used in the iterator is bounded by the tree | ||
| 213 | depth and could be easily pre-allocated to a large enough size to avoid | ||
| 214 | this "ensure" check, `itree_stack_push` is also used elsewhere to | ||
| 215 | simply collect some subset of the overlays, where it's only bounded by | ||
| 216 | the total number of overlays in the buffer (which can be large and thus | ||
| 217 | preferably not pre-allocated needlessly). */ | ||
| 218 | itree_stack_ensure_space (stack, stack->length + 1); | 181 | itree_stack_ensure_space (stack, stack->length + 1); |
| 219 | 182 | ||
| 220 | stack->nodes[stack->length] = make_nav (node, flag); | 183 | stack->nodes[stack->length] = node; |
| 221 | stack->length++; | 184 | stack->length++; |
| 222 | } | 185 | } |
| 223 | 186 | ||
| 224 | static inline void | 187 | static inline struct itree_node * |
| 225 | itree_stack_push (struct itree_stack *stack, struct itree_node *node) | ||
| 226 | { | ||
| 227 | itree_stack_push_flagged (stack, node, false); | ||
| 228 | } | ||
| 229 | |||
| 230 | static inline nodeptr_and_flag | ||
| 231 | itree_stack_pop (struct itree_stack *stack) | 188 | itree_stack_pop (struct itree_stack *stack) |
| 232 | { | 189 | { |
| 233 | if (stack->length == 0) | 190 | if (stack->length == 0) |
| 234 | return make_nav (NULL, false); | 191 | return NULL; |
| 235 | return stack->nodes[--stack->length]; | 192 | return stack->nodes[--stack->length]; |
| 236 | } | 193 | } |
| 237 | 194 | ||
| @@ -815,10 +772,7 @@ itree_contains (struct itree_tree *tree, struct itree_node *node) | |||
| 815 | struct itree_node *other; | 772 | struct itree_node *other; |
| 816 | ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING) | 773 | ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING) |
| 817 | if (other == node) | 774 | if (other == node) |
| 818 | { | 775 | return true; |
| 819 | ITREE_FOREACH_ABORT (); | ||
| 820 | return true; | ||
| 821 | } | ||
| 822 | 776 | ||
| 823 | return false; | 777 | return false; |
| 824 | } | 778 | } |
| @@ -1122,7 +1076,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1122 | } | 1076 | } |
| 1123 | } | 1077 | } |
| 1124 | for (size_t i = 0; i < saved->length; ++i) | 1078 | for (size_t i = 0; i < saved->length; ++i) |
| 1125 | itree_remove (tree, nav_nodeptr (saved->nodes[i])); | 1079 | itree_remove (tree, saved->nodes[i]); |
| 1126 | 1080 | ||
| 1127 | /* We can't use an iterator here, because we can't effectively | 1081 | /* We can't use an iterator here, because we can't effectively |
| 1128 | narrow AND shift some subtree at the same time. */ | 1082 | narrow AND shift some subtree at the same time. */ |
| @@ -1131,9 +1085,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1131 | const int size = itree_max_height (tree) + 1; | 1085 | const int size = itree_max_height (tree) + 1; |
| 1132 | struct itree_stack *stack = itree_stack_create (size); | 1086 | struct itree_stack *stack = itree_stack_create (size); |
| 1133 | itree_stack_push (stack, tree->root); | 1087 | itree_stack_push (stack, tree->root); |
| 1134 | nodeptr_and_flag nav; | 1088 | while ((node = itree_stack_pop (stack))) |
| 1135 | while ((nav = itree_stack_pop (stack), | ||
| 1136 | node = nav_nodeptr (nav))) | ||
| 1137 | { | 1089 | { |
| 1138 | /* Process in pre-order. */ | 1090 | /* Process in pre-order. */ |
| 1139 | itree_inherit_offset (tree->otick, node); | 1091 | itree_inherit_offset (tree->otick, node); |
| @@ -1170,9 +1122,7 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1170 | 1122 | ||
| 1171 | /* Reinsert nodes starting at POS having front-advance. */ | 1123 | /* Reinsert nodes starting at POS having front-advance. */ |
| 1172 | uintmax_t notick = tree->otick; | 1124 | uintmax_t notick = tree->otick; |
| 1173 | nodeptr_and_flag nav; | 1125 | while ((node = itree_stack_pop (saved))) |
| 1174 | while ((nav = itree_stack_pop (saved), | ||
| 1175 | node = nav_nodeptr (nav))) | ||
| 1176 | { | 1126 | { |
| 1177 | eassert (node->otick == ootick); | 1127 | eassert (node->otick == ootick); |
| 1178 | eassert (node->begin == pos); | 1128 | eassert (node->begin == pos); |
| @@ -1205,10 +1155,8 @@ itree_delete_gap (struct itree_tree *tree, | |||
| 1205 | struct itree_node *node; | 1155 | struct itree_node *node; |
| 1206 | 1156 | ||
| 1207 | itree_stack_push (stack, tree->root); | 1157 | itree_stack_push (stack, tree->root); |
| 1208 | nodeptr_and_flag nav; | 1158 | while ((node = itree_stack_pop (stack))) |
| 1209 | while ((nav = itree_stack_pop (stack))) | ||
| 1210 | { | 1159 | { |
| 1211 | node = nav_nodeptr (nav); | ||
| 1212 | itree_inherit_offset (tree->otick, node); | 1160 | itree_inherit_offset (tree->otick, node); |
| 1213 | if (pos > node->limit) | 1161 | if (pos > node->limit) |
| 1214 | continue; | 1162 | continue; |
| @@ -1244,16 +1192,6 @@ itree_delete_gap (struct itree_tree *tree, | |||
| 1244 | * | Iterator | 1192 | * | Iterator |
| 1245 | * +=======================================================================+ */ | 1193 | * +=======================================================================+ */ |
| 1246 | 1194 | ||
| 1247 | /* Stop using the iterator. */ | ||
| 1248 | |||
| 1249 | void | ||
| 1250 | itree_iterator_finish (struct itree_iterator *iter) | ||
| 1251 | { | ||
| 1252 | eassert (iter && iter->running); | ||
| 1253 | itree_stack_destroy (iter->stack); | ||
| 1254 | iter->running = false; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /* Return true, if NODE's interval intersects with [BEGIN, END). | 1195 | /* Return true, if NODE's interval intersects with [BEGIN, END). |
| 1258 | Note: We always include empty nodes at BEGIN (and not at END), | 1196 | Note: We always include empty nodes at BEGIN (and not at END), |
| 1259 | but if BEGIN==END, then we don't include non-empty nodes starting | 1197 | but if BEGIN==END, then we don't include non-empty nodes starting |
| @@ -1436,7 +1374,7 @@ itree_iterator_first_node (struct itree_tree *tree, | |||
| 1436 | } | 1374 | } |
| 1437 | 1375 | ||
| 1438 | /* Start a iterator enumerating all intervals in [BEGIN,END) in the | 1376 | /* Start a iterator enumerating all intervals in [BEGIN,END) in the |
| 1439 | given ORDER. Only one iterator per tree can be running at any time. */ | 1377 | given ORDER. */ |
| 1440 | 1378 | ||
| 1441 | struct itree_iterator * | 1379 | struct itree_iterator * |
| 1442 | itree_iterator_start (struct itree_iterator *iter, | 1380 | itree_iterator_start (struct itree_iterator *iter, |
| @@ -1444,133 +1382,28 @@ itree_iterator_start (struct itree_iterator *iter, | |||
| 1444 | ptrdiff_t begin, ptrdiff_t end, enum itree_order order) | 1382 | ptrdiff_t begin, ptrdiff_t end, enum itree_order order) |
| 1445 | { | 1383 | { |
| 1446 | eassert (iter); | 1384 | eassert (iter); |
| 1447 | /* eassert (!iter->running); */ | ||
| 1448 | /* 19 here just avoids starting with a silly-small stack. | ||
| 1449 | FIXME: Since this stack only needs to be about 2*max_depth | ||
| 1450 | in the worst case, we could completely pre-allocate it to something | ||
| 1451 | like word-bit-size * 2 and then never worry about growing it. */ | ||
| 1452 | const int size = (tree ? itree_max_height (tree) : 19) + 1; | ||
| 1453 | iter->stack = itree_stack_create (size); | ||
| 1454 | uintmax_t otick= tree->otick; | ||
| 1455 | iter->begin = begin; | 1385 | iter->begin = begin; |
| 1456 | iter->end = end; | 1386 | iter->end = end; |
| 1457 | iter->otick = otick; | 1387 | iter->otick = tree->otick; |
| 1458 | iter->order = order; | 1388 | iter->order = order; |
| 1459 | itree_stack_clear (iter->stack); | ||
| 1460 | if (begin <= end && tree->root != NULL) | ||
| 1461 | itree_stack_push_flagged (iter->stack, tree->root, false); | ||
| 1462 | iter->running = true; | ||
| 1463 | /* itree_stack_ensure_space (iter->stack, | ||
| 1464 | 2 * itree_max_height (tree)); */ | ||
| 1465 | iter->node = itree_iterator_first_node (tree, iter); | 1389 | iter->node = itree_iterator_first_node (tree, iter); |
| 1466 | return iter; | 1390 | return iter; |
| 1467 | } | 1391 | } |
| 1468 | 1392 | ||
| 1469 | static struct itree_node * | 1393 | struct itree_node * |
| 1470 | itree_iter_next (struct itree_iterator *iter) | 1394 | itree_iterator_next (struct itree_iterator *iter) |
| 1471 | { | 1395 | { |
| 1472 | struct itree_node *node = iter->node; | 1396 | struct itree_node *node = iter->node; |
| 1473 | while (node | 1397 | while (node |
| 1474 | && !itree_node_intersects (node, iter->begin, iter->end)) | 1398 | && !itree_node_intersects (node, iter->begin, iter->end)) |
| 1475 | { | 1399 | { |
| 1476 | node = itree_iter_next_in_subtree (node, iter); | 1400 | node = itree_iter_next_in_subtree (node, iter); |
| 1401 | eassert (itree_limit_is_stable (node)); | ||
| 1477 | } | 1402 | } |
| 1478 | iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL; | 1403 | iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL; |
| 1479 | return node; | 1404 | return node; |
| 1480 | } | 1405 | } |
| 1481 | 1406 | ||
| 1482 | /* Return the next node of the iterator in the order given when it was | ||
| 1483 | started; or NULL if there are no more nodes. */ | ||
| 1484 | |||
| 1485 | struct itree_node * | ||
| 1486 | itree_iterator_next (struct itree_iterator *g) | ||
| 1487 | { | ||
| 1488 | eassert (g && g->running); | ||
| 1489 | |||
| 1490 | struct itree_node *const null = NULL; | ||
| 1491 | struct itree_node *node; | ||
| 1492 | |||
| 1493 | /* The `visited` flag stored in each node is used here (and only here): | ||
| 1494 | We keep a "workstack" of nodes we need to consider. This stack | ||
| 1495 | consist of nodes of two types: nodes that we have decided | ||
| 1496 | should be returned by the iterator, and nodes which we may | ||
| 1497 | need to consider (including checking their children). | ||
| 1498 | We start an iteration with a stack containing just the root | ||
| 1499 | node marked as "not visited" which means that it (and its children) | ||
| 1500 | needs to be considered but we haven't yet decided whether it's included | ||
| 1501 | in the iterator's output. */ | ||
| 1502 | |||
| 1503 | do | ||
| 1504 | { | ||
| 1505 | nodeptr_and_flag nav; | ||
| 1506 | bool visited; | ||
| 1507 | while ((nav = itree_stack_pop (g->stack), | ||
| 1508 | node = nav_nodeptr (nav), | ||
| 1509 | visited = nav_flag (nav), | ||
| 1510 | node && !visited)) | ||
| 1511 | { | ||
| 1512 | struct itree_node *const left = node->left; | ||
| 1513 | struct itree_node *const right = node->right; | ||
| 1514 | |||
| 1515 | itree_inherit_offset (g->otick, node); | ||
| 1516 | eassert (itree_limit_is_stable (node)); | ||
| 1517 | switch (g->order) | ||
| 1518 | { | ||
| 1519 | case ITREE_ASCENDING: | ||
| 1520 | if (right != null && node->begin <= g->end) | ||
| 1521 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1522 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1523 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1524 | /* Node's children may still be off-set and we need to add it. */ | ||
| 1525 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1526 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1527 | break; | ||
| 1528 | case ITREE_DESCENDING: | ||
| 1529 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1530 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1531 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1532 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1533 | if (right != null && node->begin <= g->end) | ||
| 1534 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1535 | break; | ||
| 1536 | case ITREE_PRE_ORDER: | ||
| 1537 | if (right != null && node->begin <= g->end) | ||
| 1538 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1539 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1540 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1541 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1542 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1543 | break; | ||
| 1544 | case ITREE_POST_ORDER: | ||
| 1545 | if (itree_node_intersects (node, g->begin, g->end)) | ||
| 1546 | itree_stack_push_flagged (g->stack, node, true); | ||
| 1547 | if (right != null && node->begin <= g->end) | ||
| 1548 | itree_stack_push_flagged (g->stack, right, false); | ||
| 1549 | if (left != null && g->begin <= left->limit + left->offset) | ||
| 1550 | itree_stack_push_flagged (g->stack, left, false); | ||
| 1551 | break; | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | /* Node may have been invalidated by itree_iterator_narrow | ||
| 1555 | after it was pushed: Check if it still intersects. */ | ||
| 1556 | } while (node && ! itree_node_intersects (node, g->begin, g->end)); | ||
| 1557 | |||
| 1558 | struct itree_node *old_node = g->node; | ||
| 1559 | struct itree_node *other_node = itree_iter_next (g); | ||
| 1560 | if (other_node != node) | ||
| 1561 | { | ||
| 1562 | fprintf (stderr, "WOW!! %ld..%ld vs %ld..%ld\n", | ||
| 1563 | other_node ? other_node->begin : -1, | ||
| 1564 | other_node ? other_node->end : -1, | ||
| 1565 | node ? node->begin : -1, | ||
| 1566 | node ? node->end : -1); | ||
| 1567 | fprintf (stderr, "ON=%lx N=%lx OlN=%lx\n", other_node, node, | ||
| 1568 | old_node); | ||
| 1569 | emacs_abort (); | ||
| 1570 | } | ||
| 1571 | return node; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | /* Limit G to the new interval [BEGIN, END), which must be a subset of | 1407 | /* Limit G to the new interval [BEGIN, END), which must be a subset of |
| 1575 | the current one. I.E. it can't grow on either side. */ | 1408 | the current one. I.E. it can't grow on either side. */ |
| 1576 | 1409 | ||
| @@ -1578,7 +1411,7 @@ void | |||
| 1578 | itree_iterator_narrow (struct itree_iterator *g, | 1411 | itree_iterator_narrow (struct itree_iterator *g, |
| 1579 | ptrdiff_t begin, ptrdiff_t end) | 1412 | ptrdiff_t begin, ptrdiff_t end) |
| 1580 | { | 1413 | { |
| 1581 | eassert (g && g->running); | 1414 | eassert (g); |
| 1582 | eassert (begin >= g->begin); | 1415 | eassert (begin >= g->begin); |
| 1583 | eassert (end <= g->end); | 1416 | eassert (end <= g->end); |
| 1584 | g->begin = max (begin, g->begin); | 1417 | g->begin = max (begin, g->begin); |
diff --git a/src/itree.h b/src/itree.h index 37cd423d34a..291fa53fd30 100644 --- a/src/itree.h +++ b/src/itree.h | |||
| @@ -132,24 +132,21 @@ extern struct itree_iterator *itree_iterator_start (struct itree_iterator *, | |||
| 132 | enum itree_order); | 132 | enum itree_order); |
| 133 | extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t, | 133 | extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t, |
| 134 | ptrdiff_t); | 134 | ptrdiff_t); |
| 135 | extern void itree_iterator_finish (struct itree_iterator *); | ||
| 136 | extern struct itree_node *itree_iterator_next (struct itree_iterator *); | 135 | extern struct itree_node *itree_iterator_next (struct itree_iterator *); |
| 137 | 136 | ||
| 138 | /* State used when iterating interval. */ | 137 | /* State used when iterating interval. */ |
| 139 | struct itree_iterator | 138 | struct itree_iterator |
| 140 | { | 139 | { |
| 141 | struct itree_node *node; /* FIXME: It should be either `node` or `stack`. */ | 140 | struct itree_node *node; |
| 142 | struct itree_stack *stack; | ||
| 143 | ptrdiff_t begin; | 141 | ptrdiff_t begin; |
| 144 | ptrdiff_t end; | 142 | ptrdiff_t end; |
| 145 | uintmax_t otick; /* A copy of the tree's `otick`. */ | 143 | uintmax_t otick; /* A copy of the tree's `otick`. */ |
| 146 | enum itree_order order; | 144 | enum itree_order order; |
| 147 | bool running; | ||
| 148 | }; | 145 | }; |
| 149 | 146 | ||
| 150 | /* Iterate over the intervals between BEG and END in the tree T. | 147 | /* Iterate over the intervals between BEG and END in the tree T. |
| 151 | N will hold successive nodes. ORDER can be one of : `ASCENDING`, | 148 | N will hold successive nodes. ORDER can be one of : `ASCENDING`, |
| 152 | `DESCENDING`, or `PRE_ORDER`. | 149 | `DESCENDING`, `POST_ORDER`, or `PRE_ORDER`. |
| 153 | It should be used as: | 150 | It should be used as: |
| 154 | 151 | ||
| 155 | ITREE_FOREACH (n, t, beg, end, order) | 152 | ITREE_FOREACH (n, t, beg, end, order) |
| @@ -160,9 +157,6 @@ struct itree_iterator | |||
| 160 | BEWARE: | 157 | BEWARE: |
| 161 | - The expression T may be evaluated more than once, so make sure | 158 | - The expression T may be evaluated more than once, so make sure |
| 162 | it is cheap and pure. | 159 | it is cheap and pure. |
| 163 | - If you need to exit the loop early, you *have* to call `ITREE_ABORT` | ||
| 164 | just before exiting (e.g. with `break` or `return`). | ||
| 165 | - Non-local exits are not supported within the body of the loop. | ||
| 166 | - Don't modify the tree during the iteration. | 160 | - Don't modify the tree during the iteration. |
| 167 | */ | 161 | */ |
| 168 | #define ITREE_FOREACH(n, t, beg, end, order) \ | 162 | #define ITREE_FOREACH(n, t, beg, end, order) \ |
| @@ -179,11 +173,7 @@ struct itree_iterator | |||
| 179 | *itree_iter_ \ | 173 | *itree_iter_ \ |
| 180 | = itree_iterator_start (&itree_local_iter_, \ | 174 | = itree_iterator_start (&itree_local_iter_, \ |
| 181 | t, beg, end, ITREE_##order); \ | 175 | t, beg, end, ITREE_##order); \ |
| 182 | ((n = itree_iterator_next (itree_iter_)) \ | 176 | ((n = itree_iterator_next (itree_iter_)));) |
| 183 | || (itree_iterator_finish (itree_iter_), false));) | ||
| 184 | |||
| 185 | #define ITREE_FOREACH_ABORT() \ | ||
| 186 | itree_iterator_finish (itree_iter_) | ||
| 187 | 177 | ||
| 188 | #define ITREE_FOREACH_NARROW(beg, end) \ | 178 | #define ITREE_FOREACH_NARROW(beg, end) \ |
| 189 | itree_iterator_narrow (itree_iter_, beg, end) | 179 | itree_iterator_narrow (itree_iter_, beg, end) |
diff --git a/src/xdisp.c b/src/xdisp.c index f6a279636a0..414ee9bfe28 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -7036,17 +7036,11 @@ strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w) | |||
| 7036 | str = Foverlay_get (overlay, Qbefore_string); | 7036 | str = Foverlay_get (overlay, Qbefore_string); |
| 7037 | if (STRINGP (str) && SCHARS (str) | 7037 | if (STRINGP (str) && SCHARS (str) |
| 7038 | && memchr (SDATA (str), '\n', SBYTES (str))) | 7038 | && memchr (SDATA (str), '\n', SBYTES (str))) |
| 7039 | { | 7039 | return true; |
| 7040 | ITREE_FOREACH_ABORT (); | ||
| 7041 | return true; | ||
| 7042 | } | ||
| 7043 | str = Foverlay_get (overlay, Qafter_string); | 7040 | str = Foverlay_get (overlay, Qafter_string); |
| 7044 | if (STRINGP (str) && SCHARS (str) | 7041 | if (STRINGP (str) && SCHARS (str) |
| 7045 | && memchr (SDATA (str), '\n', SBYTES (str))) | 7042 | && memchr (SDATA (str), '\n', SBYTES (str))) |
| 7046 | { | 7043 | return true; |
| 7047 | ITREE_FOREACH_ABORT (); | ||
| 7048 | return true; | ||
| 7049 | } | ||
| 7050 | } | 7044 | } |
| 7051 | 7045 | ||
| 7052 | /* Check for 'display' properties whose values include strings. */ | 7046 | /* Check for 'display' properties whose values include strings. */ |