]> git.eshelyaron.com Git - emacs.git/commitdiff
* src/lisp.h (FOR_EACH_TAIL): New macro.
authorStefan Monnier <monnier@iro.umontreal.ca>
Wed, 4 Dec 2013 22:10:46 +0000 (17:10 -0500)
committerStefan Monnier <monnier@iro.umontreal.ca>
Wed, 4 Dec 2013 22:10:46 +0000 (17:10 -0500)
* src/fns.c (Fdelq): Use it to avoid inf-loops; remove QUIT.

src/ChangeLog
src/fns.c
src/lisp.h

index c88f48af5177919ed094b8d9f7098a9b73bb12e1..2a4da678b5634a5af5c08f644a87e5b9495fd2f0 100644 (file)
@@ -1,5 +1,8 @@
 2013-12-04  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+       * 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).
 
index e705bdc58e97f7509204dd01e2537aefd044c4f9..b13bb8d80dc29fc604fbf7614d146ac477219572 100644 (file)
--- 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;
 }
index 60cbc98daf89c5c19d06aa14373c7f6f996f65e0..d8cf6b6960efca9639d99abd55199854288d62aa 100644 (file)
@@ -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)            \