aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2020-01-07 11:23:11 -0800
committerPaul Eggert2020-01-07 11:29:42 -0800
commit724af7671590cd91df37f64df6be73f6dca0144d (patch)
tree075df63dcdc3653ff710ce49a5f238c165d0f0c1 /src
parentf950b078a6f2fd011312e9471998edf6b5fb957e (diff)
downloademacs-724af7671590cd91df37f64df6be73f6dca0144d.tar.gz
emacs-724af7671590cd91df37f64df6be73f6dca0144d.zip
Fix sxhash-equal on bytecodes, markers, etc.
Problem reported by Pip Cet (Bug#38912#14). * doc/lispref/objects.texi (Equality Predicates): Document better when ‘equal’ looks inside objects. * doc/lispref/windows.texi (Window Configurations): Don’t say that ‘equal’ looks inside window configurations. * etc/NEWS: Mention the change. * src/fns.c (internal_equal): Do not look inside window configurations. (sxhash_obj): Hash markers, byte-code function objects, char-tables, and font objects consistently with Fequal. * src/window.c (compare_window_configurations): Now static. Remove last argument. Caller changed. * test/lisp/ffap-tests.el (ffap-other-window--bug-25352): Use compare-window-configurations, not ‘equal’. * test/src/fns-tests.el (test-sxhash-equal): New test.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c52
-rw-r--r--src/lisp.h4
-rw-r--r--src/window.c21
-rw-r--r--src/window.h1
4 files changed, 38 insertions, 40 deletions
diff --git a/src/fns.c b/src/fns.c
index 4a0a8fd96d8..4a463a8feb2 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2434,6 +2434,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2434 same size. */ 2434 same size. */
2435 if (ASIZE (o2) != size) 2435 if (ASIZE (o2) != size)
2436 return false; 2436 return false;
2437
2438 /* Compare bignums, overlays, markers, and boolvectors
2439 specially, by comparing their values. */
2437 if (BIGNUMP (o1)) 2440 if (BIGNUMP (o1))
2438 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; 2441 return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
2439 if (OVERLAYP (o1)) 2442 if (OVERLAYP (o1))
@@ -2454,7 +2457,6 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2454 && (XMARKER (o1)->buffer == 0 2457 && (XMARKER (o1)->buffer == 0
2455 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos)); 2458 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
2456 } 2459 }
2457 /* Boolvectors are compared much like strings. */
2458 if (BOOL_VECTOR_P (o1)) 2460 if (BOOL_VECTOR_P (o1))
2459 { 2461 {
2460 EMACS_INT size = bool_vector_size (o1); 2462 EMACS_INT size = bool_vector_size (o1);
@@ -2465,11 +2467,6 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2465 return false; 2467 return false;
2466 return true; 2468 return true;
2467 } 2469 }
2468 if (WINDOW_CONFIGURATIONP (o1))
2469 {
2470 eassert (equal_kind != EQUAL_NO_QUIT);
2471 return compare_window_configurations (o1, o2, false);
2472 }
2473 2470
2474 /* Aside from them, only true vectors, char-tables, compiled 2471 /* Aside from them, only true vectors, char-tables, compiled
2475 functions, and fonts (font-spec, font-entity, font-object) 2472 functions, and fonts (font-spec, font-entity, font-object)
@@ -4703,22 +4700,35 @@ sxhash_obj (Lisp_Object obj, int depth)
4703 hash = sxhash_string (SSDATA (obj), SBYTES (obj)); 4700 hash = sxhash_string (SSDATA (obj), SBYTES (obj));
4704 break; 4701 break;
4705 4702
4706 /* This can be everything from a vector to an overlay. */
4707 case Lisp_Vectorlike: 4703 case Lisp_Vectorlike:
4708 if (BIGNUMP (obj)) 4704 {
4709 hash = sxhash_bignum (obj); 4705 enum pvec_type pvec_type = PSEUDOVECTOR_TYPE (XVECTOR (obj));
4710 else if (VECTORP (obj) || RECORDP (obj)) 4706 if (! (PVEC_NORMAL_VECTOR < pvec_type && pvec_type < PVEC_COMPILED))
4711 /* According to the CL HyperSpec, two arrays are equal only if 4707 {
4712 they are `eq', except for strings and bit-vectors. In 4708 /* According to the CL HyperSpec, two arrays are equal only if
4713 Emacs, this works differently. We have to compare element 4709 they are 'eq', except for strings and bit-vectors. In
4714 by element. Same for records. */ 4710 Emacs, this works differently. We have to compare element
4715 hash = sxhash_vector (obj, depth); 4711 by element. Same for pseudovectors that internal_equal
4716 else if (BOOL_VECTOR_P (obj)) 4712 examines the Lisp contents of. */
4717 hash = sxhash_bool_vector (obj); 4713 hash = sxhash_vector (obj, depth);
4718 else 4714 break;
4719 /* Others are `equal' if they are `eq', so let's take their 4715 }
4720 address as hash. */ 4716 else if (pvec_type == PVEC_BIGNUM)
4721 hash = XHASH (obj); 4717 hash = sxhash_bignum (obj);
4718 else if (pvec_type == PVEC_MARKER)
4719 {
4720 ptrdiff_t bytepos
4721 = XMARKER (obj)->buffer ? XMARKER (obj)->bytepos : 0;
4722 hash = sxhash_combine ((intptr_t) XMARKER (obj)->buffer, bytepos);
4723 hash = SXHASH_REDUCE (hash);
4724 }
4725 else if (pvec_type == PVEC_BOOL_VECTOR)
4726 hash = sxhash_bool_vector (obj);
4727 else
4728 /* Others are 'equal' if they are 'eq', so take their
4729 address as hash. */
4730 hash = XHASH (obj);
4731 }
4722 break; 4732 break;
4723 4733
4724 case Lisp_Cons: 4734 case Lisp_Cons:
diff --git a/src/lisp.h b/src/lisp.h
index 1a1ae0399be..3681b7b2a7c 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1069,7 +1069,7 @@ DEFINE_GDB_SYMBOL_END (PSEUDOVECTOR_FLAG)
1069 with PVEC_TYPE_MASK to indicate the actual type. */ 1069 with PVEC_TYPE_MASK to indicate the actual type. */
1070enum pvec_type 1070enum pvec_type
1071{ 1071{
1072 PVEC_NORMAL_VECTOR, 1072 PVEC_NORMAL_VECTOR, /* Should be first, for sxhash_obj. */
1073 PVEC_FREE, 1073 PVEC_FREE,
1074 PVEC_BIGNUM, 1074 PVEC_BIGNUM,
1075 PVEC_MARKER, 1075 PVEC_MARKER,
@@ -1094,7 +1094,7 @@ enum pvec_type
1094 PVEC_CONDVAR, 1094 PVEC_CONDVAR,
1095 PVEC_MODULE_FUNCTION, 1095 PVEC_MODULE_FUNCTION,
1096 1096
1097 /* These should be last, check internal_equal to see why. */ 1097 /* These should be last, for internal_equal and sxhash_obj. */
1098 PVEC_COMPILED, 1098 PVEC_COMPILED,
1099 PVEC_CHAR_TABLE, 1099 PVEC_CHAR_TABLE,
1100 PVEC_SUB_CHAR_TABLE, 1100 PVEC_SUB_CHAR_TABLE,
diff --git a/src/window.c b/src/window.c
index ff17cd88f38..8cdad27b664 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7976,19 +7976,17 @@ foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
7976/* Return true if window configurations CONFIGURATION1 and CONFIGURATION2 7976/* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
7977 describe the same state of affairs. This is used by Fequal. 7977 describe the same state of affairs. This is used by Fequal.
7978 7978
7979 IGNORE_POSITIONS means ignore non-matching scroll positions 7979 Ignore non-matching scroll positions and the like.
7980 and the like.
7981 7980
7982 This ignores a couple of things like the dedication status of 7981 This ignores a couple of things like the dedication status of
7983 window, combination_limit and the like. This might have to be 7982 window, combination_limit and the like. This might have to be
7984 fixed. */ 7983 fixed. */
7985 7984
7986bool 7985static bool
7987compare_window_configurations (Lisp_Object configuration1, 7986compare_window_configurations (Lisp_Object configuration1,
7988 Lisp_Object configuration2, 7987 Lisp_Object configuration2)
7989 bool ignore_positions)
7990{ 7988{
7991 register struct save_window_data *d1, *d2; 7989 struct save_window_data *d1, *d2;
7992 struct Lisp_Vector *sws1, *sws2; 7990 struct Lisp_Vector *sws1, *sws2;
7993 ptrdiff_t i; 7991 ptrdiff_t i;
7994 7992
@@ -8006,9 +8004,6 @@ compare_window_configurations (Lisp_Object configuration1,
8006 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines 8004 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
8007 || !EQ (d1->selected_frame, d2->selected_frame) 8005 || !EQ (d1->selected_frame, d2->selected_frame)
8008 || !EQ (d1->f_current_buffer, d2->f_current_buffer) 8006 || !EQ (d1->f_current_buffer, d2->f_current_buffer)
8009 || (!ignore_positions
8010 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
8011 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
8012 || !EQ (d1->focus_frame, d2->focus_frame) 8007 || !EQ (d1->focus_frame, d2->focus_frame)
8013 /* Verify that the two configurations have the same number of windows. */ 8008 /* Verify that the two configurations have the same number of windows. */
8014 || sws1->header.size != sws2->header.size) 8009 || sws1->header.size != sws2->header.size)
@@ -8041,12 +8036,6 @@ compare_window_configurations (Lisp_Object configuration1,
8041 equality. */ 8036 equality. */
8042 || !EQ (sw1->parent, sw2->parent) 8037 || !EQ (sw1->parent, sw2->parent)
8043 || !EQ (sw1->prev, sw2->prev) 8038 || !EQ (sw1->prev, sw2->prev)
8044 || (!ignore_positions
8045 && (!EQ (sw1->hscroll, sw2->hscroll)
8046 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
8047 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
8048 || NILP (Fequal (sw1->start, sw2->start))
8049 || NILP (Fequal (sw1->pointm, sw2->pointm))))
8050 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols) 8039 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
8051 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols) 8040 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
8052 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width) 8041 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
@@ -8071,7 +8060,7 @@ This function ignores details such as the values of point
8071and scrolling positions. */) 8060and scrolling positions. */)
8072 (Lisp_Object x, Lisp_Object y) 8061 (Lisp_Object x, Lisp_Object y)
8073{ 8062{
8074 if (compare_window_configurations (x, y, true)) 8063 if (compare_window_configurations (x, y))
8075 return Qt; 8064 return Qt;
8076 return Qnil; 8065 return Qnil;
8077} 8066}
diff --git a/src/window.h b/src/window.h
index aa8d2c8d1d2..167d1be7abb 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1184,7 +1184,6 @@ extern Lisp_Object window_list (void);
1184extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter); 1184extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter);
1185extern struct window *decode_live_window (Lisp_Object); 1185extern struct window *decode_live_window (Lisp_Object);
1186extern struct window *decode_any_window (Lisp_Object); 1186extern struct window *decode_any_window (Lisp_Object);
1187extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
1188extern void mark_window_cursors_off (struct window *); 1187extern void mark_window_cursors_off (struct window *);
1189extern bool window_wants_mode_line (struct window *); 1188extern bool window_wants_mode_line (struct window *);
1190extern bool window_wants_header_line (struct window *); 1189extern bool window_wants_header_line (struct window *);