diff options
| author | Paul Eggert | 2017-02-06 17:15:14 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-02-06 17:34:41 -0800 |
| commit | 03a012a79679c730634537f966200878bfd1c0b4 (patch) | |
| tree | 66647b38bffa3eb904da993d9d583cc770c443df /src/lisp.h | |
| parent | d45dbccc5d2360818e70bbb0bc816c62c8cf6cbe (diff) | |
| download | emacs-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.h | 48 |
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. */ |
| 4607 | struct for_each_tail_internal | 4600 | struct 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. */ |