aboutsummaryrefslogtreecommitdiffstats
path: root/src/lisp.h
diff options
context:
space:
mode:
authorPaul Eggert2017-02-06 17:15:14 -0800
committerPaul Eggert2017-02-06 17:34:41 -0800
commit03a012a79679c730634537f966200878bfd1c0b4 (patch)
tree66647b38bffa3eb904da993d9d583cc770c443df /src/lisp.h
parentd45dbccc5d2360818e70bbb0bc816c62c8cf6cbe (diff)
downloademacs-03a012a79679c730634537f966200878bfd1c0b4.tar.gz
emacs-03a012a79679c730634537f966200878bfd1c0b4.zip
Make FOR_EACH_TAIL more like other FOR_EACH macros
See comments by Stefan Monnier in: http://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00181.html and by Eli Zaretskii in: http://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00207.html * src/fns.c (internal_equal): Do not bypass check for depth overflow when tail-recursing via a dotted list tail or an overlay plist, to avoid a rare infloop. * src/lisp.h (FOR_EACH_TAIL, FOR_EACH_TAIL_SAFE): Take TAIL as an arg, and update it at each iteration, rather than have callers access it.tail. All callers changed. (FOR_EACH_TAIL): Do not check for dotted lists, as this is now the caller’s responsibility. All callers changed. (FOR_EACH_TAIL_CONS): Remove. All callers changed. (struct for_each_tail_internal.tail): Remove; no longer needed. (FOR_EACH_TAIL_INTERNAL): Remove dotted arg, and set the tail arg each time through the loop. All callers changed.
Diffstat (limited to 'src/lisp.h')
-rw-r--r--src/lisp.h48
1 files changed, 20 insertions, 28 deletions
diff --git a/src/lisp.h b/src/lisp.h
index b753971fb9c..f1e2685702d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4580,41 +4580,33 @@ enum
4580 Lisp_String)) \ 4580 Lisp_String)) \
4581 : make_unibyte_string (str, len)) 4581 : make_unibyte_string (str, len))
4582 4582
4583/* Loop over tails of LIST, checking for dotted lists and cycles, 4583/* Loop over conses of the list TAIL, signaling if a cycle is found,
4584 and possibly quitting after each loop iteration. 4584 and possibly quitting after each loop iteration. In the loop body,
4585 In the loop body, ‘li.tail’ is the current cons; the name ‘li’ is 4585 set TAIL to the current cons. If the loop exits normally,
4586 short for “list iterator”. The expression LIST may be evaluated 4586 set TAIL to the terminating non-cons, typically nil. The loop body
4587 more than once, and so should not have side effects. The loop body
4588 should not modify the list’s top level structure other than by 4587 should not modify the list’s top level structure other than by
4589 perhaps deleting the current cons. */ 4588 perhaps deleting the current cons. */
4590 4589
4591#define FOR_EACH_TAIL(list) \ 4590#define FOR_EACH_TAIL(tail) \
4592 FOR_EACH_TAIL_INTERNAL (list, CHECK_LIST_END (li.tail, list), \ 4591 FOR_EACH_TAIL_INTERNAL (tail, circular_list (tail), true)
4593 circular_list (list), true)
4594 4592
4595/* Like FOR_EACH_TAIL (LIST), except do not check for dotted lists. */ 4593/* Like FOR_EACH_TAIL (LIST), except do not signal or quit.
4594 If the loop exits due to a cycle, TAIL’s value is undefined. */
4596 4595
4597#define FOR_EACH_TAIL_CONS(list) \ 4596#define FOR_EACH_TAIL_SAFE(tail) \
4598 FOR_EACH_TAIL_INTERNAL (list, (void) 0, circular_list (list), true) 4597 FOR_EACH_TAIL_INTERNAL (tail, (void) ((tail) = Qnil), false)
4599
4600/* Like FOR_EACH_TAIL (LIST), except check for neither dotted lists
4601 nor cycles, and do not quit. */
4602
4603#define FOR_EACH_TAIL_SAFE(list) \
4604 FOR_EACH_TAIL_INTERNAL (list, (void) 0, (void) (li.tail = Qnil), false)
4605 4598
4606/* Iterator intended for use only within FOR_EACH_TAIL_INTERNAL. */ 4599/* Iterator intended for use only within FOR_EACH_TAIL_INTERNAL. */
4607struct for_each_tail_internal 4600struct for_each_tail_internal
4608{ 4601{
4609 Lisp_Object tail, tortoise; 4602 Lisp_Object tortoise;
4610 intptr_t max, n; 4603 intptr_t max, n;
4611 unsigned short int q; 4604 unsigned short int q;
4612}; 4605};
4613 4606
4614/* Like FOR_EACH_TAIL (LIST), except evaluate DOTTED or CYCLE, 4607/* Like FOR_EACH_TAIL (LIST), except evaluate CYCLE if a cycle is
4615 respectively, if a dotted list or cycle is found, and check for 4608 found, and check for quit if CHECK_QUIT. This is an internal macro
4616 quit if CHECK_QUIT. This is an internal macro intended for use 4609 intended for use only by the above macros.
4617 only by the above macros.
4618 4610
4619 Use Brent’s teleporting tortoise-hare algorithm. See: 4611 Use Brent’s teleporting tortoise-hare algorithm. See:
4620 Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190 4612 Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
@@ -4626,15 +4618,15 @@ struct for_each_tail_internal
4626 other noninterruptible areas (e.g., garbage collection) that there 4618 other noninterruptible areas (e.g., garbage collection) that there
4627 is little point to calling maybe_quit here. */ 4619 is little point to calling maybe_quit here. */
4628 4620
4629#define FOR_EACH_TAIL_INTERNAL(list, dotted, cycle, check_quit) \ 4621#define FOR_EACH_TAIL_INTERNAL(tail, cycle, check_quit) \
4630 for (struct for_each_tail_internal li = { list, list, 2, 0, 2 }; \ 4622 for (struct for_each_tail_internal li = { tail, 2, 0, 2 }; \
4631 CONSP (li.tail) || (dotted, false); \ 4623 CONSP (tail); \
4632 (li.tail = XCDR (li.tail), \ 4624 ((tail) = XCDR (tail), \
4633 ((--li.q != 0 \ 4625 ((--li.q != 0 \
4634 || ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \ 4626 || ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \
4635 || (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \ 4627 || (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \
4636 li.tortoise = li.tail, false)) \ 4628 li.tortoise = (tail), false)) \
4637 && EQ (li.tail, li.tortoise)) \ 4629 && EQ (tail, li.tortoise)) \
4638 ? (cycle) : (void) 0)) 4630 ? (cycle) : (void) 0))
4639 4631
4640/* Do a `for' loop over alist values. */ 4632/* Do a `for' loop over alist values. */