aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-11-29 14:47:58 -0500
committerStefan Monnier2013-11-29 14:47:58 -0500
commit9f4ffeee436f71fc1253b27151c087fe5d0d3e45 (patch)
tree767702294872ed28ea434b8c3f7556f22c8c545f
parent1659fa3fbd9c0d644930d4e7c8efb2c2e55467dc (diff)
downloademacs-9f4ffeee436f71fc1253b27151c087fe5d0d3e45.tar.gz
emacs-9f4ffeee436f71fc1253b27151c087fe5d0d3e45.zip
* src/fns.c (internal_equal): Add a hash_table argument to handle cycles.
-rw-r--r--src/ChangeLog2
-rw-r--r--src/fns.c54
2 files changed, 44 insertions, 12 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 02a3f4eb21d..a626c2b1963 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,7 @@
12013-11-29 Stefan Monnier <monnier@iro.umontreal.ca> 12013-11-29 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * fns.c (internal_equal): Add a hash_table argument to handle cycles.
4
3 * xdisp.c (REDISPLAY_SOME_P): New macro. 5 * xdisp.c (REDISPLAY_SOME_P): New macro.
4 (redisplay_internal): Use it (bug#15999). 6 (redisplay_internal): Use it (bug#15999).
5 (prepare_menu_bars, redisplay_window): Use it as well. 7 (prepare_menu_bars, redisplay_window): Use it as well.
diff --git a/src/fns.c b/src/fns.c
index 4c3bde1add9..e705bdc58e9 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -48,7 +48,7 @@ static Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper;
48 48
49static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512; 49static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512;
50 50
51static bool internal_equal (Lisp_Object, Lisp_Object, int, bool); 51static bool internal_equal (Lisp_Object, Lisp_Object, int, bool, Lisp_Object);
52 52
53DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 53DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
54 doc: /* Return the argument unchanged. */) 54 doc: /* Return the argument unchanged. */)
@@ -1355,7 +1355,7 @@ The value is actually the tail of LIST whose car is ELT. */)
1355 register Lisp_Object tem; 1355 register Lisp_Object tem;
1356 CHECK_LIST_CONS (tail, list); 1356 CHECK_LIST_CONS (tail, list);
1357 tem = XCAR (tail); 1357 tem = XCAR (tail);
1358 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0)) 1358 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
1359 return tail; 1359 return tail;
1360 QUIT; 1360 QUIT;
1361 } 1361 }
@@ -1959,7 +1959,7 @@ Floating-point numbers of equal value are `eql', but they may not be `eq'. */)
1959 (Lisp_Object obj1, Lisp_Object obj2) 1959 (Lisp_Object obj1, Lisp_Object obj2)
1960{ 1960{
1961 if (FLOATP (obj1)) 1961 if (FLOATP (obj1))
1962 return internal_equal (obj1, obj2, 0, 0) ? Qt : Qnil; 1962 return internal_equal (obj1, obj2, 0, 0, Qnil) ? Qt : Qnil;
1963 else 1963 else
1964 return EQ (obj1, obj2) ? Qt : Qnil; 1964 return EQ (obj1, obj2) ? Qt : Qnil;
1965} 1965}
@@ -1974,7 +1974,7 @@ Numbers are compared by value, but integers cannot equal floats.
1974Symbols must match exactly. */) 1974Symbols must match exactly. */)
1975 (register Lisp_Object o1, Lisp_Object o2) 1975 (register Lisp_Object o1, Lisp_Object o2)
1976{ 1976{
1977 return internal_equal (o1, o2, 0, 0) ? Qt : Qnil; 1977 return internal_equal (o1, o2, 0, 0, Qnil) ? Qt : Qnil;
1978} 1978}
1979 1979
1980DEFUN ("equal-including-properties", Fequal_including_properties, Sequal_including_properties, 2, 2, 0, 1980DEFUN ("equal-including-properties", Fequal_including_properties, Sequal_including_properties, 2, 2, 0,
@@ -1983,7 +1983,7 @@ This is like `equal' except that it compares the text properties
1983of strings. (`equal' ignores text properties.) */) 1983of strings. (`equal' ignores text properties.) */)
1984 (register Lisp_Object o1, Lisp_Object o2) 1984 (register Lisp_Object o1, Lisp_Object o2)
1985{ 1985{
1986 return internal_equal (o1, o2, 0, 1) ? Qt : Qnil; 1986 return internal_equal (o1, o2, 0, 1, Qnil) ? Qt : Qnil;
1987} 1987}
1988 1988
1989/* DEPTH is current depth of recursion. Signal an error if it 1989/* DEPTH is current depth of recursion. Signal an error if it
@@ -1991,10 +1991,39 @@ of strings. (`equal' ignores text properties.) */)
1991 PROPS means compare string text properties too. */ 1991 PROPS means compare string text properties too. */
1992 1992
1993static bool 1993static bool
1994internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props) 1994internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
1995 Lisp_Object ht)
1995{ 1996{
1996 if (depth > 200) 1997 if (depth > 10)
1997 error ("Stack overflow in equal"); 1998 {
1999 if (depth > 200)
2000 error ("Stack overflow in equal");
2001 if (NILP (ht))
2002 {
2003 Lisp_Object args[2] = { QCtest, Qeq };
2004 ht = Fmake_hash_table (2, args);
2005 }
2006 switch (XTYPE (o1))
2007 {
2008 case Lisp_Cons: case Lisp_Misc: case Lisp_Vectorlike:
2009 {
2010 struct Lisp_Hash_Table *h = XHASH_TABLE (ht);
2011 EMACS_UINT hash;
2012 ptrdiff_t i = hash_lookup (h, o1, &hash);
2013 if (i >= 0)
2014 { /* `o1' was seen already. */
2015 Lisp_Object o2s = HASH_VALUE (h, i);
2016 if (!NILP (Fmemq (o2, o2s)))
2017 return 1;
2018 else
2019 set_hash_value_slot (h, i, Fcons (o2, o2s));
2020 }
2021 else
2022 hash_put (h, o1, Fcons (o2, Qnil), hash);
2023 }
2024 default: ;
2025 }
2026 }
1998 2027
1999 tail_recurse: 2028 tail_recurse:
2000 QUIT; 2029 QUIT;
@@ -2017,10 +2046,11 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props)
2017 } 2046 }
2018 2047
2019 case Lisp_Cons: 2048 case Lisp_Cons:
2020 if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1, props)) 2049 if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1, props, ht))
2021 return 0; 2050 return 0;
2022 o1 = XCDR (o1); 2051 o1 = XCDR (o1);
2023 o2 = XCDR (o2); 2052 o2 = XCDR (o2);
2053 /* FIXME: This inf-loops in a circular list! */
2024 goto tail_recurse; 2054 goto tail_recurse;
2025 2055
2026 case Lisp_Misc: 2056 case Lisp_Misc:
@@ -2029,9 +2059,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props)
2029 if (OVERLAYP (o1)) 2059 if (OVERLAYP (o1))
2030 { 2060 {
2031 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), 2061 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
2032 depth + 1, props) 2062 depth + 1, props, ht)
2033 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), 2063 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
2034 depth + 1, props)) 2064 depth + 1, props, ht))
2035 return 0; 2065 return 0;
2036 o1 = XOVERLAY (o1)->plist; 2066 o1 = XOVERLAY (o1)->plist;
2037 o2 = XOVERLAY (o2)->plist; 2067 o2 = XOVERLAY (o2)->plist;
@@ -2083,7 +2113,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props)
2083 Lisp_Object v1, v2; 2113 Lisp_Object v1, v2;
2084 v1 = AREF (o1, i); 2114 v1 = AREF (o1, i);
2085 v2 = AREF (o2, i); 2115 v2 = AREF (o2, i);
2086 if (!internal_equal (v1, v2, depth + 1, props)) 2116 if (!internal_equal (v1, v2, depth + 1, props, ht))
2087 return 0; 2117 return 0;
2088 } 2118 }
2089 return 1; 2119 return 1;