aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2017-03-29 22:34:02 -0700
committerPaul Eggert2017-03-29 22:43:51 -0700
commit080a425db51e0b26b03f0f4bd06c814fc2b38578 (patch)
treeefd3c6c3b46251dd3fe97332f55e6e03daf8c317
parentb7ec73f6905df99978f7183ac8e83a3be56edc6c (diff)
downloademacs-080a425db51e0b26b03f0f4bd06c814fc2b38578.tar.gz
emacs-080a425db51e0b26b03f0f4bd06c814fc2b38578.zip
Fix assoc_no_quit so that it does not quit
The problem was that it called Fequal, which can quit. * src/fns.c (enum equal_kind): New enum, to be used in place of a boolean. (equal_no_quit): New function. (Fmemql, Feql): Use it to compare floats, as a minor tuneup. (assoc_no_quit): Use it to avoid quitting, the main point here. (internal_equal): Generalize bool to enum equal_kind arg, so that there are now 3 possibilities instead of 2. Do not signal an error if EQUAL_NO_QUIT. Put the arg before the depth, since depth should be irrelevant if the arg is EQUAL_NO_QUIT. All callers changed.
-rw-r--r--src/fns.c122
1 files changed, 80 insertions, 42 deletions
diff --git a/src/fns.c b/src/fns.c
index 10653558eb5..42e2eecf33e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -38,7 +38,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
38 38
39static void sort_vector_copy (Lisp_Object, ptrdiff_t, 39static void sort_vector_copy (Lisp_Object, ptrdiff_t,
40 Lisp_Object *restrict, Lisp_Object *restrict); 40 Lisp_Object *restrict, Lisp_Object *restrict);
41static bool internal_equal (Lisp_Object, Lisp_Object, int, bool, Lisp_Object); 41static bool equal_no_quit (Lisp_Object, Lisp_Object);
42enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES };
43static bool internal_equal (Lisp_Object, Lisp_Object,
44 enum equal_kind, int, Lisp_Object);
42 45
43DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, 46DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
44 doc: /* Return the argument unchanged. */ 47 doc: /* Return the argument unchanged. */
@@ -1377,7 +1380,7 @@ The value is actually the tail of LIST whose car is ELT. */)
1377 FOR_EACH_TAIL (tail) 1380 FOR_EACH_TAIL (tail)
1378 { 1381 {
1379 Lisp_Object tem = XCAR (tail); 1382 Lisp_Object tem = XCAR (tail);
1380 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil)) 1383 if (FLOATP (tem) && equal_no_quit (elt, tem))
1381 return tail; 1384 return tail;
1382 } 1385 }
1383 CHECK_LIST_END (tail, list); 1386 CHECK_LIST_END (tail, list);
@@ -1428,7 +1431,8 @@ The value is actually the first element of LIST whose car equals KEY. */)
1428} 1431}
1429 1432
1430/* Like Fassoc but never report an error and do not allow quits. 1433/* Like Fassoc but never report an error and do not allow quits.
1431 Use only on objects known to be non-circular lists. */ 1434 Use only on keys and lists known to be non-circular, and on keys
1435 that are not too deep and are not window configurations. */
1432 1436
1433Lisp_Object 1437Lisp_Object
1434assoc_no_quit (Lisp_Object key, Lisp_Object list) 1438assoc_no_quit (Lisp_Object key, Lisp_Object list)
@@ -1437,7 +1441,7 @@ assoc_no_quit (Lisp_Object key, Lisp_Object list)
1437 { 1441 {
1438 Lisp_Object car = XCAR (list); 1442 Lisp_Object car = XCAR (list);
1439 if (CONSP (car) 1443 if (CONSP (car)
1440 && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key)))) 1444 && (EQ (XCAR (car), key) || equal_no_quit (XCAR (car), key)))
1441 return car; 1445 return car;
1442 } 1446 }
1443 return Qnil; 1447 return Qnil;
@@ -2085,7 +2089,7 @@ Floating-point numbers of equal value are `eql', but they may not be `eq'. */)
2085 (Lisp_Object obj1, Lisp_Object obj2) 2089 (Lisp_Object obj1, Lisp_Object obj2)
2086{ 2090{
2087 if (FLOATP (obj1)) 2091 if (FLOATP (obj1))
2088 return internal_equal (obj1, obj2, 0, 0, Qnil) ? Qt : Qnil; 2092 return equal_no_quit (obj1, obj2) ? Qt : Qnil;
2089 else 2093 else
2090 return EQ (obj1, obj2) ? Qt : Qnil; 2094 return EQ (obj1, obj2) ? Qt : Qnil;
2091} 2095}
@@ -2098,31 +2102,50 @@ Vectors and strings are compared element by element.
2098Numbers are compared by value, but integers cannot equal floats. 2102Numbers are compared by value, but integers cannot equal floats.
2099 (Use `=' if you want integers and floats to be able to be equal.) 2103 (Use `=' if you want integers and floats to be able to be equal.)
2100Symbols must match exactly. */) 2104Symbols must match exactly. */)
2101 (register Lisp_Object o1, Lisp_Object o2) 2105 (Lisp_Object o1, Lisp_Object o2)
2102{ 2106{
2103 return internal_equal (o1, o2, 0, 0, Qnil) ? Qt : Qnil; 2107 return internal_equal (o1, o2, EQUAL_PLAIN, 0, Qnil) ? Qt : Qnil;
2104} 2108}
2105 2109
2106DEFUN ("equal-including-properties", Fequal_including_properties, Sequal_including_properties, 2, 2, 0, 2110DEFUN ("equal-including-properties", Fequal_including_properties, Sequal_including_properties, 2, 2, 0,
2107 doc: /* Return t if two Lisp objects have similar structure and contents. 2111 doc: /* Return t if two Lisp objects have similar structure and contents.
2108This is like `equal' except that it compares the text properties 2112This is like `equal' except that it compares the text properties
2109of strings. (`equal' ignores text properties.) */) 2113of strings. (`equal' ignores text properties.) */)
2110 (register Lisp_Object o1, Lisp_Object o2) 2114 (Lisp_Object o1, Lisp_Object o2)
2115{
2116 return (internal_equal (o1, o2, EQUAL_INCLUDING_PROPERTIES, 0, Qnil)
2117 ? Qt : Qnil);
2118}
2119
2120/* Return true if O1 and O2 are equal. Do not quit or check for cycles.
2121 Use this only on arguments that are cycle-free and not too large and
2122 are not window configurations. */
2123
2124static bool
2125equal_no_quit (Lisp_Object o1, Lisp_Object o2)
2111{ 2126{
2112 return internal_equal (o1, o2, 0, 1, Qnil) ? Qt : Qnil; 2127 return internal_equal (o1, o2, EQUAL_NO_QUIT, 0, Qnil);
2113} 2128}
2114 2129
2115/* DEPTH is current depth of recursion. Signal an error if it 2130/* Return true if O1 and O2 are equal. EQUAL_KIND specifies what kind
2116 gets too deep. 2131 of equality test to use: if it is EQUAL_NO_QUIT, do not check for
2117 PROPS means compare string text properties too. */ 2132 cycles or large arguments or quits; if EQUAL_PLAIN, do ordinary
2133 Lisp equality; and if EQUAL_INCLUDING_PROPERTIES, do
2134 equal-including-properties.
2135
2136 If DEPTH is the current depth of recursion; signal an error if it
2137 gets too deep. HT is a hash table used to detect cycles; if nil,
2138 it has not been allocated yet. But ignore the last two arguments
2139 if EQUAL_KIND == EQUAL_NO_QUIT. */
2118 2140
2119static bool 2141static bool
2120internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props, 2142internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2121 Lisp_Object ht) 2143 int depth, Lisp_Object ht)
2122{ 2144{
2123 tail_recurse: 2145 tail_recurse:
2124 if (depth > 10) 2146 if (depth > 10)
2125 { 2147 {
2148 eassert (equal_kind != EQUAL_NO_QUIT);
2126 if (depth > 200) 2149 if (depth > 200)
2127 error ("Stack overflow in equal"); 2150 error ("Stack overflow in equal");
2128 if (NILP (ht)) 2151 if (NILP (ht))
@@ -2138,7 +2161,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2138 { /* `o1' was seen already. */ 2161 { /* `o1' was seen already. */
2139 Lisp_Object o2s = HASH_VALUE (h, i); 2162 Lisp_Object o2s = HASH_VALUE (h, i);
2140 if (!NILP (Fmemq (o2, o2s))) 2163 if (!NILP (Fmemq (o2, o2s)))
2141 return 1; 2164 return true;
2142 else 2165 else
2143 set_hash_value_slot (h, i, Fcons (o2, o2s)); 2166 set_hash_value_slot (h, i, Fcons (o2, o2s));
2144 } 2167 }
@@ -2150,9 +2173,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2150 } 2173 }
2151 2174
2152 if (EQ (o1, o2)) 2175 if (EQ (o1, o2))
2153 return 1; 2176 return true;
2154 if (XTYPE (o1) != XTYPE (o2)) 2177 if (XTYPE (o1) != XTYPE (o2))
2155 return 0; 2178 return false;
2156 2179
2157 switch (XTYPE (o1)) 2180 switch (XTYPE (o1))
2158 { 2181 {
@@ -2166,31 +2189,42 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2166 } 2189 }
2167 2190
2168 case Lisp_Cons: 2191 case Lisp_Cons:
2169 { 2192 if (equal_kind == EQUAL_NO_QUIT)
2193 for (; CONSP (o1); o1 = XCDR (o1))
2194 {
2195 if (! CONSP (o2))
2196 return false;
2197 if (! equal_no_quit (XCAR (o1), XCAR (o2)))
2198 return false;
2199 o2 = XCDR (o2);
2200 if (EQ (XCDR (o1), o2))
2201 return true;
2202 }
2203 else
2170 FOR_EACH_TAIL (o1) 2204 FOR_EACH_TAIL (o1)
2171 { 2205 {
2172 if (! CONSP (o2)) 2206 if (! CONSP (o2))
2173 return false; 2207 return false;
2174 if (! internal_equal (XCAR (o1), XCAR (o2), depth + 1, props, ht)) 2208 if (! internal_equal (XCAR (o1), XCAR (o2),
2209 equal_kind, depth + 1, ht))
2175 return false; 2210 return false;
2176 o2 = XCDR (o2); 2211 o2 = XCDR (o2);
2177 if (EQ (XCDR (o1), o2)) 2212 if (EQ (XCDR (o1), o2))
2178 return true; 2213 return true;
2179 } 2214 }
2180 depth++; 2215 depth++;
2181 goto tail_recurse; 2216 goto tail_recurse;
2182 }
2183 2217
2184 case Lisp_Misc: 2218 case Lisp_Misc:
2185 if (XMISCTYPE (o1) != XMISCTYPE (o2)) 2219 if (XMISCTYPE (o1) != XMISCTYPE (o2))
2186 return 0; 2220 return false;
2187 if (OVERLAYP (o1)) 2221 if (OVERLAYP (o1))
2188 { 2222 {
2189 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), 2223 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
2190 depth + 1, props, ht) 2224 equal_kind, depth + 1, ht)
2191 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2), 2225 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
2192 depth + 1, props, ht)) 2226 equal_kind, depth + 1, ht))
2193 return 0; 2227 return false;
2194 o1 = XOVERLAY (o1)->plist; 2228 o1 = XOVERLAY (o1)->plist;
2195 o2 = XOVERLAY (o2)->plist; 2229 o2 = XOVERLAY (o2)->plist;
2196 depth++; 2230 depth++;
@@ -2212,20 +2246,23 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2212 actually checks that the objects have the same type as well as the 2246 actually checks that the objects have the same type as well as the
2213 same size. */ 2247 same size. */
2214 if (ASIZE (o2) != size) 2248 if (ASIZE (o2) != size)
2215 return 0; 2249 return false;
2216 /* Boolvectors are compared much like strings. */ 2250 /* Boolvectors are compared much like strings. */
2217 if (BOOL_VECTOR_P (o1)) 2251 if (BOOL_VECTOR_P (o1))
2218 { 2252 {
2219 EMACS_INT size = bool_vector_size (o1); 2253 EMACS_INT size = bool_vector_size (o1);
2220 if (size != bool_vector_size (o2)) 2254 if (size != bool_vector_size (o2))
2221 return 0; 2255 return false;
2222 if (memcmp (bool_vector_data (o1), bool_vector_data (o2), 2256 if (memcmp (bool_vector_data (o1), bool_vector_data (o2),
2223 bool_vector_bytes (size))) 2257 bool_vector_bytes (size)))
2224 return 0; 2258 return false;
2225 return 1; 2259 return true;
2226 } 2260 }
2227 if (WINDOW_CONFIGURATIONP (o1)) 2261 if (WINDOW_CONFIGURATIONP (o1))
2228 return compare_window_configurations (o1, o2, 0); 2262 {
2263 eassert (equal_kind != EQUAL_NO_QUIT);
2264 return compare_window_configurations (o1, o2, false);
2265 }
2229 2266
2230 /* Aside from them, only true vectors, char-tables, compiled 2267 /* Aside from them, only true vectors, char-tables, compiled
2231 functions, and fonts (font-spec, font-entity, font-object) 2268 functions, and fonts (font-spec, font-entity, font-object)
@@ -2234,7 +2271,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2234 { 2271 {
2235 if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS) 2272 if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
2236 < PVEC_COMPILED) 2273 < PVEC_COMPILED)
2237 return 0; 2274 return false;
2238 size &= PSEUDOVECTOR_SIZE_MASK; 2275 size &= PSEUDOVECTOR_SIZE_MASK;
2239 } 2276 }
2240 for (i = 0; i < size; i++) 2277 for (i = 0; i < size; i++)
@@ -2242,29 +2279,30 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2242 Lisp_Object v1, v2; 2279 Lisp_Object v1, v2;
2243 v1 = AREF (o1, i); 2280 v1 = AREF (o1, i);
2244 v2 = AREF (o2, i); 2281 v2 = AREF (o2, i);
2245 if (!internal_equal (v1, v2, depth + 1, props, ht)) 2282 if (!internal_equal (v1, v2, equal_kind, depth + 1, ht))
2246 return 0; 2283 return false;
2247 } 2284 }
2248 return 1; 2285 return true;
2249 } 2286 }
2250 break; 2287 break;
2251 2288
2252 case Lisp_String: 2289 case Lisp_String:
2253 if (SCHARS (o1) != SCHARS (o2)) 2290 if (SCHARS (o1) != SCHARS (o2))
2254 return 0; 2291 return false;
2255 if (SBYTES (o1) != SBYTES (o2)) 2292 if (SBYTES (o1) != SBYTES (o2))
2256 return 0; 2293 return false;
2257 if (memcmp (SDATA (o1), SDATA (o2), SBYTES (o1))) 2294 if (memcmp (SDATA (o1), SDATA (o2), SBYTES (o1)))
2258 return 0; 2295 return false;
2259 if (props && !compare_string_intervals (o1, o2)) 2296 if (equal_kind == EQUAL_INCLUDING_PROPERTIES
2260 return 0; 2297 && !compare_string_intervals (o1, o2))
2261 return 1; 2298 return false;
2299 return true;
2262 2300
2263 default: 2301 default:
2264 break; 2302 break;
2265 } 2303 }
2266 2304
2267 return 0; 2305 return false;
2268} 2306}
2269 2307
2270 2308