From: Paul Eggert <eggert@cs.ucla.edu>
To: 25606@debbugs.gnu.org
Cc: Paul Eggert <eggert@cs.ucla.edu>
Subject: bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc.
Date: Wed, 1 Feb 2017 15:56:22 -0800 [thread overview]
Message-ID: <20170201235622.30836-2-eggert@cs.ucla.edu> (raw)
In-Reply-To: <20170201235622.30836-1-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.
* 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
next prev parent reply other threads:[~2017-02-01 23:56 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2017-02-02 17:28 ` bug#25606: [DRAFT PATCH 2/2] Signal list cycles in ‘length’ etc 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170201235622.30836-2-eggert@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=25606@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).