From 105324ced442852eba6af80605867afe46b3dba5 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 4 Dec 2013 17:10:46 -0500 Subject: [PATCH] * src/lisp.h (FOR_EACH_TAIL): New macro. * src/fns.c (Fdelq): Use it to avoid inf-loops; remove QUIT. --- src/ChangeLog | 3 +++ src/fns.c | 13 ++++--------- src/lisp.h | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index c88f48af517..2a4da678b56 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,8 @@ 2013-12-04 Stefan Monnier + * lisp.h (FOR_EACH_TAIL): New macro. + * fns.c (Fdelq): Use it to avoid inf-loops; remove QUIT. + * window.c (select_window): Call second wset_redisplay before we change selected_window (bug#16034). diff --git a/src/fns.c b/src/fns.c index e705bdc58e9..b13bb8d80dc 100644 --- a/src/fns.c +++ b/src/fns.c @@ -1537,15 +1537,12 @@ Write `(setq foo (delq element foo))' to be sure of correctly changing the value of a list `foo'. */) (register Lisp_Object elt, Lisp_Object list) { - register Lisp_Object tail, prev; - register Lisp_Object tem; + Lisp_Object tail, tortoise, prev = Qnil; + bool skip; - tail = list; - prev = Qnil; - while (CONSP (tail)) + FOR_EACH_TAIL (tail, list, tortoise, skip) { - CHECK_LIST_CONS (tail, list); - tem = XCAR (tail); + Lisp_Object tem = XCAR (tail); if (EQ (elt, tem)) { if (NILP (prev)) @@ -1555,8 +1552,6 @@ the value of a list `foo'. */) } else prev = tail; - tail = XCDR (tail); - QUIT; } return list; } diff --git a/src/lisp.h b/src/lisp.h index 60cbc98daf8..d8cf6b6960e 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4443,6 +4443,20 @@ extern void *record_xmalloc (size_t); memory_full (SIZE_MAX); \ } while (0) +/* Loop over all tails of a list, checking for cycles. + FIXME: Make tortoise and n internal declarations. + FIXME: Unroll the loop body so we don't need `n'. */ +#define FOR_EACH_TAIL(hare, list, tortoise, n) \ + for (tortoise = hare = (list), n = true; \ + CONSP (hare); \ + (hare = XCDR (hare), n = !n, \ + (n \ + ? ((EQ (hare, tortoise) \ + && (xsignal1 (Qcircular_list, (list)), 0))) \ + /* Move tortoise before the next iteration, in case */ \ + /* the next iteration does an Fsetcdr. */ \ + : (tortoise = XCDR (tortoise), 0)))) + /* Do a `for' loop over alist values. */ #define FOR_EACH_ALIST_VALUE(head_var, list_var, value_var) \ -- 2.39.2