all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL
@ 2017-02-01 23:56 Paul Eggert
  2017-02-01 23:56 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc Paul Eggert
                   ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Paul Eggert @ 2017-02-01 23:56 UTC (permalink / raw)
  To: 25605; +Cc: Paul Eggert

* src/data.c (circular_list): New function.
* src/lisp.h (FOR_EACH_TAIL): Use Brent’s algorithm and C99 for-loop
decl, to eliminate the need for the args TAIL, TORTOISE and N, and
to speed things up a bit on typical hosts with optimization.
All uses changed.
---
 src/data.c |  6 ++++++
 src/fns.c  | 16 +++++++---------
 src/lisp.h | 34 ++++++++++++++++++++--------------
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/src/data.c b/src/data.c
index 8e07bf0..12dc2df 100644
--- a/src/data.c
+++ b/src/data.c
@@ -170,6 +170,12 @@ args_out_of_range_3 (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3)
   xsignal3 (Qargs_out_of_range, a1, a2, a3);
 }
 
+void
+circular_list (Lisp_Object list)
+{
+  xsignal1 (Qcircular_list, list);
+}
+
 \f
 /* Data type predicates.  */
 
diff --git a/src/fns.c b/src/fns.c
index ac7c1f2..4de74a5 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1544,25 +1544,23 @@ list.
 Write `(setq foo (delq element foo))' to be sure of correctly changing
 the value of a list `foo'.  See also `remq', which does not modify the
 argument.  */)
-  (register Lisp_Object elt, Lisp_Object list)
+  (Lisp_Object elt, Lisp_Object list)
 {
-  Lisp_Object tail, tortoise, prev = Qnil;
-  bool skip;
+  Lisp_Object prev = Qnil;
 
-  FOR_EACH_TAIL (tail, list, tortoise, skip)
+  FOR_EACH_TAIL (list)
     {
-      Lisp_Object tem = XCAR (tail);
+      Lisp_Object tem = XCAR (li.tail);
       if (EQ (elt, tem))
 	{
 	  if (NILP (prev))
-	    list = XCDR (tail);
+	    list = XCDR (li.tail);
 	  else
-	    Fsetcdr (prev, XCDR (tail));
+	    Fsetcdr (prev, XCDR (li.tail));
 	}
       else
-	prev = tail;
+	prev = li.tail;
     }
-  CHECK_LIST_END (tail, list);
   return list;
 }
 
diff --git a/src/lisp.h b/src/lisp.h
index 1ac3816..2d74d44 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3317,6 +3317,7 @@ extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
 extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object);
 extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object,
 					   Lisp_Object);
+extern _Noreturn void circular_list (Lisp_Object);
 extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *);
 enum Set_Internal_Bind {
   SET_INTERNAL_SET,
@@ -4586,20 +4587,25 @@ enum
 	 Lisp_String))							\
      : make_unibyte_string (str, len))
 
-/* 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)			\
-	    : (void) 0)						\
-	 /* Move tortoise before the next iteration, in case */ \
-	 /* the next iteration does an Fsetcdr.  */		\
-   	 : (void) ((tortoise) = XCDR (tortoise)))))
+/* Loop over tails of LIST, checking for dotted lists and cycles.
+   In the loop body, ‘li.tail’ is the current cons; the name ‘li’ is
+   short for “list iterator”.  The expression LIST may be evaluated
+   more than once, and so should not have side effects.  The loop body
+   should not modify the list’s top level structure other than by
+   perhaps deleting the current cons.
+
+   Use Brent’s teleporting tortoise-hare algorithm.  See:
+   Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
+   http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf  */
+
+#define FOR_EACH_TAIL(list)						\
+  for (struct { Lisp_Object tail, tortoise; intptr_t n, max; } li	\
+	 = { list, list, 2, 2 };					\
+       CONSP (li.tail) || (CHECK_LIST_END (li.tail, list), false);	\
+       (li.tail = XCDR (li.tail),					\
+	(li.n-- == 0							\
+	 ? (void) (li.n = li.max <<= 1, li.tortoise = li.tail)		\
+	 : EQ (li.tail, li.tortoise) ? circular_list (list) : (void) 0)))
 
 /* Do a `for' loop over alist values.  */
 
-- 
2.9.3






^ permalink raw reply related	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-01 23:56 bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Paul Eggert
@ 2017-02-01 23:56 ` Paul Eggert
  2017-02-02 17:28   ` Eli Zaretskii
  2017-02-02 17:29 ` bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Eli Zaretskii
  2017-02-05 21:30 ` bug#25605: patches installed for 25605, 25606 Paul Eggert
  2 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-01 23:56 UTC (permalink / raw)
  To: 25606; +Cc: Paul Eggert

Use macros like FOR_EACH_TAIL instead of maybe_quit to
catch list cycles automatically instead of relying on the
user becoming impatient and typing C-g.
* src/fns.c (Flength, Fmember, Fmemq, Fmemql, Fassq, Fassoc, Frassq)
(Frassoc, Fdelete, Freverse):
Use FOR_EACH_TAIL instead of maybe_quit.
(Fnreverse): Use simple EQ to check for circular list instead
of rarely_quit, as this suffices in this unusual case.
(Fplist_put, Flax_plist_put, Flax_plist_put):
Use FOR_EACH_TAIL_CONS instead of maybe_quit.
(internal_equal): Use FOR_EACH_TAIL_CONS to check lists, instead
of by-hand tail recursion that did not catch cycles.
* src/fns.c (Fsafe_length, Fplist_get):
* src/xdisp.c (display_mode_element):
Use FOR_EACH_TAIL_SAFE instead of by-hand Floyd’s algorithm.
* src/lisp.h (QUIT_COUNT_HEURISTIC): Remove; no longer needed.
(rarely_quit): Simply count toward USHRT_MAX + 1, since the
fancier versions are no longer needed.
(FOR_EACH_TAIL_CONS, FOR_EACH_TAIL_SAFE)
(FOR_EACH_TAIL_INTERNAL): New macros, the last with definiens
mostly taken from FOR_EACH_TAIL.
(FOR_EACH_TAIL): Rewrite in terms of FOR_EACH_TAIL_INTERNAL.
---
 etc/NEWS    |   3 +
 src/fns.c   | 290 +++++++++++++++++++++++-------------------------------------
 src/lisp.h  |  35 +++++---
 src/xdisp.c |  37 +++-----
 4 files changed, 149 insertions(+), 216 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 86a8385..23e5111 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -872,6 +872,9 @@ collection).
 +++
 ** 'car' and 'cdr' compositions 'cXXXr' and 'cXXXXr' are now part of Elisp.
 
+** Low-level list functions like 'length' and 'member' now do a better
+job of signaling list cycles instead of looping indefinitely.
+
 +++
 ** The new functions 'make-nearby-temp-file' and 'temporary-file-directory'
 can be used for creation of temporary files of remote or mounted directories.
diff --git a/src/fns.c b/src/fns.c
index 4de74a5..b5508fb 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -108,23 +108,11 @@ To get the number of bytes, use `string-bytes'.  */)
     XSETFASTINT (val, ASIZE (sequence) & PSEUDOVECTOR_SIZE_MASK);
   else if (CONSP (sequence))
     {
-      EMACS_INT i = 0;
-
-      do
-	{
-	  ++i;
-	  if ((i & (QUIT_COUNT_HEURISTIC - 1)) == 0)
-	    {
-	      if (MOST_POSITIVE_FIXNUM < i)
-		error ("List too long");
-	      maybe_quit ();
-	    }
-	  sequence = XCDR (sequence);
-	}
-      while (CONSP (sequence));
-
-      CHECK_LIST_END (sequence, sequence);
-
+      intptr_t i = 0;
+      FOR_EACH_TAIL (sequence)
+	i++;
+      if (MOST_POSITIVE_FIXNUM < i)
+	error ("List too long");
       val = make_number (i);
     }
   else if (NILP (sequence))
@@ -142,38 +130,10 @@ it returns 0.  If LIST is circular, it returns a finite value
 which is at least the number of distinct elements.  */)
   (Lisp_Object list)
 {
-  Lisp_Object tail, halftail;
-  double hilen = 0;
-  uintmax_t lolen = 1;
-
-  if (! CONSP (list))
-    return make_number (0);
-
-  /* halftail is used to detect circular lists.  */
-  for (tail = halftail = list; ; )
-    {
-      tail = XCDR (tail);
-      if (! CONSP (tail))
-	break;
-      if (EQ (tail, halftail))
-	break;
-      lolen++;
-      if ((lolen & 1) == 0)
-	{
-	  halftail = XCDR (halftail);
-	  if ((lolen & (QUIT_COUNT_HEURISTIC - 1)) == 0)
-	    {
-	      maybe_quit ();
-	      if (lolen == 0)
-		hilen += UINTMAX_MAX + 1.0;
-	    }
-	}
-    }
-
-  /* If the length does not fit into a fixnum, return a float.
-     On all known practical machines this returns an upper bound on
-     the true length.  */
-  return hilen ? make_float (hilen + lolen) : make_fixnum_or_float (lolen);
+  intptr_t len = 0;
+  FOR_EACH_TAIL_SAFE (list)
+    len++;
+  return make_fixnum_or_float (len);
 }
 
 DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
@@ -1383,15 +1343,9 @@ DEFUN ("member", Fmember, Smember, 2, 2, 0,
 The value is actually the tail of LIST whose car is ELT.  */)
   (Lisp_Object elt, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
-    {
-      if (! NILP (Fequal (elt, XCAR (tail))))
-	return tail;
-      rarely_quit (++quit_count);
-    }
-  CHECK_LIST_END (tail, list);
+  FOR_EACH_TAIL (list)
+    if (! NILP (Fequal (elt, XCAR (li.tail))))
+      return li.tail;
   return Qnil;
 }
 
@@ -1400,15 +1354,9 @@ DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
 The value is actually the tail of LIST whose car is ELT.  */)
   (Lisp_Object elt, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
-    {
-      if (EQ (XCAR (tail), elt))
-	return tail;
-      rarely_quit (++quit_count);
-    }
-  CHECK_LIST_END (tail, list);
+  FOR_EACH_TAIL (list)
+    if (EQ (XCAR (li.tail), elt))
+      return li.tail;
   return Qnil;
 }
 
@@ -1420,16 +1368,12 @@ The value is actually the tail of LIST whose car is ELT.  */)
   if (!FLOATP (elt))
     return Fmemq (elt, list);
 
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_TAIL (list)
     {
-      Lisp_Object tem = XCAR (tail);
+      Lisp_Object tem = XCAR (li.tail);
       if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
-	return tail;
-      rarely_quit (++quit_count);
+	return li.tail;
     }
-  CHECK_LIST_END (tail, list);
   return Qnil;
 }
 
@@ -1439,15 +1383,9 @@ The value is actually the first element of LIST whose car is KEY.
 Elements of LIST that are not conses are ignored.  */)
   (Lisp_Object key, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
-    {
-      if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
-	return XCAR (tail);
-      rarely_quit (++quit_count);
-    }
-  CHECK_LIST_END (tail, list);
+  FOR_EACH_TAIL (list)
+    if (CONSP (XCAR (li.tail)) && EQ (XCAR (XCAR (li.tail)), key))
+      return XCAR (li.tail);
   return Qnil;
 }
 
@@ -1468,17 +1406,13 @@ DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
 The value is actually the first element of LIST whose car equals KEY.  */)
   (Lisp_Object key, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_TAIL (list)
     {
-      Lisp_Object car = XCAR (tail);
+      Lisp_Object car = XCAR (li.tail);
       if (CONSP (car)
 	  && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
 	return car;
-      rarely_quit (++quit_count);
     }
-  CHECK_LIST_END (tail, list);
   return Qnil;
 }
 
@@ -1503,15 +1437,9 @@ DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
 The value is actually the first element of LIST whose cdr is KEY.  */)
   (Lisp_Object key, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
-    {
-      if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
-	return XCAR (tail);
-      rarely_quit (++quit_count);
-    }
-  CHECK_LIST_END (tail, list);
+  FOR_EACH_TAIL (list)
+    if (CONSP (XCAR (li.tail)) && EQ (XCDR (XCAR (li.tail)), key))
+      return XCAR (li.tail);
   return Qnil;
 }
 
@@ -1520,17 +1448,13 @@ DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
 The value is actually the first element of LIST whose cdr equals KEY.  */)
   (Lisp_Object key, Lisp_Object list)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_TAIL (list)
     {
-      Lisp_Object car = XCAR (tail);
+      Lisp_Object car = XCAR (li.tail);
       if (CONSP (car)
 	  && (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key))))
 	return car;
-      rarely_quit (++quit_count);
     }
-  CHECK_LIST_END (tail, list);
   return Qnil;
 }
 \f
@@ -1668,23 +1592,20 @@ changing the value of a sequence `foo'.  */)
     }
   else
     {
-      unsigned short int quit_count = 0;
-      Lisp_Object tail, prev;
+      Lisp_Object prev = Qnil;
 
-      for (tail = seq, prev = Qnil; CONSP (tail); tail = XCDR (tail))
+      FOR_EACH_TAIL (seq)
 	{
-	  if (!NILP (Fequal (elt, XCAR (tail))))
+	  if (!NILP (Fequal (elt, (XCAR (li.tail)))))
 	    {
 	      if (NILP (prev))
-		seq = XCDR (tail);
+		seq = XCDR (li.tail);
 	      else
-		Fsetcdr (prev, XCDR (tail));
+		Fsetcdr (prev, XCDR (li.tail));
 	    }
 	  else
-	    prev = tail;
-	  rarely_quit (++quit_count);
+	    prev = li.tail;
 	}
-      CHECK_LIST_END (tail, seq);
     }
 
   return seq;
@@ -1702,15 +1623,17 @@ This function may destructively modify SEQ to produce the value.  */)
     return Freverse (seq);
   else if (CONSP (seq))
     {
-      unsigned short int quit_count = 0;
       Lisp_Object prev, tail, next;
 
       for (prev = Qnil, tail = seq; CONSP (tail); tail = next)
 	{
 	  next = XCDR (tail);
+	  /* If SEQ contains a cycle, attempting to reverse it
+	     in-place will inevitably come back to SEQ.  */
+	  if (EQ (next, seq))
+	    circular_list (seq);
 	  Fsetcdr (tail, prev);
 	  prev = tail;
-	  rarely_quit (++quit_count);
 	}
       CHECK_LIST_END (tail, seq);
       seq = prev;
@@ -1753,13 +1676,9 @@ See also the function `nreverse', which is used more often.  */)
     return Qnil;
   else if (CONSP (seq))
     {
-      unsigned short int quit_count = 0;
-      for (new = Qnil; CONSP (seq); seq = XCDR (seq))
-	{
-	  new = Fcons (XCAR (seq), new);
-	  rarely_quit (++quit_count);
-	}
-      CHECK_LIST_END (seq, seq);
+      new = Qnil;
+      FOR_EACH_TAIL (seq)
+	new = Fcons (XCAR (li.tail), new);
     }
   else if (VECTORP (seq))
     {
@@ -2011,18 +1930,14 @@ corresponding to the given PROP, or nil if PROP is not one of the
 properties on the list.  This function never signals an error.  */)
   (Lisp_Object plist, Lisp_Object prop)
 {
-  Lisp_Object tail, halftail;
-
-  /* halftail is used to detect circular lists.  */
-  tail = halftail = plist;
-  while (CONSP (tail) && CONSP (XCDR (tail)))
+  FOR_EACH_TAIL_SAFE (plist)
     {
-      if (EQ (prop, XCAR (tail)))
-	return XCAR (XCDR (tail));
-
-      tail = XCDR (XCDR (tail));
-      halftail = XCDR (halftail);
-      if (EQ (tail, halftail))
+      if (! CONSP (XCDR (li.tail)))
+	break;
+      if (EQ (prop, XCAR (li.tail)))
+	return XCAR (XCDR (li.tail));
+      li.tail = XCDR (li.tail);
+      if (EQ (li.tail, li.tortoise))
 	break;
     }
 
@@ -2048,19 +1963,22 @@ use `(setq x (plist-put x prop val))' to be sure to use the new value.
 The PLIST is modified by side effects.  */)
   (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
 {
-  unsigned short int quit_count = 0;
   Lisp_Object prev = Qnil;
-  for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
-       tail = XCDR (XCDR (tail)))
+  FOR_EACH_TAIL_CONS (plist)
     {
-      if (EQ (prop, XCAR (tail)))
+      if (! CONSP (XCDR (li.tail)))
+	break;
+
+      if (EQ (prop, XCAR (li.tail)))
 	{
-	  Fsetcar (XCDR (tail), val);
+	  Fsetcar (XCDR (li.tail), val);
 	  return plist;
 	}
 
-      prev = tail;
-      rarely_quit (++quit_count);
+      prev = li.tail;
+      li.tail = XCDR (li.tail);
+      if (EQ (li.tail, li.tortoise))
+	circular_list (plist);
     }
   Lisp_Object newcell
     = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
@@ -2089,20 +2007,16 @@ corresponding to the given PROP, or nil if PROP is not
 one of the properties on the list.  */)
   (Lisp_Object plist, Lisp_Object prop)
 {
-  unsigned short int quit_count = 0;
-  Lisp_Object tail;
-
-  for (tail = plist;
-       CONSP (tail) && CONSP (XCDR (tail));
-       tail = XCDR (XCDR (tail)))
+  FOR_EACH_TAIL_CONS (plist)
     {
-      if (! NILP (Fequal (prop, XCAR (tail))))
-	return XCAR (XCDR (tail));
-      rarely_quit (++quit_count);
+      if (! CONSP (XCDR (li.tail)))
+	break;
+      if (! NILP (Fequal (prop, XCAR (li.tail))))
+	return XCAR (XCDR (li.tail));
+      li.tail = XCDR (li.tail);
+      if (EQ (li.tail, li.tortoise))
+	circular_list (plist);
     }
-
-  CHECK_LIST_END (tail, prop);
-
   return Qnil;
 }
 
@@ -2116,19 +2030,22 @@ use `(setq x (lax-plist-put x prop val))' to be sure to use the new value.
 The PLIST is modified by side effects.  */)
   (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
 {
-  unsigned short int quit_count = 0;
   Lisp_Object prev = Qnil;
-  for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
-       tail = XCDR (XCDR (tail)))
+  FOR_EACH_TAIL_CONS (plist)
     {
-      if (! NILP (Fequal (prop, XCAR (tail))))
+      if (! CONSP (XCDR (li.tail)))
+	break;
+
+      if (! NILP (Fequal (prop, XCAR (li.tail))))
 	{
-	  Fsetcar (XCDR (tail), val);
+	  Fsetcar (XCDR (li.tail), val);
 	  return plist;
 	}
 
-      prev = tail;
-      rarely_quit (++quit_count);
+      prev = li.tail;
+      li.tail = XCDR (li.tail);
+      if (EQ (li.tail, li.tortoise))
+	circular_list (plist);
     }
   Lisp_Object newcell = list2 (prop, val);
   if (NILP (prev))
@@ -2206,9 +2123,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
 	}
     }
 
-  unsigned short int quit_count = 0;
  tail_recurse:
-  rarely_quit (++quit_count);
   if (EQ (o1, o2))
     return 1;
   if (XTYPE (o1) != XTYPE (o2))
@@ -2228,12 +2143,24 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
       }
 
     case Lisp_Cons:
-      if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1, props, ht))
-	return 0;
-      o1 = XCDR (o1);
-      o2 = XCDR (o2);
-      /* FIXME: This inf-loops in a circular list!  */
-      goto tail_recurse;
+      {
+	Lisp_Object tail1 = o1;
+	FOR_EACH_TAIL_CONS (o1)
+	  {
+	    if (! CONSP (o2))
+	      return false;
+	    if (! internal_equal (XCAR (li.tail), XCAR (o2), depth + 1,
+				  props, ht))
+	      return false;
+	    tail1 = XCDR (li.tail);
+	    o2 = XCDR (o2);
+	    if (EQ (tail1, o2))
+	      return true;
+	  }
+	o1 = tail1;
+	depth++;
+	goto tail_recurse;
+      }
 
     case Lisp_Misc:
       if (XMISCTYPE (o1) != XMISCTYPE (o2))
@@ -2247,6 +2174,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
 	    return 0;
 	  o1 = XOVERLAY (o1)->plist;
 	  o2 = XOVERLAY (o2)->plist;
+	  depth++;
 	  goto tail_recurse;
 	}
       if (MARKERP (o1))
@@ -2397,7 +2325,6 @@ Only the last argument is not altered, and need not be a list.
 usage: (nconc &rest LISTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  unsigned short int quit_count = 0;
   Lisp_Object val = Qnil;
 
   for (ptrdiff_t argnum = 0; argnum < nargs; argnum++)
@@ -2413,13 +2340,8 @@ usage: (nconc &rest LISTS)  */)
       CHECK_CONS (tem);
 
       Lisp_Object tail;
-      do
-	{
-	  tail = tem;
-	  tem = XCDR (tail);
-	  rarely_quit (++quit_count);
-	}
-      while (CONSP (tem));
+      FOR_EACH_TAIL_CONS (tem)
+	tail = li.tail;
 
       tem = args[argnum + 1];
       Fsetcdr (tail, tem);
@@ -2841,14 +2763,20 @@ property and a property with the value nil.
 The value is actually the tail of PLIST whose car is PROP.  */)
   (Lisp_Object plist, Lisp_Object prop)
 {
-  unsigned short int quit_count = 0;
-  while (CONSP (plist) && !EQ (XCAR (plist), prop))
+  FOR_EACH_TAIL (plist)
     {
-      plist = XCDR (plist);
-      plist = CDR (plist);
-      rarely_quit (++quit_count);
+      if (EQ (XCAR (li.tail), prop))
+	return li.tail;
+      if (!CONSP (XCDR (li.tail)))
+	{
+	  CHECK_LIST_END (XCDR (li.tail), plist);
+	  return Qnil;
+	}
+      li.tail = XCDR (li.tail);
+      if (EQ (li.tail, li.tortoise))
+	circular_list (plist);
     }
-  return plist;
+  return Qnil;
 }
 
 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
diff --git a/src/lisp.h b/src/lisp.h
index 2d74d44..275e0fc 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3129,20 +3129,14 @@ extern void maybe_quit (void);
 
 #define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
 
-/* Heuristic on how many iterations of a tight loop can be safely done
-   before it's time to do a quit.  This must be a power of 2.  It
-   is nice but not necessary for it to equal USHRT_MAX + 1.  */
-
-enum { QUIT_COUNT_HEURISTIC = 1 << 16 };
-
 /* Process a quit rarely, based on a counter COUNT, for efficiency.
-   "Rarely" means once per QUIT_COUNT_HEURISTIC or per USHRT_MAX + 1
-   times, whichever is smaller (somewhat arbitrary, but often faster).  */
+   "Rarely" means once per USHRT_MAX + 1 times; this is somewhat
+   arbitrary, but efficient.  */
 
 INLINE void
 rarely_quit (unsigned short int count)
 {
-  if (! (count & (QUIT_COUNT_HEURISTIC - 1)))
+  if (! count)
     maybe_quit ();
 }
 \f
@@ -4599,13 +4593,32 @@ enum
    http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf  */
 
 #define FOR_EACH_TAIL(list)						\
+  FOR_EACH_TAIL_INTERNAL (list, CHECK_LIST_END (li.tail, list),		\
+			  circular_list (list))
+
+/* Like FOR_EACH_TAIL (LIST), except check only for cycles.  */
+
+#define FOR_EACH_TAIL_CONS(list) \
+  FOR_EACH_TAIL_INTERNAL (list, (void) 0, circular_list (list))
+
+/* Like FOR_EACH_TAIL (LIST), except check for neither dotted lists
+   nor cycles.  */
+
+#define FOR_EACH_TAIL_SAFE(list) \
+  FOR_EACH_TAIL_INTERNAL (list, (void) 0, (void) (li.tail = Qnil))
+
+/* Like FOR_EACH_TAIL (LIST), except evaluate DOTTED or CYCLE,
+   respectively, if a dotted list or cycle is found.  This is an
+   internal macro intended for use only by the above macros.  */
+
+#define FOR_EACH_TAIL_INTERNAL(list, dotted, cycle)			\
   for (struct { Lisp_Object tail, tortoise; intptr_t n, max; } li	\
 	 = { list, list, 2, 2 };					\
-       CONSP (li.tail) || (CHECK_LIST_END (li.tail, list), false);	\
+       CONSP (li.tail) || (dotted, false);				\
        (li.tail = XCDR (li.tail),					\
 	(li.n-- == 0							\
 	 ? (void) (li.n = li.max <<= 1, li.tortoise = li.tail)		\
-	 : EQ (li.tail, li.tortoise) ? circular_list (list) : (void) 0)))
+	 : EQ (li.tail, li.tortoise) ? (cycle) : (void) 0)))
 
 /* Do a `for' loop over alist values.  */
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 33661c8..31c1fe1 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -23055,30 +23055,19 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
 	    goto tail_recurse;
 	  }
 	else if (STRINGP (car) || CONSP (car))
-	  {
-	    Lisp_Object halftail = elt;
-	    int len = 0;
-
-	    while (CONSP (elt)
-		   && (precision <= 0 || n < precision))
-	      {
-		n += display_mode_element (it, depth,
-					   /* Do padding only after the last
-					      element in the list.  */
-					   (! CONSP (XCDR (elt))
-					    ? field_width - n
-					    : 0),
-					   precision - n, XCAR (elt),
-					   props, risky);
-		elt = XCDR (elt);
-		len++;
-		if ((len & 1) == 0)
-		  halftail = XCDR (halftail);
-		/* Check for cycle.  */
-		if (EQ (halftail, elt))
-		  break;
-	      }
-	  }
+	  FOR_EACH_TAIL_SAFE (elt)
+	    {
+	      if (0 < precision && precision <= n)
+		break;
+	      n += display_mode_element (it, depth,
+					 /* Pad after only the last
+					    list element.  */
+					 (! CONSP (XCDR (li.tail))
+					  ? field_width - n
+					  : 0),
+					 precision - n, XCAR (li.tail),
+					 props, risky);
+	    }
       }
       break;
 
-- 
2.9.3






^ permalink raw reply related	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-01 23:56 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc Paul Eggert
@ 2017-02-02 17:28   ` Eli Zaretskii
  2017-02-02 23:01     ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-02 17:28 UTC (permalink / raw)
  To: Paul Eggert; +Cc: eggert, 25606

> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed,  1 Feb 2017 15:56:22 -0800
> Cc: Paul Eggert <eggert@cs.ucla.edu>
> 
> Use macros like FOR_EACH_TAIL instead of maybe_quit to
> catch list cycles automatically instead of relying on the
> user becoming impatient and typing C-g.

I don't think this is a good idea.  We don't know when the user will
become impatient, and on busy systems the counter could be very low by
that time.  I think we shouldn't second-guess users this way, and
should always leave them the possibility of interrupting a possibly
prolonged calculation.

Also, could we please have tests for these functions?

Thanks.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL
  2017-02-01 23:56 bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Paul Eggert
  2017-02-01 23:56 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc Paul Eggert
@ 2017-02-02 17:29 ` Eli Zaretskii
  2017-02-05 21:30 ` bug#25605: patches installed for 25605, 25606 Paul Eggert
  2 siblings, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-02 17:29 UTC (permalink / raw)
  To: Paul Eggert; +Cc: eggert, 25605

> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed,  1 Feb 2017 15:56:21 -0800
> Cc: Paul Eggert <eggert@cs.ucla.edu>
> 
> * src/data.c (circular_list): New function.
> * src/lisp.h (FOR_EACH_TAIL): Use Brent’s algorithm and C99 for-loop
> decl, to eliminate the need for the args TAIL, TORTOISE and N, and
> to speed things up a bit on typical hosts with optimization.
> All uses changed.

Thanks, but I wonder if you could add some tests for the relevant
functions, I really feel uneasy about changing the implementation of
such basic functionality without any regression tests.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-02 17:28   ` Eli Zaretskii
@ 2017-02-02 23:01     ` Paul Eggert
  2017-02-03  7:55       ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-02 23:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25606

On 02/02/2017 09:28 AM, Eli Zaretskii wrote:

> could we please have tests for these functions?
Good point, I'll look into adding some.

> I think we shouldn't second-guess users this way, and
> should always leave them the possibility of interrupting a possibly
> prolonged calculation.

Sure, but we shouldn't insert maybe_quit calls after every nanosecond's 
worth of computation; that'd be overkill and would slow down Emacs 
unnecessarily. We should insert a maybe_quit call only when Emacs may 
have done enough computation that it would be annoying if the user typed 
C-g and Emacs did not respond for that period of time.

A reasonable rule of thumb is that if an operation can take longer than 
a garbage collection, then we should insert a maybe_quit in its loop 
body. Conversely, if an operation is always significantly faster then 
GC, then we needn't bother inserting maybe_quit, as Emacs cannot quit in 
the middle of GC anyway (and if we ever get around to fixing *that* 
problem then we will likely be able use the fix approach to attack the 
problem everywhere, not just in GC).

This rule of thumb corresponds pretty closely to what Emacs is already 
doing. For example, Emacs does a maybe_quit while doing regex searching, 
as in practice buffers can be quite large and searching them can easily 
take longer than a GC. In contrast, Emacs does not do a maybe_quit when 
FACE_FOR_CHAR searches font-encoding-charset-alist, as in practice that 
list is never so long that the a user would notice any C-g delay (and if 
the list actually did contain billions of elements (!), GC would be slow 
too as it would have to mark the list).

With cycle checking, all the loops containing removed maybe_quits are 
waaaay faster than a GC would be, which is why these loops don't need 
those maybe_quit calls once they start checking for list cycles.







^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-02 23:01     ` Paul Eggert
@ 2017-02-03  7:55       ` Eli Zaretskii
  2017-02-03 20:29         ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-03  7:55 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25606

> Cc: 25606@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Thu, 2 Feb 2017 15:01:16 -0800
> 
> On 02/02/2017 09:28 AM, Eli Zaretskii wrote:
> 
> > could we please have tests for these functions?
> Good point, I'll look into adding some.

Thanks.

> > I think we shouldn't second-guess users this way, and
> > should always leave them the possibility of interrupting a possibly
> > prolonged calculation.
> 
> Sure, but we shouldn't insert maybe_quit calls after every nanosecond's 
> worth of computation; that'd be overkill and would slow down Emacs 
> unnecessarily.

No, not that frequently, I agree.  So perhaps rarely_quit is a better
possibility in these places.

But in general, data structures on which these primitives work could
be rather large, and processing them could take a tangible amount of
time.  Moreover, on a memory-starved system or a system under heavy
computational load, the processing could take a long elapsed time even
if the CPU time used by Emacs is very small.  Users get annoyed by
elapsed time, because that's what they perceive.  So making these
uninterruptible except in case of glaring bugs sounds like losing a
valuable fire escape to me.

> We should insert a maybe_quit call only when Emacs may have done
> enough computation that it would be annoying if the user typed C-g
> and Emacs did not respond for that period of time.

Sure.  But do we have a reliable device to measure this quantity?
Once again, the elapsed time tends to annoy users regardless of the
real computational resources used by Emacs.

IOW, the removal is probably justified for 90% of use cases, maybe
even more, but it could be a problem for a small fraction of use
cases.  And since quitting is a kind of zero-level troubleshooting in
Emacs, I think we should be biased towards those rare cases here.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-03  7:55       ` Eli Zaretskii
@ 2017-02-03 20:29         ` Paul Eggert
  2017-02-04  9:05           ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-03 20:29 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25606

[-- Attachment #1: Type: text/plain, Size: 2016 bytes --]

On 02/02/2017 11:55 PM, Eli Zaretskii wrote:

> the removal is probably justified for 90% of use cases, maybe
> even more

It's 100%, as in practice any use case that has trouble because of the 
code removal will have significantly worse trouble on every GC (which is 
also noninterruptible). memq calls maybe_quit because of circular lists, 
not because of lists of length 1 billion, as huge lists don't work well 
with Emacs anyway (due to GC).

I wrote a little benchmark to try this out (attached), which used the 
new memq. On my workstation at UCLA the results were either:

1. The benchmark was so large that Emacs froze my system while building 
the test-case list, i.e., before any of the newly-affected code was 
executed. This was due to page thrashing. Obviously the draft change is 
irrelevant here.

2. The benchmark was so small that it finished instantly, from the 
user's viewpoint. Obviously not a problem.

3. The benchmark was medium sized (in my case, this was a list with 100 
million entries), so that Emacs was painfully slow but still barely 
usable while the test case was being built or while garbage collection 
was being done. In this case, the new memq was the least of the user's 
problems, as the new memq was 4x faster than a garbage collect so the 
C-g was delayed annoyingly for GC anyway. That is, GC makes Emacs so 
painful to use even with length-100-million lists that people won't use 
Emacs that way and we don't need to worry about treating such lists 
specially.

Of course I can't test all possible use cases. But if there's a 
practical use case where the draft patch will cause a problem, I haven't 
seen it yet.

By the way, I have found many cases where Emacs master will loop forever 
and will ignore C-g. If you like, I can privately send you an Elisp 
expression that, if you evaluate it, you cannot C-g out of. This problem 
is independent of the draft patch, and is far more serious than the 
somewhat-theoretical discussion we're having about memq and friends.


[-- Attachment #2: bigmemq.el --]
[-- Type: text/plain, Size: 644 bytes --]

(defun bigmemq (n)
  (let ((t0 (float-time (current-time))))
    (message "Running make-list...")
    (let ((long (make-list n nil))
          (t1 (float-time (current-time))))
      (message "Running make-list... done in %s seconds" (- t1 t0))
      (message "Running memq...")
      (let ((result (memq t long))
            (t2 (float-time (current-time))))
        (message "Running memq... done in %s seconds" (- t2 t1))
        (message "Running garbage-collect...")
        (garbage-collect)
        (let ((t3 (float-time (current-time))))
          (message "Running garbage-collect... done in %s seconds" (- t3 t2)))
        result))))

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-03 20:29         ` Paul Eggert
@ 2017-02-04  9:05           ` Eli Zaretskii
  2017-02-04 19:11             ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-04  9:05 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25606

> Cc: 25606@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Fri, 3 Feb 2017 12:29:11 -0800
> 
> On 02/02/2017 11:55 PM, Eli Zaretskii wrote:
> 
> > the removal is probably justified for 90% of use cases, maybe
> > even more
> 
> It's 100%

There is no 100% in real life, so if you want to convince me, you will
never use such arguments.

> as in practice any use case that has trouble because of the 
> code removal will have significantly worse trouble on every GC (which is 
> also noninterruptible). memq calls maybe_quit because of circular lists, 
> not because of lists of length 1 billion, as huge lists don't work well 
> with Emacs anyway (due to GC).

I don't see how arguments related to GC are relevant to the issue at
hand.  I'm interested in only one aspect of this change: how it is a
good idea to lose the ability to interrupt long loops processing large
Lisp data structures.

> 1. The benchmark was so large that Emacs froze my system while building 
> the test-case list, i.e., before any of the newly-affected code was 
> executed. This was due to page thrashing. Obviously the draft change is 
> irrelevant here.

I disagree that a use case with a paging system is irrelevant.

> 3. The benchmark was medium sized (in my case, this was a list with 100 
> million entries), so that Emacs was painfully slow but still barely 
> usable while the test case was being built or while garbage collection 
> was being done. In this case, the new memq was the least of the user's 
> problems, as the new memq was 4x faster than a garbage collect so the 
> C-g was delayed annoyingly for GC anyway. That is, GC makes Emacs so 
> painful to use even with length-100-million lists that people won't use 
> Emacs that way and we don't need to worry about treating such lists 
> specially.

Once again, the issue with GC is not relevant.  And the fact that
removing some code makes loops faster is trivial and also not
relevant.

I'm sorry, but I remain unconvinced that we should remove these
calls.  I'm okay with replacing maybe_quit with rarely_quit, which
should strike some hopefully more optimal middle ground.

> By the way, I have found many cases where Emacs master will loop forever 
> and will ignore C-g. If you like, I can privately send you an Elisp 
> expression that, if you evaluate it, you cannot C-g out of. This problem 
> is independent of the draft patch, and is far more serious than the 
> somewhat-theoretical discussion we're having about memq and friends.

We need to solve those problems, but that doesn't mean we should
introduce new ones elsewhere.  Being able to interrupt long loops in
Emacs is an important feature.

Thanks.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-04  9:05           ` Eli Zaretskii
@ 2017-02-04 19:11             ` Paul Eggert
  2017-02-04 19:52               ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-04 19:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25606

Eli Zaretskii wrote:
> I remain unconvinced that we should remove these calls.

I've provided several use cases and test code, all of which suggest that the 
maybe_quit calls are unnecessary. You have given no use cases that suggest 
otherwise. So I'm puzzled as to why you remain convinced that these calls are 
needed. All I'm asking for is a practical use case; it shouldn't be that hard to 
give one, if the calls are really important.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-04 19:11             ` Paul Eggert
@ 2017-02-04 19:52               ` Eli Zaretskii
  2017-02-04 21:45                 ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-04 19:52 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25606

> Cc: 25606@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sat, 4 Feb 2017 11:11:48 -0800
> 
> Eli Zaretskii wrote:
> > I remain unconvinced that we should remove these calls.
> 
> I've provided several use cases and test code, all of which suggest that the 
> maybe_quit calls are unnecessary. You have given no use cases that suggest 
> otherwise. So I'm puzzled as to why you remain convinced that these calls are 
> needed. All I'm asking for is a practical use case; it shouldn't be that hard to 
> give one, if the calls are really important.

I did provide use cases, you just dismiss them as unimportant.  They
are rare and perhaps even marginal, but they do exist.  And this
feature exists precisely for rare and marginal situations.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-04 19:52               ` Eli Zaretskii
@ 2017-02-04 21:45                 ` Paul Eggert
  2017-02-05 18:45                   ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-04 21:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25606

Eli Zaretskii wrote:

> I did provide use cases, you just dismiss them as unimportant.

You mentioned use cases consisting of "a memory-starved system or a system under 
heavy computational load". My test code attempted to exercise both 
possibilities, under different scenarios. My tests came up empty: there were no 
cases that caused new problems. Perhaps I misunderstood what you were driving 
at, but if so I would like to know what it was. Possibly there is a 
more-efficient change that would satisfy your concerns, once I understand them.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-04 21:45                 ` Paul Eggert
@ 2017-02-05 18:45                   ` Eli Zaretskii
  2017-02-05 21:17                     ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-05 18:45 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25606

> Cc: 25606@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sat, 4 Feb 2017 13:45:21 -0800
> 
> Eli Zaretskii wrote:
> 
> > I did provide use cases, you just dismiss them as unimportant.
> 
> You mentioned use cases consisting of "a memory-starved system or a system under 
> heavy computational load". My test code attempted to exercise both 
> possibilities, under different scenarios. My tests came up empty: there were no 
> cases that caused new problems.

That was your interpretation of the results.  It isn't mine: I don't
think that the fact that in your particular testing GC was a bugger
problem than the uninterruptible loop means the ability to interrupt
those loops has no value.

Besides, one particular simulation of the problem is not convincing
enough anyway.

> Perhaps I misunderstood what you were driving at, but if so I would
> like to know what it was.

I don't see what else can I explain in addition to what I already did.

> Possibly there is a more-efficient change that would satisfy your
> concerns, once I understand them.

How about if I turn the table and ask why is it so important to remove
those calls?





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
  2017-02-05 18:45                   ` Eli Zaretskii
@ 2017-02-05 21:17                     ` Paul Eggert
  0 siblings, 0 replies; 35+ messages in thread
From: Paul Eggert @ 2017-02-05 21:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25606

Eli Zaretskii wrote:

> How about if I turn the table and ask why is it so important to remove
> those calls?

Because they make Emacs bigger and slower for no good reason. A vague feeling 
that there might be a need for them in an unrealistic use case is not a good 
reason. However, your mind is made up and we're wasting time discussing this, so 
I give up and will install a patch with the unnecessary code.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: patches installed for 25605, 25606
  2017-02-01 23:56 bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Paul Eggert
  2017-02-01 23:56 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc Paul Eggert
  2017-02-02 17:29 ` bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Eli Zaretskii
@ 2017-02-05 21:30 ` Paul Eggert
  2017-02-06 16:04   ` bug#25605: bug#25606: " Eli Zaretskii
  2 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-05 21:30 UTC (permalink / raw)
  To: 25606, 25605

I installed patches for Bug#25605 and Bug#25606, along with all suggested 
revisions to the patches, and am closing the bug reports.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-05 21:30 ` bug#25605: patches installed for 25605, 25606 Paul Eggert
@ 2017-02-06 16:04   ` Eli Zaretskii
  2017-02-07  6:53     ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-06 16:04 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 5 Feb 2017 13:30:54 -0800
> 
> I installed patches for Bug#25605 and Bug#25606, along with all suggested 
> revisions to the patches, and am closing the bug reports.

Thanks.

Any reasons why the tests are in manual/cyclic-tests.el, and not in
src/fns-tests.el?  The tests don't need to be run interactively, do
they?





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-06 16:04   ` bug#25605: bug#25606: " Eli Zaretskii
@ 2017-02-07  6:53     ` Paul Eggert
  2017-02-07 12:47       ` Philipp Stephani
  2017-02-10  9:59       ` bug#25605: " Eli Zaretskii
  0 siblings, 2 replies; 35+ messages in thread
From: Paul Eggert @ 2017-02-07  6:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25605, 25606

Eli Zaretskii wrote:
> Any reasons why the tests are in manual/cyclic-tests.el, and not in
> src/fns-tests.el?

No particular reason, no. I don't know my way around the test directories well; 
please feel free to move them.

> The tests don't need to be run interactively, do
> they?

Only if they fail (i.e., loop forever).





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-07  6:53     ` Paul Eggert
@ 2017-02-07 12:47       ` Philipp Stephani
  2017-02-07 16:32         ` bug#25605: " Paul Eggert
  2017-02-10  9:59       ` bug#25605: " Eli Zaretskii
  1 sibling, 1 reply; 35+ messages in thread
From: Philipp Stephani @ 2017-02-07 12:47 UTC (permalink / raw)
  To: Paul Eggert, Eli Zaretskii; +Cc: 25605, 25606

[-- Attachment #1: Type: text/plain, Size: 304 bytes --]

Paul Eggert <eggert@cs.ucla.edu> schrieb am Di., 7. Feb. 2017 um 07:54 Uhr:

>
> > The tests don't need to be run interactively, do
> > they?
>
> Only if they fail (i.e., loop forever).
>
>
If they fail, shouldn't the test runner that runs these tests time out
after some time and mark them as failures?

[-- Attachment #2: Type: text/html, Size: 719 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-07 12:47       ` Philipp Stephani
@ 2017-02-07 16:32         ` Paul Eggert
  2017-02-07 21:47           ` Philipp Stephani
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-07 16:32 UTC (permalink / raw)
  To: Philipp Stephani, Eli Zaretskii; +Cc: 25605, 25606

On 02/07/2017 04:47 AM, Philipp Stephani wrote:
> If they fail, shouldn't the test runner that runs these tests time out 
> after some time and mark them as failures? 

Not if the test runner is written in elisp. The loops are deep in the C 
code and are immune to elisp timeouts. (I don't know how the test runner 
works.)






^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-07 16:32         ` bug#25605: " Paul Eggert
@ 2017-02-07 21:47           ` Philipp Stephani
  2017-02-07 22:20             ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Philipp Stephani @ 2017-02-07 21:47 UTC (permalink / raw)
  To: Paul Eggert, Eli Zaretskii; +Cc: 25605, 25606

[-- Attachment #1: Type: text/plain, Size: 478 bytes --]

Paul Eggert <eggert@cs.ucla.edu> schrieb am Di., 7. Feb. 2017 um 17:32 Uhr:

> On 02/07/2017 04:47 AM, Philipp Stephani wrote:
> > If they fail, shouldn't the test runner that runs these tests time out
> > after some time and mark them as failures?
>
> Not if the test runner is written in elisp. The loops are deep in the C
> code and are immune to elisp timeouts. (I don't know how the test runner
> works.)
>
>
How about running the Emacs binary wrapped in /usr/bin/timeout?

[-- Attachment #2: Type: text/html, Size: 932 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-07 21:47           ` Philipp Stephani
@ 2017-02-07 22:20             ` Paul Eggert
  2017-02-07 22:55               ` Philipp Stephani
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-07 22:20 UTC (permalink / raw)
  To: Philipp Stephani, Eli Zaretskii; +Cc: 25605, 25606

On 02/07/2017 01:47 PM, Philipp Stephani wrote:
> How about running the Emacs binary wrapped in /usr/bin/timeout?

That should work on GNU platforms. 'timeout' is not a standard program, 
though, and we can't rely on its presence on non-GNU platforms.






^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-07 22:20             ` Paul Eggert
@ 2017-02-07 22:55               ` Philipp Stephani
  0 siblings, 0 replies; 35+ messages in thread
From: Philipp Stephani @ 2017-02-07 22:55 UTC (permalink / raw)
  To: Paul Eggert, Eli Zaretskii; +Cc: 25605, 25606

[-- Attachment #1: Type: text/plain, Size: 488 bytes --]

Paul Eggert <eggert@cs.ucla.edu> schrieb am Di., 7. Feb. 2017 um 23:20 Uhr:

> On 02/07/2017 01:47 PM, Philipp Stephani wrote:
> > How about running the Emacs binary wrapped in /usr/bin/timeout?
>
> That should work on GNU platforms. 'timeout' is not a standard program,
> though, and we can't rely on its presence on non-GNU platforms.
>
>
This is only for running tests; don't we already require autotools for that
as well? We could also check for it in configure using AC_CHECK_PROGS.

[-- Attachment #2: Type: text/html, Size: 905 bytes --]

^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-07  6:53     ` Paul Eggert
  2017-02-07 12:47       ` Philipp Stephani
@ 2017-02-10  9:59       ` Eli Zaretskii
  2017-02-12  8:31         ` Paul Eggert
  1 sibling, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-10  9:59 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> Cc: 25606@debbugs.gnu.org, 25605@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Mon, 6 Feb 2017 22:53:35 -0800
> 
> Eli Zaretskii wrote:
> > Any reasons why the tests are in manual/cyclic-tests.el, and not in
> > src/fns-tests.el?
> 
> No particular reason, no. I don't know my way around the test directories well; 
> please feel free to move them.

Done.  I took the liberty to do the commit in your name, to keep the
attribution of the code to the original author.

Btw, 3 of the new tests fail for me:

  Test test-cycle-lax-plist-get backtrace:
    (setq value-1366 (apply fn-1364 args-1365))
    (unwind-protect (setq value-1366 (apply fn-1364 args-1365)) (setq fo
    (not (unwind-protect (setq value-1366 (apply fn-1364 args-1365)) (se
    (if (not (unwind-protect (setq value-1366 (apply fn-1364 args-1365))
    (let (form-description-1368) (if (not (unwind-protect (setq value-13
    (let ((value-1366 (quote ert-form-evaluation-aborted-1367))) (let (f
    (let ((fn-1364 (function lax-plist-get)) (args-1365 (list d1 2))) (l
    (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (dot2 1 2))) (
    (lambda nil (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (d
    ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
    ert-run-test([cl-struct-ert-test test-cycle-lax-plist-get nil (lambd
    ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test f
    ert-run-tests(t #[385 "\306☻\307\"\203G \211\211G\310U\203¶ \211@\20
    ert-run-tests-batch(nil)
    ert-run-tests-batch-and-exit(nil)
    eval((ert-run-tests-batch-and-exit nil))
    command-line-1(("-L" ";." "-l" "ert" "-l" "src/fns-tests.el" "--eval
    command-line()
    normal-top-level()
  Test test-cycle-lax-plist-get condition:
      (wrong-type-argument listp
			   (1 1 1 1 1 1 1 1 1 1 . tail))
     FAILED  18/31  test-cycle-lax-plist-get
  Test test-cycle-lax-plist-put backtrace:
    (setq value-1570 (apply fn-1568 args-1569))
    (unwind-protect (setq value-1570 (apply fn-1568 args-1569)) (setq fo
    (if (unwind-protect (setq value-1570 (apply fn-1568 args-1569)) (set
    (let (form-description-1572) (if (unwind-protect (setq value-1570 (a
    (let ((value-1570 (quote ert-form-evaluation-aborted-1571))) (let (f
    (let ((fn-1568 (function lax-plist-put)) (args-1569 (list d1 2 2)))
    (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (dot2 1 2))) (
    (lambda nil (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (d
    ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
    ert-run-test([cl-struct-ert-test test-cycle-lax-plist-put nil (lambd
    ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test f
    ert-run-tests(t #[385 "\306☻\307\"\203G \211\211G\310U\203¶ \211@\20
    ert-run-tests-batch(nil)
    ert-run-tests-batch-and-exit(nil)
    eval((ert-run-tests-batch-and-exit nil))
    command-line-1(("-L" ";." "-l" "ert" "-l" "src/fns-tests.el" "--eval
    command-line()
    normal-top-level()
  Test test-cycle-lax-plist-put condition:
      (wrong-type-argument listp
			   (1 1 1 1 1 1 1 1 1 1 . tail))
     FAILED  19/31  test-cycle-lax-plist-put
     passed  20/31  test-cycle-length
     passed  21/31  test-cycle-member
     passed  22/31  test-cycle-memq
     passed  23/31  test-cycle-memql
     passed  24/31  test-cycle-nconc
     passed  25/31  test-cycle-plist-get
     passed  26/31  test-cycle-plist-member
  Test test-cycle-plist-put backtrace:
    (setq value-1504 (apply fn-1502 args-1503))
    (unwind-protect (setq value-1504 (apply fn-1502 args-1503)) (setq fo
    (if (unwind-protect (setq value-1504 (apply fn-1502 args-1503)) (set
    (let (form-description-1506) (if (unwind-protect (setq value-1504 (a
    (let ((value-1504 (quote ert-form-evaluation-aborted-1505))) (let (f
    (let ((fn-1502 (function plist-put)) (args-1503 (list d1 2 2))) (let
    (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (dot2 1 2))) (
    (lambda nil (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) (d1 (dot1 1)) (d2 (d
    ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struc
    ert-run-test([cl-struct-ert-test test-cycle-plist-put nil (lambda ni
    ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test f
    ert-run-tests(t #[385 "\306☻\307\"\203G \211\211G\310U\203¶ \211@\20
    ert-run-tests-batch(nil)
    ert-run-tests-batch-and-exit(nil)
    eval((ert-run-tests-batch-and-exit nil))
    command-line-1(("-L" ";." "-l" "ert" "-l" "src/fns-tests.el" "--eval
    command-line()
    normal-top-level()
  Test test-cycle-plist-put condition:
      (wrong-type-argument listp
			   (1 1 1 1 1 1 1 1 1 1 . tail))
     FAILED  27/31  test-cycle-plist-put
     passed  28/31  test-cycle-rassoc
     passed  29/31  test-cycle-rassq
     passed  30/31  test-cycle-reverse
     passed  31/31  test-cycle-safe-length

  Ran 31 tests, 28 results as expected, 3 unexpected (2017-02-10 11:49:19+0200)





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-10  9:59       ` bug#25605: " Eli Zaretskii
@ 2017-02-12  8:31         ` Paul Eggert
  2017-02-12 16:13           ` bug#25605: " Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-12  8:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25605, 25606

Eli Zaretskii wrote:
> I took the liberty to do the commit in your name, to keep the
> attribution of the code to the original author.
>
> Btw, 3 of the new tests fail for me:

Although the new tests fail for me too, they succeed if I revert commit 
65298ff4d5861cbc8d88162d58c18fa972b81acf, i.e., the commit that you installed in 
my name. So there must be something wrong with that commit. It would be easy to 
revert the commit but I assume that it was done for a reason so I'll wait for 
you to look into the problem.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-12  8:31         ` Paul Eggert
@ 2017-02-12 16:13           ` Eli Zaretskii
  2017-02-12 18:55             ` Paul Eggert
  0 siblings, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-12 16:13 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> Cc: 25606@debbugs.gnu.org, 25605@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 12 Feb 2017 00:31:02 -0800
> 
> Eli Zaretskii wrote:
> > I took the liberty to do the commit in your name, to keep the
> > attribution of the code to the original author.
> >
> > Btw, 3 of the new tests fail for me:
> 
> Although the new tests fail for me too, they succeed if I revert commit 
> 65298ff4d5861cbc8d88162d58c18fa972b81acf, i.e., the commit that you installed in 
> my name. So there must be something wrong with that commit.

That's strange.  Before pushing, I verified that I get the same
failures with your original test file.  But maybe I didn't invoke the
test as you intended it to be run.  Here's how I invoke it:

  $ cd test && ../src/emacs -batch -l ert -l manual/cycle-tests.el --eval "(ert-run-tests-batch-and-exit nil)"

If that's wrong, what is the right way of running those tests?





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 16:13           ` bug#25605: " Eli Zaretskii
@ 2017-02-12 18:55             ` Paul Eggert
  2017-02-12 19:33               ` Eli Zaretskii
  2017-02-12 19:41               ` Eli Zaretskii
  0 siblings, 2 replies; 35+ messages in thread
From: Paul Eggert @ 2017-02-12 18:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25605, 25606

Eli Zaretskii wrote:
> what is the right way of running those tests?

"make check". That's what's documented, right?





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 18:55             ` Paul Eggert
@ 2017-02-12 19:33               ` Eli Zaretskii
  2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
                                   ` (2 more replies)
  2017-02-12 19:41               ` Eli Zaretskii
  1 sibling, 3 replies; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-12 19:33 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> Cc: 25606@debbugs.gnu.org, 25605@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 12 Feb 2017 10:55:00 -0800
> 
> Eli Zaretskii wrote:
> > what is the right way of running those tests?
> 
> "make check". That's what's documented, right?

This runs everything, which is too much.  How do I run this single
test?  (AFAIU, it runs each test exactly as I did.)





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-12 19:33               ` Eli Zaretskii
@ 2017-02-12 19:41                 ` Lars Ingebrigtsen
  2017-02-12 19:49                   ` bug#25606: " Lars Ingebrigtsen
  2017-02-12 20:22                   ` Eli Zaretskii
  2017-02-12 19:43                 ` Paul Eggert
  2017-02-13  9:11                 ` Michael Albinus
  2 siblings, 2 replies; 35+ messages in thread
From: Lars Ingebrigtsen @ 2017-02-12 19:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Paul Eggert, 25605, 25606

Eli Zaretskii <eliz@gnu.org> writes:

>> "make check". That's what's documented, right?
>
> This runs everything, which is too much.  How do I run this single
> test?  (AFAIU, it runs each test exactly as I did.)

I don't know how to do a single test, but I always run tests from a
single file like so:

larsi@mouse:~/src/emacs/trunk/test$ make src/fns-tests

(which hangs for me at present).

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 18:55             ` Paul Eggert
  2017-02-12 19:33               ` Eli Zaretskii
@ 2017-02-12 19:41               ` Eli Zaretskii
  2017-02-12 20:57                 ` bug#25605: " Paul Eggert
  1 sibling, 1 reply; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-12 19:41 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> Cc: 25606@debbugs.gnu.org, 25605@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 12 Feb 2017 10:55:00 -0800
> 
> Eli Zaretskii wrote:
> > what is the right way of running those tests?
> 
> "make check". That's what's documented, right?

Actually, AFAIU "make check" doesn't run the tests in manual/ at all,
so I'm not sure how you succeeded to run them.  Or maybe I'm missing
something obvious.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 19:33               ` Eli Zaretskii
  2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
@ 2017-02-12 19:43                 ` Paul Eggert
  2017-02-13  9:11                 ` Michael Albinus
  2 siblings, 0 replies; 35+ messages in thread
From: Paul Eggert @ 2017-02-12 19:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25605, 25606

Eli Zaretskii wrote:
> This runs everything, which is too much.  How do I run this single
> test?

Sorry, I don't know. I didn't have to know, as "make check" sufficed for me.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
@ 2017-02-12 19:49                   ` Lars Ingebrigtsen
  2017-02-12 20:22                   ` Eli Zaretskii
  1 sibling, 0 replies; 35+ messages in thread
From: Lars Ingebrigtsen @ 2017-02-12 19:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Paul Eggert, 25605, 25606

Lars Ingebrigtsen <larsi@gnus.org> writes:

> larsi@mouse:~/src/emacs/trunk/test$ make src/fns-tests
>
> (which hangs for me at present).

(Hm, doesn't hang after rebuilding Emacs.  But some of the tests fail.)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
  2017-02-12 19:49                   ` bug#25606: " Lars Ingebrigtsen
@ 2017-02-12 20:22                   ` Eli Zaretskii
  1 sibling, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-12 20:22 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: eggert, 25605, 25606

> From: Lars Ingebrigtsen <larsi@gnus.org>
> Cc: Paul Eggert <eggert@cs.ucla.edu>,  25605@debbugs.gnu.org,  25606@debbugs.gnu.org
> Date: Sun, 12 Feb 2017 20:41:16 +0100
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >> "make check". That's what's documented, right?
> >
> > This runs everything, which is too much.  How do I run this single
> > test?  (AFAIU, it runs each test exactly as I did.)
> 
> I don't know how to do a single test, but I always run tests from a
> single file like so:
> 
> larsi@mouse:~/src/emacs/trunk/test$ make src/fns-tests

That's what I do.  But this doesn't work for files in manual/.

> (which hangs for me at present).

(It doesn't hang for me; it fails because 3 tests fail.)





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25605: bug#25606: patches installed for 25605, 25606
  2017-02-12 19:41               ` Eli Zaretskii
@ 2017-02-12 20:57                 ` Paul Eggert
  2017-02-13  5:37                   ` Eli Zaretskii
  0 siblings, 1 reply; 35+ messages in thread
From: Paul Eggert @ 2017-02-12 20:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 25605, 25606

Eli Zaretskii wrote:
> Actually, AFAIU "make check" doesn't run the tests in manual/ at all,
> so I'm not sure how you succeeded to run them.

Well, now that I think back on it, I'm not sure either. I did run them, using 
some complicated set of arguments to 'make', but I don't remember what the 
arguments were.

Anyway, I debugged the tests under the new regime and installed a fix.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 20:57                 ` bug#25605: " Paul Eggert
@ 2017-02-13  5:37                   ` Eli Zaretskii
  0 siblings, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-13  5:37 UTC (permalink / raw)
  To: Paul Eggert; +Cc: 25605, 25606

> Cc: 25606@debbugs.gnu.org, 25605@debbugs.gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Sun, 12 Feb 2017 12:57:13 -0800
> 
> Anyway, I debugged the tests under the new regime and installed a fix.

Thanks, they all pass for me now.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-12 19:33               ` Eli Zaretskii
  2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
  2017-02-12 19:43                 ` Paul Eggert
@ 2017-02-13  9:11                 ` Michael Albinus
  2017-02-13 14:37                   ` Eli Zaretskii
  2 siblings, 1 reply; 35+ messages in thread
From: Michael Albinus @ 2017-02-13  9:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Paul Eggert, 25605, 25606

Eli Zaretskii <eliz@gnu.org> writes:

>> > what is the right way of running those tests?
>> 
>> "make check". That's what's documented, right?
>
> This runs everything, which is too much.  How do I run this single
> test?  (AFAIU, it runs each test exactly as I did.)

# make -C test fns-tests SELECTOR=\'test-cycle-lax-plist-get

See also test/README

Best regards, Michael.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* bug#25606: patches installed for 25605, 25606
  2017-02-13  9:11                 ` Michael Albinus
@ 2017-02-13 14:37                   ` Eli Zaretskii
  0 siblings, 0 replies; 35+ messages in thread
From: Eli Zaretskii @ 2017-02-13 14:37 UTC (permalink / raw)
  To: Michael Albinus; +Cc: eggert, 25605, 25606

> From: Michael Albinus <michael.albinus@gmx.de>
> Cc: Paul Eggert <eggert@cs.ucla.edu>,  25605@debbugs.gnu.org,  25606@debbugs.gnu.org
> Date: Mon, 13 Feb 2017 10:11:21 +0100
> 
> >> "make check". That's what's documented, right?
> >
> > This runs everything, which is too much.  How do I run this single
> > test?  (AFAIU, it runs each test exactly as I did.)
> 
> # make -C test fns-tests SELECTOR=\'test-cycle-lax-plist-get

Yes, I know.  But that doesn't work for tests under manual/, which is
what I was asking about.





^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2017-02-13 14:37 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-01 23:56 bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Paul Eggert
2017-02-01 23:56 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc Paul Eggert
2017-02-02 17:28   ` Eli Zaretskii
2017-02-02 23:01     ` Paul Eggert
2017-02-03  7:55       ` Eli Zaretskii
2017-02-03 20:29         ` Paul Eggert
2017-02-04  9:05           ` Eli Zaretskii
2017-02-04 19:11             ` Paul Eggert
2017-02-04 19:52               ` Eli Zaretskii
2017-02-04 21:45                 ` Paul Eggert
2017-02-05 18:45                   ` Eli Zaretskii
2017-02-05 21:17                     ` Paul Eggert
2017-02-02 17:29 ` bug#25605: [DRAFT PATCH 1/2] Simplify use of FOR_EACH_TAIL Eli Zaretskii
2017-02-05 21:30 ` bug#25605: patches installed for 25605, 25606 Paul Eggert
2017-02-06 16:04   ` bug#25605: bug#25606: " Eli Zaretskii
2017-02-07  6:53     ` Paul Eggert
2017-02-07 12:47       ` Philipp Stephani
2017-02-07 16:32         ` bug#25605: " Paul Eggert
2017-02-07 21:47           ` Philipp Stephani
2017-02-07 22:20             ` Paul Eggert
2017-02-07 22:55               ` Philipp Stephani
2017-02-10  9:59       ` bug#25605: " Eli Zaretskii
2017-02-12  8:31         ` Paul Eggert
2017-02-12 16:13           ` bug#25605: " Eli Zaretskii
2017-02-12 18:55             ` Paul Eggert
2017-02-12 19:33               ` Eli Zaretskii
2017-02-12 19:41                 ` bug#25605: " Lars Ingebrigtsen
2017-02-12 19:49                   ` bug#25606: " Lars Ingebrigtsen
2017-02-12 20:22                   ` Eli Zaretskii
2017-02-12 19:43                 ` Paul Eggert
2017-02-13  9:11                 ` Michael Albinus
2017-02-13 14:37                   ` Eli Zaretskii
2017-02-12 19:41               ` Eli Zaretskii
2017-02-12 20:57                 ` bug#25605: " Paul Eggert
2017-02-13  5:37                   ` Eli Zaretskii

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.