aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2024-02-28 20:47:57 +0100
committerAndrea Corallo2024-02-28 20:47:57 +0100
commit1fbe56c32761efdc8d268df80a97a9102d00e109 (patch)
tree8d8e76c8ae43c79ef9d76b0f97c12607567664b9 /src
parent6de60f33ed5cc438e20400aee83e1e2032773811 (diff)
parent05195e129fc933db32c9e08a155a94bfa4d75b54 (diff)
downloademacs-1fbe56c32761efdc8d268df80a97a9102d00e109.tar.gz
emacs-1fbe56c32761efdc8d268df80a97a9102d00e109.zip
Merge remote-tracking branch 'origin/master' into 'feature/type-hierarchy'
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c48
-rw-r--r--src/android.c81
-rw-r--r--src/android.h9
-rw-r--r--src/androidfns.c106
-rw-r--r--src/androidselect.c20
-rw-r--r--src/androidterm.c4
-rw-r--r--src/androidvfs.c32
-rw-r--r--src/buffer.c64
-rw-r--r--src/buffer.h2
-rw-r--r--src/bytecode.c84
-rw-r--r--src/ccl.c7
-rw-r--r--src/comp.c6
-rw-r--r--src/conf_post.h4
-rw-r--r--src/data.c58
-rw-r--r--src/dispextern.h10
-rw-r--r--src/doc.c58
-rw-r--r--src/editfns.c85
-rw-r--r--src/emacs.c4
-rw-r--r--src/eval.c61
-rw-r--r--src/fileio.c10
-rw-r--r--src/fns.c207
-rw-r--r--src/inotify.c10
-rw-r--r--src/keyboard.c26
-rw-r--r--src/lisp.h311
-rw-r--r--src/lread.c498
-rw-r--r--src/macfont.m96
-rw-r--r--src/marker.c2
-rw-r--r--src/minibuf.c110
-rw-r--r--src/pdumper.c68
-rw-r--r--src/pgtkterm.c4
-rw-r--r--src/print.c29
-rw-r--r--src/process.c33
-rw-r--r--src/sfnt.c10
-rw-r--r--src/sfnt.h2
-rw-r--r--src/sfntfont.c6
-rw-r--r--src/term.c21
-rw-r--r--src/textconv.c10
-rw-r--r--src/thread.c39
-rw-r--r--src/thread.h11
-rw-r--r--src/timefns.c12
-rw-r--r--src/treesit.c4
-rw-r--r--src/verbose.mk.in29
-rw-r--r--src/window.c11
-rw-r--r--src/xdisp.c594
-rw-r--r--src/xfaces.c35
45 files changed, 1860 insertions, 1071 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 15bb65cf74f..16257469aa6 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -360,13 +360,13 @@ static struct gcstat
360 object_ct total_intervals, total_free_intervals; 360 object_ct total_intervals, total_free_intervals;
361 object_ct total_buffers; 361 object_ct total_buffers;
362 362
363 /* Size of the ancillary arrays of live hash-table objects. 363 /* Size of the ancillary arrays of live hash-table and obarray objects.
364 The objects themselves are not included (counted as vectors above). */ 364 The objects themselves are not included (counted as vectors above). */
365 byte_ct total_hash_table_bytes; 365 byte_ct total_hash_table_bytes;
366} gcstat; 366} gcstat;
367 367
368/* Total size of ancillary arrays of all allocated hash-table objects, 368/* Total size of ancillary arrays of all allocated hash-table and obarray
369 both dead and alive. This number is always kept up-to-date. */ 369 objects, both dead and alive. This number is always kept up-to-date. */
370static ptrdiff_t hash_table_allocated_bytes = 0; 370static ptrdiff_t hash_table_allocated_bytes = 0;
371 371
372/* Points to memory space allocated as "spare", to be freed if we run 372/* Points to memory space allocated as "spare", to be freed if we run
@@ -3443,7 +3443,7 @@ cleanup_vector (struct Lisp_Vector *vector)
3443 struct Lisp_Hash_Table *h = PSEUDOVEC_STRUCT (vector, Lisp_Hash_Table); 3443 struct Lisp_Hash_Table *h = PSEUDOVEC_STRUCT (vector, Lisp_Hash_Table);
3444 if (h->table_size > 0) 3444 if (h->table_size > 0)
3445 { 3445 {
3446 eassert (h->index_size > 1); 3446 eassert (h->index_bits > 0);
3447 xfree (h->index); 3447 xfree (h->index);
3448 xfree (h->key_and_value); 3448 xfree (h->key_and_value);
3449 xfree (h->next); 3449 xfree (h->next);
@@ -3451,10 +3451,19 @@ cleanup_vector (struct Lisp_Vector *vector)
3451 ptrdiff_t bytes = (h->table_size * (2 * sizeof *h->key_and_value 3451 ptrdiff_t bytes = (h->table_size * (2 * sizeof *h->key_and_value
3452 + sizeof *h->hash 3452 + sizeof *h->hash
3453 + sizeof *h->next) 3453 + sizeof *h->next)
3454 + h->index_size * sizeof *h->index); 3454 + hash_table_index_size (h) * sizeof *h->index);
3455 hash_table_allocated_bytes -= bytes; 3455 hash_table_allocated_bytes -= bytes;
3456 } 3456 }
3457 } 3457 }
3458 break;
3459 case PVEC_OBARRAY:
3460 {
3461 struct Lisp_Obarray *o = PSEUDOVEC_STRUCT (vector, Lisp_Obarray);
3462 xfree (o->buckets);
3463 ptrdiff_t bytes = obarray_size (o) * sizeof *o->buckets;
3464 hash_table_allocated_bytes -= bytes;
3465 }
3466 break;
3458 /* Keep the switch exhaustive. */ 3467 /* Keep the switch exhaustive. */
3459 case PVEC_NORMAL_VECTOR: 3468 case PVEC_NORMAL_VECTOR:
3460 case PVEC_FREE: 3469 case PVEC_FREE:
@@ -3951,7 +3960,7 @@ Its value is void, and its function definition and property list are nil. */)
3951 if (symbol_free_list) 3960 if (symbol_free_list)
3952 { 3961 {
3953 ASAN_UNPOISON_SYMBOL (symbol_free_list); 3962 ASAN_UNPOISON_SYMBOL (symbol_free_list);
3954 XSETSYMBOL (val, symbol_free_list); 3963 val = make_lisp_symbol (symbol_free_list);
3955 symbol_free_list = symbol_free_list->u.s.next; 3964 symbol_free_list = symbol_free_list->u.s.next;
3956 } 3965 }
3957 else 3966 else
@@ -3967,7 +3976,7 @@ Its value is void, and its function definition and property list are nil. */)
3967 } 3976 }
3968 3977
3969 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]); 3978 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
3970 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); 3979 val = make_lisp_symbol (&symbol_block->symbols[symbol_block_index]);
3971 symbol_block_index++; 3980 symbol_block_index++;
3972 } 3981 }
3973 3982
@@ -5632,7 +5641,8 @@ valid_lisp_object_p (Lisp_Object obj)
5632 return 0; 5641 return 0;
5633} 5642}
5634 5643
5635/* Like xmalloc, but makes allocation count toward the total consing. 5644/* Like xmalloc, but makes allocation count toward the total consing
5645 and hash table or obarray usage.
5636 Return NULL for a zero-sized allocation. */ 5646 Return NULL for a zero-sized allocation. */
5637void * 5647void *
5638hash_table_alloc_bytes (ptrdiff_t nbytes) 5648hash_table_alloc_bytes (ptrdiff_t nbytes)
@@ -5959,7 +5969,8 @@ purecopy_hash_table (struct Lisp_Hash_Table *table)
5959 for (ptrdiff_t i = 0; i < nvalues; i++) 5969 for (ptrdiff_t i = 0; i < nvalues; i++)
5960 pure->key_and_value[i] = purecopy (table->key_and_value[i]); 5970 pure->key_and_value[i] = purecopy (table->key_and_value[i]);
5961 5971
5962 ptrdiff_t index_bytes = table->index_size * sizeof *table->index; 5972 ptrdiff_t index_bytes = hash_table_index_size (table)
5973 * sizeof *table->index;
5963 pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index); 5974 pure->index = pure_alloc (index_bytes, -(int)sizeof *table->index);
5964 memcpy (pure->index, table->index, index_bytes); 5975 memcpy (pure->index, table->index, index_bytes);
5965 } 5976 }
@@ -6033,8 +6044,7 @@ purecopy (Lisp_Object obj)
6033 return obj; /* Don't hash cons it. */ 6044 return obj; /* Don't hash cons it. */
6034 } 6045 }
6035 6046
6036 struct Lisp_Hash_Table *h = purecopy_hash_table (table); 6047 obj = make_lisp_hash_table (purecopy_hash_table (table));
6037 XSET_HASH_TABLE (obj, h);
6038 } 6048 }
6039 else if (COMPILEDP (obj) || VECTORP (obj) || RECORDP (obj)) 6049 else if (COMPILEDP (obj) || VECTORP (obj) || RECORDP (obj))
6040 { 6050 {
@@ -7310,6 +7320,14 @@ process_mark_stack (ptrdiff_t base_sp)
7310 break; 7320 break;
7311 } 7321 }
7312 7322
7323 case PVEC_OBARRAY:
7324 {
7325 struct Lisp_Obarray *o = (struct Lisp_Obarray *)ptr;
7326 set_vector_marked (ptr);
7327 mark_stack_push_values (o->buckets, obarray_size (o));
7328 break;
7329 }
7330
7313 case PVEC_CHAR_TABLE: 7331 case PVEC_CHAR_TABLE:
7314 case PVEC_SUB_CHAR_TABLE: 7332 case PVEC_SUB_CHAR_TABLE:
7315 mark_char_table (ptr, (enum pvec_type) pvectype); 7333 mark_char_table (ptr, (enum pvec_type) pvectype);
@@ -7380,12 +7398,8 @@ process_mark_stack (ptrdiff_t base_sp)
7380 mark_stack_push_value (SYMBOL_VAL (ptr)); 7398 mark_stack_push_value (SYMBOL_VAL (ptr));
7381 break; 7399 break;
7382 case SYMBOL_VARALIAS: 7400 case SYMBOL_VARALIAS:
7383 { 7401 mark_stack_push_value (make_lisp_symbol (SYMBOL_ALIAS (ptr)));
7384 Lisp_Object tem; 7402 break;
7385 XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
7386 mark_stack_push_value (tem);
7387 break;
7388 }
7389 case SYMBOL_LOCALIZED: 7403 case SYMBOL_LOCALIZED:
7390 { 7404 {
7391 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); 7405 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
diff --git a/src/android.c b/src/android.c
index 4a74f5b2af4..41481afa475 100644
--- a/src/android.c
+++ b/src/android.c
@@ -40,6 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/stat.h> 42#include <sys/stat.h>
43#include <sys/select.h>
43 44
44/* Old NDK versions lack MIN and MAX. */ 45/* Old NDK versions lack MIN and MAX. */
45#include <minmax.h> 46#include <minmax.h>
@@ -112,6 +113,8 @@ struct android_emacs_window
112 jmethodID define_cursor; 113 jmethodID define_cursor;
113 jmethodID damage_rect; 114 jmethodID damage_rect;
114 jmethodID recreate_activity; 115 jmethodID recreate_activity;
116 jmethodID clear_window;
117 jmethodID clear_area;
115}; 118};
116 119
117struct android_emacs_cursor 120struct android_emacs_cursor
@@ -152,6 +155,13 @@ static char *android_files_dir;
152/* The Java environment being used for the main thread. */ 155/* The Java environment being used for the main thread. */
153JNIEnv *android_java_env; 156JNIEnv *android_java_env;
154 157
158#ifdef THREADS_ENABLED
159
160/* The Java VM new threads attach to. */
161JavaVM *android_jvm;
162
163#endif /* THREADS_ENABLED */
164
155/* The EmacsGC class. */ 165/* The EmacsGC class. */
156static jclass emacs_gc_class; 166static jclass emacs_gc_class;
157 167
@@ -496,6 +506,9 @@ android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg)
496 This should ideally be defined further down. */ 506 This should ideally be defined further down. */
497static sem_t android_query_sem; 507static sem_t android_query_sem;
498 508
509/* ID of the Emacs thread. */
510static pthread_t main_thread_id;
511
499/* Set up the global event queue by initializing the mutex and two 512/* Set up the global event queue by initializing the mutex and two
500 condition variables, and the linked list of events. This must be 513 condition variables, and the linked list of events. This must be
501 called before starting the Emacs thread. Also, initialize the 514 called before starting the Emacs thread. Also, initialize the
@@ -531,6 +544,8 @@ android_init_events (void)
531 event_queue.events.next = &event_queue.events; 544 event_queue.events.next = &event_queue.events;
532 event_queue.events.last = &event_queue.events; 545 event_queue.events.last = &event_queue.events;
533 546
547 main_thread_id = pthread_self ();
548
534#if __ANDROID_API__ >= 16 549#if __ANDROID_API__ >= 16
535 550
536 /* Before starting the select thread, make sure the disposition for 551 /* Before starting the select thread, make sure the disposition for
@@ -579,10 +594,6 @@ android_pending (void)
579 return i; 594 return i;
580} 595}
581 596
582/* Forward declaration. */
583
584static void android_check_query (void);
585
586/* Wait for events to become available synchronously. Return once an 597/* Wait for events to become available synchronously. Return once an
587 event arrives. Also, reply to the UI thread whenever it requires a 598 event arrives. Also, reply to the UI thread whenever it requires a
588 response. */ 599 response. */
@@ -732,6 +743,12 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds,
732 static char byte; 743 static char byte;
733#endif 744#endif
734 745
746#ifdef THREADS_ENABLED
747 if (!pthread_equal (pthread_self (), main_thread_id))
748 return pselect (nfds, readfds, writefds, exceptfds, timeout,
749 NULL);
750#endif /* THREADS_ENABLED */
751
735 /* Since Emacs is reading keyboard input again, signify that queries 752 /* Since Emacs is reading keyboard input again, signify that queries
736 from input methods are no longer ``urgent''. */ 753 from input methods are no longer ``urgent''. */
737 754
@@ -837,9 +854,11 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds,
837 if (nfds_return < 0) 854 if (nfds_return < 0)
838 errno = EINTR; 855 errno = EINTR;
839 856
857#ifndef THREADS_ENABLED
840 /* Now check for and run anything the UI thread wants to run in the 858 /* Now check for and run anything the UI thread wants to run in the
841 main thread. */ 859 main thread. */
842 android_check_query (); 860 android_check_query ();
861#endif /* THREADS_ENABLED */
843 862
844 return nfds_return; 863 return nfds_return;
845} 864}
@@ -1315,12 +1334,17 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
1315 const char *java_string; 1334 const char *java_string;
1316 struct stat statb; 1335 struct stat statb;
1317 1336
1337#ifdef THREADS_ENABLED
1338 /* Save the Java VM. */
1339 if ((*env)->GetJavaVM (env, &android_jvm))
1340 emacs_abort ();
1341#endif /* THREADS_ENABLED */
1342
1318 /* Set the Android API level early, as it is used by 1343 /* Set the Android API level early, as it is used by
1319 `android_vfs_init'. */ 1344 `android_vfs_init'. */
1320 android_api_level = api_level; 1345 android_api_level = api_level;
1321 1346
1322 /* This function should only be called from the main thread. */ 1347 /* This function should only be called from the main thread. */
1323
1324 android_pixel_density_x = pixel_density_x; 1348 android_pixel_density_x = pixel_density_x;
1325 android_pixel_density_y = pixel_density_y; 1349 android_pixel_density_y = pixel_density_y;
1326 android_scaled_pixel_density = scaled_density; 1350 android_scaled_pixel_density = scaled_density;
@@ -1583,16 +1607,13 @@ android_init_emacs_service (void)
1583 FIND_METHOD (draw_point, "drawPoint", 1607 FIND_METHOD (draw_point, "drawPoint",
1584 "(Lorg/gnu/emacs/EmacsDrawable;" 1608 "(Lorg/gnu/emacs/EmacsDrawable;"
1585 "Lorg/gnu/emacs/EmacsGC;II)V"); 1609 "Lorg/gnu/emacs/EmacsGC;II)V");
1586 FIND_METHOD (clear_window, "clearWindow",
1587 "(Lorg/gnu/emacs/EmacsWindow;)V");
1588 FIND_METHOD (clear_area, "clearArea",
1589 "(Lorg/gnu/emacs/EmacsWindow;IIII)V");
1590 FIND_METHOD (ring_bell, "ringBell", "(I)V"); 1610 FIND_METHOD (ring_bell, "ringBell", "(I)V");
1591 FIND_METHOD (query_tree, "queryTree", 1611 FIND_METHOD (query_tree, "queryTree",
1592 "(Lorg/gnu/emacs/EmacsWindow;)[S"); 1612 "(Lorg/gnu/emacs/EmacsWindow;)[S");
1593 FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I"); 1613 FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I");
1594 FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I"); 1614 FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I");
1595 FIND_METHOD (detect_mouse, "detectMouse", "()Z"); 1615 FIND_METHOD (detect_mouse, "detectMouse", "()Z");
1616 FIND_METHOD (detect_keyboard, "detectKeyboard", "()Z");
1596 FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;"); 1617 FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;");
1597 FIND_METHOD (browse_url, "browseUrl", "(Ljava/lang/String;Z)" 1618 FIND_METHOD (browse_url, "browseUrl", "(Ljava/lang/String;Z)"
1598 "Ljava/lang/String;"); 1619 "Ljava/lang/String;");
@@ -1809,6 +1830,8 @@ android_init_emacs_window (void)
1809 android_damage_window. */ 1830 android_damage_window. */
1810 FIND_METHOD (damage_rect, "damageRect", "(IIII)V"); 1831 FIND_METHOD (damage_rect, "damageRect", "(IIII)V");
1811 FIND_METHOD (recreate_activity, "recreateActivity", "()V"); 1832 FIND_METHOD (recreate_activity, "recreateActivity", "()V");
1833 FIND_METHOD (clear_window, "clearWindow", "()V");
1834 FIND_METHOD (clear_area, "clearArea", "(IIII)V");
1812#undef FIND_METHOD 1835#undef FIND_METHOD
1813} 1836}
1814 1837
@@ -2496,6 +2519,8 @@ JNIEXPORT jboolean JNICALL
2496NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, 2519NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env,
2497 jobject object) 2520 jobject object)
2498{ 2521{
2522 JNI_STACK_ALIGNMENT_PROLOGUE;
2523
2499 /* Yes, android_pass_multimedia_buttons_to_system is being 2524 /* Yes, android_pass_multimedia_buttons_to_system is being
2500 read from the UI thread. */ 2525 read from the UI thread. */
2501 return !android_pass_multimedia_buttons_to_system; 2526 return !android_pass_multimedia_buttons_to_system;
@@ -2504,6 +2529,8 @@ NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env,
2504JNIEXPORT jboolean JNICALL 2529JNIEXPORT jboolean JNICALL
2505NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object) 2530NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object)
2506{ 2531{
2532 JNI_STACK_ALIGNMENT_PROLOGUE;
2533
2507 return !android_intercept_control_space; 2534 return !android_intercept_control_space;
2508} 2535}
2509 2536
@@ -2607,6 +2634,8 @@ JNIEXPORT void JNICALL
2607NATIVE_NAME (notifyPixelsChanged) (JNIEnv *env, jobject object, 2634NATIVE_NAME (notifyPixelsChanged) (JNIEnv *env, jobject object,
2608 jobject bitmap) 2635 jobject bitmap)
2609{ 2636{
2637 JNI_STACK_ALIGNMENT_PROLOGUE;
2638
2610 void *data; 2639 void *data;
2611 2640
2612 /* Lock and unlock the bitmap. This calls 2641 /* Lock and unlock the bitmap. This calls
@@ -2660,6 +2689,8 @@ NATIVE_NAME (answerQuerySpin) (JNIEnv *env, jobject object)
2660JNIEXPORT void JNICALL 2689JNIEXPORT void JNICALL
2661NATIVE_NAME (setupSystemThread) (void) 2690NATIVE_NAME (setupSystemThread) (void)
2662{ 2691{
2692 JNI_STACK_ALIGNMENT_PROLOGUE;
2693
2663 sigset_t sigset; 2694 sigset_t sigset;
2664 2695
2665 /* Block everything except for SIGSEGV and SIGBUS; those two are 2696 /* Block everything except for SIGSEGV and SIGBUS; those two are
@@ -3408,10 +3439,9 @@ android_clear_window (android_window handle)
3408 window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); 3439 window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
3409 3440
3410 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, 3441 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
3411 emacs_service, 3442 window,
3412 service_class.class, 3443 window_class.class,
3413 service_class.clear_window, 3444 window_class.clear_window);
3414 window);
3415 android_exception_check (); 3445 android_exception_check ();
3416} 3446}
3417 3447
@@ -4722,10 +4752,10 @@ android_clear_area (android_window handle, int x, int y,
4722 window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); 4752 window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
4723 4753
4724 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, 4754 (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
4725 emacs_service, 4755 window,
4726 service_class.class, 4756 window_class.class,
4727 service_class.clear_area, 4757 window_class.clear_area,
4728 window, (jint) x, (jint) y, 4758 (jint) x, (jint) y,
4729 (jint) width, (jint) height); 4759 (jint) width, (jint) height);
4730} 4760}
4731 4761
@@ -5626,6 +5656,21 @@ android_detect_mouse (void)
5626 return rc; 5656 return rc;
5627} 5657}
5628 5658
5659bool
5660android_detect_keyboard (void)
5661{
5662 bool rc;
5663 jmethodID method;
5664
5665 method = service_class.detect_keyboard;
5666 rc = (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env,
5667 emacs_service,
5668 service_class.class,
5669 method);
5670 android_exception_check ();
5671 return rc;
5672}
5673
5629void 5674void
5630android_set_dont_focus_on_map (android_window handle, 5675android_set_dont_focus_on_map (android_window handle,
5631 bool no_focus_on_map) 5676 bool no_focus_on_map)
@@ -6701,7 +6746,7 @@ static void *android_query_context;
6701/* Run any function that the UI thread has asked to run, and then 6746/* Run any function that the UI thread has asked to run, and then
6702 signal its completion. */ 6747 signal its completion. */
6703 6748
6704static void 6749void
6705android_check_query (void) 6750android_check_query (void)
6706{ 6751{
6707 void (*proc) (void *); 6752 void (*proc) (void *);
diff --git a/src/android.h b/src/android.h
index 2f5f32037c5..e1834cebf68 100644
--- a/src/android.h
+++ b/src/android.h
@@ -24,6 +24,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24 a table of function pointers. */ 24 a table of function pointers. */
25 25
26#ifndef _ANDROID_H_ 26#ifndef _ANDROID_H_
27#define _ANDROID_H_
28
27#ifndef ANDROID_STUBIFY 29#ifndef ANDROID_STUBIFY
28#include <jni.h> 30#include <jni.h>
29#include <pwd.h> 31#include <pwd.h>
@@ -103,6 +105,7 @@ extern int android_get_screen_height (void);
103extern int android_get_mm_width (void); 105extern int android_get_mm_width (void);
104extern int android_get_mm_height (void); 106extern int android_get_mm_height (void);
105extern bool android_detect_mouse (void); 107extern bool android_detect_mouse (void);
108extern bool android_detect_keyboard (void);
106 109
107extern void android_set_dont_focus_on_map (android_window, bool); 110extern void android_set_dont_focus_on_map (android_window, bool);
108extern void android_set_dont_accept_focus (android_window, bool); 111extern void android_set_dont_accept_focus (android_window, bool);
@@ -225,6 +228,7 @@ extern void android_display_toast (const char *);
225 228
226/* Event loop functions. */ 229/* Event loop functions. */
227 230
231extern void android_check_query (void);
228extern void android_check_query_urgent (void); 232extern void android_check_query_urgent (void);
229extern int android_run_in_emacs_thread (void (*) (void *), void *); 233extern int android_run_in_emacs_thread (void (*) (void *), void *);
230extern void android_write_event (union android_event *); 234extern void android_write_event (union android_event *);
@@ -265,6 +269,7 @@ struct android_emacs_service
265 jmethodID get_screen_width; 269 jmethodID get_screen_width;
266 jmethodID get_screen_height; 270 jmethodID get_screen_height;
267 jmethodID detect_mouse; 271 jmethodID detect_mouse;
272 jmethodID detect_keyboard;
268 jmethodID name_keysym; 273 jmethodID name_keysym;
269 jmethodID browse_url; 274 jmethodID browse_url;
270 jmethodID restart_emacs; 275 jmethodID restart_emacs;
@@ -297,6 +302,10 @@ struct android_emacs_service
297 302
298extern JNIEnv *android_java_env; 303extern JNIEnv *android_java_env;
299 304
305#ifdef THREADS_ENABLED
306extern JavaVM *android_jvm;
307#endif /* THREADS_ENABLED */
308
300/* The EmacsService object. */ 309/* The EmacsService object. */
301extern jobject emacs_service; 310extern jobject emacs_service;
302 311
diff --git a/src/androidfns.c b/src/androidfns.c
index eaecb78338b..0675a0a3c98 100644
--- a/src/androidfns.c
+++ b/src/androidfns.c
@@ -2287,6 +2287,57 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2287 2287
2288 goto start_timer; 2288 goto start_timer;
2289 } 2289 }
2290 else if (tooltip_reuse_hidden_frame && BASE_EQ (frame, tip_last_frame))
2291 {
2292 bool delete = false;
2293 Lisp_Object tail, elt, parm, last;
2294
2295 /* Check if every parameter in PARMS has the same value in
2296 tip_last_parms. This may destruct tip_last_parms which,
2297 however, will be recreated below. */
2298 for (tail = parms; CONSP (tail); tail = XCDR (tail))
2299 {
2300 elt = XCAR (tail);
2301 parm = CAR (elt);
2302 /* The left, top, right and bottom parameters are handled
2303 by compute_tip_xy so they can be ignored here. */
2304 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
2305 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
2306 {
2307 last = Fassq (parm, tip_last_parms);
2308 if (NILP (Fequal (CDR (elt), CDR (last))))
2309 {
2310 /* We lost, delete the old tooltip. */
2311 delete = true;
2312 break;
2313 }
2314 else
2315 tip_last_parms
2316 = call2 (Qassq_delete_all, parm, tip_last_parms);
2317 }
2318 else
2319 tip_last_parms
2320 = call2 (Qassq_delete_all, parm, tip_last_parms);
2321 }
2322
2323 /* Now check if every parameter in what is left of
2324 tip_last_parms with a non-nil value has an association in
2325 PARMS. */
2326 for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
2327 {
2328 elt = XCAR (tail);
2329 parm = CAR (elt);
2330 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
2331 && !EQ (parm, Qbottom) && !NILP (CDR (elt)))
2332 {
2333 /* We lost, delete the old tooltip. */
2334 delete = true;
2335 break;
2336 }
2337 }
2338
2339 android_hide_tip (delete);
2340 }
2290 else 2341 else
2291 android_hide_tip (true); 2342 android_hide_tip (true);
2292 } 2343 }
@@ -2453,7 +2504,7 @@ DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2453#endif /* 0 */ 2504#endif /* 0 */
2454 return Qnil; 2505 return Qnil;
2455#else /* !ANDROID_STUBIFY */ 2506#else /* !ANDROID_STUBIFY */
2456 return android_hide_tip (true); 2507 return android_hide_tip (!tooltip_reuse_hidden_frame);
2457#endif /* ANDROID_STUBIFY */ 2508#endif /* ANDROID_STUBIFY */
2458} 2509}
2459 2510
@@ -2476,6 +2527,25 @@ there is no mouse. */)
2476#endif 2527#endif
2477} 2528}
2478 2529
2530DEFUN ("android-detect-keyboard", Fandroid_detect_keyboard,
2531 Sandroid_detect_keyboard, 0, 0, 0,
2532 doc: /* Return whether a keyboard is connected.
2533Return non-nil if a key is connected to this computer, or nil
2534if there is no keyboard. */)
2535 (void)
2536{
2537#ifndef ANDROID_STUBIFY
2538 /* If no display connection is present, just return nil. */
2539
2540 if (!android_init_gui)
2541 return Qnil;
2542
2543 return android_detect_keyboard () ? Qt : Qnil;
2544#else /* ANDROID_STUBIFY */
2545 return Qt;
2546#endif /* ANDROID_STUBIFY */
2547}
2548
2479DEFUN ("android-toggle-on-screen-keyboard", 2549DEFUN ("android-toggle-on-screen-keyboard",
2480 Fandroid_toggle_on_screen_keyboard, 2550 Fandroid_toggle_on_screen_keyboard,
2481 Sandroid_toggle_on_screen_keyboard, 2, 2, 0, 2551 Sandroid_toggle_on_screen_keyboard, 2, 2, 0,
@@ -3197,6 +3267,10 @@ syms_of_androidfns_for_pdumper (void)
3197 jstring string; 3267 jstring string;
3198 Lisp_Object language, country, script, variant; 3268 Lisp_Object language, country, script, variant;
3199 const char *data; 3269 const char *data;
3270 FILE *fd;
3271 char *line;
3272 size_t size;
3273 long pid;
3200 3274
3201 /* Find the Locale class. */ 3275 /* Find the Locale class. */
3202 3276
@@ -3367,6 +3441,35 @@ syms_of_androidfns_for_pdumper (void)
3367 3441
3368 /* Set Vandroid_os_language. */ 3442 /* Set Vandroid_os_language. */
3369 Vandroid_os_language = list4 (language, country, script, variant); 3443 Vandroid_os_language = list4 (language, country, script, variant);
3444
3445 /* Detect whether Emacs is running under libloader.so or another
3446 process tracing mechanism, and disable `android_use_exec_loader' if
3447 so, leaving subprocesses started by Emacs to the care of that
3448 loader instance. */
3449
3450 if (android_get_current_api_level () >= 29) /* Q */
3451 {
3452 fd = fopen ("/proc/self/status", "r");
3453 if (!fd)
3454 return;
3455
3456 line = NULL;
3457 while (getline (&line, &size, fd) != -1)
3458 {
3459 if (strncmp (line, "TracerPid:", sizeof "TracerPid:" - 1))
3460 continue;
3461
3462 pid = atol (line + sizeof "TracerPid:" - 1);
3463
3464 if (pid)
3465 android_use_exec_loader = false;
3466
3467 break;
3468 }
3469
3470 free (line);
3471 fclose (fd);
3472 }
3370} 3473}
3371 3474
3372#endif /* ANDROID_STUBIFY */ 3475#endif /* ANDROID_STUBIFY */
@@ -3560,6 +3663,7 @@ language to be US English if LANGUAGE is empty. */);
3560 defsubr (&Sx_show_tip); 3663 defsubr (&Sx_show_tip);
3561 defsubr (&Sx_hide_tip); 3664 defsubr (&Sx_hide_tip);
3562 defsubr (&Sandroid_detect_mouse); 3665 defsubr (&Sandroid_detect_mouse);
3666 defsubr (&Sandroid_detect_keyboard);
3563 defsubr (&Sandroid_toggle_on_screen_keyboard); 3667 defsubr (&Sandroid_toggle_on_screen_keyboard);
3564 defsubr (&Sx_server_vendor); 3668 defsubr (&Sx_server_vendor);
3565 defsubr (&Sx_server_version); 3669 defsubr (&Sx_server_version);
diff --git a/src/androidselect.c b/src/androidselect.c
index 5b23c559d2c..61f1c6045db 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -237,15 +237,21 @@ DEFUN ("android-clipboard-exists-p", Fandroid_clipboard_exists_p,
237 return rc ? Qt : Qnil; 237 return rc ? Qt : Qnil;
238} 238}
239 239
240DEFUN ("android-browse-url", Fandroid_browse_url, 240DEFUN ("android-browse-url-internal", Fandroid_browse_url_internal,
241 Sandroid_browse_url, 1, 2, 0, 241 Sandroid_browse_url_internal, 1, 2, 0,
242 doc: /* Open URL in an external application. URL should be a 242 doc: /* Open URL in an external application.
243URL-encoded URL with a scheme specified unless SEND is non-nil. 243
244Signal an error upon failure. 244URL should be a URL-encoded URL with a scheme specified unless SEND is
245non-nil. Signal an error upon failure.
245 246
246If SEND is nil, start a program that is able to display the URL, such 247If SEND is nil, start a program that is able to display the URL, such
247as a web browser. Otherwise, try to share URL using programs such as 248as a web browser. Otherwise, try to share URL using programs such as
248email clients. */) 249email clients.
250
251If URL is a file URI, convert it into a `content' address accessible to
252other programs. Files inside the /content or /assets directories cannot
253be opened through such addresses, which this function does not provide
254for. Use `android-browse-url' instead. */)
249 (Lisp_Object url, Lisp_Object send) 255 (Lisp_Object url, Lisp_Object send)
250{ 256{
251 Lisp_Object value; 257 Lisp_Object value;
@@ -803,7 +809,7 @@ syms_of_androidselect (void)
803 defsubr (&Sandroid_set_clipboard); 809 defsubr (&Sandroid_set_clipboard);
804 defsubr (&Sandroid_get_clipboard); 810 defsubr (&Sandroid_get_clipboard);
805 defsubr (&Sandroid_clipboard_exists_p); 811 defsubr (&Sandroid_clipboard_exists_p);
806 defsubr (&Sandroid_browse_url); 812 defsubr (&Sandroid_browse_url_internal);
807 defsubr (&Sandroid_get_clipboard_targets); 813 defsubr (&Sandroid_get_clipboard_targets);
808 defsubr (&Sandroid_get_clipboard_data); 814 defsubr (&Sandroid_get_clipboard_data);
809 815
diff --git a/src/androidterm.c b/src/androidterm.c
index d4612bb20fa..2bd2b45743d 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -495,8 +495,8 @@ android_note_mouse_movement (struct frame *frame,
495 /* Has the mouse moved off the glyph it was on at the last sighting? */ 495 /* Has the mouse moved off the glyph it was on at the last sighting? */
496 r = &dpyinfo->last_mouse_glyph; 496 r = &dpyinfo->last_mouse_glyph;
497 if (frame != dpyinfo->last_mouse_glyph_frame 497 if (frame != dpyinfo->last_mouse_glyph_frame
498 || event->x < r->x || event->x >= r->x + r->width 498 || event->x < r->x || event->x >= r->x + (int) r->width
499 || event->y < r->y || event->y >= r->y + r->height) 499 || event->y < r->y || event->y >= r->y + (int) r->height)
500 { 500 {
501 frame->mouse_moved = true; 501 frame->mouse_moved = true;
502 note_mouse_highlight (frame, event->x, event->y); 502 note_mouse_highlight (frame, event->x, event->y);
diff --git a/src/androidvfs.c b/src/androidvfs.c
index 78f6b6da6a8..d618e351204 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -1018,8 +1018,8 @@ android_extract_long (char *pointer)
1018static const char * 1018static const char *
1019android_scan_directory_tree (char *file, size_t *limit_return) 1019android_scan_directory_tree (char *file, size_t *limit_return)
1020{ 1020{
1021 char *token, *saveptr, *copy, *copy1, *start, *max, *limit; 1021 char *token, *saveptr, *copy, *start, *max, *limit;
1022 size_t token_length, ntokens, i; 1022 size_t token_length, ntokens, i, len;
1023 char *tokens[10]; 1023 char *tokens[10];
1024 1024
1025 USE_SAFE_ALLOCA; 1025 USE_SAFE_ALLOCA;
@@ -1031,11 +1031,14 @@ android_scan_directory_tree (char *file, size_t *limit_return)
1031 limit = (char *) directory_tree + directory_tree_size; 1031 limit = (char *) directory_tree + directory_tree_size;
1032 1032
1033 /* Now, split `file' into tokens, with the delimiter being the file 1033 /* Now, split `file' into tokens, with the delimiter being the file
1034 name separator. Look for the file and seek past it. */ 1034 name separator. Look for the file and seek past it. Create a copy
1035 of FILE for the enjoyment of `strtok_r'. */
1035 1036
1036 ntokens = 0; 1037 ntokens = 0;
1037 saveptr = NULL; 1038 saveptr = NULL;
1038 copy = copy1 = xstrdup (file); 1039 len = strlen (file) + 1;
1040 copy = SAFE_ALLOCA (len);
1041 memcpy (copy, file, len);
1039 memset (tokens, 0, sizeof tokens); 1042 memset (tokens, 0, sizeof tokens);
1040 1043
1041 while ((token = strtok_r (copy, "/", &saveptr))) 1044 while ((token = strtok_r (copy, "/", &saveptr)))
@@ -1044,19 +1047,14 @@ android_scan_directory_tree (char *file, size_t *limit_return)
1044 1047
1045 /* Make sure ntokens is within bounds. */ 1048 /* Make sure ntokens is within bounds. */
1046 if (ntokens == ARRAYELTS (tokens)) 1049 if (ntokens == ARRAYELTS (tokens))
1047 { 1050 goto fail;
1048 xfree (copy1);
1049 goto fail;
1050 }
1051 1051
1052 tokens[ntokens] = SAFE_ALLOCA (strlen (token) + 1); 1052 len = strlen (token) + 1;
1053 memcpy (tokens[ntokens], token, strlen (token) + 1); 1053 tokens[ntokens] = SAFE_ALLOCA (len);
1054 memcpy (tokens[ntokens], token, len);
1054 ntokens++; 1055 ntokens++;
1055 } 1056 }
1056 1057
1057 /* Free the copy created for strtok_r. */
1058 xfree (copy1);
1059
1060 /* If there are no tokens, just return the start of the directory 1058 /* If there are no tokens, just return the start of the directory
1061 tree. */ 1059 tree. */
1062 1060
@@ -6319,6 +6317,8 @@ static sem_t saf_completion_sem;
6319JNIEXPORT jint JNICALL 6317JNIEXPORT jint JNICALL
6320NATIVE_NAME (safSyncAndReadInput) (JNIEnv *env, jobject object) 6318NATIVE_NAME (safSyncAndReadInput) (JNIEnv *env, jobject object)
6321{ 6319{
6320 JNI_STACK_ALIGNMENT_PROLOGUE;
6321
6322 while (sem_wait (&saf_completion_sem) < 0) 6322 while (sem_wait (&saf_completion_sem) < 0)
6323 { 6323 {
6324 if (input_blocked_p ()) 6324 if (input_blocked_p ())
@@ -6340,6 +6340,8 @@ NATIVE_NAME (safSyncAndReadInput) (JNIEnv *env, jobject object)
6340JNIEXPORT void JNICALL 6340JNIEXPORT void JNICALL
6341NATIVE_NAME (safSync) (JNIEnv *env, jobject object) 6341NATIVE_NAME (safSync) (JNIEnv *env, jobject object)
6342{ 6342{
6343 JNI_STACK_ALIGNMENT_PROLOGUE;
6344
6343 while (sem_wait (&saf_completion_sem) < 0) 6345 while (sem_wait (&saf_completion_sem) < 0)
6344 process_pending_signals (); 6346 process_pending_signals ();
6345} 6347}
@@ -6347,12 +6349,16 @@ NATIVE_NAME (safSync) (JNIEnv *env, jobject object)
6347JNIEXPORT void JNICALL 6349JNIEXPORT void JNICALL
6348NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject object) 6350NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject object)
6349{ 6351{
6352 JNI_STACK_ALIGNMENT_PROLOGUE;
6353
6350 sem_post (&saf_completion_sem); 6354 sem_post (&saf_completion_sem);
6351} 6355}
6352 6356
6353JNIEXPORT jboolean JNICALL 6357JNIEXPORT jboolean JNICALL
6354NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd) 6358NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd)
6355{ 6359{
6360 JNI_STACK_ALIGNMENT_PROLOGUE;
6361
6356 if (ftruncate (fd, 0) < 0) 6362 if (ftruncate (fd, 0) < 0)
6357 return false; 6363 return false;
6358 6364
diff --git a/src/buffer.c b/src/buffer.c
index 352aca8ddfd..e235ff8f9f8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1334,7 +1334,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
1334 case SYMBOL_LOCALIZED: 1334 case SYMBOL_LOCALIZED:
1335 { /* Look in local_var_alist. */ 1335 { /* Look in local_var_alist. */
1336 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 1336 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
1337 XSETSYMBOL (variable, sym); /* Update In case of aliasing. */ 1337 variable = make_lisp_symbol (sym); /* Update In case of aliasing. */
1338 result = assq_no_quit (variable, BVAR (buf, local_var_alist)); 1338 result = assq_no_quit (variable, BVAR (buf, local_var_alist));
1339 if (!NILP (result)) 1339 if (!NILP (result))
1340 { 1340 {
@@ -3002,7 +3002,7 @@ the normal hook `change-major-mode-hook'. */)
3002 But still return the total number of overlays. 3002 But still return the total number of overlays.
3003*/ 3003*/
3004 3004
3005ptrdiff_t 3005static ptrdiff_t
3006overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend, 3006overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
3007 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr, 3007 Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
3008 bool empty, bool trailing, 3008 bool empty, bool trailing,
@@ -3125,56 +3125,38 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
3125{ 3125{
3126 ptrdiff_t start = OVERLAY_START (overlay); 3126 ptrdiff_t start = OVERLAY_START (overlay);
3127 ptrdiff_t end = OVERLAY_END (overlay); 3127 ptrdiff_t end = OVERLAY_END (overlay);
3128 ptrdiff_t n, i, size; 3128 Lisp_Object tem;
3129 Lisp_Object *v, tem; 3129 struct itree_node *node;
3130 Lisp_Object vbuf[10];
3131 USE_SAFE_ALLOCA;
3132 3130
3133 size = ARRAYELTS (vbuf); 3131 ITREE_FOREACH (node, current_buffer->overlays,
3134 v = vbuf; 3132 start, min (end, ZV) + 1,
3135 n = overlays_in (start, end, 0, &v, &size, true, false, NULL); 3133 ASCENDING)
3136 if (n > size)
3137 { 3134 {
3138 SAFE_NALLOCA (v, 1, n); 3135 if (node->begin < end && node->end > start
3139 overlays_in (start, end, 0, &v, &n, true, false, NULL); 3136 && node->begin < node->end
3137 && !EQ (node->data, overlay)
3138 && (tem = Foverlay_get (overlay, Qmouse_face),
3139 !NILP (tem)))
3140 return true;
3140 } 3141 }
3141 3142 return false;
3142 for (i = 0; i < n; ++i)
3143 if (!EQ (v[i], overlay)
3144 && (tem = Foverlay_get (overlay, Qmouse_face),
3145 !NILP (tem)))
3146 break;
3147
3148 SAFE_FREE ();
3149 return i < n;
3150} 3143}
3151 3144
3152/* Return the value of the 'display-line-numbers-disable' property at 3145/* Return the value of the 'display-line-numbers-disable' property at
3153 EOB, if there's an overlay at ZV with a non-nil value of that property. */ 3146 EOB, if there's an overlay at ZV with a non-nil value of that property. */
3154Lisp_Object 3147bool
3155disable_line_numbers_overlay_at_eob (void) 3148disable_line_numbers_overlay_at_eob (void)
3156{ 3149{
3157 ptrdiff_t n, i, size; 3150 Lisp_Object tem = Qnil;
3158 Lisp_Object *v, tem = Qnil; 3151 struct itree_node *node;
3159 Lisp_Object vbuf[10];
3160 USE_SAFE_ALLOCA;
3161 3152
3162 size = ARRAYELTS (vbuf); 3153 ITREE_FOREACH (node, current_buffer->overlays, ZV, ZV, ASCENDING)
3163 v = vbuf;
3164 n = overlays_in (ZV, ZV, 0, &v, &size, false, false, NULL);
3165 if (n > size)
3166 { 3154 {
3167 SAFE_NALLOCA (v, 1, n); 3155 if ((tem = Foverlay_get (node->data, Qdisplay_line_numbers_disable),
3168 overlays_in (ZV, ZV, 0, &v, &n, false, false, NULL); 3156 !NILP (tem)))
3157 return true;
3169 } 3158 }
3170 3159 return false;
3171 for (i = 0; i < n; ++i)
3172 if ((tem = Foverlay_get (v[i], Qdisplay_line_numbers_disable),
3173 !NILP (tem)))
3174 break;
3175
3176 SAFE_FREE ();
3177 return tem;
3178} 3160}
3179 3161
3180 3162
@@ -4989,7 +4971,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
4989 sym->u.s.declared_special = true; 4971 sym->u.s.declared_special = true;
4990 sym->u.s.redirect = SYMBOL_FORWARDED; 4972 sym->u.s.redirect = SYMBOL_FORWARDED;
4991 SET_SYMBOL_FWD (sym, bo_fwd); 4973 SET_SYMBOL_FWD (sym, bo_fwd);
4992 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym); 4974 PER_BUFFER_SYMBOL (offset) = make_lisp_symbol (sym);
4993 4975
4994 if (PER_BUFFER_IDX (offset) == 0) 4976 if (PER_BUFFER_IDX (offset) == 0)
4995 /* Did a DEFVAR_PER_BUFFER without initializing the corresponding 4977 /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
diff --git a/src/buffer.h b/src/buffer.h
index 9e0982f5da7..87ba2802b39 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1174,8 +1174,6 @@ extern void delete_all_overlays (struct buffer *);
1174extern void reset_buffer (struct buffer *); 1174extern void reset_buffer (struct buffer *);
1175extern void compact_buffer (struct buffer *); 1175extern void compact_buffer (struct buffer *);
1176extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); 1176extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *);
1177extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **,
1178 ptrdiff_t *, bool, bool, ptrdiff_t *);
1179extern ptrdiff_t previous_overlay_change (ptrdiff_t); 1177extern ptrdiff_t previous_overlay_change (ptrdiff_t);
1180extern ptrdiff_t next_overlay_change (ptrdiff_t); 1178extern ptrdiff_t next_overlay_change (ptrdiff_t);
1181extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); 1179extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *);
diff --git a/src/bytecode.c b/src/bytecode.c
index ed6e2b34e77..8d7240b9966 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -625,9 +625,10 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
625 varref: 625 varref:
626 { 626 {
627 Lisp_Object v1 = vectorp[op], v2; 627 Lisp_Object v1 = vectorp[op], v2;
628 if (!SYMBOLP (v1) 628 if (!BARE_SYMBOL_P (v1)
629 || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL 629 || XBARE_SYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL
630 || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound))) 630 || (v2 = XBARE_SYMBOL (v1)->u.s.val.value,
631 BASE_EQ (v2, Qunbound)))
631 v2 = Fsymbol_value (v1); 632 v2 = Fsymbol_value (v1);
632 PUSH (v2); 633 PUSH (v2);
633 NEXT; 634 NEXT;
@@ -699,11 +700,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
699 Lisp_Object val = POP; 700 Lisp_Object val = POP;
700 701
701 /* Inline the most common case. */ 702 /* Inline the most common case. */
702 if (SYMBOLP (sym) 703 if (BARE_SYMBOL_P (sym)
703 && !BASE_EQ (val, Qunbound) 704 && !BASE_EQ (val, Qunbound)
704 && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL 705 && XBARE_SYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL
705 && !SYMBOL_TRAPPED_WRITE_P (sym)) 706 && !XBARE_SYMBOL (sym)->u.s.trapped_write)
706 SET_SYMBOL_VAL (XSYMBOL (sym), val); 707 SET_SYMBOL_VAL (XBARE_SYMBOL (sym), val);
707 else 708 else
708 set_internal (sym, val, Qnil, SET_INTERNAL_SET); 709 set_internal (sym, val, Qnil, SET_INTERNAL_SET);
709 } 710 }
@@ -790,24 +791,22 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
790 do_debug_on_call (Qlambda, count1); 791 do_debug_on_call (Qlambda, count1);
791 792
792 Lisp_Object original_fun = call_fun; 793 Lisp_Object original_fun = call_fun;
793 if (SYMBOLP (call_fun)) 794 /* Calls to symbols-with-pos don't need to be on the fast path. */
794 call_fun = XSYMBOL (call_fun)->u.s.function; 795 if (BARE_SYMBOL_P (call_fun))
795 Lisp_Object template; 796 call_fun = XBARE_SYMBOL (call_fun)->u.s.function;
796 Lisp_Object bytecode; 797 if (COMPILEDP (call_fun))
797 if (COMPILEDP (call_fun)
798 /* Lexical binding only. */
799 && (template = AREF (call_fun, COMPILED_ARGLIST),
800 FIXNUMP (template))
801 /* No autoloads. */
802 && (bytecode = AREF (call_fun, COMPILED_BYTECODE),
803 !CONSP (bytecode)))
804 { 798 {
805 fun = call_fun; 799 Lisp_Object template = AREF (call_fun, COMPILED_ARGLIST);
806 bytestr = bytecode; 800 if (FIXNUMP (template))
807 args_template = XFIXNUM (template); 801 {
808 nargs = call_nargs; 802 /* Fast path for lexbound functions. */
809 args = call_args; 803 fun = call_fun;
810 goto setup_frame; 804 bytestr = AREF (call_fun, COMPILED_BYTECODE),
805 args_template = XFIXNUM (template);
806 nargs = call_nargs;
807 args = call_args;
808 goto setup_frame;
809 }
811 } 810 }
812 811
813 Lisp_Object val; 812 Lisp_Object val;
@@ -1738,28 +1737,29 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
1738 if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table)) 1737 if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table))
1739 emacs_abort (); 1738 emacs_abort ();
1740 Lisp_Object v1 = POP; 1739 Lisp_Object v1 = POP;
1741 ptrdiff_t i;
1742 struct Lisp_Hash_Table *h = XHASH_TABLE (jmp_table); 1740 struct Lisp_Hash_Table *h = XHASH_TABLE (jmp_table);
1743 1741 /* Do a linear search if there are few cases and the test is `eq'.
1744 /* h->count is a faster approximation for HASH_TABLE_SIZE (h) 1742 (The table is assumed to be sized exactly; all entries are
1745 here. */ 1743 consecutive at the beginning.)
1746 if (h->count <= 5 && !h->test->cmpfn) 1744 FIXME: 5 is arbitrarily chosen. */
1747 { /* Do a linear search if there are not many cases 1745 if (h->count <= 5 && !h->test->cmpfn && !symbols_with_pos_enabled)
1748 FIXME: 5 is arbitrarily chosen. */ 1746 {
1749 for (i = h->count; 0 <= --i; ) 1747 eassume (h->count >= 2);
1750 if (EQ (v1, HASH_KEY (h, i))) 1748 for (ptrdiff_t i = h->count - 1; i >= 0; i--)
1751 break; 1749 if (BASE_EQ (v1, HASH_KEY (h, i)))
1750 {
1751 op = XFIXNUM (HASH_VALUE (h, i));
1752 goto op_branch;
1753 }
1752 } 1754 }
1753 else 1755 else
1754 i = hash_lookup (h, v1);
1755
1756 if (i >= 0)
1757 { 1756 {
1758 Lisp_Object val = HASH_VALUE (h, i); 1757 ptrdiff_t i = hash_lookup (h, v1);
1759 if (BYTE_CODE_SAFE && !FIXNUMP (val)) 1758 if (i >= 0)
1760 emacs_abort (); 1759 {
1761 op = XFIXNUM (val); 1760 op = XFIXNUM (HASH_VALUE (h, i));
1762 goto op_branch; 1761 goto op_branch;
1762 }
1763 } 1763 }
1764 } 1764 }
1765 NEXT; 1765 NEXT;
diff --git a/src/ccl.c b/src/ccl.c
index a3a03a5b7b1..8bb8a78fe3d 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -35,11 +35,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
35#include "coding.h" 35#include "coding.h"
36#include "keyboard.h" 36#include "keyboard.h"
37 37
38/* Avoid GCC 12 bug <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105784>. */
39#if GNUC_PREREQ (12, 0, 0)
40# pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value"
41#endif
42
43/* Table of registered CCL programs. Each element is a vector of 38/* Table of registered CCL programs. Each element is a vector of
44 NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the 39 NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the
45 name of the program, CCL_PROG (vector) is the compiled code of the 40 name of the program, CCL_PROG (vector) is the compiled code of the
@@ -609,7 +604,7 @@ while (0)
609 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109579 604 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109579
610 which causes GCC to mistakenly complain about 605 which causes GCC to mistakenly complain about
611 popping the mapping stack. */ 606 popping the mapping stack. */
612#if GNUC_PREREQ (13, 0, 0) 607#if __GNUC__ == 13
613# pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds" 608# pragma GCC diagnostic ignored "-Wanalyzer-out-of-bounds"
614#endif 609#endif
615 610
diff --git a/src/comp.c b/src/comp.c
index 853757f6162..3f989c722d4 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -4859,8 +4859,8 @@ add_compiler_options (void)
4859#endif 4859#endif
4860} 4860}
4861 4861
4862DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file, 4862DEFUN ("comp--compile-ctxt-to-file0", Fcomp__compile_ctxt_to_file0,
4863 Scomp__compile_ctxt_to_file, 4863 Scomp__compile_ctxt_to_file0,
4864 1, 1, 0, 4864 1, 1, 0,
4865 doc: /* Compile the current context as native code to file FILENAME. */) 4865 doc: /* Compile the current context as native code to file FILENAME. */)
4866 (Lisp_Object filename) 4866 (Lisp_Object filename)
@@ -5789,7 +5789,7 @@ natively-compiled one. */);
5789 defsubr (&Scomp__install_trampoline); 5789 defsubr (&Scomp__install_trampoline);
5790 defsubr (&Scomp__init_ctxt); 5790 defsubr (&Scomp__init_ctxt);
5791 defsubr (&Scomp__release_ctxt); 5791 defsubr (&Scomp__release_ctxt);
5792 defsubr (&Scomp__compile_ctxt_to_file); 5792 defsubr (&Scomp__compile_ctxt_to_file0);
5793 defsubr (&Scomp_libgccjit_version); 5793 defsubr (&Scomp_libgccjit_version);
5794 defsubr (&Scomp__register_lambda); 5794 defsubr (&Scomp__register_lambda);
5795 defsubr (&Scomp__register_subr); 5795 defsubr (&Scomp__register_subr);
diff --git a/src/conf_post.h b/src/conf_post.h
index 83a0dd1b09b..f2353803074 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -471,3 +471,7 @@ extern int emacs_setenv_TZ (char const *);
471#undef MB_CUR_MAX 471#undef MB_CUR_MAX
472#define MB_CUR_MAX REPLACEMENT_MB_CUR_MAX 472#define MB_CUR_MAX REPLACEMENT_MB_CUR_MAX
473#endif /* REPLACEMENT_MB_CUR_MAX */ 473#endif /* REPLACEMENT_MB_CUR_MAX */
474
475/* Emacs does not need glibc strftime behavior for AM and PM
476 indicators. */
477#define REQUIRE_GNUISH_STRFTIME_AM_PM false
diff --git a/src/data.c b/src/data.c
index fd4b1fe4e44..c87b5317618 100644
--- a/src/data.c
+++ b/src/data.c
@@ -231,6 +231,7 @@ for example, (type-of 1) returns `integer'. */)
231 case PVEC_BOOL_VECTOR: return Qbool_vector; 231 case PVEC_BOOL_VECTOR: return Qbool_vector;
232 case PVEC_FRAME: return Qframe; 232 case PVEC_FRAME: return Qframe;
233 case PVEC_HASH_TABLE: return Qhash_table; 233 case PVEC_HASH_TABLE: return Qhash_table;
234 case PVEC_OBARRAY: return Qobarray;
234 case PVEC_FONT: 235 case PVEC_FONT:
235 if (FONT_SPEC_P (object)) 236 if (FONT_SPEC_P (object))
236 return Qfont_spec; 237 return Qfont_spec;
@@ -791,18 +792,16 @@ DEFUN ("bare-symbol", Fbare_symbol, Sbare_symbol, 1, 1, 0,
791 doc: /* Extract, if need be, the bare symbol from SYM, a symbol. */) 792 doc: /* Extract, if need be, the bare symbol from SYM, a symbol. */)
792 (register Lisp_Object sym) 793 (register Lisp_Object sym)
793{ 794{
794 if (BARE_SYMBOL_P (sym)) 795 CHECK_SYMBOL (sym);
795 return sym; 796 return BARE_SYMBOL_P (sym) ? sym : XSYMBOL_WITH_POS_SYM (sym);
796 /* Type checking is done in the following macro. */
797 return SYMBOL_WITH_POS_SYM (sym);
798} 797}
799 798
800DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0, 799DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0,
801 doc: /* Extract the position from a symbol with position. */) 800 doc: /* Extract the position from a symbol with position. */)
802 (register Lisp_Object ls) 801 (register Lisp_Object ls)
803{ 802{
804 /* Type checking is done in the following macro. */ 803 CHECK_TYPE (SYMBOL_WITH_POS_P (ls), Qsymbol_with_pos_p, ls);
805 return SYMBOL_WITH_POS_POS (ls); 804 return XSYMBOL_WITH_POS_POS (ls);
806} 805}
807 806
808DEFUN ("remove-pos-from-symbol", Fremove_pos_from_symbol, 807DEFUN ("remove-pos-from-symbol", Fremove_pos_from_symbol,
@@ -812,7 +811,7 @@ Otherwise, return ARG unchanged. Compare with `bare-symbol'. */)
812 (register Lisp_Object arg) 811 (register Lisp_Object arg)
813{ 812{
814 if (SYMBOL_WITH_POS_P (arg)) 813 if (SYMBOL_WITH_POS_P (arg))
815 return (SYMBOL_WITH_POS_SYM (arg)); 814 return XSYMBOL_WITH_POS_SYM (arg);
816 return arg; 815 return arg;
817} 816}
818 817
@@ -823,20 +822,13 @@ POS, the position, is either a fixnum or a symbol with position from which
823the position will be taken. */) 822the position will be taken. */)
824 (register Lisp_Object sym, register Lisp_Object pos) 823 (register Lisp_Object sym, register Lisp_Object pos)
825{ 824{
826 Lisp_Object bare; 825 Lisp_Object bare = Fbare_symbol (sym);
827 Lisp_Object position; 826 Lisp_Object position;
828 827
829 if (BARE_SYMBOL_P (sym))
830 bare = sym;
831 else if (SYMBOL_WITH_POS_P (sym))
832 bare = XSYMBOL_WITH_POS (sym)->sym;
833 else
834 wrong_type_argument (Qsymbolp, sym);
835
836 if (FIXNUMP (pos)) 828 if (FIXNUMP (pos))
837 position = pos; 829 position = pos;
838 else if (SYMBOL_WITH_POS_P (pos)) 830 else if (SYMBOL_WITH_POS_P (pos))
839 position = XSYMBOL_WITH_POS (pos)->pos; 831 position = XSYMBOL_WITH_POS_POS (pos);
840 else 832 else
841 wrong_type_argument (Qfixnum_or_symbol_with_pos_p, pos); 833 wrong_type_argument (Qfixnum_or_symbol_with_pos_p, pos);
842 834
@@ -1264,7 +1256,7 @@ If OBJECT is not a symbol, just return it. */)
1264 struct Lisp_Symbol *sym = XSYMBOL (object); 1256 struct Lisp_Symbol *sym = XSYMBOL (object);
1265 while (sym->u.s.redirect == SYMBOL_VARALIAS) 1257 while (sym->u.s.redirect == SYMBOL_VARALIAS)
1266 sym = SYMBOL_ALIAS (sym); 1258 sym = SYMBOL_ALIAS (sym);
1267 XSETSYMBOL (object, sym); 1259 object = make_lisp_symbol (sym);
1268 } 1260 }
1269 return object; 1261 return object;
1270} 1262}
@@ -1514,12 +1506,9 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
1514 if (blv->fwd.fwdptr) 1506 if (blv->fwd.fwdptr)
1515 set_blv_value (blv, do_symval_forwarding (blv->fwd)); 1507 set_blv_value (blv, do_symval_forwarding (blv->fwd));
1516 /* Choose the new binding. */ 1508 /* Choose the new binding. */
1517 { 1509 tem1 = assq_no_quit (make_lisp_symbol (symbol),
1518 Lisp_Object var; 1510 BVAR (current_buffer, local_var_alist));
1519 XSETSYMBOL (var, symbol); 1511 set_blv_where (blv, Fcurrent_buffer ());
1520 tem1 = assq_no_quit (var, BVAR (current_buffer, local_var_alist));
1521 set_blv_where (blv, Fcurrent_buffer ());
1522 }
1523 if (!(blv->found = !NILP (tem1))) 1512 if (!(blv->found = !NILP (tem1)))
1524 tem1 = blv->defcell; 1513 tem1 = blv->defcell;
1525 1514
@@ -1663,7 +1652,8 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1663 set_blv_value (blv, do_symval_forwarding (blv->fwd)); 1652 set_blv_value (blv, do_symval_forwarding (blv->fwd));
1664 1653
1665 /* Find the new binding. */ 1654 /* Find the new binding. */
1666 XSETSYMBOL (symbol, sym); /* May have changed via aliasing. */ 1655 /* May have changed via aliasing. */
1656 symbol = make_lisp_symbol (sym);
1667 Lisp_Object tem1 1657 Lisp_Object tem1
1668 = assq_no_quit (symbol, 1658 = assq_no_quit (symbol,
1669 BVAR (XBUFFER (where), local_var_alist)); 1659 BVAR (XBUFFER (where), local_var_alist));
@@ -2067,13 +2057,10 @@ make_blv (struct Lisp_Symbol *sym, bool forwarded,
2067 union Lisp_Val_Fwd valcontents) 2057 union Lisp_Val_Fwd valcontents)
2068{ 2058{
2069 struct Lisp_Buffer_Local_Value *blv = xmalloc (sizeof *blv); 2059 struct Lisp_Buffer_Local_Value *blv = xmalloc (sizeof *blv);
2070 Lisp_Object symbol; 2060 Lisp_Object tem = Fcons (make_lisp_symbol (sym),
2071 Lisp_Object tem; 2061 forwarded
2072 2062 ? do_symval_forwarding (valcontents.fwd)
2073 XSETSYMBOL (symbol, sym); 2063 : valcontents.value);
2074 tem = Fcons (symbol, (forwarded
2075 ? do_symval_forwarding (valcontents.fwd)
2076 : valcontents.value));
2077 2064
2078 /* Buffer_Local_Values cannot have as realval a buffer-local 2065 /* Buffer_Local_Values cannot have as realval a buffer-local
2079 or keyboard-local forwarding. */ 2066 or keyboard-local forwarding. */
@@ -2229,7 +2216,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
2229 } 2216 }
2230 2217
2231 /* Make sure this buffer has its own value of symbol. */ 2218 /* Make sure this buffer has its own value of symbol. */
2232 XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ 2219 variable = make_lisp_symbol (sym); /* Update in case of aliasing. */
2233 tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist)); 2220 tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
2234 if (NILP (tem)) 2221 if (NILP (tem))
2235 { 2222 {
@@ -2309,7 +2296,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
2309 notify_variable_watchers (variable, Qnil, Qmakunbound, Fcurrent_buffer ()); 2296 notify_variable_watchers (variable, Qnil, Qmakunbound, Fcurrent_buffer ());
2310 2297
2311 /* Get rid of this buffer's alist element, if any. */ 2298 /* Get rid of this buffer's alist element, if any. */
2312 XSETSYMBOL (variable, sym); /* Propagate variable indirection. */ 2299 variable = make_lisp_symbol (sym); /* Propagate variable indirection. */
2313 tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist)); 2300 tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
2314 if (!NILP (tem)) 2301 if (!NILP (tem))
2315 bset_local_var_alist 2302 bset_local_var_alist
@@ -2354,7 +2341,7 @@ Also see `buffer-local-boundp'.*/)
2354 Lisp_Object tmp; 2341 Lisp_Object tmp;
2355 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 2342 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
2356 XSETBUFFER (tmp, buf); 2343 XSETBUFFER (tmp, buf);
2357 XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ 2344 variable = make_lisp_symbol (sym); /* Update in case of aliasing. */
2358 2345
2359 if (EQ (blv->where, tmp)) /* The binding is already loaded. */ 2346 if (EQ (blv->where, tmp)) /* The binding is already loaded. */
2360 return blv_found (blv) ? Qt : Qnil; 2347 return blv_found (blv) ? Qt : Qnil;
@@ -2404,7 +2391,7 @@ value in BUFFER, or if VARIABLE is automatically buffer-local (see
2404 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 2391 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
2405 if (blv->local_if_set) 2392 if (blv->local_if_set)
2406 return Qt; 2393 return Qt;
2407 XSETSYMBOL (variable, sym); /* Update in case of aliasing. */ 2394 variable = make_lisp_symbol (sym); /* Update in case of aliasing. */
2408 return Flocal_variable_p (variable, buffer); 2395 return Flocal_variable_p (variable, buffer);
2409 } 2396 }
2410 case SYMBOL_FORWARDED: 2397 case SYMBOL_FORWARDED:
@@ -4238,6 +4225,7 @@ syms_of_data (void)
4238 DEFSYM (Qtreesit_parser, "treesit-parser"); 4225 DEFSYM (Qtreesit_parser, "treesit-parser");
4239 DEFSYM (Qtreesit_node, "treesit-node"); 4226 DEFSYM (Qtreesit_node, "treesit-node");
4240 DEFSYM (Qtreesit_compiled_query, "treesit-compiled-query"); 4227 DEFSYM (Qtreesit_compiled_query, "treesit-compiled-query");
4228 DEFSYM (Qobarray, "obarray");
4241 4229
4242 DEFSYM (Qdefun, "defun"); 4230 DEFSYM (Qdefun, "defun");
4243 4231
diff --git a/src/dispextern.h b/src/dispextern.h
index 84b9dadc184..5387cb45603 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2752,6 +2752,16 @@ struct it
2752 pixel_width with each call to produce_glyphs. */ 2752 pixel_width with each call to produce_glyphs. */
2753 int current_x; 2753 int current_x;
2754 2754
2755 /* Pixel position within a display line with a wrap prefix. Updated
2756 to reflect current_x in produce_glyphs when producing glyphs from
2757 a prefix string and continuation_lines_width > 0, which is to
2758 say, from a wrap prefix.
2759
2760 Such updates are unnecessary where it is impossible for a wrap
2761 prefix to be active, e.g. when continuation lines are being
2762 produced. */
2763 int wrap_prefix_width;
2764
2755 /* Accumulated width of continuation lines. If > 0, this means we 2765 /* Accumulated width of continuation lines. If > 0, this means we
2756 are currently in a continuation line. This is initially zero and 2766 are currently in a continuation line. This is initially zero and
2757 incremented/reset by display_line, move_it_to etc. */ 2767 incremented/reset by display_line, move_it_to etc. */
diff --git a/src/doc.c b/src/doc.c
index a451b468ef2..b5a9ed498af 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -357,6 +357,20 @@ reread_doc_file (Lisp_Object file)
357 return 1; 357 return 1;
358} 358}
359 359
360DEFUN ("documentation-stringp", Fdocumentation_stringp, Sdocumentation_stringp,
361 1, 1, 0,
362 doc: /* Return non-nil if OBJECT is a well-formed docstring object.
363OBJECT can be either a string or a reference if it's kept externally. */)
364 (Lisp_Object object)
365{
366 return (STRINGP (object)
367 || FIXNUMP (object) /* Reference to DOC. */
368 || (CONSP (object) /* Reference to .elc. */
369 && STRINGP (XCAR (object))
370 && FIXNUMP (XCDR (object)))
371 ? Qt : Qnil);
372}
373
360DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0, 374DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
361 doc: /* Return the documentation string of FUNCTION. 375 doc: /* Return the documentation string of FUNCTION.
362Unless a non-nil second argument RAW is given, the 376Unless a non-nil second argument RAW is given, the
@@ -502,46 +516,13 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset)
502 /* If it's a lisp form, stick it in the form. */ 516 /* If it's a lisp form, stick it in the form. */
503 if (CONSP (fun) && EQ (XCAR (fun), Qmacro)) 517 if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
504 fun = XCDR (fun); 518 fun = XCDR (fun);
505 if (CONSP (fun))
506 {
507 Lisp_Object tem = XCAR (fun);
508 if (EQ (tem, Qlambda) || EQ (tem, Qautoload)
509 || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1)))
510 {
511 tem = Fcdr (Fcdr (fun));
512 if (CONSP (tem) && FIXNUMP (XCAR (tem)))
513 /* FIXME: This modifies typically pure hash-cons'd data, so its
514 correctness is quite delicate. */
515 XSETCAR (tem, make_fixnum (offset));
516 }
517 }
518 /* Lisp_Subrs have a slot for it. */ 519 /* Lisp_Subrs have a slot for it. */
519 else if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun)) 520 if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
520 { 521 XSUBR (fun)->doc = offset;
521 XSUBR (fun)->doc = offset; 522 else
522 }
523
524 /* Bytecode objects sometimes have slots for it. */
525 else if (COMPILEDP (fun))
526 { 523 {
527 /* This bytecode object must have a slot for the 524 AUTO_STRING (format, "Ignoring DOC string on non-subr: %S");
528 docstring, since we've found a docstring for it. */ 525 CALLN (Fmessage, format, obj);
529 if (PVSIZE (fun) > COMPILED_DOC_STRING
530 /* Don't overwrite a non-docstring value placed there,
531 * such as the symbols used for Oclosures. */
532 && VALID_DOCSTRING_P (AREF (fun, COMPILED_DOC_STRING)))
533 ASET (fun, COMPILED_DOC_STRING, make_fixnum (offset));
534 else
535 {
536 AUTO_STRING (format,
537 (PVSIZE (fun) > COMPILED_DOC_STRING
538 ? "Docstring slot busy for %s"
539 : "No docstring slot for %s"));
540 CALLN (Fmessage, format,
541 (SYMBOLP (obj)
542 ? SYMBOL_NAME (obj)
543 : build_string ("<anonymous>")));
544 }
545 } 526 }
546} 527}
547 528
@@ -776,6 +757,7 @@ compute the correct value for the current terminal in the nil case. */);
776 doc: /* If nil, a nil `text-quoting-style' is treated as `grave'. */); 757 doc: /* If nil, a nil `text-quoting-style' is treated as `grave'. */);
777 /* Initialized by ‘main’. */ 758 /* Initialized by ‘main’. */
778 759
760 defsubr (&Sdocumentation_stringp);
779 defsubr (&Sdocumentation); 761 defsubr (&Sdocumentation);
780 defsubr (&Ssubr_documentation); 762 defsubr (&Ssubr_documentation);
781 defsubr (&Sdocumentation_property); 763 defsubr (&Sdocumentation_property);
diff --git a/src/editfns.c b/src/editfns.c
index 0cecd81c07f..4ccf765bd4b 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -272,24 +272,6 @@ If you set the marker not to point anywhere, the buffer will have no mark. */)
272} 272}
273 273
274 274
275/* Find all the overlays in the current buffer that touch position POS.
276 Return the number found, and store them in a vector in VEC
277 of length LEN.
278
279 Note: this can return overlays that do not touch POS. The caller
280 should filter these out. */
281
282static ptrdiff_t
283overlays_around (ptrdiff_t pos, Lisp_Object *vec, ptrdiff_t len)
284{
285 /* Find all potentially rear-advance overlays at (POS - 1). Find
286 all overlays at POS, so end at (POS + 1). Find even empty
287 overlays, which due to the way 'overlays-in' works implies that
288 we might also fetch empty overlays starting at (POS + 1). */
289 return overlays_in (pos - 1, pos + 1, false, &vec, &len,
290 true, false, NULL);
291}
292
293DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0, 275DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0,
294 doc: /* Return the value of POSITION's property PROP, in OBJECT. 276 doc: /* Return the value of POSITION's property PROP, in OBJECT.
295Almost identical to `get-char-property' except for the following difference: 277Almost identical to `get-char-property' except for the following difference:
@@ -315,53 +297,44 @@ at POSITION. */)
315 else 297 else
316 { 298 {
317 EMACS_INT posn = XFIXNUM (position); 299 EMACS_INT posn = XFIXNUM (position);
318 ptrdiff_t noverlays; 300 Lisp_Object tem;
319 Lisp_Object *overlay_vec, tem;
320 struct buffer *obuf = current_buffer; 301 struct buffer *obuf = current_buffer;
321 USE_SAFE_ALLOCA; 302 struct itree_node *node;
322 303 struct sortvec items[2];
323 set_buffer_temp (XBUFFER (object)); 304 struct buffer *b = XBUFFER (object);
305 struct sortvec *result = NULL;
306 Lisp_Object res = Qnil;
324 307
325 /* First try with room for 40 overlays. */ 308 set_buffer_temp (b);
326 Lisp_Object overlay_vecbuf[40];
327 noverlays = ARRAYELTS (overlay_vecbuf);
328 overlay_vec = overlay_vecbuf;
329 noverlays = overlays_around (posn, overlay_vec, noverlays);
330 309
331 /* If there are more than 40, 310 ITREE_FOREACH (node, b->overlays, posn - 1, posn + 1, ASCENDING)
332 make enough space for all, and try again. */
333 if (ARRAYELTS (overlay_vecbuf) < noverlays)
334 { 311 {
335 SAFE_ALLOCA_LISP (overlay_vec, noverlays); 312 Lisp_Object ol = node->data;
336 noverlays = overlays_around (posn, overlay_vec, noverlays);
337 }
338 noverlays = sort_overlays (overlay_vec, noverlays, NULL);
339
340 set_buffer_temp (obuf);
341
342 /* Now check the overlays in order of decreasing priority. */
343 while (--noverlays >= 0)
344 {
345 Lisp_Object ol = overlay_vec[noverlays];
346 tem = Foverlay_get (ol, prop); 313 tem = Foverlay_get (ol, prop);
347 if (!NILP (tem)) 314 if (NILP (tem)
348 {
349 /* Check the overlay is indeed active at point. */ 315 /* Check the overlay is indeed active at point. */
350 if ((OVERLAY_START (ol) == posn 316 || ((node->begin == posn
351 && OVERLAY_FRONT_ADVANCE_P (ol)) 317 && OVERLAY_FRONT_ADVANCE_P (ol))
352 || (OVERLAY_END (ol) == posn 318 || (node->end == posn
353 && ! OVERLAY_REAR_ADVANCE_P (ol)) 319 && ! OVERLAY_REAR_ADVANCE_P (ol))
354 || OVERLAY_START (ol) > posn 320 || node->begin > posn
355 || OVERLAY_END (ol) < posn) 321 || node->end < posn))
356 ; /* The overlay will not cover a char inserted at point. */ 322 /* The overlay will not cover a char inserted at point. */
357 else 323 continue;
358 { 324
359 SAFE_FREE (); 325 struct sortvec *this = (result == items ? items + 1 : items);
360 return tem; 326 if (NILP (res)
361 } 327 || (make_sortvec_item (this, node->data),
362 } 328 compare_overlays (result, this) < 0))
329 {
330 result = this;
331 res = tem;
332 }
363 } 333 }
364 SAFE_FREE (); 334 set_buffer_temp (obuf);
335
336 if (!NILP (res))
337 return res;
365 338
366 { /* Now check the text properties. */ 339 { /* Now check the text properties. */
367 int stickiness = text_property_stickiness (prop, position, object); 340 int stickiness = text_property_stickiness (prop, position, object);
diff --git a/src/emacs.c b/src/emacs.c
index 97c65fbfd33..f4bfb9a6bbd 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -3116,10 +3116,6 @@ shut_down_emacs (int sig, Lisp_Object stuff)
3116 check_message_stack (); 3116 check_message_stack ();
3117 } 3117 }
3118 3118
3119#ifdef HAVE_NATIVE_COMP
3120 eln_load_path_final_clean_up ();
3121#endif
3122
3123#ifdef MSDOS 3119#ifdef MSDOS
3124 dos_cleanup (); 3120 dos_cleanup ();
3125#endif 3121#endif
diff --git a/src/eval.c b/src/eval.c
index 6f1c39ffb0e..9d3b98eb359 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3122,19 +3122,6 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
3122 xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs)); 3122 xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs));
3123} 3123}
3124 3124
3125/* Call the compiled Lisp function FUN. If we have not yet read FUN's
3126 bytecode string and constants vector, fetch them from the file first. */
3127
3128static Lisp_Object
3129fetch_and_exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
3130 ptrdiff_t nargs, Lisp_Object *args)
3131{
3132 if (CONSP (AREF (fun, COMPILED_BYTECODE)))
3133 Ffetch_bytecode (fun);
3134
3135 return exec_byte_code (fun, args_template, nargs, args);
3136}
3137
3138static Lisp_Object 3125static Lisp_Object
3139apply_lambda (Lisp_Object fun, Lisp_Object args, specpdl_ref count) 3126apply_lambda (Lisp_Object fun, Lisp_Object args, specpdl_ref count)
3140{ 3127{
@@ -3204,8 +3191,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
3204 ARGLIST slot value: pass the arguments to the byte-code 3191 ARGLIST slot value: pass the arguments to the byte-code
3205 engine directly. */ 3192 engine directly. */
3206 if (FIXNUMP (syms_left)) 3193 if (FIXNUMP (syms_left))
3207 return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left), 3194 return exec_byte_code (fun, XFIXNUM (syms_left), nargs, arg_vector);
3208 nargs, arg_vector);
3209 /* Otherwise the bytecode object uses dynamic binding and the 3195 /* Otherwise the bytecode object uses dynamic binding and the
3210 ARGLIST slot contains a standard formal argument list whose 3196 ARGLIST slot contains a standard formal argument list whose
3211 variables are bound dynamically below. */ 3197 variables are bound dynamically below. */
@@ -3293,7 +3279,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
3293 val = XSUBR (fun)->function.a0 (); 3279 val = XSUBR (fun)->function.a0 ();
3294 } 3280 }
3295 else 3281 else
3296 val = fetch_and_exec_byte_code (fun, 0, 0, NULL); 3282 val = exec_byte_code (fun, 0, 0, NULL);
3297 3283
3298 return unbind_to (count, val); 3284 return unbind_to (count, val);
3299} 3285}
@@ -3411,46 +3397,6 @@ lambda_arity (Lisp_Object fun)
3411 return Fcons (make_fixnum (minargs), make_fixnum (maxargs)); 3397 return Fcons (make_fixnum (minargs), make_fixnum (maxargs));
3412} 3398}
3413 3399
3414DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
3415 1, 1, 0,
3416 doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now. */)
3417 (Lisp_Object object)
3418{
3419 Lisp_Object tem;
3420
3421 if (COMPILEDP (object))
3422 {
3423 if (CONSP (AREF (object, COMPILED_BYTECODE)))
3424 {
3425 tem = read_doc_string (AREF (object, COMPILED_BYTECODE));
3426 if (! (CONSP (tem) && STRINGP (XCAR (tem))
3427 && VECTORP (XCDR (tem))))
3428 {
3429 tem = AREF (object, COMPILED_BYTECODE);
3430 if (CONSP (tem) && STRINGP (XCAR (tem)))
3431 error ("Invalid byte code in %s", SDATA (XCAR (tem)));
3432 else
3433 error ("Invalid byte code");
3434 }
3435
3436 Lisp_Object bytecode = XCAR (tem);
3437 if (STRING_MULTIBYTE (bytecode))
3438 {
3439 /* BYTECODE must have been produced by Emacs 20.2 or earlier
3440 because it produced a raw 8-bit string for byte-code and now
3441 such a byte-code string is loaded as multibyte with raw 8-bit
3442 characters converted to multibyte form. Convert them back to
3443 the original unibyte form. */
3444 bytecode = Fstring_as_unibyte (bytecode);
3445 }
3446
3447 pin_string (bytecode);
3448 ASET (object, COMPILED_BYTECODE, bytecode);
3449 ASET (object, COMPILED_CONSTANTS, XCDR (tem));
3450 }
3451 }
3452 return object;
3453}
3454 3400
3455/* Return true if SYMBOL's default currently has a let-binding 3401/* Return true if SYMBOL's default currently has a let-binding
3456 which was made in the buffer that is now current. */ 3402 which was made in the buffer that is now current. */
@@ -3529,7 +3475,7 @@ specbind (Lisp_Object symbol, Lisp_Object value)
3529 switch (sym->u.s.redirect) 3475 switch (sym->u.s.redirect)
3530 { 3476 {
3531 case SYMBOL_VARALIAS: 3477 case SYMBOL_VARALIAS:
3532 sym = SYMBOL_ALIAS (sym); XSETSYMBOL (symbol, sym); goto start; 3478 sym = SYMBOL_ALIAS (sym); symbol = make_lisp_symbol (sym); goto start;
3533 case SYMBOL_PLAINVAL: 3479 case SYMBOL_PLAINVAL:
3534 /* The most common case is that of a non-constant symbol with a 3480 /* The most common case is that of a non-constant symbol with a
3535 trivial value. Make that as fast as we can. */ 3481 trivial value. Make that as fast as we can. */
@@ -4512,7 +4458,6 @@ alist of active lexical bindings. */);
4512 defsubr (&Srun_hook_with_args_until_success); 4458 defsubr (&Srun_hook_with_args_until_success);
4513 defsubr (&Srun_hook_with_args_until_failure); 4459 defsubr (&Srun_hook_with_args_until_failure);
4514 defsubr (&Srun_hook_wrapped); 4460 defsubr (&Srun_hook_wrapped);
4515 defsubr (&Sfetch_bytecode);
4516 defsubr (&Sbacktrace_debug); 4461 defsubr (&Sbacktrace_debug);
4517 DEFSYM (QCdebug_on_exit, ":debug-on-exit"); 4462 DEFSYM (QCdebug_on_exit, ":debug-on-exit");
4518 defsubr (&Smapbacktrace); 4463 defsubr (&Smapbacktrace);
diff --git a/src/fileio.c b/src/fileio.c
index a92da93ae48..483498fd879 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5628,7 +5628,15 @@ write_region (Lisp_Object start, Lisp_Object end, Lisp_Object filename,
5628 changed to a call to `stat'. */ 5628 changed to a call to `stat'. */
5629 5629
5630 if (emacs_fstatat (AT_FDCWD, fn, &st1, 0) == 0 5630 if (emacs_fstatat (AT_FDCWD, fn, &st1, 0) == 0
5631 && st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) 5631 && st.st_dev == st1.st_dev
5632 && (st.st_ino == st1.st_ino
5633#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
5634 /* `st1.st_ino' == 0 indicates that the inode number
5635 cannot be extracted from this document file, despite
5636 `st' potentially being backed by a real file. */
5637 || st1.st_ino == 0
5638#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
5639 ))
5632 { 5640 {
5633 /* Use the heuristic if it appears to be valid. With neither 5641 /* Use the heuristic if it appears to be valid. With neither
5634 O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the 5642 O_EXCL nor O_TRUNC, if Emacs happened to write nothing to the
diff --git a/src/fns.c b/src/fns.c
index e4fa8157000..0a64e515402 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2782,13 +2782,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2782 2782
2783 /* A symbol with position compares the contained symbol, and is 2783 /* A symbol with position compares the contained symbol, and is
2784 `equal' to the corresponding ordinary symbol. */ 2784 `equal' to the corresponding ordinary symbol. */
2785 if (symbols_with_pos_enabled) 2785 o1 = maybe_remove_pos_from_symbol (o1);
2786 { 2786 o2 = maybe_remove_pos_from_symbol (o2);
2787 if (SYMBOL_WITH_POS_P (o1))
2788 o1 = SYMBOL_WITH_POS_SYM (o1);
2789 if (SYMBOL_WITH_POS_P (o2))
2790 o2 = SYMBOL_WITH_POS_SYM (o2);
2791 }
2792 2787
2793 if (BASE_EQ (o1, o2)) 2788 if (BASE_EQ (o1, o2))
2794 return true; 2789 return true;
@@ -2869,11 +2864,14 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
2869 if (TS_NODEP (o1)) 2864 if (TS_NODEP (o1))
2870 return treesit_node_eq (o1, o2); 2865 return treesit_node_eq (o1, o2);
2871#endif 2866#endif
2872 if (SYMBOL_WITH_POS_P(o1)) /* symbols_with_pos_enabled is false. */ 2867 if (SYMBOL_WITH_POS_P (o1))
2873 return (BASE_EQ (XSYMBOL_WITH_POS (o1)->sym, 2868 {
2874 XSYMBOL_WITH_POS (o2)->sym) 2869 eassert (!symbols_with_pos_enabled);
2875 && BASE_EQ (XSYMBOL_WITH_POS (o1)->pos, 2870 return (BASE_EQ (XSYMBOL_WITH_POS_SYM (o1),
2876 XSYMBOL_WITH_POS (o2)->pos)); 2871 XSYMBOL_WITH_POS_SYM (o2))
2872 && BASE_EQ (XSYMBOL_WITH_POS_POS (o1),
2873 XSYMBOL_WITH_POS_POS (o2)));
2874 }
2877 2875
2878 /* Aside from them, only true vectors, char-tables, compiled 2876 /* Aside from them, only true vectors, char-tables, compiled
2879 functions, and fonts (font-spec, font-entity, font-object) 2877 functions, and fonts (font-spec, font-entity, font-object)
@@ -3211,7 +3209,7 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string. */)
3211Lisp_Object 3209Lisp_Object
3212do_yes_or_no_p (Lisp_Object prompt) 3210do_yes_or_no_p (Lisp_Object prompt)
3213{ 3211{
3214 return call1 (intern ("yes-or-no-p"), prompt); 3212 return call1 (Qyes_or_no_p, prompt);
3215} 3213}
3216 3214
3217DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0, 3215DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
@@ -3256,7 +3254,7 @@ by a mouse, or by some window-system gesture, or via a menu. */)
3256 } 3254 }
3257 3255
3258 if (use_short_answers) 3256 if (use_short_answers)
3259 return call1 (intern ("y-or-n-p"), prompt); 3257 return call1 (Qy_or_n_p, prompt);
3260 3258
3261 { 3259 {
3262 char *s = SSDATA (prompt); 3260 char *s = SSDATA (prompt);
@@ -4291,7 +4289,7 @@ set_hash_hash_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, hash_hash_t val)
4291static void 4289static void
4292set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val) 4290set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val)
4293{ 4291{
4294 eassert (idx >= 0 && idx < h->index_size); 4292 eassert (idx >= 0 && idx < hash_table_index_size (h));
4295 h->index[idx] = val; 4293 h->index[idx] = val;
4296} 4294}
4297 4295
@@ -4392,7 +4390,7 @@ HASH_NEXT (struct Lisp_Hash_Table *h, ptrdiff_t idx)
4392static ptrdiff_t 4390static ptrdiff_t
4393HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) 4391HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx)
4394{ 4392{
4395 eassert (idx >= 0 && idx < h->index_size); 4393 eassert (idx >= 0 && idx < hash_table_index_size (h));
4396 return h->index[idx]; 4394 return h->index[idx];
4397} 4395}
4398 4396
@@ -4452,22 +4450,11 @@ cmpfn_user_defined (Lisp_Object key1, Lisp_Object key2,
4452 return hash_table_user_defined_call (ARRAYELTS (args), args, h); 4450 return hash_table_user_defined_call (ARRAYELTS (args), args, h);
4453} 4451}
4454 4452
4455/* Reduce an EMACS_UINT hash value to hash_hash_t. */
4456static inline hash_hash_t
4457reduce_emacs_uint_to_hash_hash (EMACS_UINT x)
4458{
4459 verify (sizeof x <= 2 * sizeof (hash_hash_t));
4460 return (sizeof x == sizeof (hash_hash_t)
4461 ? x
4462 : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t)))));
4463}
4464
4465static EMACS_INT 4453static EMACS_INT
4466sxhash_eq (Lisp_Object key) 4454sxhash_eq (Lisp_Object key)
4467{ 4455{
4468 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (key)) 4456 Lisp_Object k = maybe_remove_pos_from_symbol (key);
4469 key = SYMBOL_WITH_POS_SYM (key); 4457 return XHASH (k) ^ XTYPE (k);
4470 return XHASH (key) ^ XTYPE (key);
4471} 4458}
4472 4459
4473static EMACS_INT 4460static EMACS_INT
@@ -4527,26 +4514,19 @@ allocate_hash_table (void)
4527 return ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Hash_Table, PVEC_HASH_TABLE); 4514 return ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Hash_Table, PVEC_HASH_TABLE);
4528} 4515}
4529 4516
4530/* Compute the size of the index from the table capacity. */ 4517/* Compute the size of the index (as log2) from the table capacity. */
4531static ptrdiff_t 4518static int
4532hash_index_size (ptrdiff_t size) 4519compute_hash_index_bits (hash_idx_t size)
4533{ 4520{
4534 /* An upper bound on the size of a hash table index. It must fit in 4521 /* An upper bound on the size of a hash table index index. */
4535 ptrdiff_t and be a valid Emacs fixnum. */ 4522 hash_idx_t upper_bound = min (MOST_POSITIVE_FIXNUM,
4536 ptrdiff_t upper_bound = min (MOST_POSITIVE_FIXNUM, 4523 min (TYPE_MAXIMUM (hash_idx_t),
4537 min (TYPE_MAXIMUM (hash_idx_t), 4524 PTRDIFF_MAX / sizeof (hash_idx_t)));
4538 PTRDIFF_MAX / sizeof (ptrdiff_t))); 4525 /* Use next higher power of 2. This works even for size=0. */
4539 /* Single-element index vectors are used iff size=0. */ 4526 int bits = elogb (size) + 1;
4540 eassert (size > 0); 4527 if (bits >= TYPE_WIDTH (uintmax_t) || ((uintmax_t)1 << bits) > upper_bound)
4541 ptrdiff_t lower_bound = 2;
4542 ptrdiff_t index_size = size + max (size >> 2, 1); /* 1.25x larger */
4543 if (index_size < upper_bound)
4544 index_size = (index_size < lower_bound
4545 ? lower_bound
4546 : next_almost_prime (index_size));
4547 if (index_size > upper_bound)
4548 error ("Hash table too large"); 4528 error ("Hash table too large");
4549 return index_size; 4529 return bits;
4550} 4530}
4551 4531
4552/* Constant hash index vector used when the table size is zero. 4532/* Constant hash index vector used when the table size is zero.
@@ -4587,7 +4567,7 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size,
4587 h->key_and_value = NULL; 4567 h->key_and_value = NULL;
4588 h->hash = NULL; 4568 h->hash = NULL;
4589 h->next = NULL; 4569 h->next = NULL;
4590 h->index_size = 1; 4570 h->index_bits = 0;
4591 h->index = (hash_idx_t *)empty_hash_index_vector; 4571 h->index = (hash_idx_t *)empty_hash_index_vector;
4592 h->next_free = -1; 4572 h->next_free = -1;
4593 } 4573 }
@@ -4605,8 +4585,9 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size,
4605 h->next[i] = i + 1; 4585 h->next[i] = i + 1;
4606 h->next[size - 1] = -1; 4586 h->next[size - 1] = -1;
4607 4587
4608 int index_size = hash_index_size (size); 4588 int index_bits = compute_hash_index_bits (size);
4609 h->index_size = index_size; 4589 h->index_bits = index_bits;
4590 ptrdiff_t index_size = hash_table_index_size (h);
4610 h->index = hash_table_alloc_bytes (index_size * sizeof *h->index); 4591 h->index = hash_table_alloc_bytes (index_size * sizeof *h->index);
4611 for (ptrdiff_t i = 0; i < index_size; i++) 4592 for (ptrdiff_t i = 0; i < index_size; i++)
4612 h->index[i] = -1; 4593 h->index[i] = -1;
@@ -4617,13 +4598,7 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size,
4617 h->next_weak = NULL; 4598 h->next_weak = NULL;
4618 h->purecopy = purecopy; 4599 h->purecopy = purecopy;
4619 h->mutable = true; 4600 h->mutable = true;
4620 4601 return make_lisp_hash_table (h);
4621 Lisp_Object table;
4622 XSET_HASH_TABLE (table, h);
4623 eassert (HASH_TABLE_P (table));
4624 eassert (XHASH_TABLE (table) == h);
4625
4626 return table;
4627} 4602}
4628 4603
4629 4604
@@ -4633,7 +4608,6 @@ make_hash_table (const struct hash_table_test *test, EMACS_INT size,
4633static Lisp_Object 4608static Lisp_Object
4634copy_hash_table (struct Lisp_Hash_Table *h1) 4609copy_hash_table (struct Lisp_Hash_Table *h1)
4635{ 4610{
4636 Lisp_Object table;
4637 struct Lisp_Hash_Table *h2; 4611 struct Lisp_Hash_Table *h2;
4638 4612
4639 h2 = allocate_hash_table (); 4613 h2 = allocate_hash_table ();
@@ -4654,22 +4628,18 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
4654 h2->next = hash_table_alloc_bytes (next_bytes); 4628 h2->next = hash_table_alloc_bytes (next_bytes);
4655 memcpy (h2->next, h1->next, next_bytes); 4629 memcpy (h2->next, h1->next, next_bytes);
4656 4630
4657 ptrdiff_t index_bytes = h1->index_size * sizeof *h1->index; 4631 ptrdiff_t index_bytes = hash_table_index_size (h1) * sizeof *h1->index;
4658 h2->index = hash_table_alloc_bytes (index_bytes); 4632 h2->index = hash_table_alloc_bytes (index_bytes);
4659 memcpy (h2->index, h1->index, index_bytes); 4633 memcpy (h2->index, h1->index, index_bytes);
4660 } 4634 }
4661 XSET_HASH_TABLE (table, h2); 4635 return make_lisp_hash_table (h2);
4662
4663 return table;
4664} 4636}
4665 4637
4666
4667/* Compute index into the index vector from a hash value. */ 4638/* Compute index into the index vector from a hash value. */
4668static inline ptrdiff_t 4639static inline ptrdiff_t
4669hash_index_index (struct Lisp_Hash_Table *h, hash_hash_t hash) 4640hash_index_index (struct Lisp_Hash_Table *h, hash_hash_t hash)
4670{ 4641{
4671 eassert (h->index_size > 0); 4642 return knuth_hash (hash, h->index_bits);
4672 return hash % h->index_size;
4673} 4643}
4674 4644
4675/* Resize hash table H if it's too full. If H cannot be resized 4645/* Resize hash table H if it's too full. If H cannot be resized
@@ -4681,7 +4651,7 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
4681 if (h->next_free < 0) 4651 if (h->next_free < 0)
4682 { 4652 {
4683 ptrdiff_t old_size = HASH_TABLE_SIZE (h); 4653 ptrdiff_t old_size = HASH_TABLE_SIZE (h);
4684 ptrdiff_t min_size = 8; 4654 ptrdiff_t min_size = 6;
4685 ptrdiff_t base_size = min (max (old_size, min_size), PTRDIFF_MAX / 2); 4655 ptrdiff_t base_size = min (max (old_size, min_size), PTRDIFF_MAX / 2);
4686 /* Grow aggressively at small sizes, then just double. */ 4656 /* Grow aggressively at small sizes, then just double. */
4687 ptrdiff_t new_size = 4657 ptrdiff_t new_size =
@@ -4706,13 +4676,14 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
4706 hash_hash_t *hash = hash_table_alloc_bytes (new_size * sizeof *hash); 4676 hash_hash_t *hash = hash_table_alloc_bytes (new_size * sizeof *hash);
4707 memcpy (hash, h->hash, old_size * sizeof *hash); 4677 memcpy (hash, h->hash, old_size * sizeof *hash);
4708 4678
4709 ptrdiff_t old_index_size = h->index_size; 4679 ptrdiff_t old_index_size = hash_table_index_size (h);
4710 ptrdiff_t index_size = hash_index_size (new_size); 4680 ptrdiff_t index_bits = compute_hash_index_bits (new_size);
4681 ptrdiff_t index_size = (ptrdiff_t)1 << index_bits;
4711 hash_idx_t *index = hash_table_alloc_bytes (index_size * sizeof *index); 4682 hash_idx_t *index = hash_table_alloc_bytes (index_size * sizeof *index);
4712 for (ptrdiff_t i = 0; i < index_size; i++) 4683 for (ptrdiff_t i = 0; i < index_size; i++)
4713 index[i] = -1; 4684 index[i] = -1;
4714 4685
4715 h->index_size = index_size; 4686 h->index_bits = index_bits;
4716 h->table_size = new_size; 4687 h->table_size = new_size;
4717 h->next_free = old_size; 4688 h->next_free = old_size;
4718 4689
@@ -4778,18 +4749,19 @@ hash_table_thaw (Lisp_Object hash_table)
4778 h->key_and_value = NULL; 4749 h->key_and_value = NULL;
4779 h->hash = NULL; 4750 h->hash = NULL;
4780 h->next = NULL; 4751 h->next = NULL;
4781 h->index_size = 1; 4752 h->index_bits = 0;
4782 h->index = (hash_idx_t *)empty_hash_index_vector; 4753 h->index = (hash_idx_t *)empty_hash_index_vector;
4783 } 4754 }
4784 else 4755 else
4785 { 4756 {
4786 ptrdiff_t index_size = hash_index_size (size); 4757 ptrdiff_t index_bits = compute_hash_index_bits (size);
4787 h->index_size = index_size; 4758 h->index_bits = index_bits;
4788 4759
4789 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash); 4760 h->hash = hash_table_alloc_bytes (size * sizeof *h->hash);
4790 4761
4791 h->next = hash_table_alloc_bytes (size * sizeof *h->next); 4762 h->next = hash_table_alloc_bytes (size * sizeof *h->next);
4792 4763
4764 ptrdiff_t index_size = hash_table_index_size (h);
4793 h->index = hash_table_alloc_bytes (index_size * sizeof *h->index); 4765 h->index = hash_table_alloc_bytes (index_size * sizeof *h->index);
4794 for (ptrdiff_t i = 0; i < index_size; i++) 4766 for (ptrdiff_t i = 0; i < index_size; i++)
4795 h->index[i] = -1; 4767 h->index[i] = -1;
@@ -4937,7 +4909,8 @@ hash_clear (struct Lisp_Hash_Table *h)
4937 set_hash_value_slot (h, i, Qnil); 4909 set_hash_value_slot (h, i, Qnil);
4938 } 4910 }
4939 4911
4940 for (ptrdiff_t i = 0; i < h->index_size; i++) 4912 ptrdiff_t index_size = hash_table_index_size (h);
4913 for (ptrdiff_t i = 0; i < index_size; i++)
4941 h->index[i] = -1; 4914 h->index[i] = -1;
4942 4915
4943 h->next_free = 0; 4916 h->next_free = 0;
@@ -4976,7 +4949,7 @@ keep_entry_p (hash_table_weakness_t weakness,
4976bool 4949bool
4977sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) 4950sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
4978{ 4951{
4979 ptrdiff_t n = h->index_size; 4952 ptrdiff_t n = hash_table_index_size (h);
4980 bool marked = false; 4953 bool marked = false;
4981 4954
4982 for (ptrdiff_t bucket = 0; bucket < n; ++bucket) 4955 for (ptrdiff_t bucket = 0; bucket < n; ++bucket)
@@ -5072,24 +5045,52 @@ hash_string (char const *ptr, ptrdiff_t len)
5072 EMACS_UINT hash = len; 5045 EMACS_UINT hash = len;
5073 /* At most 8 steps. We could reuse SXHASH_MAX_LEN, of course, 5046 /* At most 8 steps. We could reuse SXHASH_MAX_LEN, of course,
5074 * but dividing by 8 is cheaper. */ 5047 * but dividing by 8 is cheaper. */
5075 ptrdiff_t step = sizeof hash + ((end - p) >> 3); 5048 ptrdiff_t step = max (sizeof hash, ((end - p) >> 3));
5076 5049
5077 while (p + sizeof hash <= end) 5050 if (p + sizeof hash <= end)
5078 { 5051 {
5052 do
5053 {
5054 EMACS_UINT c;
5055 /* We presume that the compiler will replace this `memcpy` with
5056 a single load/move instruction when applicable. */
5057 memcpy (&c, p, sizeof hash);
5058 p += step;
5059 hash = sxhash_combine (hash, c);
5060 }
5061 while (p + sizeof hash <= end);
5062 /* Hash the last wordful of bytes in the string, because that is
5063 is often the part where strings differ. This may cause some
5064 bytes to be hashed twice but we assume that's not a big problem. */
5079 EMACS_UINT c; 5065 EMACS_UINT c;
5080 /* We presume that the compiler will replace this `memcpy` with 5066 memcpy (&c, end - sizeof c, sizeof c);
5081 a single load/move instruction when applicable. */
5082 memcpy (&c, p, sizeof hash);
5083 p += step;
5084 hash = sxhash_combine (hash, c); 5067 hash = sxhash_combine (hash, c);
5085 } 5068 }
5086 /* A few last bytes may remain (smaller than an EMACS_UINT). */ 5069 else
5087 /* FIXME: We could do this without a loop, but it'd require
5088 endian-dependent code :-( */
5089 while (p < end)
5090 { 5070 {
5091 unsigned char c = *p++; 5071 /* String is shorter than an EMACS_UINT. Use smaller loads. */
5092 hash = sxhash_combine (hash, c); 5072 eassume (p <= end && end - p < sizeof (EMACS_UINT));
5073 EMACS_UINT tail = 0;
5074 verify (sizeof tail <= 8);
5075#if EMACS_INT_MAX > INT32_MAX
5076 if (end - p >= 4)
5077 {
5078 uint32_t c;
5079 memcpy (&c, p, sizeof c);
5080 tail = (tail << (8 * sizeof c)) + c;
5081 p += sizeof c;
5082 }
5083#endif
5084 if (end - p >= 2)
5085 {
5086 uint16_t c;
5087 memcpy (&c, p, sizeof c);
5088 tail = (tail << (8 * sizeof c)) + c;
5089 p += sizeof c;
5090 }
5091 if (p < end)
5092 tail = (tail << 8) + (unsigned char)*p;
5093 hash = sxhash_combine (hash, tail);
5093 } 5094 }
5094 5095
5095 return hash; 5096 return hash;
@@ -5177,7 +5178,7 @@ sxhash_bignum (Lisp_Object bignum)
5177{ 5178{
5178 mpz_t const *n = xbignum_val (bignum); 5179 mpz_t const *n = xbignum_val (bignum);
5179 size_t i, nlimbs = mpz_size (*n); 5180 size_t i, nlimbs = mpz_size (*n);
5180 EMACS_UINT hash = 0; 5181 EMACS_UINT hash = mpz_sgn(*n) < 0;
5181 5182
5182 for (i = 0; i < nlimbs; ++i) 5183 for (i = 0; i < nlimbs; ++i)
5183 hash = sxhash_combine (hash, mpz_getlimbn (*n, i)); 5184 hash = sxhash_combine (hash, mpz_getlimbn (*n, i));
@@ -5247,12 +5248,15 @@ sxhash_obj (Lisp_Object obj, int depth)
5247 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth)); 5248 hash = sxhash_combine (hash, sxhash_obj (XOVERLAY (obj)->plist, depth));
5248 return hash; 5249 return hash;
5249 } 5250 }
5250 else if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS)
5251 return sxhash_obj (XSYMBOL_WITH_POS (obj)->sym, depth + 1);
5252 else 5251 else
5253 /* Others are 'equal' if they are 'eq', so take their 5252 {
5254 address as hash. */ 5253 if (symbols_with_pos_enabled && pvec_type == PVEC_SYMBOL_WITH_POS)
5255 return XHASH (obj); 5254 obj = XSYMBOL_WITH_POS_SYM (obj);
5255
5256 /* Others are 'equal' if they are 'eq', so take their
5257 address as hash. */
5258 return XHASH (obj);
5259 }
5256 } 5260 }
5257 5261
5258 case Lisp_Cons: 5262 case Lisp_Cons:
@@ -5374,6 +5378,8 @@ mark_fns (void)
5374 } 5378 }
5375} 5379}
5376 5380
5381/* Find the hash_table_test object corresponding to the (bare) symbol TEST,
5382 creating one if none existed. */
5377static struct hash_table_test * 5383static struct hash_table_test *
5378get_hash_table_user_test (Lisp_Object test) 5384get_hash_table_user_test (Lisp_Object test)
5379{ 5385{
@@ -5384,7 +5390,8 @@ get_hash_table_user_test (Lisp_Object test)
5384 Lisp_Object equal_fn = XCAR (prop); 5390 Lisp_Object equal_fn = XCAR (prop);
5385 Lisp_Object hash_fn = XCAR (XCDR (prop)); 5391 Lisp_Object hash_fn = XCAR (XCDR (prop));
5386 struct hash_table_user_test *ut = hash_table_user_tests; 5392 struct hash_table_user_test *ut = hash_table_user_tests;
5387 while (ut && !(EQ (equal_fn, ut->test.user_cmp_function) 5393 while (ut && !(BASE_EQ (test, ut->test.name)
5394 && EQ (equal_fn, ut->test.user_cmp_function)
5388 && EQ (hash_fn, ut->test.user_hash_function))) 5395 && EQ (hash_fn, ut->test.user_hash_function)))
5389 ut = ut->next; 5396 ut = ut->next;
5390 if (!ut) 5397 if (!ut)
@@ -5444,9 +5451,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
5444 5451
5445 /* See if there's a `:test TEST' among the arguments. */ 5452 /* See if there's a `:test TEST' among the arguments. */
5446 ptrdiff_t i = get_key_arg (QCtest, nargs, args, used); 5453 ptrdiff_t i = get_key_arg (QCtest, nargs, args, used);
5447 Lisp_Object test = i ? args[i] : Qeql; 5454 Lisp_Object test = i ? maybe_remove_pos_from_symbol (args[i]) : Qeql;
5448 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (test))
5449 test = SYMBOL_WITH_POS_SYM (test);
5450 const struct hash_table_test *testdesc; 5455 const struct hash_table_test *testdesc;
5451 if (BASE_EQ (test, Qeq)) 5456 if (BASE_EQ (test, Qeq))
5452 testdesc = &hashtest_eq; 5457 testdesc = &hashtest_eq;
@@ -5698,7 +5703,7 @@ DEFUN ("internal--hash-table-histogram",
5698 struct Lisp_Hash_Table *h = check_hash_table (hash_table); 5703 struct Lisp_Hash_Table *h = check_hash_table (hash_table);
5699 ptrdiff_t size = HASH_TABLE_SIZE (h); 5704 ptrdiff_t size = HASH_TABLE_SIZE (h);
5700 ptrdiff_t *freq = xzalloc (size * sizeof *freq); 5705 ptrdiff_t *freq = xzalloc (size * sizeof *freq);
5701 ptrdiff_t index_size = h->index_size; 5706 ptrdiff_t index_size = hash_table_index_size (h);
5702 for (ptrdiff_t i = 0; i < index_size; i++) 5707 for (ptrdiff_t i = 0; i < index_size; i++)
5703 { 5708 {
5704 ptrdiff_t n = 0; 5709 ptrdiff_t n = 0;
@@ -5726,7 +5731,7 @@ Internal use only. */)
5726{ 5731{
5727 struct Lisp_Hash_Table *h = check_hash_table (hash_table); 5732 struct Lisp_Hash_Table *h = check_hash_table (hash_table);
5728 Lisp_Object ret = Qnil; 5733 Lisp_Object ret = Qnil;
5729 ptrdiff_t index_size = h->index_size; 5734 ptrdiff_t index_size = hash_table_index_size (h);
5730 for (ptrdiff_t i = 0; i < index_size; i++) 5735 for (ptrdiff_t i = 0; i < index_size; i++)
5731 { 5736 {
5732 Lisp_Object bucket = Qnil; 5737 Lisp_Object bucket = Qnil;
@@ -5747,7 +5752,7 @@ DEFUN ("internal--hash-table-index-size",
5747 (Lisp_Object hash_table) 5752 (Lisp_Object hash_table)
5748{ 5753{
5749 struct Lisp_Hash_Table *h = check_hash_table (hash_table); 5754 struct Lisp_Hash_Table *h = check_hash_table (hash_table);
5750 return make_int (h->index_size); 5755 return make_int (hash_table_index_size (h));
5751} 5756}
5752 5757
5753 5758
@@ -6615,4 +6620,6 @@ For best results this should end in a space. */);
6615 6620
6616 DEFSYM (Qreal_this_command, "real-this-command"); 6621 DEFSYM (Qreal_this_command, "real-this-command");
6617 DEFSYM (Qfrom__tty_menu_p, "from--tty-menu-p"); 6622 DEFSYM (Qfrom__tty_menu_p, "from--tty-menu-p");
6623 DEFSYM (Qyes_or_no_p, "yes-or-no-p");
6624 DEFSYM (Qy_or_n_p, "y-or-n-p");
6618} 6625}
diff --git a/src/inotify.c b/src/inotify.c
index 2ee874530cc..7140568f1b6 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -26,6 +26,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26#include "termhooks.h" 26#include "termhooks.h"
27 27
28#include <errno.h> 28#include <errno.h>
29#include <fcntl.h>
30
29#include <sys/inotify.h> 31#include <sys/inotify.h>
30#include <sys/ioctl.h> 32#include <sys/ioctl.h>
31 33
@@ -434,7 +436,15 @@ IN_ONESHOT */)
434 436
435 if (inotifyfd < 0) 437 if (inotifyfd < 0)
436 { 438 {
439#ifdef HAVE_INOTIFY_INIT1
437 inotifyfd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC); 440 inotifyfd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC);
441#else /* !HAVE_INOTIFY_INIT1 */
442 /* This is prey to race conditions with other threads calling
443 exec. */
444 inotifyfd = inotify_init ();
445 fcntl (inotifyfd, F_SETFL, O_NONBLOCK);
446 fcntl (inotifyfd, F_SETFD, O_CLOEXEC);
447#endif /* HAVE_INOTIFY_INIT1 */
438 if (inotifyfd < 0) 448 if (inotifyfd < 0)
439 report_file_notify_error ("File watching is not available", Qnil); 449 report_file_notify_error ("File watching is not available", Qnil);
440 watch_list = Qnil; 450 watch_list = Qnil;
diff --git a/src/keyboard.c b/src/keyboard.c
index 1f7253a7da1..eb0de98bad1 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -580,7 +580,10 @@ echo_dash (void)
580 idx = make_fixnum (SCHARS (KVAR (current_kboard, echo_string)) - 1); 580 idx = make_fixnum (SCHARS (KVAR (current_kboard, echo_string)) - 1);
581 last_char = Faref (KVAR (current_kboard, echo_string), idx); 581 last_char = Faref (KVAR (current_kboard, echo_string), idx);
582 582
583 if (XFIXNUM (last_char) == '-' && XFIXNUM (prev_char) != ' ') 583 if ((XFIXNUM (last_char) == '-' && XFIXNUM (prev_char) != ' ')
584 /* Or a keystroke help message. */
585 || (echo_keystrokes_help
586 && XFIXNUM (last_char) == ')' && XFIXNUM (prev_char) == 'p'))
584 return; 587 return;
585 } 588 }
586 589
@@ -589,6 +592,12 @@ echo_dash (void)
589 AUTO_STRING (dash, "-"); 592 AUTO_STRING (dash, "-");
590 kset_echo_string (current_kboard, 593 kset_echo_string (current_kboard,
591 concat2 (KVAR (current_kboard, echo_string), dash)); 594 concat2 (KVAR (current_kboard, echo_string), dash));
595
596 if (echo_keystrokes_help)
597 kset_echo_string (current_kboard,
598 calln (Qhelp__append_keystrokes_help,
599 KVAR (current_kboard, echo_string)));
600
592 echo_now (); 601 echo_now ();
593} 602}
594 603
@@ -1067,8 +1076,9 @@ Default value of `command-error-function'. */)
1067 write to stderr and quit. In daemon mode, there are 1076 write to stderr and quit. In daemon mode, there are
1068 many other potential errors that do not prevent frames 1077 many other potential errors that do not prevent frames
1069 from being created, so continuing as normal is better in 1078 from being created, so continuing as normal is better in
1070 that case. */ 1079 that case, as long as the daemon has actually finished
1071 || (!IS_DAEMON && FRAME_INITIAL_P (sf)) 1080 initialization. */
1081 || (!(IS_DAEMON && !DAEMON_RUNNING) && FRAME_INITIAL_P (sf))
1072 || noninteractive)) 1082 || noninteractive))
1073 { 1083 {
1074 print_error_message (data, Qexternal_debugging_output, 1084 print_error_message (data, Qexternal_debugging_output,
@@ -12948,6 +12958,8 @@ syms_of_keyboard (void)
12948 12958
12949 DEFSYM (Qhelp_key_binding, "help-key-binding"); 12959 DEFSYM (Qhelp_key_binding, "help-key-binding");
12950 12960
12961 DEFSYM (Qhelp__append_keystrokes_help, "help--append-keystrokes-help");
12962
12951 DEFSYM (Qecho_keystrokes, "echo-keystrokes"); 12963 DEFSYM (Qecho_keystrokes, "echo-keystrokes");
12952 12964
12953 Fset (Qinput_method_exit_on_first_char, Qnil); 12965 Fset (Qinput_method_exit_on_first_char, Qnil);
@@ -13223,11 +13235,17 @@ Emacs also does a garbage collection if that seems to be warranted. */);
13223 XSETFASTINT (Vauto_save_timeout, 30); 13235 XSETFASTINT (Vauto_save_timeout, 30);
13224 13236
13225 DEFVAR_LISP ("echo-keystrokes", Vecho_keystrokes, 13237 DEFVAR_LISP ("echo-keystrokes", Vecho_keystrokes,
13226 doc: /* Nonzero means echo unfinished commands after this many seconds of pause. 13238 doc: /* Nonzero means echo unfinished commands after this many seconds of pause.
13227The value may be integer or floating point. 13239The value may be integer or floating point.
13228If the value is zero, don't echo at all. */); 13240If the value is zero, don't echo at all. */);
13229 Vecho_keystrokes = make_fixnum (1); 13241 Vecho_keystrokes = make_fixnum (1);
13230 13242
13243 DEFVAR_BOOL ("echo-keystrokes-help", echo_keystrokes_help,
13244 doc: /* Whether to append help text to echoed commands.
13245When non-nil, a reference to `C-h' is printed after echoed
13246keystrokes. */);
13247 echo_keystrokes_help = true;
13248
13231 DEFVAR_LISP ("polling-period", Vpolling_period, 13249 DEFVAR_LISP ("polling-period", Vpolling_period,
13232 doc: /* Interval between polling for input during Lisp execution. 13250 doc: /* Interval between polling for input during Lisp execution.
13233The reason for polling is to make C-g work to stop a running program. 13251The reason for polling is to make C-g work to stop a running program.
diff --git a/src/lisp.h b/src/lisp.h
index 75134425a07..4fc44745211 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -330,7 +330,8 @@ typedef EMACS_INT Lisp_Word;
330 without worrying about the implementations diverging, since 330 without worrying about the implementations diverging, since
331 lisp_h_OP defines the actual implementation. The lisp_h_OP macros 331 lisp_h_OP defines the actual implementation. The lisp_h_OP macros
332 are intended to be private to this include file, and should not be 332 are intended to be private to this include file, and should not be
333 used elsewhere. 333 used elsewhere. They should evaluate each argument exactly once,
334 so that they behave like their functional counterparts.
334 335
335 FIXME: Remove the lisp_h_OP macros, and define just the inline OP 336 FIXME: Remove the lisp_h_OP macros, and define just the inline OP
336 functions, once "gcc -Og" (new to GCC 4.8) or equivalent works well 337 functions, once "gcc -Og" (new to GCC 4.8) or equivalent works well
@@ -372,39 +373,12 @@ typedef EMACS_INT Lisp_Word;
372# define lisp_h_Qnil {0} 373# define lisp_h_Qnil {0}
373#endif 374#endif
374 375
375#define lisp_h_PSEUDOVECTORP(a,code) \
376 (lisp_h_VECTORLIKEP (a) \
377 && ((XUNTAG (a, Lisp_Vectorlike, union vectorlike_header)->size \
378 & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \
379 == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))))
380
381#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x) 376#define lisp_h_CHECK_FIXNUM(x) CHECK_TYPE (FIXNUMP (x), Qfixnump, x)
382#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x) 377#define lisp_h_CHECK_SYMBOL(x) CHECK_TYPE (SYMBOLP (x), Qsymbolp, x)
383#define lisp_h_CHECK_TYPE(ok, predicate, x) \ 378#define lisp_h_CHECK_TYPE(ok, predicate, x) \
384 ((ok) ? (void) 0 : wrong_type_argument (predicate, x)) 379 ((ok) ? (void) 0 : wrong_type_argument (predicate, x))
385#define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons) 380#define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons)
386#define lisp_h_BASE_EQ(x, y) (XLI (x) == XLI (y)) 381#define lisp_h_BASE_EQ(x, y) (XLI (x) == XLI (y))
387#define lisp_h_BASE2_EQ(x, y) \
388 (BASE_EQ (x, y) \
389 || (symbols_with_pos_enabled \
390 && SYMBOL_WITH_POS_P (x) \
391 && BASE_EQ (XSYMBOL_WITH_POS (x)->sym, y)))
392
393/* FIXME: Do we really need to inline the whole thing?
394 * What about keeping the part after `symbols_with_pos_enabled` in
395 * a separate function? */
396#define lisp_h_EQ(x, y) \
397 (XLI (x) == XLI (y) \
398 || (symbols_with_pos_enabled \
399 && (SYMBOL_WITH_POS_P (x) \
400 ? (BARE_SYMBOL_P (y) \
401 ? XLI (XSYMBOL_WITH_POS (x)->sym) == XLI (y) \
402 : (SYMBOL_WITH_POS_P (y) \
403 && (XLI (XSYMBOL_WITH_POS (x)->sym) \
404 == XLI (XSYMBOL_WITH_POS (y)->sym)))) \
405 : (SYMBOL_WITH_POS_P (y) \
406 && BARE_SYMBOL_P (x) \
407 && (XLI (x) == XLI (XSYMBOL_WITH_POS (y)->sym))))))
408 382
409#define lisp_h_FIXNUMP(x) \ 383#define lisp_h_FIXNUMP(x) \
410 (! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \ 384 (! (((unsigned) (XLI (x) >> (USE_LSB_TAG ? 0 : FIXNUM_BITS)) \
@@ -412,18 +386,11 @@ typedef EMACS_INT Lisp_Word;
412 & ((1 << INTTYPEBITS) - 1))) 386 & ((1 << INTTYPEBITS) - 1)))
413#define lisp_h_FLOATP(x) TAGGEDP (x, Lisp_Float) 387#define lisp_h_FLOATP(x) TAGGEDP (x, Lisp_Float)
414#define lisp_h_NILP(x) BASE_EQ (x, Qnil) 388#define lisp_h_NILP(x) BASE_EQ (x, Qnil)
415#define lisp_h_SET_SYMBOL_VAL(sym, v) \
416 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \
417 (sym)->u.s.val.value = (v))
418#define lisp_h_SYMBOL_CONSTANT_P(sym) \ 389#define lisp_h_SYMBOL_CONSTANT_P(sym) \
419 (XSYMBOL (sym)->u.s.trapped_write == SYMBOL_NOWRITE) 390 (XSYMBOL (sym)->u.s.trapped_write == SYMBOL_NOWRITE)
420#define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write) 391#define lisp_h_SYMBOL_TRAPPED_WRITE_P(sym) (XSYMBOL (sym)->u.s.trapped_write)
421#define lisp_h_SYMBOL_VAL(sym) \
422 (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), (sym)->u.s.val.value)
423#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP (x, PVEC_SYMBOL_WITH_POS) 392#define lisp_h_SYMBOL_WITH_POS_P(x) PSEUDOVECTORP (x, PVEC_SYMBOL_WITH_POS)
424#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP (x, Lisp_Symbol) 393#define lisp_h_BARE_SYMBOL_P(x) TAGGEDP (x, Lisp_Symbol)
425#define lisp_h_SYMBOLP(x) \
426 (BARE_SYMBOL_P (x) || (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (x)))
427#define lisp_h_TAGGEDP(a, tag) \ 394#define lisp_h_TAGGEDP(a, tag) \
428 (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \ 395 (! (((unsigned) (XLI (a) >> (USE_LSB_TAG ? 0 : VALBITS)) \
429 - (unsigned) (tag)) \ 396 - (unsigned) (tag)) \
@@ -431,8 +398,6 @@ typedef EMACS_INT Lisp_Word;
431#define lisp_h_VECTORLIKEP(x) TAGGEDP (x, Lisp_Vectorlike) 398#define lisp_h_VECTORLIKEP(x) TAGGEDP (x, Lisp_Vectorlike)
432#define lisp_h_XCAR(c) XCONS (c)->u.s.car 399#define lisp_h_XCAR(c) XCONS (c)->u.s.car
433#define lisp_h_XCDR(c) XCONS (c)->u.s.u.cdr 400#define lisp_h_XCDR(c) XCONS (c)->u.s.u.cdr
434#define lisp_h_XCONS(a) \
435 (eassert (CONSP (a)), XUNTAG (a, Lisp_Cons, struct Lisp_Cons))
436#define lisp_h_XHASH(a) XUFIXNUM_RAW (a) 401#define lisp_h_XHASH(a) XUFIXNUM_RAW (a)
437#if USE_LSB_TAG 402#if USE_LSB_TAG
438# define lisp_h_make_fixnum_wrap(n) \ 403# define lisp_h_make_fixnum_wrap(n) \
@@ -474,20 +439,15 @@ typedef EMACS_INT Lisp_Word;
474# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) 439# define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
475# define CONSP(x) lisp_h_CONSP (x) 440# define CONSP(x) lisp_h_CONSP (x)
476# define BASE_EQ(x, y) lisp_h_BASE_EQ (x, y) 441# define BASE_EQ(x, y) lisp_h_BASE_EQ (x, y)
477# define BASE2_EQ(x, y) lisp_h_BASE2_EQ (x, y)
478# define FLOATP(x) lisp_h_FLOATP (x) 442# define FLOATP(x) lisp_h_FLOATP (x)
479# define FIXNUMP(x) lisp_h_FIXNUMP (x) 443# define FIXNUMP(x) lisp_h_FIXNUMP (x)
480# define NILP(x) lisp_h_NILP (x) 444# define NILP(x) lisp_h_NILP (x)
481# define SET_SYMBOL_VAL(sym, v) lisp_h_SET_SYMBOL_VAL (sym, v)
482# define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym) 445# define SYMBOL_CONSTANT_P(sym) lisp_h_SYMBOL_CONSTANT_P (sym)
483# define SYMBOL_TRAPPED_WRITE_P(sym) lisp_h_SYMBOL_TRAPPED_WRITE_P (sym) 446# define SYMBOL_TRAPPED_WRITE_P(sym) lisp_h_SYMBOL_TRAPPED_WRITE_P (sym)
484# define SYMBOL_VAL(sym) lisp_h_SYMBOL_VAL (sym)
485/* # define SYMBOLP(x) lisp_h_SYMBOLP (x) */ /* X is accessed more than once. */
486# define TAGGEDP(a, tag) lisp_h_TAGGEDP (a, tag) 447# define TAGGEDP(a, tag) lisp_h_TAGGEDP (a, tag)
487# define VECTORLIKEP(x) lisp_h_VECTORLIKEP (x) 448# define VECTORLIKEP(x) lisp_h_VECTORLIKEP (x)
488# define XCAR(c) lisp_h_XCAR (c) 449# define XCAR(c) lisp_h_XCAR (c)
489# define XCDR(c) lisp_h_XCDR (c) 450# define XCDR(c) lisp_h_XCDR (c)
490# define XCONS(a) lisp_h_XCONS (a)
491# define XHASH(a) lisp_h_XHASH (a) 451# define XHASH(a) lisp_h_XHASH (a)
492# if USE_LSB_TAG 452# if USE_LSB_TAG
493# define make_fixnum(n) lisp_h_make_fixnum (n) 453# define make_fixnum(n) lisp_h_make_fixnum (n)
@@ -518,6 +478,16 @@ typedef EMACS_INT Lisp_Word;
518#endif 478#endif
519 479
520 480
481/* Lisp_Object tagging scheme:
482 Tag location
483 Upper bits Lower bits Type Payload
484 000....... .......000 symbol offset from lispsym to struct Lisp_Symbol
485 001....... .......001 unused
486 01........ ........10 fixnum signed integer of FIXNUM_BITS
487 110....... .......011 cons pointer to struct Lisp_Cons
488 100....... .......100 string pointer to struct Lisp_String
489 101....... .......101 vectorlike pointer to union vectorlike_header
490 111....... .......111 float pointer to struct Lisp_Float */
521enum Lisp_Type 491enum Lisp_Type
522 { 492 {
523 /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */ 493 /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */
@@ -1062,6 +1032,7 @@ enum pvec_type
1062 PVEC_BOOL_VECTOR, 1032 PVEC_BOOL_VECTOR,
1063 PVEC_BUFFER, 1033 PVEC_BUFFER,
1064 PVEC_HASH_TABLE, 1034 PVEC_HASH_TABLE,
1035 PVEC_OBARRAY,
1065 PVEC_TERMINAL, 1036 PVEC_TERMINAL,
1066 PVEC_WINDOW_CONFIGURATION, 1037 PVEC_WINDOW_CONFIGURATION,
1067 PVEC_SUBR, 1038 PVEC_SUBR,
@@ -1121,7 +1092,10 @@ enum More_Lisp_Bits
1121INLINE bool 1092INLINE bool
1122PSEUDOVECTORP (Lisp_Object a, int code) 1093PSEUDOVECTORP (Lisp_Object a, int code)
1123{ 1094{
1124 return lisp_h_PSEUDOVECTORP (a, code); 1095 return (lisp_h_VECTORLIKEP (a)
1096 && ((XUNTAG (a, Lisp_Vectorlike, union vectorlike_header)->size
1097 & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK))
1098 == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS))));
1125} 1099}
1126 1100
1127INLINE bool 1101INLINE bool
@@ -1137,9 +1111,10 @@ INLINE bool
1137} 1111}
1138 1112
1139INLINE bool 1113INLINE bool
1140(SYMBOLP) (Lisp_Object x) 1114SYMBOLP (Lisp_Object x)
1141{ 1115{
1142 return lisp_h_SYMBOLP (x); 1116 return (BARE_SYMBOL_P (x)
1117 || (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (x)));
1143} 1118}
1144 1119
1145INLINE struct Lisp_Symbol_With_Pos * 1120INLINE struct Lisp_Symbol_With_Pos *
@@ -1149,6 +1124,27 @@ XSYMBOL_WITH_POS (Lisp_Object a)
1149 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Symbol_With_Pos); 1124 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Symbol_With_Pos);
1150} 1125}
1151 1126
1127INLINE Lisp_Object
1128XSYMBOL_WITH_POS_SYM (Lisp_Object a)
1129{
1130 Lisp_Object sym = XSYMBOL_WITH_POS (a)->sym;
1131 eassume (BARE_SYMBOL_P (sym));
1132 return sym;
1133}
1134
1135INLINE Lisp_Object
1136XSYMBOL_WITH_POS_POS (Lisp_Object a)
1137{
1138 return XSYMBOL_WITH_POS (a)->pos;
1139}
1140
1141INLINE Lisp_Object
1142maybe_remove_pos_from_symbol (Lisp_Object x)
1143{
1144 return (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (x)
1145 ? XSYMBOL_WITH_POS_SYM (x) : x);
1146}
1147
1152INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED 1148INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED
1153XBARE_SYMBOL (Lisp_Object a) 1149XBARE_SYMBOL (Lisp_Object a)
1154{ 1150{
@@ -1163,8 +1159,8 @@ XSYMBOL (Lisp_Object a)
1163{ 1159{
1164 if (!BARE_SYMBOL_P (a)) 1160 if (!BARE_SYMBOL_P (a))
1165 { 1161 {
1166 eassert (symbols_with_pos_enabled); 1162 eassume (symbols_with_pos_enabled);
1167 a = XSYMBOL_WITH_POS (a)->sym; 1163 a = XSYMBOL_WITH_POS_SYM (a);
1168 } 1164 }
1169 return XBARE_SYMBOL (a); 1165 return XBARE_SYMBOL (a);
1170} 1166}
@@ -1352,20 +1348,15 @@ INLINE bool
1352 return lisp_h_BASE_EQ (x, y); 1348 return lisp_h_BASE_EQ (x, y);
1353} 1349}
1354 1350
1355/* Return true if X and Y are the same object, reckoning X to be the
1356 same as a bare symbol Y if X is Y with position. */
1357INLINE bool
1358(BASE2_EQ) (Lisp_Object x, Lisp_Object y)
1359{
1360 return lisp_h_BASE2_EQ (x, y);
1361}
1362
1363/* Return true if X and Y are the same object, reckoning a symbol with 1351/* Return true if X and Y are the same object, reckoning a symbol with
1364 position as being the same as the bare symbol. */ 1352 position as being the same as the bare symbol. */
1365INLINE bool 1353INLINE bool
1366(EQ) (Lisp_Object x, Lisp_Object y) 1354EQ (Lisp_Object x, Lisp_Object y)
1367{ 1355{
1368 return lisp_h_EQ (x, y); 1356 return BASE_EQ ((symbols_with_pos_enabled && SYMBOL_WITH_POS_P (x)
1357 ? XSYMBOL_WITH_POS_SYM (x) : x),
1358 (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (y)
1359 ? XSYMBOL_WITH_POS_SYM (y) : y));
1369} 1360}
1370 1361
1371INLINE intmax_t 1362INLINE intmax_t
@@ -1389,7 +1380,6 @@ make_lisp_ptr (void *ptr, enum Lisp_Type type)
1389#define XSETCONS(a, b) ((a) = make_lisp_ptr (b, Lisp_Cons)) 1380#define XSETCONS(a, b) ((a) = make_lisp_ptr (b, Lisp_Cons))
1390#define XSETVECTOR(a, b) ((a) = make_lisp_ptr (b, Lisp_Vectorlike)) 1381#define XSETVECTOR(a, b) ((a) = make_lisp_ptr (b, Lisp_Vectorlike))
1391#define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String)) 1382#define XSETSTRING(a, b) ((a) = make_lisp_ptr (b, Lisp_String))
1392#define XSETSYMBOL(a, b) ((a) = make_lisp_symbol (b))
1393#define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float)) 1383#define XSETFLOAT(a, b) ((a) = make_lisp_ptr (b, Lisp_Float))
1394 1384
1395/* Return a Lisp_Object value that does not correspond to any object. 1385/* Return a Lisp_Object value that does not correspond to any object.
@@ -1510,9 +1500,10 @@ CHECK_CONS (Lisp_Object x)
1510} 1500}
1511 1501
1512INLINE struct Lisp_Cons * 1502INLINE struct Lisp_Cons *
1513(XCONS) (Lisp_Object a) 1503XCONS (Lisp_Object a)
1514{ 1504{
1515 return lisp_h_XCONS (a); 1505 eassert (CONSP (a));
1506 return XUNTAG (a, Lisp_Cons, struct Lisp_Cons);
1516} 1507}
1517 1508
1518/* Take the car or cdr of something known to be a cons cell. */ 1509/* Take the car or cdr of something known to be a cons cell. */
@@ -2297,9 +2288,10 @@ typedef jmp_buf sys_jmp_buf;
2297/* Value is name of symbol. */ 2288/* Value is name of symbol. */
2298 2289
2299INLINE Lisp_Object 2290INLINE Lisp_Object
2300(SYMBOL_VAL) (struct Lisp_Symbol *sym) 2291SYMBOL_VAL (struct Lisp_Symbol *sym)
2301{ 2292{
2302 return lisp_h_SYMBOL_VAL (sym); 2293 eassert (sym->u.s.redirect == SYMBOL_PLAINVAL);
2294 return sym->u.s.val.value;
2303} 2295}
2304 2296
2305INLINE struct Lisp_Symbol * 2297INLINE struct Lisp_Symbol *
@@ -2322,9 +2314,10 @@ SYMBOL_FWD (struct Lisp_Symbol *sym)
2322} 2314}
2323 2315
2324INLINE void 2316INLINE void
2325(SET_SYMBOL_VAL) (struct Lisp_Symbol *sym, Lisp_Object v) 2317SET_SYMBOL_VAL (struct Lisp_Symbol *sym, Lisp_Object v)
2326{ 2318{
2327 lisp_h_SET_SYMBOL_VAL (sym, v); 2319 eassert (sym->u.s.redirect == SYMBOL_PLAINVAL);
2320 sym->u.s.val.value = v;
2328} 2321}
2329 2322
2330INLINE void 2323INLINE void
@@ -2393,6 +2386,118 @@ INLINE int
2393 definition is done by lread.c's define_symbol. */ 2386 definition is done by lread.c's define_symbol. */
2394#define DEFSYM(sym, name) /* empty */ 2387#define DEFSYM(sym, name) /* empty */
2395 2388
2389
2390struct Lisp_Obarray
2391{
2392 union vectorlike_header header;
2393
2394 /* Array of 2**size_bits values, each being either a (bare) symbol or
2395 the fixnum 0. The symbols for each bucket are chained via
2396 their s.next field. */
2397 Lisp_Object *buckets;
2398
2399 unsigned size_bits; /* log2(size of buckets vector) */
2400 unsigned count; /* number of symbols in obarray */
2401};
2402
2403INLINE bool
2404OBARRAYP (Lisp_Object a)
2405{
2406 return PSEUDOVECTORP (a, PVEC_OBARRAY);
2407}
2408
2409INLINE struct Lisp_Obarray *
2410XOBARRAY (Lisp_Object a)
2411{
2412 eassert (OBARRAYP (a));
2413 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Obarray);
2414}
2415
2416INLINE void
2417CHECK_OBARRAY (Lisp_Object x)
2418{
2419 CHECK_TYPE (OBARRAYP (x), Qobarrayp, x);
2420}
2421
2422INLINE Lisp_Object
2423make_lisp_obarray (struct Lisp_Obarray *o)
2424{
2425 eassert (PSEUDOVECTOR_TYPEP (&o->header, PVEC_OBARRAY));
2426 return make_lisp_ptr (o, Lisp_Vectorlike);
2427}
2428
2429INLINE ptrdiff_t
2430obarray_size (const struct Lisp_Obarray *o)
2431{
2432 return (ptrdiff_t)1 << o->size_bits;
2433}
2434
2435Lisp_Object check_obarray_slow (Lisp_Object);
2436
2437/* Return an obarray object from OBARRAY or signal an error. */
2438INLINE Lisp_Object
2439check_obarray (Lisp_Object obarray)
2440{
2441 return OBARRAYP (obarray) ? obarray : check_obarray_slow (obarray);
2442}
2443
2444/* Obarray iterator state. Don't access these members directly.
2445 The iterator functions must be called in the order followed by DOOBARRAY. */
2446typedef struct {
2447 struct Lisp_Obarray *o;
2448 ptrdiff_t idx; /* Current bucket index. */
2449 struct Lisp_Symbol *symbol; /* Current symbol, or NULL if at end
2450 of current bucket. */
2451} obarray_iter_t;
2452
2453INLINE obarray_iter_t
2454make_obarray_iter (struct Lisp_Obarray *oa)
2455{
2456 return (obarray_iter_t){.o = oa, .idx = -1, .symbol = NULL};
2457}
2458
2459/* Whether IT has reached the end and there are no more symbols.
2460 If true, IT is dead and cannot be used any more. */
2461INLINE bool
2462obarray_iter_at_end (obarray_iter_t *it)
2463{
2464 if (it->symbol)
2465 return false;
2466 ptrdiff_t size = obarray_size (it->o);
2467 while (++it->idx < size)
2468 {
2469 Lisp_Object obj = it->o->buckets[it->idx];
2470 if (!BASE_EQ (obj, make_fixnum (0)))
2471 {
2472 it->symbol = XBARE_SYMBOL (obj);
2473 return false;
2474 }
2475 }
2476 return true;
2477}
2478
2479/* Advance IT to the next symbol if any. */
2480INLINE void
2481obarray_iter_step (obarray_iter_t *it)
2482{
2483 it->symbol = it->symbol->u.s.next;
2484}
2485
2486/* The Lisp symbol at IT, if obarray_iter_at_end returned false. */
2487INLINE Lisp_Object
2488obarray_iter_symbol (obarray_iter_t *it)
2489{
2490 return make_lisp_symbol (it->symbol);
2491}
2492
2493/* Iterate IT over the symbols of the obarray OA.
2494 The body shouldn't add or remove symbols in OA, but disobeying that rule
2495 only risks symbols to be iterated more than once or not at all,
2496 not crashes or data corruption. */
2497#define DOOBARRAY(oa, it) \
2498 for (obarray_iter_t it = make_obarray_iter (oa); \
2499 !obarray_iter_at_end (&it); obarray_iter_step (&it))
2500
2396 2501
2397/*********************************************************************** 2502/***********************************************************************
2398 Hash Tables 2503 Hash Tables
@@ -2475,14 +2580,11 @@ struct Lisp_Hash_Table
2475 The table is physically split into three vectors (hash, next, 2580 The table is physically split into three vectors (hash, next,
2476 key_and_value) which may or may not be beneficial. */ 2581 key_and_value) which may or may not be beneficial. */
2477 2582
2478 hash_idx_t index_size; /* Size of the index vector. */
2479 hash_idx_t table_size; /* Size of the next and hash vectors. */
2480
2481 /* Bucket vector. An entry of -1 indicates no item is present, 2583 /* Bucket vector. An entry of -1 indicates no item is present,
2482 and a nonnegative entry is the index of the first item in 2584 and a nonnegative entry is the index of the first item in
2483 a collision chain. 2585 a collision chain.
2484 This vector is index_size entries long. 2586 This vector is 2**index_bits entries long.
2485 If index_size is 1 (and table_size is 0), then this is the 2587 If index_bits is 0 (and table_size is 0), then this is the
2486 constant read-only vector {-1}, shared between all instances. 2588 constant read-only vector {-1}, shared between all instances.
2487 Otherwise it is heap-allocated. */ 2589 Otherwise it is heap-allocated. */
2488 hash_idx_t *index; 2590 hash_idx_t *index;
@@ -2514,20 +2616,24 @@ struct Lisp_Hash_Table
2514 /* Index of first free entry in free list, or -1 if none. */ 2616 /* Index of first free entry in free list, or -1 if none. */
2515 hash_idx_t next_free; 2617 hash_idx_t next_free;
2516 2618
2619 hash_idx_t table_size; /* Size of the next and hash vectors. */
2620
2621 unsigned char index_bits; /* log2 (size of the index vector). */
2622
2517 /* Weakness of the table. */ 2623 /* Weakness of the table. */
2518 hash_table_weakness_t weakness : 8; 2624 hash_table_weakness_t weakness : 3;
2519 2625
2520 /* Hash table test (only used when frozen in dump) */ 2626 /* Hash table test (only used when frozen in dump) */
2521 hash_table_std_test_t frozen_test : 8; 2627 hash_table_std_test_t frozen_test : 2;
2522 2628
2523 /* True if the table can be purecopied. The table cannot be 2629 /* True if the table can be purecopied. The table cannot be
2524 changed afterwards. */ 2630 changed afterwards. */
2525 bool purecopy; 2631 bool_bf purecopy : 1;
2526 2632
2527 /* True if the table is mutable. Ordinarily tables are mutable, but 2633 /* True if the table is mutable. Ordinarily tables are mutable, but
2528 pure tables are not, and while a table is being mutated it is 2634 pure tables are not, and while a table is being mutated it is
2529 immutable for recursive attempts to mutate it. */ 2635 immutable for recursive attempts to mutate it. */
2530 bool mutable; 2636 bool_bf mutable : 1;
2531 2637
2532 /* Next weak hash table if this is a weak hash table. The head of 2638 /* Next weak hash table if this is a weak hash table. The head of
2533 the list is in weak_hash_tables. Used only during garbage 2639 the list is in weak_hash_tables. Used only during garbage
@@ -2563,8 +2669,12 @@ XHASH_TABLE (Lisp_Object a)
2563 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Hash_Table); 2669 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Hash_Table);
2564} 2670}
2565 2671
2566#define XSET_HASH_TABLE(VAR, PTR) \ 2672INLINE Lisp_Object
2567 XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE) 2673make_lisp_hash_table (struct Lisp_Hash_Table *h)
2674{
2675 eassert (PSEUDOVECTOR_TYPEP (&h->header, PVEC_HASH_TABLE));
2676 return make_lisp_ptr (h, Lisp_Vectorlike);
2677}
2568 2678
2569/* Value is the key part of entry IDX in hash table H. */ 2679/* Value is the key part of entry IDX in hash table H. */
2570INLINE Lisp_Object 2680INLINE Lisp_Object
@@ -2597,6 +2707,13 @@ HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
2597 return h->table_size; 2707 return h->table_size;
2598} 2708}
2599 2709
2710/* Size of the index vector in hash table H. */
2711INLINE ptrdiff_t
2712hash_table_index_size (const struct Lisp_Hash_Table *h)
2713{
2714 return (ptrdiff_t)1 << h->index_bits;
2715}
2716
2600/* Hash value for KEY in hash table H. */ 2717/* Hash value for KEY in hash table H. */
2601INLINE hash_hash_t 2718INLINE hash_hash_t
2602hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key) 2719hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key)
@@ -2661,6 +2778,28 @@ SXHASH_REDUCE (EMACS_UINT x)
2661 return (x ^ x >> (EMACS_INT_WIDTH - FIXNUM_BITS)) & INTMASK; 2778 return (x ^ x >> (EMACS_INT_WIDTH - FIXNUM_BITS)) & INTMASK;
2662} 2779}
2663 2780
2781/* Reduce an EMACS_UINT hash value to hash_hash_t. */
2782INLINE hash_hash_t
2783reduce_emacs_uint_to_hash_hash (EMACS_UINT x)
2784{
2785 verify (sizeof x <= 2 * sizeof (hash_hash_t));
2786 return (sizeof x == sizeof (hash_hash_t)
2787 ? x
2788 : x ^ (x >> (8 * (sizeof x - sizeof (hash_hash_t)))));
2789}
2790
2791/* Reduce HASH to a value BITS wide. */
2792INLINE ptrdiff_t
2793knuth_hash (hash_hash_t hash, unsigned bits)
2794{
2795 /* Knuth multiplicative hashing, tailored for 32-bit indices
2796 (avoiding a 64-bit multiply). */
2797 uint32_t alpha = 2654435769; /* 2**32/phi */
2798 /* Note the cast to uint64_t, to make it work for bits=0. */
2799 return (uint64_t)((uint32_t)hash * alpha) >> (32 - bits);
2800}
2801
2802
2664struct Lisp_Marker 2803struct Lisp_Marker
2665{ 2804{
2666 union vectorlike_header header; 2805 union vectorlike_header header;
@@ -2839,22 +2978,6 @@ XOVERLAY (Lisp_Object a)
2839 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay); 2978 return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Overlay);
2840} 2979}
2841 2980
2842INLINE Lisp_Object
2843SYMBOL_WITH_POS_SYM (Lisp_Object a)
2844{
2845 if (!SYMBOL_WITH_POS_P (a))
2846 wrong_type_argument (Qsymbol_with_pos_p, a);
2847 return XSYMBOL_WITH_POS (a)->sym;
2848}
2849
2850INLINE Lisp_Object
2851SYMBOL_WITH_POS_POS (Lisp_Object a)
2852{
2853 if (!SYMBOL_WITH_POS_P (a))
2854 wrong_type_argument (Qsymbol_with_pos_p, a);
2855 return XSYMBOL_WITH_POS (a)->pos;
2856}
2857
2858INLINE bool 2981INLINE bool
2859USER_PTRP (Lisp_Object x) 2982USER_PTRP (Lisp_Object x)
2860{ 2983{
@@ -4596,7 +4719,6 @@ extern ptrdiff_t evxprintf (char **, ptrdiff_t *, char *, ptrdiff_t,
4596 ATTRIBUTE_FORMAT_PRINTF (5, 0); 4719 ATTRIBUTE_FORMAT_PRINTF (5, 0);
4597 4720
4598/* Defined in lread.c. */ 4721/* Defined in lread.c. */
4599extern Lisp_Object check_obarray (Lisp_Object);
4600extern Lisp_Object intern_1 (const char *, ptrdiff_t); 4722extern Lisp_Object intern_1 (const char *, ptrdiff_t);
4601extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t); 4723extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t);
4602extern Lisp_Object intern_driver (Lisp_Object, Lisp_Object, Lisp_Object); 4724extern Lisp_Object intern_driver (Lisp_Object, Lisp_Object, Lisp_Object);
@@ -4802,7 +4924,7 @@ extern void syms_of_editfns (void);
4802 4924
4803/* Defined in buffer.c. */ 4925/* Defined in buffer.c. */
4804extern bool mouse_face_overlay_overlaps (Lisp_Object); 4926extern bool mouse_face_overlay_overlaps (Lisp_Object);
4805extern Lisp_Object disable_line_numbers_overlay_at_eob (void); 4927extern bool disable_line_numbers_overlay_at_eob (void);
4806extern AVOID nsberror (Lisp_Object); 4928extern AVOID nsberror (Lisp_Object);
4807extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool); 4929extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool);
4808extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); 4930extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);
@@ -5030,6 +5152,7 @@ extern bool build_details;
5030/* 0 not a daemon, 1 foreground daemon, 2 background daemon. */ 5152/* 0 not a daemon, 1 foreground daemon, 2 background daemon. */
5031extern int daemon_type; 5153extern int daemon_type;
5032#define IS_DAEMON (daemon_type != 0) 5154#define IS_DAEMON (daemon_type != 0)
5155/* Non-zero means daemon-initialized has not yet been called. */
5033#define DAEMON_RUNNING (daemon_type >= 0) 5156#define DAEMON_RUNNING (daemon_type >= 0)
5034#else /* WINDOWSNT */ 5157#else /* WINDOWSNT */
5035extern void *w32_daemon_event; 5158extern void *w32_daemon_event;
@@ -5550,7 +5673,7 @@ safe_free_unbind_to (specpdl_ref count, specpdl_ref sa_count, Lisp_Object val)
5550 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109577 5673 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109577
5551 which causes GCC to mistakenly complain about the 5674 which causes GCC to mistakenly complain about the
5552 memory allocation in SAFE_ALLOCA_LISP_EXTRA. */ 5675 memory allocation in SAFE_ALLOCA_LISP_EXTRA. */
5553#if GNUC_PREREQ (13, 0, 0) 5676#if GNUC_PREREQ (13, 0, 0) && !GNUC_PREREQ (14, 0, 0)
5554# pragma GCC diagnostic ignored "-Wanalyzer-allocation-size" 5677# pragma GCC diagnostic ignored "-Wanalyzer-allocation-size"
5555#endif 5678#endif
5556 5679
diff --git a/src/lread.c b/src/lread.c
index 929f86ef283..49683d02401 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2369,8 +2369,14 @@ build_load_history (Lisp_Object filename, bool entire)
2369 front of load-history, the most-recently-loaded position. Also 2369 front of load-history, the most-recently-loaded position. Also
2370 do this if we didn't find an existing member for the file. */ 2370 do this if we didn't find an existing member for the file. */
2371 if (entire || !foundit) 2371 if (entire || !foundit)
2372 Vload_history = Fcons (Fnreverse (Vcurrent_load_list), 2372 {
2373 Vload_history); 2373 Lisp_Object tem = Fnreverse (Vcurrent_load_list);
2374 eassert (EQ (filename, Fcar (tem)));
2375 Vload_history = Fcons (tem, Vload_history);
2376 /* FIXME: There should be an unbind_to right after calling us which
2377 should re-establish the previous value of Vcurrent_load_list. */
2378 Vcurrent_load_list = Qt;
2379 }
2374} 2380}
2375 2381
2376static void 2382static void
@@ -2437,11 +2443,13 @@ readevalloop (Lisp_Object readcharfun,
2437 bool whole_buffer = 0; 2443 bool whole_buffer = 0;
2438 /* True on the first time around. */ 2444 /* True on the first time around. */
2439 bool first_sexp = 1; 2445 bool first_sexp = 1;
2440 Lisp_Object macroexpand = intern ("internal-macroexpand-for-load"); 2446 Lisp_Object macroexpand;
2441 2447
2442 if (!NILP (sourcename)) 2448 if (!NILP (sourcename))
2443 CHECK_STRING (sourcename); 2449 CHECK_STRING (sourcename);
2444 2450
2451 macroexpand = Qinternal_macroexpand_for_load;
2452
2445 if (NILP (Ffboundp (macroexpand)) 2453 if (NILP (Ffboundp (macroexpand))
2446 || (STRINGP (sourcename) && suffix_p (sourcename, ".elc"))) 2454 || (STRINGP (sourcename) && suffix_p (sourcename, ".elc")))
2447 /* Don't macroexpand before the corresponding function is defined 2455 /* Don't macroexpand before the corresponding function is defined
@@ -3481,6 +3489,8 @@ vector_from_rev_list (Lisp_Object elems)
3481 return obj; 3489 return obj;
3482} 3490}
3483 3491
3492static Lisp_Object get_lazy_string (Lisp_Object val);
3493
3484static Lisp_Object 3494static Lisp_Object
3485bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) 3495bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3486{ 3496{
@@ -3488,49 +3498,50 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun)
3488 Lisp_Object *vec = XVECTOR (obj)->contents; 3498 Lisp_Object *vec = XVECTOR (obj)->contents;
3489 ptrdiff_t size = ASIZE (obj); 3499 ptrdiff_t size = ASIZE (obj);
3490 3500
3501 if (infile && size >= COMPILED_CONSTANTS)
3502 {
3503 /* Always read 'lazily-loaded' bytecode (generated by the
3504 `byte-compile-dynamic' feature prior to Emacs 30) eagerly, to
3505 avoid code in the fast path during execution. */
3506 if (CONSP (vec[COMPILED_BYTECODE])
3507 && FIXNUMP (XCDR (vec[COMPILED_BYTECODE])))
3508 vec[COMPILED_BYTECODE] = get_lazy_string (vec[COMPILED_BYTECODE]);
3509
3510 /* Lazily-loaded bytecode is represented by the constant slot being nil
3511 and the bytecode slot a (lazily loaded) string containing the
3512 print representation of (BYTECODE . CONSTANTS). Unpack the
3513 pieces by coerceing the string to unibyte and reading the result. */
3514 if (NILP (vec[COMPILED_CONSTANTS]) && STRINGP (vec[COMPILED_BYTECODE]))
3515 {
3516 Lisp_Object enc = vec[COMPILED_BYTECODE];
3517 Lisp_Object pair = Fread (Fcons (enc, readcharfun));
3518 if (!CONSP (pair))
3519 invalid_syntax ("Invalid byte-code object", readcharfun);
3520
3521 vec[COMPILED_BYTECODE] = XCAR (pair);
3522 vec[COMPILED_CONSTANTS] = XCDR (pair);
3523 }
3524 }
3525
3491 if (!(size >= COMPILED_STACK_DEPTH + 1 && size <= COMPILED_INTERACTIVE + 1 3526 if (!(size >= COMPILED_STACK_DEPTH + 1 && size <= COMPILED_INTERACTIVE + 1
3492 && (FIXNUMP (vec[COMPILED_ARGLIST]) 3527 && (FIXNUMP (vec[COMPILED_ARGLIST])
3493 || CONSP (vec[COMPILED_ARGLIST]) 3528 || CONSP (vec[COMPILED_ARGLIST])
3494 || NILP (vec[COMPILED_ARGLIST])) 3529 || NILP (vec[COMPILED_ARGLIST]))
3530 && STRINGP (vec[COMPILED_BYTECODE])
3531 && VECTORP (vec[COMPILED_CONSTANTS])
3495 && FIXNATP (vec[COMPILED_STACK_DEPTH]))) 3532 && FIXNATP (vec[COMPILED_STACK_DEPTH])))
3496 invalid_syntax ("Invalid byte-code object", readcharfun); 3533 invalid_syntax ("Invalid byte-code object", readcharfun);
3497 3534
3498 if (load_force_doc_strings 3535 if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE]))
3499 && NILP (vec[COMPILED_CONSTANTS]) 3536 /* BYTESTR must have been produced by Emacs 20.2 or earlier
3500 && STRINGP (vec[COMPILED_BYTECODE])) 3537 because it produced a raw 8-bit string for byte-code and
3501 { 3538 now such a byte-code string is loaded as multibyte with
3502 /* Lazily-loaded bytecode is represented by the constant slot being nil 3539 raw 8-bit characters converted to multibyte form.
3503 and the bytecode slot a (lazily loaded) string containing the 3540 Convert them back to the original unibyte form. */
3504 print representation of (BYTECODE . CONSTANTS). Unpack the 3541 vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]);
3505 pieces by coerceing the string to unibyte and reading the result. */
3506 Lisp_Object enc = vec[COMPILED_BYTECODE];
3507 Lisp_Object pair = Fread (Fcons (enc, readcharfun));
3508 if (!CONSP (pair))
3509 invalid_syntax ("Invalid byte-code object", readcharfun);
3510
3511 vec[COMPILED_BYTECODE] = XCAR (pair);
3512 vec[COMPILED_CONSTANTS] = XCDR (pair);
3513 }
3514
3515 if (!((STRINGP (vec[COMPILED_BYTECODE])
3516 && VECTORP (vec[COMPILED_CONSTANTS]))
3517 || CONSP (vec[COMPILED_BYTECODE])))
3518 invalid_syntax ("Invalid byte-code object", readcharfun);
3519 3542
3520 if (STRINGP (vec[COMPILED_BYTECODE])) 3543 /* Bytecode must be immovable. */
3521 { 3544 pin_string (vec[COMPILED_BYTECODE]);
3522 if (STRING_MULTIBYTE (vec[COMPILED_BYTECODE]))
3523 {
3524 /* BYTESTR must have been produced by Emacs 20.2 or earlier
3525 because it produced a raw 8-bit string for byte-code and
3526 now such a byte-code string is loaded as multibyte with
3527 raw 8-bit characters converted to multibyte form.
3528 Convert them back to the original unibyte form. */
3529 vec[COMPILED_BYTECODE] = Fstring_as_unibyte (vec[COMPILED_BYTECODE]);
3530 }
3531 /* Bytecode must be immovable. */
3532 pin_string (vec[COMPILED_BYTECODE]);
3533 }
3534 3545
3535 XSETPVECTYPE (XVECTOR (obj), PVEC_COMPILED); 3546 XSETPVECTYPE (XVECTOR (obj), PVEC_COMPILED);
3536 return obj; 3547 return obj;
@@ -4469,7 +4480,7 @@ read0 (Lisp_Object readcharfun, bool locate_syms)
4469 &longhand_chars, 4480 &longhand_chars,
4470 &longhand_bytes); 4481 &longhand_bytes);
4471 4482
4472 if (SYMBOLP (found)) 4483 if (BARE_SYMBOL_P (found))
4473 result = found; 4484 result = found;
4474 else if (longhand) 4485 else if (longhand)
4475 { 4486 {
@@ -4875,49 +4886,65 @@ static Lisp_Object initial_obarray;
4875 4886
4876static size_t oblookup_last_bucket_number; 4887static size_t oblookup_last_bucket_number;
4877 4888
4878/* Get an error if OBARRAY is not an obarray. 4889static Lisp_Object make_obarray (unsigned bits);
4879 If it is one, return it. */
4880 4890
4891/* Slow path obarray check: return the obarray to use or signal an error. */
4881Lisp_Object 4892Lisp_Object
4882check_obarray (Lisp_Object obarray) 4893check_obarray_slow (Lisp_Object obarray)
4883{ 4894{
4884 /* We don't want to signal a wrong-type-argument error when we are 4895 /* For compatibility, we accept vectors whose first element is 0,
4885 shutting down due to a fatal error, and we don't want to hit 4896 and store an obarray object there. */
4886 assertions in VECTORP and ASIZE if the fatal error was during GC. */ 4897 if (VECTORP (obarray) && ASIZE (obarray) > 0)
4887 if (!fatal_error_in_progress
4888 && (!VECTORP (obarray) || ASIZE (obarray) == 0))
4889 { 4898 {
4890 /* If Vobarray is now invalid, force it to be valid. */ 4899 Lisp_Object obj = AREF (obarray, 0);
4891 if (EQ (Vobarray, obarray)) Vobarray = initial_obarray; 4900 if (OBARRAYP (obj))
4892 wrong_type_argument (Qvectorp, obarray); 4901 return obj;
4902 if (BASE_EQ (obj, make_fixnum (0)))
4903 {
4904 /* Put an actual obarray object in the first slot.
4905 The rest of the vector remains unused. */
4906 obj = make_obarray (0);
4907 ASET (obarray, 0, obj);
4908 return obj;
4909 }
4893 } 4910 }
4894 return obarray; 4911 /* Reset Vobarray to the standard obarray for nicer error handling. */
4912 if (BASE_EQ (Vobarray, obarray)) Vobarray = initial_obarray;
4913
4914 wrong_type_argument (Qobarrayp, obarray);
4895} 4915}
4896 4916
4917static void grow_obarray (struct Lisp_Obarray *o);
4918
4897/* Intern symbol SYM in OBARRAY using bucket INDEX. */ 4919/* Intern symbol SYM in OBARRAY using bucket INDEX. */
4898 4920
4921/* FIXME: retype arguments as pure C types */
4899static Lisp_Object 4922static Lisp_Object
4900intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index) 4923intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index)
4901{ 4924{
4902 Lisp_Object *ptr; 4925 eassert (BARE_SYMBOL_P (sym) && OBARRAYP (obarray) && FIXNUMP (index));
4926 struct Lisp_Symbol *s = XBARE_SYMBOL (sym);
4927 s->u.s.interned = (BASE_EQ (obarray, initial_obarray)
4928 ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY
4929 : SYMBOL_INTERNED);
4903 4930
4904 XSYMBOL (sym)->u.s.interned = (EQ (obarray, initial_obarray) 4931 if (SREF (s->u.s.name, 0) == ':' && BASE_EQ (obarray, initial_obarray))
4905 ? SYMBOL_INTERNED_IN_INITIAL_OBARRAY
4906 : SYMBOL_INTERNED);
4907
4908 if (SREF (SYMBOL_NAME (sym), 0) == ':' && EQ (obarray, initial_obarray))
4909 { 4932 {
4910 make_symbol_constant (sym); 4933 s->u.s.trapped_write = SYMBOL_NOWRITE;
4911 XSYMBOL (sym)->u.s.redirect = SYMBOL_PLAINVAL; 4934 s->u.s.redirect = SYMBOL_PLAINVAL;
4912 /* Mark keywords as special. This makes (let ((:key 'foo)) ...) 4935 /* Mark keywords as special. This makes (let ((:key 'foo)) ...)
4913 in lexically bound elisp signal an error, as documented. */ 4936 in lexically bound elisp signal an error, as documented. */
4914 XSYMBOL (sym)->u.s.declared_special = true; 4937 s->u.s.declared_special = true;
4915 SET_SYMBOL_VAL (XSYMBOL (sym), sym); 4938 SET_SYMBOL_VAL (s, sym);
4916 } 4939 }
4917 4940
4918 ptr = aref_addr (obarray, XFIXNUM (index)); 4941 struct Lisp_Obarray *o = XOBARRAY (obarray);
4919 set_symbol_next (sym, SYMBOLP (*ptr) ? XSYMBOL (*ptr) : NULL); 4942 Lisp_Object *ptr = o->buckets + XFIXNUM (index);
4943 s->u.s.next = BARE_SYMBOL_P (*ptr) ? XBARE_SYMBOL (*ptr) : NULL;
4920 *ptr = sym; 4944 *ptr = sym;
4945 o->count++;
4946 if (o->count > obarray_size (o))
4947 grow_obarray (o);
4921 return sym; 4948 return sym;
4922} 4949}
4923 4950
@@ -4926,7 +4953,7 @@ intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index)
4926Lisp_Object 4953Lisp_Object
4927intern_driver (Lisp_Object string, Lisp_Object obarray, Lisp_Object index) 4954intern_driver (Lisp_Object string, Lisp_Object obarray, Lisp_Object index)
4928{ 4955{
4929 SET_SYMBOL_VAL (XSYMBOL (Qobarray_cache), Qnil); 4956 SET_SYMBOL_VAL (XBARE_SYMBOL (Qobarray_cache), Qnil);
4930 return intern_sym (Fmake_symbol (string), obarray, index); 4957 return intern_sym (Fmake_symbol (string), obarray, index);
4931} 4958}
4932 4959
@@ -4939,7 +4966,7 @@ intern_1 (const char *str, ptrdiff_t len)
4939 Lisp_Object obarray = check_obarray (Vobarray); 4966 Lisp_Object obarray = check_obarray (Vobarray);
4940 Lisp_Object tem = oblookup (obarray, str, len, len); 4967 Lisp_Object tem = oblookup (obarray, str, len, len);
4941 4968
4942 return (SYMBOLP (tem) ? tem 4969 return (BARE_SYMBOL_P (tem) ? tem
4943 /* The above `oblookup' was done on the basis of nchars==nbytes, so 4970 /* The above `oblookup' was done on the basis of nchars==nbytes, so
4944 the string has to be unibyte. */ 4971 the string has to be unibyte. */
4945 : intern_driver (make_unibyte_string (str, len), 4972 : intern_driver (make_unibyte_string (str, len),
@@ -4952,7 +4979,7 @@ intern_c_string_1 (const char *str, ptrdiff_t len)
4952 Lisp_Object obarray = check_obarray (Vobarray); 4979 Lisp_Object obarray = check_obarray (Vobarray);
4953 Lisp_Object tem = oblookup (obarray, str, len, len); 4980 Lisp_Object tem = oblookup (obarray, str, len, len);
4954 4981
4955 if (!SYMBOLP (tem)) 4982 if (!BARE_SYMBOL_P (tem))
4956 { 4983 {
4957 Lisp_Object string; 4984 Lisp_Object string;
4958 4985
@@ -5004,7 +5031,7 @@ it defaults to the value of `obarray'. */)
5004 &longhand, &longhand_chars, 5031 &longhand, &longhand_chars,
5005 &longhand_bytes); 5032 &longhand_bytes);
5006 5033
5007 if (!SYMBOLP (tem)) 5034 if (!BARE_SYMBOL_P (tem))
5008 { 5035 {
5009 if (longhand) 5036 if (longhand)
5010 { 5037 {
@@ -5053,10 +5080,11 @@ it defaults to the value of `obarray'. */)
5053 { 5080 {
5054 /* If already a symbol, we don't do shorthand-longhand translation, 5081 /* If already a symbol, we don't do shorthand-longhand translation,
5055 as promised in the docstring. */ 5082 as promised in the docstring. */
5056 string = SYMBOL_NAME (name); 5083 Lisp_Object sym = maybe_remove_pos_from_symbol (name);
5084 string = XSYMBOL (name)->u.s.name;
5057 tem 5085 tem
5058 = oblookup (obarray, SSDATA (string), SCHARS (string), SBYTES (string)); 5086 = oblookup (obarray, SSDATA (string), SCHARS (string), SBYTES (string));
5059 return EQ (name, tem) ? name : Qnil; 5087 return BASE_EQ (sym, tem) ? name : Qnil;
5060 } 5088 }
5061} 5089}
5062 5090
@@ -5071,13 +5099,16 @@ usage: (unintern NAME OBARRAY) */)
5071{ 5099{
5072 register Lisp_Object tem; 5100 register Lisp_Object tem;
5073 Lisp_Object string; 5101 Lisp_Object string;
5074 size_t hash;
5075 5102
5076 if (NILP (obarray)) obarray = Vobarray; 5103 if (NILP (obarray)) obarray = Vobarray;
5077 obarray = check_obarray (obarray); 5104 obarray = check_obarray (obarray);
5078 5105
5079 if (SYMBOLP (name)) 5106 if (SYMBOLP (name))
5080 string = SYMBOL_NAME (name); 5107 {
5108 if (!BARE_SYMBOL_P (name))
5109 name = XSYMBOL_WITH_POS (name)->sym;
5110 string = SYMBOL_NAME (name);
5111 }
5081 else 5112 else
5082 { 5113 {
5083 CHECK_STRING (name); 5114 CHECK_STRING (name);
@@ -5097,7 +5128,7 @@ usage: (unintern NAME OBARRAY) */)
5097 if (FIXNUMP (tem)) 5128 if (FIXNUMP (tem))
5098 return Qnil; 5129 return Qnil;
5099 /* If arg was a symbol, don't delete anything but that symbol itself. */ 5130 /* If arg was a symbol, don't delete anything but that symbol itself. */
5100 if (SYMBOLP (name) && !EQ (name, tem)) 5131 if (BARE_SYMBOL_P (name) && !BASE_EQ (name, tem))
5101 return Qnil; 5132 return Qnil;
5102 5133
5103 /* There are plenty of other symbols which will screw up the Emacs 5134 /* There are plenty of other symbols which will screw up the Emacs
@@ -5107,41 +5138,42 @@ usage: (unintern NAME OBARRAY) */)
5107 /* if (NILP (tem) || EQ (tem, Qt)) 5138 /* if (NILP (tem) || EQ (tem, Qt))
5108 error ("Attempt to unintern t or nil"); */ 5139 error ("Attempt to unintern t or nil"); */
5109 5140
5110 XSYMBOL (tem)->u.s.interned = SYMBOL_UNINTERNED; 5141 struct Lisp_Symbol *sym = XBARE_SYMBOL (tem);
5142 sym->u.s.interned = SYMBOL_UNINTERNED;
5111 5143
5112 hash = oblookup_last_bucket_number; 5144 ptrdiff_t idx = oblookup_last_bucket_number;
5145 Lisp_Object *loc = &XOBARRAY (obarray)->buckets[idx];
5113 5146
5114 if (EQ (AREF (obarray, hash), tem)) 5147 eassert (BARE_SYMBOL_P (*loc));
5115 { 5148 struct Lisp_Symbol *prev = XBARE_SYMBOL (*loc);
5116 if (XSYMBOL (tem)->u.s.next) 5149 if (sym == prev)
5117 { 5150 *loc = sym->u.s.next ? make_lisp_symbol (sym->u.s.next) : make_fixnum (0);
5118 Lisp_Object sym;
5119 XSETSYMBOL (sym, XSYMBOL (tem)->u.s.next);
5120 ASET (obarray, hash, sym);
5121 }
5122 else
5123 ASET (obarray, hash, make_fixnum (0));
5124 }
5125 else 5151 else
5126 { 5152 while (1)
5127 Lisp_Object tail, following; 5153 {
5154 struct Lisp_Symbol *next = prev->u.s.next;
5155 if (next == sym)
5156 {
5157 prev->u.s.next = next->u.s.next;
5158 break;
5159 }
5160 prev = next;
5161 }
5128 5162
5129 for (tail = AREF (obarray, hash); 5163 XOBARRAY (obarray)->count--;
5130 XSYMBOL (tail)->u.s.next;
5131 tail = following)
5132 {
5133 XSETSYMBOL (following, XSYMBOL (tail)->u.s.next);
5134 if (EQ (following, tem))
5135 {
5136 set_symbol_next (tail, XSYMBOL (following)->u.s.next);
5137 break;
5138 }
5139 }
5140 }
5141 5164
5142 return Qt; 5165 return Qt;
5143} 5166}
5144 5167
5168
5169/* Bucket index of the string STR of length SIZE_BYTE bytes in obarray OA. */
5170static ptrdiff_t
5171obarray_index (struct Lisp_Obarray *oa, const char *str, ptrdiff_t size_byte)
5172{
5173 EMACS_UINT hash = hash_string (str, size_byte);
5174 return knuth_hash (reduce_emacs_uint_to_hash_hash (hash), oa->size_bits);
5175}
5176
5145/* Return the symbol in OBARRAY whose names matches the string 5177/* Return the symbol in OBARRAY whose names matches the string
5146 of SIZE characters (SIZE_BYTE bytes) at PTR. 5178 of SIZE characters (SIZE_BYTE bytes) at PTR.
5147 If there is no such symbol, return the integer bucket number of 5179 If there is no such symbol, return the integer bucket number of
@@ -5152,35 +5184,27 @@ usage: (unintern NAME OBARRAY) */)
5152Lisp_Object 5184Lisp_Object
5153oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff_t size_byte) 5185oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff_t size_byte)
5154{ 5186{
5155 size_t hash; 5187 struct Lisp_Obarray *o = XOBARRAY (obarray);
5156 size_t obsize; 5188 ptrdiff_t idx = obarray_index (o, ptr, size_byte);
5157 register Lisp_Object tail; 5189 Lisp_Object bucket = o->buckets[idx];
5158 Lisp_Object bucket, tem;
5159 5190
5160 obarray = check_obarray (obarray); 5191 oblookup_last_bucket_number = idx;
5161 /* This is sometimes needed in the middle of GC. */ 5192 if (!BASE_EQ (bucket, make_fixnum (0)))
5162 obsize = gc_asize (obarray); 5193 {
5163 hash = hash_string (ptr, size_byte) % obsize; 5194 Lisp_Object sym = bucket;
5164 bucket = AREF (obarray, hash); 5195 while (1)
5165 oblookup_last_bucket_number = hash; 5196 {
5166 if (BASE_EQ (bucket, make_fixnum (0))) 5197 struct Lisp_Symbol *s = XBARE_SYMBOL (sym);
5167 ; 5198 Lisp_Object name = s->u.s.name;
5168 else if (!SYMBOLP (bucket)) 5199 if (SBYTES (name) == size_byte && SCHARS (name) == size
5169 /* Like CADR error message. */ 5200 && memcmp (SDATA (name), ptr, size_byte) == 0)
5170 xsignal2 (Qwrong_type_argument, Qobarrayp, 5201 return sym;
5171 build_string ("Bad data in guts of obarray")); 5202 if (s->u.s.next == NULL)
5172 else 5203 break;
5173 for (tail = bucket; ; XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next)) 5204 sym = make_lisp_symbol(s->u.s.next);
5174 { 5205 }
5175 if (SBYTES (SYMBOL_NAME (tail)) == size_byte 5206 }
5176 && SCHARS (SYMBOL_NAME (tail)) == size 5207 return make_fixnum (idx);
5177 && !memcmp (SDATA (SYMBOL_NAME (tail)), ptr, size_byte))
5178 return tail;
5179 else if (XSYMBOL (tail)->u.s.next == 0)
5180 break;
5181 }
5182 XSETINT (tem, hash);
5183 return tem;
5184} 5208}
5185 5209
5186/* Like 'oblookup', but considers 'Vread_symbol_shorthands', 5210/* Like 'oblookup', but considers 'Vread_symbol_shorthands',
@@ -5247,24 +5271,134 @@ oblookup_considering_shorthand (Lisp_Object obarray, const char *in,
5247} 5271}
5248 5272
5249 5273
5250void 5274static struct Lisp_Obarray *
5251map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object), Lisp_Object arg) 5275allocate_obarray (void)
5276{
5277 return ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Obarray, PVEC_OBARRAY);
5278}
5279
5280static Lisp_Object
5281make_obarray (unsigned bits)
5282{
5283 struct Lisp_Obarray *o = allocate_obarray ();
5284 o->count = 0;
5285 o->size_bits = bits;
5286 ptrdiff_t size = (ptrdiff_t)1 << bits;
5287 o->buckets = hash_table_alloc_bytes (size * sizeof *o->buckets);
5288 for (ptrdiff_t i = 0; i < size; i++)
5289 o->buckets[i] = make_fixnum (0);
5290 return make_lisp_obarray (o);
5291}
5292
5293enum {
5294 obarray_default_bits = 3,
5295 word_size_log2 = word_size < 8 ? 5 : 6, /* good enough */
5296 obarray_max_bits = min (8 * sizeof (int),
5297 8 * sizeof (ptrdiff_t) - word_size_log2) - 1,
5298};
5299
5300static void
5301grow_obarray (struct Lisp_Obarray *o)
5252{ 5302{
5253 ptrdiff_t i; 5303 ptrdiff_t old_size = obarray_size (o);
5254 register Lisp_Object tail; 5304 eassert (o->count > old_size);
5255 CHECK_VECTOR (obarray); 5305 Lisp_Object *old_buckets = o->buckets;
5256 for (i = ASIZE (obarray) - 1; i >= 0; i--) 5306
5307 int new_bits = o->size_bits + 1;
5308 if (new_bits > obarray_max_bits)
5309 error ("Obarray too big");
5310 ptrdiff_t new_size = (ptrdiff_t)1 << new_bits;
5311 o->buckets = hash_table_alloc_bytes (new_size * sizeof *o->buckets);
5312 for (ptrdiff_t i = 0; i < new_size; i++)
5313 o->buckets[i] = make_fixnum (0);
5314 o->size_bits = new_bits;
5315
5316 /* Rehash symbols.
5317 FIXME: this is expensive since we need to recompute the hash for every
5318 symbol name. Would it be reasonable to store it in the symbol? */
5319 for (ptrdiff_t i = 0; i < old_size; i++)
5257 { 5320 {
5258 tail = AREF (obarray, i); 5321 Lisp_Object obj = old_buckets[i];
5259 if (SYMBOLP (tail)) 5322 if (BARE_SYMBOL_P (obj))
5260 while (1) 5323 {
5261 { 5324 struct Lisp_Symbol *s = XBARE_SYMBOL (obj);
5262 (*fn) (tail, arg); 5325 while (1)
5263 if (XSYMBOL (tail)->u.s.next == 0) 5326 {
5264 break; 5327 Lisp_Object name = s->u.s.name;
5265 XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next); 5328 ptrdiff_t idx = obarray_index (o, SSDATA (name), SBYTES (name));
5266 } 5329 Lisp_Object *loc = o->buckets + idx;
5330 struct Lisp_Symbol *next = s->u.s.next;
5331 s->u.s.next = BARE_SYMBOL_P (*loc) ? XBARE_SYMBOL (*loc) : NULL;
5332 *loc = make_lisp_symbol (s);
5333 if (next == NULL)
5334 break;
5335 s = next;
5336 }
5337 }
5338 }
5339
5340 hash_table_free_bytes (old_buckets, old_size * sizeof *old_buckets);
5341}
5342
5343DEFUN ("obarray-make", Fobarray_make, Sobarray_make, 0, 1, 0,
5344 doc: /* Return a new obarray of size SIZE.
5345The obarray will grow to accommodate any number of symbols; the size, if
5346given, is only a hint for the expected number. */)
5347 (Lisp_Object size)
5348{
5349 int bits;
5350 if (NILP (size))
5351 bits = obarray_default_bits;
5352 else
5353 {
5354 CHECK_FIXNAT (size);
5355 EMACS_UINT n = XFIXNUM (size);
5356 bits = elogb (n) + 1;
5357 if (bits > obarray_max_bits)
5358 xsignal (Qargs_out_of_range, size);
5267 } 5359 }
5360 return make_obarray (bits);
5361}
5362
5363DEFUN ("obarrayp", Fobarrayp, Sobarrayp, 1, 1, 0,
5364 doc: /* Return t iff OBJECT is an obarray. */)
5365 (Lisp_Object object)
5366{
5367 return OBARRAYP (object) ? Qt : Qnil;
5368}
5369
5370DEFUN ("obarray-clear", Fobarray_clear, Sobarray_clear, 1, 1, 0,
5371 doc: /* Remove all symbols from OBARRAY. */)
5372 (Lisp_Object obarray)
5373{
5374 CHECK_OBARRAY (obarray);
5375 struct Lisp_Obarray *o = XOBARRAY (obarray);
5376
5377 /* This function does not bother setting the status of its contained symbols
5378 to uninterned. It doesn't matter very much. */
5379 int new_bits = obarray_default_bits;
5380 int new_size = (ptrdiff_t)1 << new_bits;
5381 Lisp_Object *new_buckets
5382 = hash_table_alloc_bytes (new_size * sizeof *new_buckets);
5383 for (ptrdiff_t i = 0; i < new_size; i++)
5384 new_buckets[i] = make_fixnum (0);
5385
5386 int old_size = obarray_size (o);
5387 hash_table_free_bytes (o->buckets, old_size * sizeof *o->buckets);
5388 o->buckets = new_buckets;
5389 o->size_bits = new_bits;
5390 o->count = 0;
5391
5392 return Qnil;
5393}
5394
5395void
5396map_obarray (Lisp_Object obarray,
5397 void (*fn) (Lisp_Object, Lisp_Object), Lisp_Object arg)
5398{
5399 CHECK_OBARRAY (obarray);
5400 DOOBARRAY (XOBARRAY (obarray), it)
5401 (*fn) (obarray_iter_symbol (&it), arg);
5268} 5402}
5269 5403
5270static void 5404static void
@@ -5285,12 +5419,37 @@ OBARRAY defaults to the value of `obarray'. */)
5285 return Qnil; 5419 return Qnil;
5286} 5420}
5287 5421
5288#define OBARRAY_SIZE 15121 5422DEFUN ("internal--obarray-buckets",
5423 Finternal__obarray_buckets, Sinternal__obarray_buckets, 1, 1, 0,
5424 doc: /* Symbols in each bucket of OBARRAY. Internal use only. */)
5425 (Lisp_Object obarray)
5426{
5427 obarray = check_obarray (obarray);
5428 ptrdiff_t size = obarray_size (XOBARRAY (obarray));
5429
5430 Lisp_Object ret = Qnil;
5431 for (ptrdiff_t i = 0; i < size; i++)
5432 {
5433 Lisp_Object bucket = Qnil;
5434 Lisp_Object sym = XOBARRAY (obarray)->buckets[i];
5435 if (BARE_SYMBOL_P (sym))
5436 while (1)
5437 {
5438 bucket = Fcons (sym, bucket);
5439 struct Lisp_Symbol *s = XBARE_SYMBOL (sym)->u.s.next;
5440 if (!s)
5441 break;
5442 sym = make_lisp_symbol (s);
5443 }
5444 ret = Fcons (Fnreverse (bucket), ret);
5445 }
5446 return Fnreverse (ret);
5447}
5289 5448
5290void 5449void
5291init_obarray_once (void) 5450init_obarray_once (void)
5292{ 5451{
5293 Vobarray = make_vector (OBARRAY_SIZE, make_fixnum (0)); 5452 Vobarray = make_obarray (15);
5294 initial_obarray = Vobarray; 5453 initial_obarray = Vobarray;
5295 staticpro (&initial_obarray); 5454 staticpro (&initial_obarray);
5296 5455
@@ -5300,14 +5459,14 @@ init_obarray_once (void)
5300 DEFSYM (Qunbound, "unbound"); 5459 DEFSYM (Qunbound, "unbound");
5301 5460
5302 DEFSYM (Qnil, "nil"); 5461 DEFSYM (Qnil, "nil");
5303 SET_SYMBOL_VAL (XSYMBOL (Qnil), Qnil); 5462 SET_SYMBOL_VAL (XBARE_SYMBOL (Qnil), Qnil);
5304 make_symbol_constant (Qnil); 5463 make_symbol_constant (Qnil);
5305 XSYMBOL (Qnil)->u.s.declared_special = true; 5464 XBARE_SYMBOL (Qnil)->u.s.declared_special = true;
5306 5465
5307 DEFSYM (Qt, "t"); 5466 DEFSYM (Qt, "t");
5308 SET_SYMBOL_VAL (XSYMBOL (Qt), Qt); 5467 SET_SYMBOL_VAL (XBARE_SYMBOL (Qt), Qt);
5309 make_symbol_constant (Qt); 5468 make_symbol_constant (Qt);
5310 XSYMBOL (Qt)->u.s.declared_special = true; 5469 XBARE_SYMBOL (Qt)->u.s.declared_special = true;
5311 5470
5312 /* Qt is correct even if not dumping. loadup.el will set to nil at end. */ 5471 /* Qt is correct even if not dumping. loadup.el will set to nil at end. */
5313 Vpurify_flag = Qt; 5472 Vpurify_flag = Qt;
@@ -5331,16 +5490,6 @@ defsubr (union Aligned_Lisp_Subr *aname)
5331#endif 5490#endif
5332} 5491}
5333 5492
5334#ifdef NOTDEF /* Use fset in subr.el now! */
5335void
5336defalias (struct Lisp_Subr *sname, char *string)
5337{
5338 Lisp_Object sym;
5339 sym = intern (string);
5340 XSETSUBR (XSYMBOL (sym)->u.s.function, sname);
5341}
5342#endif /* NOTDEF */
5343
5344/* Define an "integer variable"; a symbol whose value is forwarded to a 5493/* Define an "integer variable"; a symbol whose value is forwarded to a
5345 C variable of type intmax_t. Sample call (with "xx" to fool make-docfile): 5494 C variable of type intmax_t. Sample call (with "xx" to fool make-docfile):
5346 DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation"); */ 5495 DEFxxVAR_INT ("emacs-priority", &emacs_priority, "Documentation"); */
@@ -5348,9 +5497,9 @@ void
5348defvar_int (struct Lisp_Intfwd const *i_fwd, char const *namestring) 5497defvar_int (struct Lisp_Intfwd const *i_fwd, char const *namestring)
5349{ 5498{
5350 Lisp_Object sym = intern_c_string (namestring); 5499 Lisp_Object sym = intern_c_string (namestring);
5351 XSYMBOL (sym)->u.s.declared_special = true; 5500 XBARE_SYMBOL (sym)->u.s.declared_special = true;
5352 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 5501 XBARE_SYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
5353 SET_SYMBOL_FWD (XSYMBOL (sym), i_fwd); 5502 SET_SYMBOL_FWD (XBARE_SYMBOL (sym), i_fwd);
5354} 5503}
5355 5504
5356/* Similar but define a variable whose value is t if 1, nil if 0. */ 5505/* Similar but define a variable whose value is t if 1, nil if 0. */
@@ -5358,9 +5507,9 @@ void
5358defvar_bool (struct Lisp_Boolfwd const *b_fwd, char const *namestring) 5507defvar_bool (struct Lisp_Boolfwd const *b_fwd, char const *namestring)
5359{ 5508{
5360 Lisp_Object sym = intern_c_string (namestring); 5509 Lisp_Object sym = intern_c_string (namestring);
5361 XSYMBOL (sym)->u.s.declared_special = true; 5510 XBARE_SYMBOL (sym)->u.s.declared_special = true;
5362 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 5511 XBARE_SYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
5363 SET_SYMBOL_FWD (XSYMBOL (sym), b_fwd); 5512 SET_SYMBOL_FWD (XBARE_SYMBOL (sym), b_fwd);
5364 Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars); 5513 Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars);
5365} 5514}
5366 5515
@@ -5373,9 +5522,9 @@ void
5373defvar_lisp_nopro (struct Lisp_Objfwd const *o_fwd, char const *namestring) 5522defvar_lisp_nopro (struct Lisp_Objfwd const *o_fwd, char const *namestring)
5374{ 5523{
5375 Lisp_Object sym = intern_c_string (namestring); 5524 Lisp_Object sym = intern_c_string (namestring);
5376 XSYMBOL (sym)->u.s.declared_special = true; 5525 XBARE_SYMBOL (sym)->u.s.declared_special = true;
5377 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 5526 XBARE_SYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
5378 SET_SYMBOL_FWD (XSYMBOL (sym), o_fwd); 5527 SET_SYMBOL_FWD (XBARE_SYMBOL (sym), o_fwd);
5379} 5528}
5380 5529
5381void 5530void
@@ -5392,9 +5541,9 @@ void
5392defvar_kboard (struct Lisp_Kboard_Objfwd const *ko_fwd, char const *namestring) 5541defvar_kboard (struct Lisp_Kboard_Objfwd const *ko_fwd, char const *namestring)
5393{ 5542{
5394 Lisp_Object sym = intern_c_string (namestring); 5543 Lisp_Object sym = intern_c_string (namestring);
5395 XSYMBOL (sym)->u.s.declared_special = true; 5544 XBARE_SYMBOL (sym)->u.s.declared_special = true;
5396 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 5545 XBARE_SYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
5397 SET_SYMBOL_FWD (XSYMBOL (sym), ko_fwd); 5546 SET_SYMBOL_FWD (XBARE_SYMBOL (sym), ko_fwd);
5398} 5547}
5399 5548
5400/* Check that the elements of lpath exist. */ 5549/* Check that the elements of lpath exist. */
@@ -5682,6 +5831,10 @@ syms_of_lread (void)
5682 defsubr (&Sget_file_char); 5831 defsubr (&Sget_file_char);
5683 defsubr (&Smapatoms); 5832 defsubr (&Smapatoms);
5684 defsubr (&Slocate_file_internal); 5833 defsubr (&Slocate_file_internal);
5834 defsubr (&Sinternal__obarray_buckets);
5835 defsubr (&Sobarray_make);
5836 defsubr (&Sobarrayp);
5837 defsubr (&Sobarray_clear);
5685 5838
5686 DEFVAR_LISP ("obarray", Vobarray, 5839 DEFVAR_LISP ("obarray", Vobarray,
5687 doc: /* Symbol table for use by `intern' and `read'. 5840 doc: /* Symbol table for use by `intern' and `read'.
@@ -5693,7 +5846,7 @@ to find all the symbols in an obarray, use `mapatoms'. */);
5693 doc: /* List of values of all expressions which were read, evaluated and printed. 5846 doc: /* List of values of all expressions which were read, evaluated and printed.
5694Order is reverse chronological. 5847Order is reverse chronological.
5695This variable is obsolete as of Emacs 28.1 and should not be used. */); 5848This variable is obsolete as of Emacs 28.1 and should not be used. */);
5696 XSYMBOL (intern ("values"))->u.s.declared_special = false; 5849 XBARE_SYMBOL (intern ("values"))->u.s.declared_special = false;
5697 5850
5698 DEFVAR_LISP ("standard-input", Vstandard_input, 5851 DEFVAR_LISP ("standard-input", Vstandard_input,
5699 doc: /* Stream for read to get input from. 5852 doc: /* Stream for read to get input from.
@@ -6007,4 +6160,7 @@ See Info node `(elisp)Shorthands' for more details. */);
6007 doc: /* List of variables declared dynamic in the current scope. 6160 doc: /* List of variables declared dynamic in the current scope.
6008Only valid during macro-expansion. Internal use only. */); 6161Only valid during macro-expansion. Internal use only. */);
6009 Vmacroexp__dynvars = Qnil; 6162 Vmacroexp__dynvars = Qnil;
6163
6164 DEFSYM (Qinternal_macroexpand_for_load,
6165 "internal-macroexpand-for-load");
6010} 6166}
diff --git a/src/macfont.m b/src/macfont.m
index 6f192b00f1b..e3b3d40df43 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -855,21 +855,42 @@ macfont_store_descriptor_attributes (CTFontDescriptorRef desc,
855 struct { 855 struct {
856 enum font_property_index index; 856 enum font_property_index index;
857 CFStringRef trait; 857 CFStringRef trait;
858 CGPoint points[6]; 858 CGPoint points[12];
859 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat); 859 CGFloat (*adjust_func) (CTFontDescriptorRef, CGFloat);
860 } numeric_traits[] = 860 } numeric_traits[] = {
861 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait, 861 { FONT_WEIGHT_INDEX,
862 {{-0.4, 50}, /* light */ 862 kCTFontWeightTrait,
863 {-0.24, 87.5}, /* (semi-light + normal) / 2 */ 863 { { -0.6, 0 }, /* thin */
864 {0, 80}, /* normal */ 864 { -0.4, 40 }, /* ultra-light, ultralight, extra-light, extralight */
865 {0.24, 140}, /* (semi-bold + normal) / 2 */ 865 { -0.23, 50 }, /* light */
866 {0.4, 200}, /* bold */ 866 { -0.115, 55 }, /* semi-light, semilight, demilight */
867 {CGFLOAT_MAX, CGFLOAT_MAX}}, 867 { 0, 80 }, /* regular, normal, unspecified, book */
868 mac_font_descriptor_get_adjusted_weight}, 868 { 0.2, 100 }, /* medium */
869 {FONT_SLANT_INDEX, kCTFontSlantTrait, 869 { 0.3, 180 }, /* semi-bold, semibold, demibold, demi-bold, demi */
870 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}, 870 { 0.4, 200 }, /* bold */
871 {FONT_WIDTH_INDEX, kCTFontWidthTrait, 871 { 0.6, 205 }, /* extra-bold, extrabold, ultra-bold, ultrabold */
872 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}, NULL}}; 872 { 0.8, 210 }, /* black, heavy */
873 { 1, 250 }, /* ultra-heavy, ultraheavy */
874 { CGFLOAT_MAX, CGFLOAT_MAX } },
875 mac_font_descriptor_get_adjusted_weight },
876 { FONT_SLANT_INDEX,
877 kCTFontSlantTrait,
878 { { 0, 100 }, { 0.1, 200 }, { CGFLOAT_MAX, CGFLOAT_MAX } },
879 NULL },
880 { FONT_WIDTH_INDEX,
881 kCTFontWidthTrait,
882 { { -0.4, 50 }, /* ultra-condensed, ultracondensed */
883 { -0.3, 63 }, /* extra-condensed, extracondensed */
884 { -0.2, 75 }, /* condensed, compressed, narrow */
885 { -0.1, 87 }, /* semi-condensed, semicondensed, demicondensed */
886 { 0, 100 }, /* normal, medium, regular, unspecified */
887 { 0.1, 113 }, /* semi-expanded, semiexpanded, demiexpanded */
888 { 0.2, 125 }, /* expanded */
889 { 0.3, 150 }, /* extra-expanded, extraexpanded */
890 { 0.4, 200 }, /* ultra-expanded, ultraexpanded, wide */
891 { CGFLOAT_MAX, CGFLOAT_MAX } },
892 NULL }
893 };
873 int i; 894 int i;
874 895
875 for (i = 0; i < ARRAYELTS (numeric_traits); i++) 896 for (i = 0; i < ARRAYELTS (numeric_traits); i++)
@@ -1941,19 +1962,38 @@ macfont_create_attributes_with_spec (Lisp_Object spec)
1941 struct { 1962 struct {
1942 enum font_property_index index; 1963 enum font_property_index index;
1943 CFStringRef trait; 1964 CFStringRef trait;
1944 CGPoint points[6]; 1965 CGPoint points[12];
1945 } numeric_traits[] = 1966 } numeric_traits[] = {
1946 {{FONT_WEIGHT_INDEX, kCTFontWeightTrait, 1967 { FONT_WEIGHT_INDEX,
1947 {{-0.4, 50}, /* light */ 1968 kCTFontWeightTrait,
1948 {-0.24, 87.5}, /* (semi-light + normal) / 2 */ 1969 { { -0.6, 0 }, /* thin */
1949 {0, 100}, /* normal */ 1970 { -0.4, 40 }, /* ultra-light, ultralight, extra-light, extralight */
1950 {0.24, 140}, /* (semi-bold + normal) / 2 */ 1971 { -0.23, 50 }, /* light */
1951 {0.4, 200}, /* bold */ 1972 { -0.115, 55 }, /* semi-light, semilight, demilight */
1952 {CGFLOAT_MAX, CGFLOAT_MAX}}}, 1973 { 0, 80 }, /* regular, normal, unspecified, book */
1953 {FONT_SLANT_INDEX, kCTFontSlantTrait, 1974 { 0.2, 100 }, /* medium */
1954 {{0, 100}, {0.1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}, 1975 { 0.3, 180 }, /* semi-bold, semibold, demibold, demi-bold, demi */
1955 {FONT_WIDTH_INDEX, kCTFontWidthTrait, 1976 { 0.4, 200 }, /* bold */
1956 {{0, 100}, {1, 200}, {CGFLOAT_MAX, CGFLOAT_MAX}}}}; 1977 { 0.6, 205 }, /* extra-bold, extrabold, ultra-bold, ultrabold */
1978 { 0.8, 210 }, /* black, heavy */
1979 { 1, 250 }, /* ultra-heavy, ultraheavy */
1980 { CGFLOAT_MAX, CGFLOAT_MAX } } },
1981 { FONT_SLANT_INDEX,
1982 kCTFontSlantTrait,
1983 { { 0, 100 }, { 0.1, 200 }, { CGFLOAT_MAX, CGFLOAT_MAX } } },
1984 { FONT_WIDTH_INDEX,
1985 kCTFontWidthTrait,
1986 { { -0.4, 50 }, /* ultra-condensed, ultracondensed */
1987 { -0.3, 63 }, /* extra-condensed, extracondensed */
1988 { -0.2, 75 }, /* condensed, compressed, narrow */
1989 { -0.1, 87 }, /* semi-condensed, semicondensed, demicondensed */
1990 { 0, 100 }, /* normal, medium, regular, unspecified */
1991 { 0.1, 113 }, /* semi-expanded, semiexpanded, demiexpanded */
1992 { 0.2, 125 }, /* expanded */
1993 { 0.3, 150 }, /* extra-expanded, extraexpanded */
1994 { 0.4, 200 }, /* ultra-expanded, ultraexpanded, wide */
1995 { CGFLOAT_MAX, CGFLOAT_MAX } } }
1996 };
1957 1997
1958 registry = AREF (spec, FONT_REGISTRY_INDEX); 1998 registry = AREF (spec, FONT_REGISTRY_INDEX);
1959 if (NILP (registry) 1999 if (NILP (registry)
diff --git a/src/marker.c b/src/marker.c
index 0101e144b4d..1559dd52719 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -21,7 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21#include <config.h> 21#include <config.h>
22 22
23/* Work around GCC bug 113253. */ 23/* Work around GCC bug 113253. */
24#if 13 <= __GNUC__ 24#if __GNUC__ == 13
25# pragma GCC diagnostic ignored "-Wanalyzer-deref-before-check" 25# pragma GCC diagnostic ignored "-Wanalyzer-deref-before-check"
26#endif 26#endif
27 27
diff --git a/src/minibuf.c b/src/minibuf.c
index 7c0c9799a60..df6ca7ce1d8 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1615,13 +1615,15 @@ or from one of the possible completions. */)
1615 ptrdiff_t bestmatchsize = 0; 1615 ptrdiff_t bestmatchsize = 0;
1616 /* These are in bytes, too. */ 1616 /* These are in bytes, too. */
1617 ptrdiff_t compare, matchsize; 1617 ptrdiff_t compare, matchsize;
1618 if (VECTORP (collection))
1619 collection = check_obarray (collection);
1618 enum { function_table, list_table, obarray_table, hash_table} 1620 enum { function_table, list_table, obarray_table, hash_table}
1619 type = (HASH_TABLE_P (collection) ? hash_table 1621 type = (HASH_TABLE_P (collection) ? hash_table
1620 : VECTORP (collection) ? obarray_table 1622 : OBARRAYP (collection) ? obarray_table
1621 : ((NILP (collection) 1623 : ((NILP (collection)
1622 || (CONSP (collection) && !FUNCTIONP (collection))) 1624 || (CONSP (collection) && !FUNCTIONP (collection)))
1623 ? list_table : function_table)); 1625 ? list_table : function_table));
1624 ptrdiff_t idx = 0, obsize = 0; 1626 ptrdiff_t idx = 0;
1625 int matchcount = 0; 1627 int matchcount = 0;
1626 Lisp_Object bucket, zero, end, tem; 1628 Lisp_Object bucket, zero, end, tem;
1627 1629
@@ -1634,12 +1636,9 @@ or from one of the possible completions. */)
1634 1636
1635 /* If COLLECTION is not a list, set TAIL just for gc pro. */ 1637 /* If COLLECTION is not a list, set TAIL just for gc pro. */
1636 tail = collection; 1638 tail = collection;
1639 obarray_iter_t obit;
1637 if (type == obarray_table) 1640 if (type == obarray_table)
1638 { 1641 obit = make_obarray_iter (XOBARRAY (collection));
1639 collection = check_obarray (collection);
1640 obsize = ASIZE (collection);
1641 bucket = AREF (collection, idx);
1642 }
1643 1642
1644 while (1) 1643 while (1)
1645 { 1644 {
@@ -1658,24 +1657,10 @@ or from one of the possible completions. */)
1658 } 1657 }
1659 else if (type == obarray_table) 1658 else if (type == obarray_table)
1660 { 1659 {
1661 if (!EQ (bucket, zero)) 1660 if (obarray_iter_at_end (&obit))
1662 {
1663 if (!SYMBOLP (bucket))
1664 error ("Bad data in guts of obarray");
1665 elt = bucket;
1666 eltstring = elt;
1667 if (XSYMBOL (bucket)->u.s.next)
1668 XSETSYMBOL (bucket, XSYMBOL (bucket)->u.s.next);
1669 else
1670 XSETFASTINT (bucket, 0);
1671 }
1672 else if (++idx >= obsize)
1673 break; 1661 break;
1674 else 1662 elt = eltstring = obarray_iter_symbol (&obit);
1675 { 1663 obarray_iter_step (&obit);
1676 bucket = AREF (collection, idx);
1677 continue;
1678 }
1679 } 1664 }
1680 else /* if (type == hash_table) */ 1665 else /* if (type == hash_table) */
1681 { 1666 {
@@ -1858,10 +1843,12 @@ with a space are ignored unless STRING itself starts with a space. */)
1858{ 1843{
1859 Lisp_Object tail, elt, eltstring; 1844 Lisp_Object tail, elt, eltstring;
1860 Lisp_Object allmatches; 1845 Lisp_Object allmatches;
1846 if (VECTORP (collection))
1847 collection = check_obarray (collection);
1861 int type = HASH_TABLE_P (collection) ? 3 1848 int type = HASH_TABLE_P (collection) ? 3
1862 : VECTORP (collection) ? 2 1849 : OBARRAYP (collection) ? 2
1863 : NILP (collection) || (CONSP (collection) && !FUNCTIONP (collection)); 1850 : NILP (collection) || (CONSP (collection) && !FUNCTIONP (collection));
1864 ptrdiff_t idx = 0, obsize = 0; 1851 ptrdiff_t idx = 0;
1865 Lisp_Object bucket, tem, zero; 1852 Lisp_Object bucket, tem, zero;
1866 1853
1867 CHECK_STRING (string); 1854 CHECK_STRING (string);
@@ -1872,12 +1859,9 @@ with a space are ignored unless STRING itself starts with a space. */)
1872 1859
1873 /* If COLLECTION is not a list, set TAIL just for gc pro. */ 1860 /* If COLLECTION is not a list, set TAIL just for gc pro. */
1874 tail = collection; 1861 tail = collection;
1862 obarray_iter_t obit;
1875 if (type == 2) 1863 if (type == 2)
1876 { 1864 obit = make_obarray_iter (XOBARRAY (collection));
1877 collection = check_obarray (collection);
1878 obsize = ASIZE (collection);
1879 bucket = AREF (collection, idx);
1880 }
1881 1865
1882 while (1) 1866 while (1)
1883 { 1867 {
@@ -1896,24 +1880,10 @@ with a space are ignored unless STRING itself starts with a space. */)
1896 } 1880 }
1897 else if (type == 2) 1881 else if (type == 2)
1898 { 1882 {
1899 if (!EQ (bucket, zero)) 1883 if (obarray_iter_at_end (&obit))
1900 {
1901 if (!SYMBOLP (bucket))
1902 error ("Bad data in guts of obarray");
1903 elt = bucket;
1904 eltstring = elt;
1905 if (XSYMBOL (bucket)->u.s.next)
1906 XSETSYMBOL (bucket, XSYMBOL (bucket)->u.s.next);
1907 else
1908 XSETFASTINT (bucket, 0);
1909 }
1910 else if (++idx >= obsize)
1911 break; 1884 break;
1912 else 1885 elt = eltstring = obarray_iter_symbol (&obit);
1913 { 1886 obarray_iter_step (&obit);
1914 bucket = AREF (collection, idx);
1915 continue;
1916 }
1917 } 1887 }
1918 else /* if (type == 3) */ 1888 else /* if (type == 3) */
1919 { 1889 {
@@ -2059,7 +2029,7 @@ If COLLECTION is a function, it is called with three arguments:
2059the values STRING, PREDICATE and `lambda'. */) 2029the values STRING, PREDICATE and `lambda'. */)
2060 (Lisp_Object string, Lisp_Object collection, Lisp_Object predicate) 2030 (Lisp_Object string, Lisp_Object collection, Lisp_Object predicate)
2061{ 2031{
2062 Lisp_Object tail, tem = Qnil, arg = Qnil; 2032 Lisp_Object tem = Qnil, arg = Qnil;
2063 2033
2064 CHECK_STRING (string); 2034 CHECK_STRING (string);
2065 2035
@@ -2069,38 +2039,30 @@ the values STRING, PREDICATE and `lambda'. */)
2069 if (NILP (tem)) 2039 if (NILP (tem))
2070 return Qnil; 2040 return Qnil;
2071 } 2041 }
2072 else if (VECTORP (collection)) 2042 else if (OBARRAYP (collection) || VECTORP (collection))
2073 { 2043 {
2044 collection = check_obarray (collection);
2074 /* Bypass intern-soft as that loses for nil. */ 2045 /* Bypass intern-soft as that loses for nil. */
2075 tem = oblookup (collection, 2046 tem = oblookup (collection,
2076 SSDATA (string), 2047 SSDATA (string),
2077 SCHARS (string), 2048 SCHARS (string),
2078 SBYTES (string)); 2049 SBYTES (string));
2079 if (completion_ignore_case && !SYMBOLP (tem)) 2050 if (completion_ignore_case && !BARE_SYMBOL_P (tem))
2080 { 2051 DOOBARRAY (XOBARRAY (collection), it)
2081 for (ptrdiff_t i = ASIZE (collection) - 1; i >= 0; i--) 2052 {
2082 { 2053 Lisp_Object obj = obarray_iter_symbol (&it);
2083 tail = AREF (collection, i); 2054 if (BASE_EQ (Fcompare_strings (string, make_fixnum (0),
2084 if (SYMBOLP (tail)) 2055 Qnil,
2085 while (1) 2056 Fsymbol_name (obj),
2086 { 2057 make_fixnum (0) , Qnil, Qt),
2087 if (BASE_EQ (Fcompare_strings (string, make_fixnum (0), 2058 Qt))
2088 Qnil, 2059 {
2089 Fsymbol_name (tail), 2060 tem = obj;
2090 make_fixnum (0) , Qnil, Qt), 2061 break;
2091 Qt)) 2062 }
2092 { 2063 }
2093 tem = tail;
2094 break;
2095 }
2096 if (XSYMBOL (tail)->u.s.next == 0)
2097 break;
2098 XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next);
2099 }
2100 }
2101 }
2102 2064
2103 if (!SYMBOLP (tem)) 2065 if (!BARE_SYMBOL_P (tem))
2104 return Qnil; 2066 return Qnil;
2105 } 2067 }
2106 else if (HASH_TABLE_P (collection)) 2068 else if (HASH_TABLE_P (collection))
diff --git a/src/pdumper.c b/src/pdumper.c
index ee554cda55a..f0bce09cbde 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2688,7 +2688,7 @@ hash_table_freeze (struct Lisp_Hash_Table *h)
2688 h->hash = NULL; 2688 h->hash = NULL;
2689 h->index = NULL; 2689 h->index = NULL;
2690 h->table_size = 0; 2690 h->table_size = 0;
2691 h->index_size = 0; 2691 h->index_bits = 0;
2692 h->frozen_test = hash_table_std_test (h->test); 2692 h->frozen_test = hash_table_std_test (h->test);
2693 h->test = NULL; 2693 h->test = NULL;
2694} 2694}
@@ -2719,7 +2719,7 @@ dump_hash_table_contents (struct dump_context *ctx, struct Lisp_Hash_Table *h)
2719static dump_off 2719static dump_off
2720dump_hash_table (struct dump_context *ctx, Lisp_Object object) 2720dump_hash_table (struct dump_context *ctx, Lisp_Object object)
2721{ 2721{
2722#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_313A489F0A 2722#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_0360833954
2723# error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h." 2723# error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h."
2724#endif 2724#endif
2725 const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object); 2725 const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object);
@@ -2749,6 +2749,51 @@ dump_hash_table (struct dump_context *ctx, Lisp_Object object)
2749} 2749}
2750 2750
2751static dump_off 2751static dump_off
2752dump_obarray_buckets (struct dump_context *ctx, const struct Lisp_Obarray *o)
2753{
2754 dump_align_output (ctx, DUMP_ALIGNMENT);
2755 dump_off start_offset = ctx->offset;
2756 ptrdiff_t n = obarray_size (o);
2757
2758 struct dump_flags old_flags = ctx->flags;
2759 ctx->flags.pack_objects = true;
2760
2761 for (ptrdiff_t i = 0; i < n; i++)
2762 {
2763 Lisp_Object out;
2764 const Lisp_Object *slot = &o->buckets[i];
2765 dump_object_start (ctx, &out, sizeof out);
2766 dump_field_lv (ctx, &out, slot, slot, WEIGHT_STRONG);
2767 dump_object_finish (ctx, &out, sizeof out);
2768 }
2769
2770 ctx->flags = old_flags;
2771 return start_offset;
2772}
2773
2774static dump_off
2775dump_obarray (struct dump_context *ctx, Lisp_Object object)
2776{
2777#if CHECK_STRUCTS && !defined HASH_Lisp_Obarray_D2757E61AD
2778# error "Lisp_Obarray changed. See CHECK_STRUCTS comment in config.h."
2779#endif
2780 const struct Lisp_Obarray *in_oa = XOBARRAY (object);
2781 struct Lisp_Obarray munged_oa = *in_oa;
2782 struct Lisp_Obarray *oa = &munged_oa;
2783 START_DUMP_PVEC (ctx, &oa->header, struct Lisp_Obarray, out);
2784 dump_pseudovector_lisp_fields (ctx, &out->header, &oa->header);
2785 DUMP_FIELD_COPY (out, oa, count);
2786 DUMP_FIELD_COPY (out, oa, size_bits);
2787 dump_field_fixup_later (ctx, out, oa, &oa->buckets);
2788 dump_off offset = finish_dump_pvec (ctx, &out->header);
2789 dump_remember_fixup_ptr_raw
2790 (ctx,
2791 offset + dump_offsetof (struct Lisp_Obarray, buckets),
2792 dump_obarray_buckets (ctx, oa));
2793 return offset;
2794}
2795
2796static dump_off
2752dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2797dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2753{ 2798{
2754#if CHECK_STRUCTS && !defined HASH_buffer_EBBA38AEFA 2799#if CHECK_STRUCTS && !defined HASH_buffer_EBBA38AEFA
@@ -2912,17 +2957,17 @@ dump_subr (struct dump_context *ctx, const struct Lisp_Subr *subr)
2912 dump_object_start (ctx, &out, sizeof (out)); 2957 dump_object_start (ctx, &out, sizeof (out));
2913 DUMP_FIELD_COPY (&out, subr, header.size); 2958 DUMP_FIELD_COPY (&out, subr, header.size);
2914#ifdef HAVE_NATIVE_COMP 2959#ifdef HAVE_NATIVE_COMP
2915 bool native_comp = !NILP (subr->native_comp_u); 2960 bool non_primitive = !NILP (subr->native_comp_u);
2916#else 2961#else
2917 bool native_comp = false; 2962 bool non_primitive = false;
2918#endif 2963#endif
2919 if (native_comp) 2964 if (non_primitive)
2920 out.function.a0 = NULL; 2965 out.function.a0 = NULL;
2921 else 2966 else
2922 dump_field_emacs_ptr (ctx, &out, subr, &subr->function.a0); 2967 dump_field_emacs_ptr (ctx, &out, subr, &subr->function.a0);
2923 DUMP_FIELD_COPY (&out, subr, min_args); 2968 DUMP_FIELD_COPY (&out, subr, min_args);
2924 DUMP_FIELD_COPY (&out, subr, max_args); 2969 DUMP_FIELD_COPY (&out, subr, max_args);
2925 if (native_comp) 2970 if (non_primitive)
2926 { 2971 {
2927 dump_field_fixup_later (ctx, &out, subr, &subr->symbol_name); 2972 dump_field_fixup_later (ctx, &out, subr, &subr->symbol_name);
2928 dump_remember_cold_op (ctx, 2973 dump_remember_cold_op (ctx,
@@ -2947,7 +2992,7 @@ dump_subr (struct dump_context *ctx, const struct Lisp_Subr *subr)
2947 dump_field_lv (ctx, &out, subr, &subr->type, WEIGHT_NORMAL); 2992 dump_field_lv (ctx, &out, subr, &subr->type, WEIGHT_NORMAL);
2948#endif 2993#endif
2949 dump_off subr_off = dump_object_finish (ctx, &out, sizeof (out)); 2994 dump_off subr_off = dump_object_finish (ctx, &out, sizeof (out));
2950 if (native_comp && ctx->flags.dump_object_contents) 2995 if (non_primitive && ctx->flags.dump_object_contents)
2951 /* We'll do the final addr relocation during VERY_LATE_RELOCS time 2996 /* We'll do the final addr relocation during VERY_LATE_RELOCS time
2952 after the compilation units has been loaded. */ 2997 after the compilation units has been loaded. */
2953 dump_push (&ctx->dump_relocs[VERY_LATE_RELOCS], 2998 dump_push (&ctx->dump_relocs[VERY_LATE_RELOCS],
@@ -3004,7 +3049,7 @@ dump_vectorlike (struct dump_context *ctx,
3004 Lisp_Object lv, 3049 Lisp_Object lv,
3005 dump_off offset) 3050 dump_off offset)
3006{ 3051{
3007#if CHECK_STRUCTS && !defined HASH_pvec_type_D8A254BC70 3052#if CHECK_STRUCTS && !defined HASH_pvec_type_2D583AC566
3008# error "pvec_type changed. See CHECK_STRUCTS comment in config.h." 3053# error "pvec_type changed. See CHECK_STRUCTS comment in config.h."
3009#endif 3054#endif
3010 const struct Lisp_Vector *v = XVECTOR (lv); 3055 const struct Lisp_Vector *v = XVECTOR (lv);
@@ -3031,6 +3076,8 @@ dump_vectorlike (struct dump_context *ctx,
3031 return dump_bool_vector(ctx, v); 3076 return dump_bool_vector(ctx, v);
3032 case PVEC_HASH_TABLE: 3077 case PVEC_HASH_TABLE:
3033 return dump_hash_table (ctx, lv); 3078 return dump_hash_table (ctx, lv);
3079 case PVEC_OBARRAY:
3080 return dump_obarray (ctx, lv);
3034 case PVEC_BUFFER: 3081 case PVEC_BUFFER:
3035 return dump_buffer (ctx, XBUFFER (lv)); 3082 return dump_buffer (ctx, XBUFFER (lv));
3036 case PVEC_SUBR: 3083 case PVEC_SUBR:
@@ -5593,10 +5640,7 @@ pdumper_load (const char *dump_filename, char *argv0)
5593 5640
5594 struct dump_header header_buf = { 0 }; 5641 struct dump_header header_buf = { 0 };
5595 struct dump_header *header = &header_buf; 5642 struct dump_header *header = &header_buf;
5596 struct dump_memory_map sections[NUMBER_DUMP_SECTIONS]; 5643 struct dump_memory_map sections[NUMBER_DUMP_SECTIONS] = { 0 };
5597
5598 /* Use memset instead of "= { 0 }" to work around GCC bug 105961. */
5599 memset (sections, 0, sizeof sections);
5600 5644
5601 const struct timespec start_time = current_timespec (); 5645 const struct timespec start_time = current_timespec ();
5602 char *dump_filename_copy; 5646 char *dump_filename_copy;
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index b731f52983d..1ec6bfcda4e 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -5825,8 +5825,8 @@ note_mouse_movement (struct frame *frame,
5825 /* Has the mouse moved off the glyph it was on at the last sighting? */ 5825 /* Has the mouse moved off the glyph it was on at the last sighting? */
5826 r = &dpyinfo->last_mouse_glyph; 5826 r = &dpyinfo->last_mouse_glyph;
5827 if (frame != dpyinfo->last_mouse_glyph_frame 5827 if (frame != dpyinfo->last_mouse_glyph_frame
5828 || event->x < r->x || event->x >= r->x + r->width 5828 || event->x < r->x || event->x >= r->x + (int) r->width
5829 || event->y < r->y || event->y >= r->y + r->height) 5829 || event->y < r->y || event->y >= r->y + (int) r->height)
5830 { 5830 {
5831 frame->mouse_moved = true; 5831 frame->mouse_moved = true;
5832 dpyinfo->last_mouse_scroll_bar = NULL; 5832 dpyinfo->last_mouse_scroll_bar = NULL;
diff --git a/src/print.c b/src/print.c
index c6a3dba3163..76c577ec800 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1412,7 +1412,7 @@ print_preprocess (Lisp_Object obj)
1412 && SYMBOLP (obj) 1412 && SYMBOLP (obj)
1413 && !SYMBOL_INTERNED_P (obj))) 1413 && !SYMBOL_INTERNED_P (obj)))
1414 { /* OBJ appears more than once. Let's remember that. */ 1414 { /* OBJ appears more than once. Let's remember that. */
1415 if (!FIXNUMP (num)) 1415 if (SYMBOLP (num)) /* In practice, nil or t. */
1416 { 1416 {
1417 print_number_index++; 1417 print_number_index++;
1418 /* Negative number indicates it hasn't been printed yet. */ 1418 /* Negative number indicates it hasn't been printed yet. */
@@ -2078,6 +2078,16 @@ print_vectorlike_unreadable (Lisp_Object obj, Lisp_Object printcharfun,
2078 } 2078 }
2079 return; 2079 return;
2080 2080
2081 case PVEC_OBARRAY:
2082 {
2083 struct Lisp_Obarray *o = XOBARRAY (obj);
2084 /* FIXME: Would it make sense to print the actual symbols (up to
2085 a limit)? */
2086 int i = sprintf (buf, "#<obarray n=%u>", o->count);
2087 strout (buf, i, i, printcharfun);
2088 return;
2089 }
2090
2081 /* Types handled earlier. */ 2091 /* Types handled earlier. */
2082 case PVEC_NORMAL_VECTOR: 2092 case PVEC_NORMAL_VECTOR:
2083 case PVEC_RECORD: 2093 case PVEC_RECORD:
@@ -2265,6 +2275,11 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2265 goto next_obj; 2275 goto next_obj;
2266 } 2276 }
2267 } 2277 }
2278 else if (STRINGP (num))
2279 {
2280 strout (SSDATA (num), SCHARS (num), SBYTES (num), printcharfun);
2281 goto next_obj;
2282 }
2268 } 2283 }
2269 2284
2270 print_depth++; 2285 print_depth++;
@@ -2554,11 +2569,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2554 goto next_obj; 2569 goto next_obj;
2555 case PVEC_SUB_CHAR_TABLE: 2570 case PVEC_SUB_CHAR_TABLE:
2556 { 2571 {
2557 /* Make each lowest sub_char_table start a new line.
2558 Otherwise we'll make a line extremely long, which
2559 results in slow redisplay. */
2560 if (XSUB_CHAR_TABLE (obj)->depth == 3)
2561 printchar ('\n', printcharfun);
2562 print_c_string ("#^^[", printcharfun); 2572 print_c_string ("#^^[", printcharfun);
2563 int n = sprintf (buf, "%d %d", 2573 int n = sprintf (buf, "%d %d",
2564 XSUB_CHAR_TABLE (obj)->depth, 2574 XSUB_CHAR_TABLE (obj)->depth,
@@ -2664,7 +2674,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2664 /* With the print-circle feature. */ 2674 /* With the print-circle feature. */
2665 Lisp_Object num = Fgethash (next, Vprint_number_table, 2675 Lisp_Object num = Fgethash (next, Vprint_number_table,
2666 Qnil); 2676 Qnil);
2667 if (FIXNUMP (num)) 2677 if (!(NILP (num) || EQ (num, Qt)))
2668 { 2678 {
2669 print_c_string (" . ", printcharfun); 2679 print_c_string (" . ", printcharfun);
2670 obj = next; 2680 obj = next;
@@ -2928,7 +2938,10 @@ This variable should not be set with `setq'; bind it with a `let' instead. */);
2928 DEFVAR_LISP ("print-number-table", Vprint_number_table, 2938 DEFVAR_LISP ("print-number-table", Vprint_number_table,
2929 doc: /* A vector used internally to produce `#N=' labels and `#N#' references. 2939 doc: /* A vector used internally to produce `#N=' labels and `#N#' references.
2930The Lisp printer uses this vector to detect Lisp objects referenced more 2940The Lisp printer uses this vector to detect Lisp objects referenced more
2931than once. 2941than once. If an entry contains a number, then the corresponding key is
2942referenced more than once: a positive sign indicates that it's already been
2943printed, and the absolute value indicates the number to use when printing.
2944If an entry contains a string, that string is printed instead.
2932 2945
2933When you bind `print-continuous-numbering' to t, you should probably 2946When you bind `print-continuous-numbering' to t, you should probably
2934also bind `print-number-table' to nil. This ensures that the value of 2947also bind `print-number-table' to nil. This ensures that the value of
diff --git a/src/process.c b/src/process.c
index ddab9ed6c01..48a2c0c8e53 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5209,6 +5209,27 @@ wait_reading_process_output_1 (void)
5209{ 5209{
5210} 5210}
5211 5211
5212#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY \
5213 && defined THREADS_ENABLED
5214
5215/* Wrapper around `android_select' that exposes a calling interface with
5216 an extra argument for compatibility with `thread_pselect'. */
5217
5218static int
5219android_select_wrapper (int nfds, fd_set *readfds, fd_set *writefds,
5220 fd_set *exceptfds, const struct timespec *timeout,
5221 const sigset_t *sigmask)
5222{
5223 /* sigmask is not supported. */
5224 if (sigmask)
5225 emacs_abort ();
5226
5227 return android_select (nfds, readfds, writefds, exceptfds,
5228 (struct timespec *) timeout);
5229}
5230
5231#endif /* HAVE_ANDROID && !ANDROID_STUBIFY && THREADS_ENABLED */
5232
5212/* Read and dispose of subprocess output while waiting for timeout to 5233/* Read and dispose of subprocess output while waiting for timeout to
5213 elapse and/or keyboard input to be available. 5234 elapse and/or keyboard input to be available.
5214 5235
@@ -5701,13 +5722,19 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5701 timeout = short_timeout; 5722 timeout = short_timeout;
5702#endif 5723#endif
5703 5724
5704 /* Android doesn't support threads and requires using a 5725 /* Android requires using a replacement for pselect in
5705 replacement for pselect in android.c to poll for 5726 android.c to poll for events. */
5706 events. */
5707#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY 5727#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
5728#ifndef THREADS_ENABLED
5708 nfds = android_select (max_desc + 1, 5729 nfds = android_select (max_desc + 1,
5709 &Available, (check_write ? &Writeok : 0), 5730 &Available, (check_write ? &Writeok : 0),
5710 NULL, &timeout); 5731 NULL, &timeout);
5732#else /* THREADS_ENABLED */
5733 nfds = thread_select (android_select_wrapper,
5734 max_desc + 1,
5735 &Available, (check_write ? &Writeok : 0),
5736 NULL, &timeout, NULL);
5737#endif /* THREADS_ENABLED */
5711#else 5738#else
5712 5739
5713 /* Non-macOS HAVE_GLIB builds call thread_select in 5740 /* Non-macOS HAVE_GLIB builds call thread_select in
diff --git a/src/sfnt.c b/src/sfnt.c
index 6df43af4293..8598b052044 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -2798,12 +2798,6 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
2798 if (component->flags & 04000) /* SCALED_COMPONENT_OFFSET */ 2798 if (component->flags & 04000) /* SCALED_COMPONENT_OFFSET */
2799 sfnt_transform_coordinates (component, &x, &y, 1, 2799 sfnt_transform_coordinates (component, &x, &y, 1,
2800 0, 0); 2800 0, 0);
2801
2802 if (component->flags & 04) /* ROUND_XY_TO_GRID */
2803 {
2804 x = sfnt_round_fixed (x);
2805 y = sfnt_round_fixed (y);
2806 }
2807 } 2801 }
2808 else 2802 else
2809 { 2803 {
@@ -20800,8 +20794,8 @@ main (int argc, char **argv)
20800 return 1; 20794 return 1;
20801 } 20795 }
20802 20796
20803#define FANCY_PPEM 12 20797#define FANCY_PPEM 18
20804#define EASY_PPEM 12 20798#define EASY_PPEM 18
20805 20799
20806 interpreter = NULL; 20800 interpreter = NULL;
20807 head = sfnt_read_head_table (fd, font); 20801 head = sfnt_read_head_table (fd, font);
diff --git a/src/sfnt.h b/src/sfnt.h
index 5b01270e8ce..444b1dfe427 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -248,7 +248,7 @@ enum sfnt_macintosh_platform_specific_id
248 SFNT_MACINTOSH_GREEK = 6, 248 SFNT_MACINTOSH_GREEK = 6,
249 SFNT_MACINTOSH_RUSSIAN = 7, 249 SFNT_MACINTOSH_RUSSIAN = 7,
250 SFNT_MACINTOSH_RSYMBOL = 8, 250 SFNT_MACINTOSH_RSYMBOL = 8,
251 SFNT_MACINTOSH_DEVANGARI = 9, 251 SFNT_MACINTOSH_DEVANAGARI = 9,
252 SFNT_MACINTOSH_GURMUKHI = 10, 252 SFNT_MACINTOSH_GURMUKHI = 10,
253 SFNT_MACINTOSH_GUJARATI = 11, 253 SFNT_MACINTOSH_GUJARATI = 11,
254 SFNT_MACINTOSH_ORIYA = 12, 254 SFNT_MACINTOSH_ORIYA = 12,
diff --git a/src/sfntfont.c b/src/sfntfont.c
index 860fc446184..3be770f650e 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -3308,7 +3308,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
3308 ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name); 3308 ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name);
3309 ASET (font_object, FONT_FOUNDRY_INDEX, desc->designer); 3309 ASET (font_object, FONT_FOUNDRY_INDEX, desc->designer);
3310 ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil)); 3310 ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
3311 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil); 3311 ASET (font_object, FONT_ADSTYLE_INDEX, desc->adstyle);
3312 ASET (font_object, FONT_REGISTRY_INDEX, 3312 ASET (font_object, FONT_REGISTRY_INDEX,
3313 sfntfont_registry_for_desc (desc)); 3313 sfntfont_registry_for_desc (desc));
3314 3314
@@ -3326,8 +3326,6 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
3326 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX, 3326 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
3327 make_fixnum (desc->slant)); 3327 make_fixnum (desc->slant));
3328 3328
3329 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
3330
3331 /* Clear various offsets. */ 3329 /* Clear various offsets. */
3332 font_info->font.baseline_offset = 0; 3330 font_info->font.baseline_offset = 0;
3333 font_info->font.relative_compose = 0; 3331 font_info->font.relative_compose = 0;
@@ -3412,7 +3410,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
3412 AREF (tem, 3)); 3410 AREF (tem, 3));
3413 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX, 3411 FONT_SET_STYLE (font_object, FONT_SLANT_INDEX,
3414 AREF (tem, 4)); 3412 AREF (tem, 4));
3415 ASET (font_object, FONT_ADSTYLE_INDEX, Qnil); 3413 ASET (font_object, FONT_ADSTYLE_INDEX, AREF (tem, 1));
3416 } 3414 }
3417 } 3415 }
3418 3416
diff --git a/src/term.c b/src/term.c
index 447876d288a..3fa244be824 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1631,8 +1631,19 @@ produce_glyphs (struct it *it)
1631 it->pixel_width = it->nglyphs = 0; 1631 it->pixel_width = it->nglyphs = 0;
1632 else if (it->char_to_display == '\t') 1632 else if (it->char_to_display == '\t')
1633 { 1633 {
1634 /* wrap-prefix strings are prepended to continuation lines, so
1635 the width of tab characters inside should be computed from
1636 the start of this screen line rather than as a product of the
1637 total width of the physical line being wrapped. */
1634 int absolute_x = (it->current_x 1638 int absolute_x = (it->current_x
1635 + it->continuation_lines_width); 1639 + (it->string_from_prefix_prop_p
1640 /* Subtract the width of the
1641 prefix from it->current_x if
1642 it exists. */
1643 ? 0 : (it->continuation_lines_width
1644 ? (it->continuation_lines_width
1645 - it->wrap_prefix_width)
1646 : 0)));
1636 int x0 = absolute_x; 1647 int x0 = absolute_x;
1637 /* Adjust for line numbers. */ 1648 /* Adjust for line numbers. */
1638 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) 1649 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
@@ -1704,7 +1715,13 @@ produce_glyphs (struct it *it)
1704 /* Advance current_x by the pixel width as a convenience for 1715 /* Advance current_x by the pixel width as a convenience for
1705 the caller. */ 1716 the caller. */
1706 if (it->area == TEXT_AREA) 1717 if (it->area == TEXT_AREA)
1707 it->current_x += it->pixel_width; 1718 {
1719 it->current_x += it->pixel_width;
1720
1721 if (it->continuation_lines_width
1722 && it->string_from_prefix_prop_p)
1723 it->wrap_prefix_width = it->current_x;
1724 }
1708 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0; 1725 it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
1709 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1; 1726 it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
1710#endif 1727#endif
diff --git a/src/textconv.c b/src/textconv.c
index 0d35ec19c55..0941848dd09 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -1705,11 +1705,8 @@ set_composing_region (struct frame *f, ptrdiff_t start,
1705{ 1705{
1706 struct text_conversion_action *action, **last; 1706 struct text_conversion_action *action, **last;
1707 1707
1708 if (start > MOST_POSITIVE_FIXNUM) 1708 start = min (start, MOST_POSITIVE_FIXNUM);
1709 start = MOST_POSITIVE_FIXNUM; 1709 end = min (end, MOST_POSITIVE_FIXNUM);
1710
1711 if (end > MOST_POSITIVE_FIXNUM)
1712 end = MOST_POSITIVE_FIXNUM;
1713 1710
1714 action = xmalloc (sizeof *action); 1711 action = xmalloc (sizeof *action);
1715 action->operation = TEXTCONV_SET_COMPOSING_REGION; 1712 action->operation = TEXTCONV_SET_COMPOSING_REGION;
@@ -1734,8 +1731,7 @@ textconv_set_point_and_mark (struct frame *f, ptrdiff_t point,
1734{ 1731{
1735 struct text_conversion_action *action, **last; 1732 struct text_conversion_action *action, **last;
1736 1733
1737 if (point > MOST_POSITIVE_FIXNUM) 1734 point = min (point, MOST_POSITIVE_FIXNUM);
1738 point = MOST_POSITIVE_FIXNUM;
1739 1735
1740 action = xmalloc (sizeof *action); 1736 action = xmalloc (sizeof *action);
1741 action->operation = TEXTCONV_SET_POINT_AND_MARK; 1737 action->operation = TEXTCONV_SET_POINT_AND_MARK;
diff --git a/src/thread.c b/src/thread.c
index 040ca39511e..2f5d7a08838 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -106,6 +106,12 @@ post_acquire_global_lock (struct thread_state *self)
106{ 106{
107 struct thread_state *prev_thread = current_thread; 107 struct thread_state *prev_thread = current_thread;
108 108
109 /* Switch the JNI interface pointer to the environment assigned to the
110 current thread. */
111#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
112 android_java_env = self->java_env;
113#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
114
109 /* Do this early on, so that code below could signal errors (e.g., 115 /* Do this early on, so that code below could signal errors (e.g.,
110 unbind_for_thread_switch might) correctly, because we are already 116 unbind_for_thread_switch might) correctly, because we are already
111 running in the context of the thread pointed by SELF. */ 117 running in the context of the thread pointed by SELF. */
@@ -126,6 +132,12 @@ post_acquire_global_lock (struct thread_state *self)
126 set_buffer_internal_2 (current_buffer); 132 set_buffer_internal_2 (current_buffer);
127 } 133 }
128 134
135#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
136 /* This step is performed in android_select when built without
137 threads. */
138 android_check_query ();
139#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
140
129 /* We could have been signaled while waiting to grab the global lock 141 /* We could have been signaled while waiting to grab the global lock
130 for the first time since this thread was created, in which case 142 for the first time since this thread was created, in which case
131 we didn't yet have the opportunity to set up the handlers. Delay 143 we didn't yet have the opportunity to set up the handlers. Delay
@@ -756,6 +768,11 @@ run_thread (void *state)
756 768
757 struct thread_state *self = state; 769 struct thread_state *self = state;
758 struct thread_state **iter; 770 struct thread_state **iter;
771#ifdef THREADS_ENABLED
772#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
773 jint rc;
774#endif /* #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
775#endif /* THREADS_ENABLED */
759 776
760#ifdef HAVE_NS 777#ifdef HAVE_NS
761 /* Allocate an autorelease pool in case this thread calls any 778 /* Allocate an autorelease pool in case this thread calls any
@@ -766,6 +783,16 @@ run_thread (void *state)
766 void *pool = ns_alloc_autorelease_pool (); 783 void *pool = ns_alloc_autorelease_pool ();
767#endif 784#endif
768 785
786#ifdef THREADS_ENABLED
787#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
788 rc
789 = (*android_jvm)->AttachCurrentThread (android_jvm, &self->java_env,
790 NULL);
791 if (rc != JNI_OK)
792 emacs_abort ();
793#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
794#endif /* THREADS_ENABLED */
795
769 self->m_stack_bottom = self->stack_top = &stack_pos.c; 796 self->m_stack_bottom = self->stack_top = &stack_pos.c;
770 self->thread_id = sys_thread_self (); 797 self->thread_id = sys_thread_self ();
771 798
@@ -812,6 +839,14 @@ run_thread (void *state)
812 ns_release_autorelease_pool (pool); 839 ns_release_autorelease_pool (pool);
813#endif 840#endif
814 841
842#ifdef THREADS_ENABLED
843#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
844 rc = (*android_jvm)->DetachCurrentThread (android_jvm);
845 if (rc != JNI_OK)
846 emacs_abort ();
847#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
848#endif /* THREADS_ENABLED */
849
815 /* Unlink this thread from the list of all threads. Note that we 850 /* Unlink this thread from the list of all threads. Note that we
816 have to do this very late, after broadcasting our death. 851 have to do this very late, after broadcasting our death.
817 Otherwise the GC may decide to reap the thread_state object, 852 Otherwise the GC may decide to reap the thread_state object,
@@ -1131,6 +1166,10 @@ init_threads (void)
1131 sys_mutex_init (&global_lock); 1166 sys_mutex_init (&global_lock);
1132 sys_mutex_lock (&global_lock); 1167 sys_mutex_lock (&global_lock);
1133 current_thread = &main_thread.s; 1168 current_thread = &main_thread.s;
1169#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
1170 current_thread->java_env = android_java_env;
1171#endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
1172
1134 main_thread.s.thread_id = sys_thread_self (); 1173 main_thread.s.thread_id = sys_thread_self ();
1135 init_bc_thread (&main_thread.s.bc); 1174 init_bc_thread (&main_thread.s.bc);
1136} 1175}
diff --git a/src/thread.h b/src/thread.h
index 6ce2b7f30df..1844cf03967 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -30,6 +30,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
30#include <signal.h> /* sigset_t */ 30#include <signal.h> /* sigset_t */
31#endif 31#endif
32 32
33#ifdef HAVE_ANDROID
34#ifndef ANDROID_STUBIFY
35#include "android.h"
36#endif /* ANDROID_STUBIFY */
37#endif /* HAVE_ANDROID */
38
33#include "sysselect.h" /* FIXME */ 39#include "sysselect.h" /* FIXME */
34#include "systhread.h" 40#include "systhread.h"
35 41
@@ -84,6 +90,11 @@ struct thread_state
84 Lisp_Object event_object; 90 Lisp_Object event_object;
85 /* event_object must be the last Lisp field. */ 91 /* event_object must be the last Lisp field. */
86 92
93#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
94 /* Pointer to an object to call Java functions through. */
95 JNIEnv *java_env;
96#endif /* HAVE_ANDROID && !ANDROID_STUBIFY */
97
87 /* An address near the bottom of the stack. 98 /* An address near the bottom of the stack.
88 Tells GC how to save a copy of the stack. */ 99 Tells GC how to save a copy of the stack. */
89 char const *m_stack_bottom; 100 char const *m_stack_bottom;
diff --git a/src/timefns.c b/src/timefns.c
index 1541583b485..0ecbb6e6793 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -225,7 +225,7 @@ tzlookup (Lisp_Object zone, bool settz)
225 225
226 if (NILP (zone)) 226 if (NILP (zone))
227 return local_tz; 227 return local_tz;
228 else if (BASE_EQ (zone, make_fixnum (0)) || BASE2_EQ (zone, Qt)) 228 else if (BASE_EQ (zone, make_fixnum (0)) || EQ (zone, Qt))
229 { 229 {
230 zone_string = "UTC0"; 230 zone_string = "UTC0";
231 new_tz = utc_tz; 231 new_tz = utc_tz;
@@ -234,7 +234,7 @@ tzlookup (Lisp_Object zone, bool settz)
234 { 234 {
235 bool plain_integer = FIXNUMP (zone); 235 bool plain_integer = FIXNUMP (zone);
236 236
237 if (BASE2_EQ (zone, Qwall)) 237 if (EQ (zone, Qwall))
238 zone_string = 0; 238 zone_string = 0;
239 else if (STRINGP (zone)) 239 else if (STRINGP (zone))
240 zone_string = SSDATA (ENCODE_SYSTEM (zone)); 240 zone_string = SSDATA (ENCODE_SYSTEM (zone));
@@ -1548,7 +1548,7 @@ usage: (decode-time &optional TIME ZONE FORM) */)
1548 1548
1549 /* Compute SEC from LOCAL_TM.tm_sec and HZ. */ 1549 /* Compute SEC from LOCAL_TM.tm_sec and HZ. */
1550 Lisp_Object hz = lt.hz, sec; 1550 Lisp_Object hz = lt.hz, sec;
1551 if (BASE_EQ (hz, make_fixnum (1)) || !BASE2_EQ (form, Qt)) 1551 if (BASE_EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
1552 sec = make_fixnum (local_tm.tm_sec); 1552 sec = make_fixnum (local_tm.tm_sec);
1553 else 1553 else
1554 { 1554 {
@@ -1765,10 +1765,8 @@ but new code should not rely on it. */)
1765 well, since we accept it as input? */ 1765 well, since we accept it as input? */
1766 struct lisp_time t; 1766 struct lisp_time t;
1767 enum timeform input_form = decode_lisp_time (time, false, &t, 0); 1767 enum timeform input_form = decode_lisp_time (time, false, &t, 0);
1768 if (NILP (form)) 1768 form = (!NILP (form) ? maybe_remove_pos_from_symbol (form)
1769 form = current_time_list ? Qlist : Qt; 1769 : current_time_list ? Qlist : Qt);
1770 if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (form))
1771 form = SYMBOL_WITH_POS_SYM (form);
1772 if (BASE_EQ (form, Qlist)) 1770 if (BASE_EQ (form, Qlist))
1773 return ticks_hz_list4 (t.ticks, t.hz); 1771 return ticks_hz_list4 (t.ticks, t.hz);
1774 if (BASE_EQ (form, Qinteger)) 1772 if (BASE_EQ (form, Qinteger))
diff --git a/src/treesit.c b/src/treesit.c
index 12915ea9a10..d86ab501187 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -3275,11 +3275,11 @@ treesit_traverse_child_helper (TSTreeCursor *cursor,
3275static Lisp_Object 3275static Lisp_Object
3276treesit_traverse_get_predicate (Lisp_Object thing, Lisp_Object language) 3276treesit_traverse_get_predicate (Lisp_Object thing, Lisp_Object language)
3277{ 3277{
3278 Lisp_Object cons = assq_no_quit (language, Vtreesit_thing_settings); 3278 Lisp_Object cons = assq_no_signal (language, Vtreesit_thing_settings);
3279 if (NILP (cons)) 3279 if (NILP (cons))
3280 return Qnil; 3280 return Qnil;
3281 Lisp_Object definitions = XCDR (cons); 3281 Lisp_Object definitions = XCDR (cons);
3282 Lisp_Object entry = assq_no_quit (thing, definitions); 3282 Lisp_Object entry = assq_no_signal (thing, definitions);
3283 if (NILP (entry)) 3283 if (NILP (entry))
3284 return Qnil; 3284 return Qnil;
3285 /* ENTRY looks like (THING PRED). */ 3285 /* ENTRY looks like (THING PRED). */
diff --git a/src/verbose.mk.in b/src/verbose.mk.in
index e72c182f276..6efb6b9416b 100644
--- a/src/verbose.mk.in
+++ b/src/verbose.mk.in
@@ -53,38 +53,39 @@ have_working_info = $(filter notintermediate,$(value .FEATURES))
53# The workaround is done only for AM_V_ELC and AM_V_ELN, 53# The workaround is done only for AM_V_ELC and AM_V_ELN,
54# since the bug is not annoying elsewhere. 54# since the bug is not annoying elsewhere.
55 55
56AM_V_AR = @$(info $ AR $@) 56. :=
57AM_V_AR = @$(info $. AR $@)
57AM_V_at = @ 58AM_V_at = @
58AM_V_CC = @$(info $ CC $@) 59AM_V_CC = @$(info $. CC $@)
59AM_V_CXX = @$(info $ CXX $@) 60AM_V_CXX = @$(info $. CXX $@)
60AM_V_CCLD = @$(info $ CCLD $@) 61AM_V_CCLD = @$(info $. CCLD $@)
61AM_V_CXXLD = @$(info $ CXXLD $@) 62AM_V_CXXLD = @$(info $. CXXLD $@)
62 63
63ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--) 64ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--)
64ifneq (,$(have_working_info)) 65ifneq (,$(have_working_info))
65AM_V_ELC = @$(info $ ELC+ELN $@) 66AM_V_ELC = @$(info $. ELC+ELN $@)
66AM_V_ELN = @$(info $ ELN $@) 67AM_V_ELN = @$(info $. ELN $@)
67else 68else
68AM_V_ELC = @echo " ELC+ELN " $@; 69AM_V_ELC = @echo " ELC+ELN " $@;
69AM_V_ELN = @echo " ELN " $@; 70AM_V_ELN = @echo " ELN " $@;
70endif 71endif
71else 72else
72ifneq (,$(have_working_info)) 73ifneq (,$(have_working_info))
73AM_V_ELC = @$(info $ ELC $@) 74AM_V_ELC = @$(info $. ELC $@)
74else 75else
75AM_V_ELC = @echo " ELC " $@; 76AM_V_ELC = @echo " ELC " $@;
76endif 77endif
77AM_V_ELN = 78AM_V_ELN =
78endif 79endif
79 80
80AM_V_GEN = @$(info $ GEN $@) 81AM_V_GEN = @$(info $. GEN $@)
81AM_V_GLOBALS = @$(info $ GEN globals.h) 82AM_V_GLOBALS = @$(info $. GEN globals.h)
82AM_V_NO_PD = --no-print-directory 83AM_V_NO_PD = --no-print-directory
83AM_V_RC = @$(info $ RC $@) 84AM_V_RC = @$(info $. RC $@)
84 85
85# These are used for the Android port. 86# These are used for the Android port.
86AM_V_JAVAC = @$(info $ JAVAC $@) 87AM_V_JAVAC = @$(info $. JAVAC $@)
87AM_V_D8 = @$(info $ D8 $@) 88AM_V_D8 = @$(info $. D8 $@)
88AM_V_AAPT = @$(info $ AAPT $@) 89AM_V_AAPT = @$(info $. AAPT $@)
89AM_V_SILENT = @ 90AM_V_SILENT = @
90endif 91endif
diff --git a/src/window.c b/src/window.c
index 915f591221d..0c84b4f4bf3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -4151,6 +4151,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
4151 buffer); 4151 buffer);
4152 w->start_at_line_beg = false; 4152 w->start_at_line_beg = false;
4153 w->force_start = false; 4153 w->force_start = false;
4154 /* Flush the base_line cache since it applied to another buffer. */
4155 w->base_line_number = 0;
4154 } 4156 }
4155 4157
4156 wset_redisplay (w); 4158 wset_redisplay (w);
@@ -5378,7 +5380,14 @@ grow_mini_window (struct window *w, int delta)
5378 grow = call3 (Qwindow__resize_root_window_vertically, 5380 grow = call3 (Qwindow__resize_root_window_vertically,
5379 root, make_fixnum (- delta), Qt); 5381 root, make_fixnum (- delta), Qt);
5380 5382
5381 if (FIXNUMP (grow) && window_resize_check (r, false)) 5383 if (FIXNUMP (grow)
5384 /* It might be impossible to resize the window, in which case
5385 calling resize_mini_window_apply will set off an infinite
5386 loop where the redisplay cycle so forced returns to
5387 resize_mini_window, making endless attempts to expand the
5388 minibuffer window to this impossible size. (bug#69140) */
5389 && XFIXNUM (grow) != 0
5390 && window_resize_check (r, false))
5382 resize_mini_window_apply (w, -XFIXNUM (grow)); 5391 resize_mini_window_apply (w, -XFIXNUM (grow));
5383 } 5392 }
5384} 5393}
diff --git a/src/xdisp.c b/src/xdisp.c
index 19f176459c7..d03769e2a31 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2508,7 +2508,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
2508 r.x = s->clip_head->x; 2508 r.x = s->clip_head->x;
2509 } 2509 }
2510 if (s->clip_tail) 2510 if (s->clip_tail)
2511 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width) 2511 if (r.x + (int) r.width > s->clip_tail->x + s->clip_tail->background_width)
2512 { 2512 {
2513 if (s->clip_tail->x + s->clip_tail->background_width >= r.x) 2513 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2514 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x; 2514 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
@@ -2588,7 +2588,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
2588 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent); 2588 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2589 if (height < r.height) 2589 if (height < r.height)
2590 { 2590 {
2591 max_y = r.y + r.height; 2591 max_y = r.y + (int) r.height;
2592 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height)); 2592 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2593 r.height = min (max_y - r.y, height); 2593 r.height = min (max_y - r.y, height);
2594 } 2594 }
@@ -2629,7 +2629,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
2629 if (s->for_overlaps & OVERLAPS_PRED) 2629 if (s->for_overlaps & OVERLAPS_PRED)
2630 { 2630 {
2631 rs[i] = r; 2631 rs[i] = r;
2632 if (r.y + r.height > row_y) 2632 if (r.y + (int) r.height > row_y)
2633 { 2633 {
2634 if (r.y < row_y) 2634 if (r.y < row_y)
2635 rs[i].height = row_y - r.y; 2635 rs[i].height = row_y - r.y;
@@ -2643,10 +2643,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
2643 rs[i] = r; 2643 rs[i] = r;
2644 if (r.y < row_y + s->row->visible_height) 2644 if (r.y < row_y + s->row->visible_height)
2645 { 2645 {
2646 if (r.y + r.height > row_y + s->row->visible_height) 2646 if (r.y + (int) r.height > row_y + s->row->visible_height)
2647 { 2647 {
2648 rs[i].y = row_y + s->row->visible_height; 2648 rs[i].y = row_y + s->row->visible_height;
2649 rs[i].height = r.y + r.height - rs[i].y; 2649 rs[i].height = r.y + (int) r.height - rs[i].y;
2650 } 2650 }
2651 else 2651 else
2652 rs[i].height = 0; 2652 rs[i].height = 0;
@@ -2831,7 +2831,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2831 text_glyph: 2831 text_glyph:
2832 gr = 0; gy = 0; 2832 gr = 0; gy = 0;
2833 for (; r <= end_row && r->enabled_p; ++r) 2833 for (; r <= end_row && r->enabled_p; ++r)
2834 if (r->y + r->height > y) 2834 if (r->y + (int) r->height > y)
2835 { 2835 {
2836 gr = r; gy = r->y; 2836 gr = r; gy = r->y;
2837 break; 2837 break;
@@ -2931,7 +2931,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2931 row_glyph: 2931 row_glyph:
2932 gr = 0, gy = 0; 2932 gr = 0, gy = 0;
2933 for (; r <= end_row && r->enabled_p; ++r) 2933 for (; r <= end_row && r->enabled_p; ++r)
2934 if (r->y + r->height > y) 2934 if (r->y + (int) r->height > y)
2935 { 2935 {
2936 gr = r; gy = r->y; 2936 gr = r; gy = r->y;
2937 break; 2937 break;
@@ -3821,7 +3821,7 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
3821 3821
3822 it->current_y = first_y; 3822 it->current_y = first_y;
3823 it->vpos = 0; 3823 it->vpos = 0;
3824 it->current_x = it->hpos = 0; 3824 it->current_x = it->hpos = it->wrap_prefix_width = 0;
3825 } 3825 }
3826 } 3826 }
3827} 3827}
@@ -4345,10 +4345,7 @@ compute_stop_pos (struct it *it)
4345 } 4345 }
4346 } 4346 }
4347 4347
4348 if (it->cmp_it.id < 0 4348 if (it->cmp_it.id < 0)
4349 && (STRINGP (it->string)
4350 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4351 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4352 { 4349 {
4353 ptrdiff_t stoppos = it->end_charpos; 4350 ptrdiff_t stoppos = it->end_charpos;
4354 4351
@@ -4357,7 +4354,9 @@ compute_stop_pos (struct it *it)
4357 characters to that position. */ 4354 characters to that position. */
4358 if (it->bidi_p && it->bidi_it.scan_dir < 0) 4355 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4359 stoppos = -1; 4356 stoppos = -1;
4360 else if (cmp_limit_pos > 0) 4357 else if (!STRINGP (it->string)
4358 && it->cmp_it.stop_pos <= IT_CHARPOS (*it)
4359 && cmp_limit_pos > 0)
4361 stoppos = cmp_limit_pos; 4360 stoppos = cmp_limit_pos;
4362 /* Force composition_compute_stop_pos avoid the costly search 4361 /* Force composition_compute_stop_pos avoid the costly search
4363 for static compositions, since those were already found by 4362 for static compositions, since those were already found by
@@ -5062,31 +5061,169 @@ handle_invisible_prop (struct it *it)
5062{ 5061{
5063 enum prop_handled handled = HANDLED_NORMALLY; 5062 enum prop_handled handled = HANDLED_NORMALLY;
5064 int invis; 5063 int invis;
5065 Lisp_Object prop; 5064 ptrdiff_t curpos, endpos;
5065 Lisp_Object prop, pos, overlay;
5066 5066
5067 /* Get the value of the invisible text property at the current
5068 position. Value will be nil if there is no such property. */
5067 if (STRINGP (it->string)) 5069 if (STRINGP (it->string))
5068 { 5070 {
5069 Lisp_Object end_charpos, limit; 5071 curpos = IT_STRING_CHARPOS (*it);
5072 endpos = SCHARS (it->string);
5073 pos = make_fixnum (curpos);
5074 prop = Fget_text_property (pos, Qinvisible, it->string);
5075 }
5076 else /* buffer */
5077 {
5078 curpos = IT_CHARPOS (*it);
5079 endpos = ZV;
5080 pos = make_fixnum (curpos);
5081 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5082 &overlay);
5083 }
5070 5084
5071 /* Get the value of the invisible text property at the 5085 /* Do we have anything to do here? */
5072 current position. Value will be nil if there is no such 5086 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5073 property. */ 5087 if (invis == 0 || curpos >= it->end_charpos)
5074 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it)); 5088 return handled;
5075 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5076 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5077 5089
5078 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos) 5090 /* If not bidi, or the bidi iteration is at base paragraph level, we
5091 can use a faster method; otherwise we need to check invisibility
5092 of every character while bidi-iterating out of invisible text. */
5093 bool slow = it->bidi_p && !BIDI_AT_BASE_LEVEL (it->bidi_it);
5094 /* Record whether we have to display an ellipsis for the
5095 invisible text. */
5096 bool display_ellipsis_p = (invis == 2);
5097
5098 handled = HANDLED_RECOMPUTE_PROPS;
5099
5100 if (slow)
5101 {
5102 if (it->bidi_it.first_elt && it->bidi_it.charpos < endpos)
5103 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
5104
5105 if (STRINGP (it->string))
5106 {
5107 bool done = false;
5108 /* Bidi-iterate out of the invisible part of the string. */
5109 do
5110 {
5111 bidi_move_to_visually_next (&it->bidi_it);
5112 if (it->bidi_it.charpos < 0 || it->bidi_it.charpos >= endpos)
5113 done = true;
5114 else
5115 {
5116 pos = make_fixnum (it->bidi_it.charpos);
5117 prop = Fget_text_property (pos, Qinvisible, it->string);
5118 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5119 /* If there are adjacent invisible texts, don't lose
5120 the second one's ellipsis. */
5121 if (invis == 2)
5122 display_ellipsis_p = true;
5123 }
5124 }
5125 while (!done && invis != 0);
5126
5127 if (display_ellipsis_p)
5128 it->ellipsis_p = true;
5129 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5130 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5131 if (IT_STRING_BYTEPOS (*it) >= endpos)
5132 {
5133 /* The rest of the string is invisible. If this is an
5134 overlay string, proceed with the next overlay string
5135 or whatever comes and return a character from there. */
5136 if (it->current.overlay_string_index >= 0
5137 && !display_ellipsis_p)
5138 {
5139 next_overlay_string (it);
5140 /* Don't check for overlay strings when we just
5141 finished processing them. */
5142 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5143 }
5144 }
5145 }
5146 else
5079 { 5147 {
5080 /* Record whether we have to display an ellipsis for the 5148 bool done = false;
5081 invisible text. */ 5149 /* Bidi-iterate out of the invisible text. */
5082 bool display_ellipsis_p = (invis == 2); 5150 do
5083 ptrdiff_t len, endpos; 5151 {
5152 bidi_move_to_visually_next (&it->bidi_it);
5153 if (it->bidi_it.charpos < BEGV || it->bidi_it.charpos >= endpos)
5154 done = true;
5155 else
5156 {
5157 pos = make_fixnum (it->bidi_it.charpos);
5158 prop = Fget_char_property (pos, Qinvisible, it->window);
5159 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5160 /* If there are adjacent invisible texts, don't lose
5161 the second one's ellipsis. */
5162 if (invis == 2)
5163 display_ellipsis_p = true;
5164 }
5165 }
5166 while (!done && invis != 0);
5167
5168 IT_CHARPOS (*it) = it->bidi_it.charpos;
5169 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5170 if (display_ellipsis_p)
5171 {
5172 /* Make sure that the glyphs of the ellipsis will get
5173 correct `charpos' values. See below for detailed
5174 explanation why this is needed. */
5175 it->position.charpos = IT_CHARPOS (*it) - 1;
5176 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5177 }
5178 /* If there are before-strings at the start of invisible
5179 text, and the text is invisible because of a text
5180 property, arrange to show before-strings because 20.x did
5181 it that way. (If the text is invisible because of an
5182 overlay property instead of a text property, this is
5183 already handled in the overlay code.) */
5184 if (NILP (overlay)
5185 && get_overlay_strings (it, it->stop_charpos))
5186 {
5187 handled = HANDLED_RECOMPUTE_PROPS;
5188 if (it->sp > 0)
5189 {
5190 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5191 /* The call to get_overlay_strings above recomputes
5192 it->stop_charpos, but it only considers changes
5193 in properties and overlays beyond iterator's
5194 current position. This causes us to miss changes
5195 that happen exactly where the invisible property
5196 ended. So we play it safe here and force the
5197 iterator to check for potential stop positions
5198 immediately after the invisible text. Note that
5199 if get_overlay_strings returns true, it
5200 normally also pushed the iterator stack, so we
5201 need to update the stop position in the slot
5202 below the current one. */
5203 it->stack[it->sp - 1].stop_charpos
5204 = CHARPOS (it->stack[it->sp - 1].current.pos);
5205 }
5206 }
5207 else if (display_ellipsis_p)
5208 {
5209 it->ellipsis_p = true;
5210 /* Let the ellipsis display before
5211 considering any properties of the following char.
5212 Fixes jasonr@gnu.org 01 Oct 07 bug. */
5213 handled = HANDLED_RETURN;
5214 }
5215 }
5216 }
5217 else if (STRINGP (it->string))
5218 {
5219 Lisp_Object end_charpos = pos, limit;
5084 5220
5085 handled = HANDLED_RECOMPUTE_PROPS; 5221 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5222 {
5223 ptrdiff_t len = endpos;
5086 5224
5087 /* Get the position at which the next visible text can be 5225 /* Get the position at which the next visible text can be
5088 found in IT->string, if any. */ 5226 found in IT->string, if any. */
5089 endpos = len = SCHARS (it->string);
5090 XSETINT (limit, len); 5227 XSETINT (limit, len);
5091 do 5228 do
5092 { 5229 {
@@ -5137,7 +5274,7 @@ handle_invisible_prop (struct it *it)
5137 5274
5138 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; 5275 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5139 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; 5276 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5140 if (IT_CHARPOS (*it) >= endpos) 5277 if (IT_STRING_CHARPOS (*it) >= endpos)
5141 it->prev_stop = endpos; 5278 it->prev_stop = endpos;
5142 } 5279 }
5143 else 5280 else
@@ -5167,27 +5304,14 @@ handle_invisible_prop (struct it *it)
5167 } 5304 }
5168 } 5305 }
5169 } 5306 }
5170 else 5307 else /* we are iterating over buffer text at base paragraph level */
5171 { 5308 {
5172 ptrdiff_t newpos, next_stop, start_charpos, tem; 5309 ptrdiff_t newpos, next_stop, tem = curpos;
5173 Lisp_Object pos, overlay; 5310 Lisp_Object pos;
5174
5175 /* First of all, is there invisible text at this position? */
5176 tem = start_charpos = IT_CHARPOS (*it);
5177 pos = make_fixnum (tem);
5178 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5179 &overlay);
5180 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5181 5311
5182 /* If we are on invisible text, skip over it. */ 5312 /* If we are on invisible text, skip over it. */
5183 if (invis != 0 && start_charpos < it->end_charpos) 5313 if (invis != 0 && curpos < it->end_charpos)
5184 { 5314 {
5185 /* Record whether we have to display an ellipsis for the
5186 invisible text. */
5187 bool display_ellipsis_p = invis == 2;
5188
5189 handled = HANDLED_RECOMPUTE_PROPS;
5190
5191 /* Loop skipping over invisible text. The loop is left at 5315 /* Loop skipping over invisible text. The loop is left at
5192 ZV or with IT on the first char being visible again. */ 5316 ZV or with IT on the first char being visible again. */
5193 do 5317 do
@@ -5487,9 +5611,6 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
5487 if (!NILP (it->min_width_property) 5611 if (!NILP (it->min_width_property)
5488 && !EQ (width_spec, it->min_width_property)) 5612 && !EQ (width_spec, it->min_width_property))
5489 { 5613 {
5490 if (!it->glyph_row)
5491 return;
5492
5493 /* When called from display_string (i.e., the mode line), 5614 /* When called from display_string (i.e., the mode line),
5494 we're being called with a string as the object, and we 5615 we're being called with a string as the object, and we
5495 may be called with many sub-strings belonging to the same 5616 may be called with many sub-strings belonging to the same
@@ -5532,7 +5653,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
5532 it->object = list3 (Qspace, QCwidth, w); 5653 it->object = list3 (Qspace, QCwidth, w);
5533 produce_stretch_glyph (it); 5654 produce_stretch_glyph (it);
5534 if (it->area == TEXT_AREA) 5655 if (it->area == TEXT_AREA)
5535 it->current_x += it->pixel_width; 5656 {
5657 it->current_x += it->pixel_width;
5658
5659 if (it->continuation_lines_width
5660 && it->string_from_prefix_prop_p)
5661 it->wrap_prefix_width = it->current_x;
5662 }
5536 it->min_width_property = Qnil; 5663 it->min_width_property = Qnil;
5537 } 5664 }
5538 } 5665 }
@@ -9733,6 +9860,13 @@ move_it_in_display_line_to (struct it *it,
9733 ptrdiff_t prev_pos = IT_CHARPOS (*it); 9860 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9734 bool saw_smaller_pos = prev_pos < to_charpos; 9861 bool saw_smaller_pos = prev_pos < to_charpos;
9735 bool line_number_pending = false; 9862 bool line_number_pending = false;
9863 int this_line_subject_to_line_prefix = 0;
9864
9865#ifdef GLYPH_DEBUG
9866 /* atx_flag, atpos_flag and wrap_flag are assigned but never used;
9867 these hold information useful while debugging. */
9868 int atx_flag, atpos_flag, wrap_flag;
9869#endif /* GLYPH_DEBUG */
9736 9870
9737 /* Don't produce glyphs in produce_glyphs. */ 9871 /* Don't produce glyphs in produce_glyphs. */
9738 saved_glyph_row = it->glyph_row; 9872 saved_glyph_row = it->glyph_row;
@@ -9798,6 +9932,11 @@ move_it_in_display_line_to (struct it *it,
9798 /* If there's a line-/wrap-prefix, handle it, if we didn't already. */ 9932 /* If there's a line-/wrap-prefix, handle it, if we didn't already. */
9799 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p) 9933 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9800 handle_line_prefix (it); 9934 handle_line_prefix (it);
9935
9936 /* Save whether this line has received a wrap prefix, as this
9937 affects whether Emacs attempts to move glyphs into
9938 continuation lines. */
9939 this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
9801 } 9940 }
9802 9941
9803 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) 9942 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
@@ -9841,10 +9980,15 @@ move_it_in_display_line_to (struct it *it,
9841 break; 9980 break;
9842 } 9981 }
9843 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) 9982 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9844 /* If wrap_it is valid, the current position might be in a 9983 {
9845 word that is wrapped. So, save the iterator in 9984 /* If wrap_it is valid, the current position might be in
9846 atpos_it and continue to see if wrapping happens. */ 9985 a word that is wrapped. So, save the iterator in
9847 SAVE_IT (atpos_it, *it, atpos_data); 9986 atpos_it and continue to see if wrapping happens. */
9987 SAVE_IT (atpos_it, *it, atpos_data);
9988#ifdef GLYPH_DEBUG
9989 atpos_flag = this_line_subject_to_line_prefix;
9990#endif /* GLYPH_DEBUG */
9991 }
9848 } 9992 }
9849 9993
9850 /* Stop when ZV reached. 9994 /* Stop when ZV reached.
@@ -9906,6 +10050,9 @@ move_it_in_display_line_to (struct it *it,
9906 } 10050 }
9907 /* Otherwise, we can wrap here. */ 10051 /* Otherwise, we can wrap here. */
9908 SAVE_IT (wrap_it, *it, wrap_data); 10052 SAVE_IT (wrap_it, *it, wrap_data);
10053#ifdef GLYPH_DEBUG
10054 wrap_flag = this_line_subject_to_line_prefix;
10055#endif /* GLYPH_DEBUG */
9909 } 10056 }
9910 /* Update may_wrap for the next iteration. */ 10057 /* Update may_wrap for the next iteration. */
9911 may_wrap = next_may_wrap; 10058 may_wrap = next_may_wrap;
@@ -9984,6 +10131,9 @@ move_it_in_display_line_to (struct it *it,
9984 { 10131 {
9985 SAVE_IT (atpos_it, *it, atpos_data); 10132 SAVE_IT (atpos_it, *it, atpos_data);
9986 IT_RESET_X_ASCENT_DESCENT (&atpos_it); 10133 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10134#ifdef GLYPH_DEBUG
10135 atpos_flag = this_line_subject_to_line_prefix;
10136#endif /* GLYPH_DEBUG */
9987 } 10137 }
9988 } 10138 }
9989 else 10139 else
@@ -9998,6 +10148,9 @@ move_it_in_display_line_to (struct it *it,
9998 { 10148 {
9999 SAVE_IT (atx_it, *it, atx_data); 10149 SAVE_IT (atx_it, *it, atx_data);
10000 IT_RESET_X_ASCENT_DESCENT (&atx_it); 10150 IT_RESET_X_ASCENT_DESCENT (&atx_it);
10151#ifdef GLYPH_DEBUG
10152 atx_flag = this_line_subject_to_line_prefix;
10153#endif /* GLYPH_DEBUG */
10001 } 10154 }
10002 } 10155 }
10003 } 10156 }
@@ -10012,12 +10165,27 @@ move_it_in_display_line_to (struct it *it,
10012 && FRAME_WINDOW_P (it->f) 10165 && FRAME_WINDOW_P (it->f)
10013 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L) 10166 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10014 ? WINDOW_LEFT_FRINGE_WIDTH (it->w) 10167 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10015 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) 10168 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
10169 /* There is no line prefix, next to which the
10170 iterator _must_ produce a minimum of one actual
10171 glyph. */
10172 && (!this_line_subject_to_line_prefix
10173 /* Or this is the second glyph to be produced
10174 beyond the confines of the line. */
10175 || (i != 0
10176 && (x > it->last_visible_x
10177 || (x == it->last_visible_x
10178 && FRAME_WINDOW_P (it->f)
10179 && ((it->bidi_p
10180 && it->bidi_it.paragraph_dir == R2L)
10181 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10182 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
10016 { 10183 {
10017 bool moved_forward = false; 10184 bool moved_forward = false;
10018 10185
10019 if (/* IT->hpos == 0 means the very first glyph 10186 if (/* IT->hpos == 0 means the very first glyph
10020 doesn't fit on the line, e.g. a wide image. */ 10187 doesn't fit on the line, e.g. a wide
10188 image. */
10021 it->hpos == 0 10189 it->hpos == 0
10022 || (new_x == it->last_visible_x 10190 || (new_x == it->last_visible_x
10023 && FRAME_WINDOW_P (it->f))) 10191 && FRAME_WINDOW_P (it->f)))
@@ -10078,6 +10246,9 @@ move_it_in_display_line_to (struct it *it,
10078 SAVE_IT (atpos_it, *it, atpos_data); 10246 SAVE_IT (atpos_it, *it, atpos_data);
10079 atpos_it.current_x = x_before_this_char; 10247 atpos_it.current_x = x_before_this_char;
10080 atpos_it.hpos = hpos_before_this_char; 10248 atpos_it.hpos = hpos_before_this_char;
10249#ifdef GLYPH_DEBUG
10250 atpos_flag = this_line_subject_to_line_prefix;
10251#endif /* GLYPH_DEBUG */
10081 } 10252 }
10082 } 10253 }
10083 10254
@@ -10175,6 +10346,9 @@ move_it_in_display_line_to (struct it *it,
10175 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) 10346 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10176 { 10347 {
10177 SAVE_IT (atpos_it, *it, atpos_data); 10348 SAVE_IT (atpos_it, *it, atpos_data);
10349#ifdef GLYPH_DEBUG
10350 atpos_flag = this_line_subject_to_line_prefix;
10351#endif /* GLYPH_DEBUG */
10178 IT_RESET_X_ASCENT_DESCENT (&atpos_it); 10352 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10179 } 10353 }
10180 } 10354 }
@@ -10273,24 +10447,24 @@ move_it_in_display_line_to (struct it *it,
10273 if (it->method == GET_FROM_BUFFER) 10447 if (it->method == GET_FROM_BUFFER)
10274 prev_pos = IT_CHARPOS (*it); 10448 prev_pos = IT_CHARPOS (*it);
10275 10449
10276 /* Detect overly-wide wrap-prefixes made of (space ...) display 10450 /* The current display element has been consumed. Advance to
10277 properties. When such a wrap prefix reaches past the right 10451 the next. */
10278 margin of the window, we need to avoid the call to 10452 set_iterator_to_next (it, true);
10279 set_iterator_to_next below, so that it->line_wrap is left at 10453
10280 its TRUNCATE value wisely set by handle_line_prefix. 10454 /* If IT has just finished producing glyphs for the wrap prefix
10281 Otherwise, set_iterator_to_next will pop the iterator stack, 10455 and is proceeding to the next method, there might not be
10282 restore it->line_wrap, and we might miss the opportunity to 10456 sufficient space remaining in this line to accommodate its
10283 exit the loop and return. */ 10457 glyphs, and one real glyph must be produced to prevent an
10284 bool overwide_wrap_prefix = 10458 infinite loop. Next, clear this flag if such a glyph has
10285 CONSP (it->object) && EQ (XCAR (it->object), Qspace) 10459 already been produced. */
10286 && it->sp > 0 && it->method == GET_FROM_STRETCH 10460
10287 && it->current_x >= it->last_visible_x 10461 if (this_line_subject_to_line_prefix == 1
10288 && it->continuation_lines_width > 0 10462 && !it->string_from_prefix_prop_p)
10289 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE; 10463 this_line_subject_to_line_prefix = 2;
10290 /* The current display element has been consumed. Advance 10464 else if (this_line_subject_to_line_prefix == 2
10291 to the next. */ 10465 && !it->string_from_prefix_prop_p)
10292 if (!overwide_wrap_prefix) 10466 this_line_subject_to_line_prefix = 0;
10293 set_iterator_to_next (it, true); 10467
10294 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) 10468 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10295 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it)); 10469 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10296 if (IT_CHARPOS (*it) < to_charpos) 10470 if (IT_CHARPOS (*it) < to_charpos)
@@ -10374,11 +10548,26 @@ move_it_in_display_line_to (struct it *it,
10374 && wrap_it.sp >= 0 10548 && wrap_it.sp >= 0
10375 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x) 10549 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10376 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x))) 10550 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10377 RESTORE_IT (it, &wrap_it, wrap_data); 10551 {
10552#ifdef GLYPH_DEBUG
10553 this_line_subject_to_line_prefix = wrap_flag;
10554#endif /* GLYPH_DEBUG */
10555 RESTORE_IT (it, &wrap_it, wrap_data);
10556 }
10378 else if (atpos_it.sp >= 0) 10557 else if (atpos_it.sp >= 0)
10379 RESTORE_IT (it, &atpos_it, atpos_data); 10558 {
10559#ifdef GLYPH_DEBUG
10560 this_line_subject_to_line_prefix = atpos_flag;
10561#endif /* GLYPH_DEBUG */
10562 RESTORE_IT (it, &atpos_it, atpos_data);
10563 }
10380 else if (atx_it.sp >= 0) 10564 else if (atx_it.sp >= 0)
10381 RESTORE_IT (it, &atx_it, atx_data); 10565 {
10566#ifdef GLYPH_DEBUG
10567 this_line_subject_to_line_prefix = atx_flag;
10568#endif /* GLYPH_DEBUG */
10569 RESTORE_IT (it, &atx_it, atx_data);
10570 }
10382 10571
10383 done: 10572 done:
10384 10573
@@ -10452,13 +10641,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
10452 int line_height, line_start_x = 0, reached = 0; 10641 int line_height, line_start_x = 0, reached = 0;
10453 int max_current_x = 0; 10642 int max_current_x = 0;
10454 void *backup_data = NULL; 10643 void *backup_data = NULL;
10455 ptrdiff_t orig_charpos = -1;
10456 enum it_method orig_method = NUM_IT_METHODS;
10457 10644
10458 for (;;) 10645 for (;;)
10459 { 10646 {
10460 orig_charpos = IT_CHARPOS (*it);
10461 orig_method = it->method;
10462 if (op & MOVE_TO_VPOS) 10647 if (op & MOVE_TO_VPOS)
10463 { 10648 {
10464 /* If no TO_CHARPOS and no TO_X specified, stop at the 10649 /* If no TO_CHARPOS and no TO_X specified, stop at the
@@ -10730,21 +10915,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
10730 } 10915 }
10731 } 10916 }
10732 else 10917 else
10733 { 10918 it->continuation_lines_width += it->current_x;
10734 /* Make sure we do advance, otherwise we might infloop.
10735 This could happen when the first display element is
10736 wider than the window, or if we have a wrap-prefix
10737 that doesn't leave enough space after it to display
10738 even a single character. We only do this for moving
10739 through buffer text, as with display/overlay strings
10740 we'd need to also compare it->object's, and this is
10741 unlikely to happen in that case anyway. */
10742 if (IT_CHARPOS (*it) == orig_charpos
10743 && it->method == orig_method
10744 && orig_method == GET_FROM_BUFFER)
10745 set_iterator_to_next (it, false);
10746 it->continuation_lines_width += it->current_x;
10747 }
10748 break; 10919 break;
10749 10920
10750 default: 10921 default:
@@ -10753,6 +10924,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
10753 10924
10754 /* Reset/increment for the next run. */ 10925 /* Reset/increment for the next run. */
10755 it->current_x = line_start_x; 10926 it->current_x = line_start_x;
10927 it->wrap_prefix_width = 0;
10756 line_start_x = 0; 10928 line_start_x = 0;
10757 it->hpos = 0; 10929 it->hpos = 0;
10758 it->line_number_produced_p = false; 10930 it->line_number_produced_p = false;
@@ -10783,6 +10955,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
10783 { 10955 {
10784 it->continuation_lines_width += it->current_x; 10956 it->continuation_lines_width += it->current_x;
10785 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0; 10957 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10958 it->wrap_prefix_width = 0;
10786 it->current_y += it->max_ascent + it->max_descent; 10959 it->current_y += it->max_ascent + it->max_descent;
10787 ++it->vpos; 10960 ++it->vpos;
10788 last_height = it->max_ascent + it->max_descent; 10961 last_height = it->max_ascent + it->max_descent;
@@ -10842,6 +11015,7 @@ move_it_vertically_backward (struct it *it, int dy)
10842 reseat_1 (it, it->current.pos, true); 11015 reseat_1 (it, it->current.pos, true);
10843 11016
10844 /* We are now surely at a line start. */ 11017 /* We are now surely at a line start. */
11018 it->wrap_prefix_width = 0;
10845 it->current_x = it->hpos = 0; /* FIXME: this is incorrect when bidi 11019 it->current_x = it->hpos = 0; /* FIXME: this is incorrect when bidi
10846 reordering is in effect. */ 11020 reordering is in effect. */
10847 it->continuation_lines_width = 0; 11021 it->continuation_lines_width = 0;
@@ -11120,7 +11294,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11120 dvpos--; 11294 dvpos--;
11121 } 11295 }
11122 11296
11123 it->current_x = it->hpos = 0; 11297 it->current_x = it->hpos = it->wrap_prefix_width = 0;
11124 11298
11125 /* Above call may have moved too far if continuation lines 11299 /* Above call may have moved too far if continuation lines
11126 are involved. Scan forward and see if it did. */ 11300 are involved. Scan forward and see if it did. */
@@ -11129,7 +11303,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
11129 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); 11303 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11130 it->vpos -= it2.vpos; 11304 it->vpos -= it2.vpos;
11131 it->current_y -= it2.current_y; 11305 it->current_y -= it2.current_y;
11132 it->current_x = it->hpos = 0; 11306 it->current_x = it->hpos = it->wrap_prefix_width = 0;
11133 11307
11134 /* If we moved too far back, move IT some lines forward. */ 11308 /* If we moved too far back, move IT some lines forward. */
11135 if (it2.vpos > -dvpos) 11309 if (it2.vpos > -dvpos)
@@ -11408,7 +11582,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11408 IT.current_x will be incorrectly set to zero at some arbitrary 11582 IT.current_x will be incorrectly set to zero at some arbitrary
11409 non-zero X coordinate. */ 11583 non-zero X coordinate. */
11410 move_it_by_lines (&it, 0); 11584 move_it_by_lines (&it, 0);
11411 it.current_x = it.hpos = 0; 11585 it.current_x = it.hpos = it.wrap_prefix_width = 0;
11412 if (IT_CHARPOS (it) != start) 11586 if (IT_CHARPOS (it) != start)
11413 { 11587 {
11414 void *it1data = NULL; 11588 void *it1data = NULL;
@@ -11461,7 +11635,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11461 /* If FROM is on a newline, pretend that we start at the beginning 11635 /* If FROM is on a newline, pretend that we start at the beginning
11462 of the next line, because the newline takes no place on display. */ 11636 of the next line, because the newline takes no place on display. */
11463 if (FETCH_BYTE (start) == '\n') 11637 if (FETCH_BYTE (start) == '\n')
11464 it.current_x = 0; 11638 it.current_x = 0, it.wrap_prefix_width = 0;
11465 if (!NILP (x_limit)) 11639 if (!NILP (x_limit))
11466 { 11640 {
11467 it.last_visible_x = max_x; 11641 it.last_visible_x = max_x;
@@ -14373,7 +14547,7 @@ display_tab_bar_line (struct it *it, int height)
14373 row->truncated_on_left_p = false; 14547 row->truncated_on_left_p = false;
14374 row->truncated_on_right_p = false; 14548 row->truncated_on_right_p = false;
14375 14549
14376 it->current_x = it->hpos = 0; 14550 it->current_x = it->hpos = it->wrap_prefix_width = 0;
14377 it->current_y += row->height; 14551 it->current_y += row->height;
14378 ++it->vpos; 14552 ++it->vpos;
14379 ++it->glyph_row; 14553 ++it->glyph_row;
@@ -15397,7 +15571,7 @@ display_tool_bar_line (struct it *it, int height)
15397 row->truncated_on_left_p = false; 15571 row->truncated_on_left_p = false;
15398 row->truncated_on_right_p = false; 15572 row->truncated_on_right_p = false;
15399 15573
15400 it->current_x = it->hpos = 0; 15574 it->current_x = it->hpos = it->wrap_prefix_width = 0;
15401 it->current_y += row->height; 15575 it->current_y += row->height;
15402 ++it->vpos; 15576 ++it->vpos;
15403 ++it->glyph_row; 15577 ++it->glyph_row;
@@ -17097,6 +17271,7 @@ redisplay_internal (void)
17097 NULL, DEFAULT_FACE_ID); 17271 NULL, DEFAULT_FACE_ID);
17098 it.current_x = this_line_start_x; 17272 it.current_x = this_line_start_x;
17099 it.current_y = this_line_y; 17273 it.current_y = this_line_y;
17274 it.wrap_prefix_width = 0;
17100 it.vpos = this_line_vpos; 17275 it.vpos = this_line_vpos;
17101 17276
17102 if (current_buffer->long_line_optimizations_p 17277 if (current_buffer->long_line_optimizations_p
@@ -18682,6 +18857,14 @@ enum
18682 `scroll-conservatively' and the Emacs manual. */ 18857 `scroll-conservatively' and the Emacs manual. */
18683#define SCROLL_LIMIT 100 18858#define SCROLL_LIMIT 100
18684 18859
18860/* The freshness of the w->base_line_number cache is only ensured at every
18861 redisplay cycle, so the cache can be used only if there's been
18862 no relevant changes to the buffer since the last redisplay. */
18863#define BASE_LINE_NUMBER_VALID_P(w) \
18864 (eassert (current_buffer == XBUFFER ((w)->contents)), \
18865 !current_buffer->clip_changed \
18866 && BEG_UNCHANGED >= (w)->base_line_pos)
18867
18685static int 18868static int
18686try_scrolling (Lisp_Object window, bool just_this_one_p, 18869try_scrolling (Lisp_Object window, bool just_this_one_p,
18687 intmax_t arg_scroll_conservatively, intmax_t scroll_step, 18870 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
@@ -18982,9 +19165,10 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
18982 else 19165 else
18983 { 19166 {
18984 /* Maybe forget recorded base line for line number display. */ 19167 /* Maybe forget recorded base line for line number display. */
18985 if (!just_this_one_p 19168 /* FIXME: Why do we need this? `try_scrolling` can only be called from
18986 || current_buffer->clip_changed 19169 `redisplay_window` which should have flushed this cache already when
18987 || BEG_UNCHANGED < CHARPOS (startp)) 19170 eeded. */
19171 if (!BASE_LINE_NUMBER_VALID_P (w))
18988 w->base_line_number = 0; 19172 w->base_line_number = 0;
18989 19173
18990 /* If cursor ends up on a partially visible line, 19174 /* If cursor ends up on a partially visible line,
@@ -19754,9 +19938,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19754 /* Record it now because it's overwritten. */ 19938 /* Record it now because it's overwritten. */
19755 bool current_matrix_up_to_date_p = false; 19939 bool current_matrix_up_to_date_p = false;
19756 bool used_current_matrix_p = false; 19940 bool used_current_matrix_p = false;
19757 /* This is less strict than current_matrix_up_to_date_p.
19758 It indicates that the buffer contents and narrowing are unchanged. */
19759 bool buffer_unchanged_p = false;
19760 bool temp_scroll_step = false; 19941 bool temp_scroll_step = false;
19761 specpdl_ref count = SPECPDL_INDEX (); 19942 specpdl_ref count = SPECPDL_INDEX ();
19762 int rc; 19943 int rc;
@@ -19862,11 +20043,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19862 20043
19863 specbind (Qinhibit_point_motion_hooks, Qt); 20044 specbind (Qinhibit_point_motion_hooks, Qt);
19864 20045
19865 buffer_unchanged_p
19866 = (w->window_end_valid
19867 && !current_buffer->clip_changed
19868 && !window_outdated (w));
19869
19870 /* When windows_or_buffers_changed is non-zero, we can't rely 20046 /* When windows_or_buffers_changed is non-zero, we can't rely
19871 on the window end being valid, so set it to zero there. */ 20047 on the window end being valid, so set it to zero there. */
19872 if (windows_or_buffers_changed) 20048 if (windows_or_buffers_changed)
@@ -20006,6 +20182,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20006 } 20182 }
20007 } 20183 }
20008 20184
20185 if (!BASE_LINE_NUMBER_VALID_P (w))
20186 /* Forget any recorded base line for line number display. */
20187 w->base_line_number = 0;
20188
20009 force_start: 20189 force_start:
20010 20190
20011 /* Handle case where place to start displaying has been specified, 20191 /* Handle case where place to start displaying has been specified,
@@ -20026,10 +20206,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20026 w->preserve_vscroll_p = false; 20206 w->preserve_vscroll_p = false;
20027 w->window_end_valid = false; 20207 w->window_end_valid = false;
20028 20208
20029 /* Forget any recorded base line for line number display. */
20030 if (!buffer_unchanged_p)
20031 w->base_line_number = 0;
20032
20033 /* Redisplay the mode line. Select the buffer properly for that. 20209 /* Redisplay the mode line. Select the buffer properly for that.
20034 Also, run the hook window-scroll-functions 20210 Also, run the hook window-scroll-functions
20035 because we have scrolled. */ 20211 because we have scrolled. */
@@ -20358,12 +20534,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20358 20534
20359 if (w->cursor.vpos >= 0) 20535 if (w->cursor.vpos >= 0)
20360 { 20536 {
20361 if (!just_this_one_p
20362 || current_buffer->clip_changed
20363 || BEG_UNCHANGED < CHARPOS (startp))
20364 /* Forget any recorded base line for line number display. */
20365 w->base_line_number = 0;
20366
20367 if (!cursor_row_fully_visible_p (w, true, false, false)) 20537 if (!cursor_row_fully_visible_p (w, true, false, false))
20368 { 20538 {
20369 clear_glyph_matrix (w->desired_matrix); 20539 clear_glyph_matrix (w->desired_matrix);
@@ -20434,10 +20604,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20434 debug_method_add (w, "recenter"); 20604 debug_method_add (w, "recenter");
20435#endif 20605#endif
20436 20606
20437 /* Forget any previously recorded base line for line number display. */
20438 if (!buffer_unchanged_p)
20439 w->base_line_number = 0;
20440
20441 /* Determine the window start relative to point. */ 20607 /* Determine the window start relative to point. */
20442 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); 20608 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20443 it.current_y = it.last_visible_y; 20609 it.current_y = it.last_visible_y;
@@ -20543,7 +20709,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
20543 it.current_y = 0; 20709 it.current_y = 0;
20544 } 20710 }
20545 20711
20546 it.current_x = it.hpos = 0; 20712 it.current_x = it.wrap_prefix_width = it.hpos = 0;
20547 20713
20548 /* Set the window start position here explicitly, to avoid an 20714 /* Set the window start position here explicitly, to avoid an
20549 infinite loop in case the functions in window-scroll-functions 20715 infinite loop in case the functions in window-scroll-functions
@@ -22511,7 +22677,7 @@ try_window_id (struct window *w)
22511 /* We may start in a continuation line. If so, we have to 22677 /* We may start in a continuation line. If so, we have to
22512 get the right continuation_lines_width and current_x. */ 22678 get the right continuation_lines_width and current_x. */
22513 it.continuation_lines_width = last_row->continuation_lines_width; 22679 it.continuation_lines_width = last_row->continuation_lines_width;
22514 it.hpos = it.current_x = 0; 22680 it.hpos = it.current_x = it.wrap_prefix_width = 0;
22515 22681
22516 /* Display the rest of the lines at the window end. */ 22682 /* Display the rest of the lines at the window end. */
22517 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos); 22683 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
@@ -23116,6 +23282,7 @@ insert_left_trunc_glyphs (struct it *it)
23116 /* Get the truncation glyphs. */ 23282 /* Get the truncation glyphs. */
23117 truncate_it = *it; 23283 truncate_it = *it;
23118 truncate_it.current_x = 0; 23284 truncate_it.current_x = 0;
23285 truncate_it.wrap_prefix_width = 0;
23119 truncate_it.face_id = DEFAULT_FACE_ID; 23286 truncate_it.face_id = DEFAULT_FACE_ID;
23120 truncate_it.glyph_row = &scratch_glyph_row; 23287 truncate_it.glyph_row = &scratch_glyph_row;
23121 truncate_it.area = TEXT_AREA; 23288 truncate_it.area = TEXT_AREA;
@@ -23878,6 +24045,10 @@ extend_face_to_end_of_line (struct it *it)
23878 for (it->current_x = 0; g < e; g++) 24045 for (it->current_x = 0; g < e; g++)
23879 it->current_x += g->pixel_width; 24046 it->current_x += g->pixel_width;
23880 24047
24048 if (it->continuation_lines_width
24049 && it->string_from_prefix_prop_p)
24050 it->wrap_prefix_width = it->current_x;
24051
23881 it->area = LEFT_MARGIN_AREA; 24052 it->area = LEFT_MARGIN_AREA;
23882 it->face_id = default_face->id; 24053 it->face_id = default_face->id;
23883 while (it->glyph_row->used[LEFT_MARGIN_AREA] 24054 while (it->glyph_row->used[LEFT_MARGIN_AREA]
@@ -24599,6 +24770,13 @@ maybe_produce_line_number (struct it *it)
24599 if (!last_line) 24770 if (!last_line)
24600 { 24771 {
24601 /* If possible, reuse data cached by line-number-mode. */ 24772 /* If possible, reuse data cached by line-number-mode. */
24773 /* NOTE: We use `base_line_number` without checking
24774 BASE_LINE_NUMBER_VALID_P because we assume that `redisplay_window`
24775 has already flushed this cache for us when needed.
24776 NOTE2: Checking BASE_LINE_NUMBER_VALID_P here would be
24777 overly pessimistic because it might say that the cache
24778 was invalid before entering `redisplay_window` yet the
24779 value has just been refreshed. */
24602 if (it->w->base_line_number > 0 24780 if (it->w->base_line_number > 0
24603 && it->w->base_line_pos > 0 24781 && it->w->base_line_pos > 0
24604 && it->w->base_line_pos <= IT_CHARPOS (*it) 24782 && it->w->base_line_pos <= IT_CHARPOS (*it)
@@ -24878,7 +25056,7 @@ should_produce_line_number (struct it *it)
24878 because get-char-property always returns nil for ZV, except if 25056 because get-char-property always returns nil for ZV, except if
24879 the property is in 'default-text-properties'. */ 25057 the property is in 'default-text-properties'. */
24880 if (NILP (val) && IT_CHARPOS (*it) >= ZV) 25058 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24881 val = disable_line_numbers_overlay_at_eob (); 25059 return !disable_line_numbers_overlay_at_eob ();
24882 return NILP (val) ? true : false; 25060 return NILP (val) ? true : false;
24883} 25061}
24884 25062
@@ -24943,6 +25121,7 @@ display_line (struct it *it, int cursor_vpos)
24943 int first_visible_x = it->first_visible_x; 25121 int first_visible_x = it->first_visible_x;
24944 int last_visible_x = it->last_visible_x; 25122 int last_visible_x = it->last_visible_x;
24945 int x_incr = 0; 25123 int x_incr = 0;
25124 int this_line_subject_to_line_prefix = 0;
24946 25125
24947 /* We always start displaying at hpos zero even if hscrolled. */ 25126 /* We always start displaying at hpos zero even if hscrolled. */
24948 eassert (it->hpos == 0 && it->current_x == 0); 25127 eassert (it->hpos == 0 && it->current_x == 0);
@@ -25019,7 +25198,10 @@ display_line (struct it *it, int cursor_vpos)
25019 if (it->current_x < it->first_visible_x 25198 if (it->current_x < it->first_visible_x
25020 && (move_result == MOVE_NEWLINE_OR_CR 25199 && (move_result == MOVE_NEWLINE_OR_CR
25021 || move_result == MOVE_POS_MATCH_OR_ZV)) 25200 || move_result == MOVE_POS_MATCH_OR_ZV))
25022 it->current_x = it->first_visible_x; 25201 {
25202 it->current_x = it->first_visible_x;
25203 it->wrap_prefix_width = 0;
25204 }
25023 25205
25024 /* In case move_it_in_display_line_to above "produced" the line 25206 /* In case move_it_in_display_line_to above "produced" the line
25025 number. */ 25207 number. */
@@ -25048,6 +25230,7 @@ display_line (struct it *it, int cursor_vpos)
25048 /* We only do this when not calling move_it_in_display_line_to 25230 /* We only do this when not calling move_it_in_display_line_to
25049 above, because that function calls itself handle_line_prefix. */ 25231 above, because that function calls itself handle_line_prefix. */
25050 handle_line_prefix (it); 25232 handle_line_prefix (it);
25233 this_line_subject_to_line_prefix = it->string_from_prefix_prop_p;
25051 } 25234 }
25052 else 25235 else
25053 { 25236 {
@@ -25214,12 +25397,15 @@ display_line (struct it *it, int cursor_vpos)
25214 process the prefix now. */ 25397 process the prefix now. */
25215 if (it->area == TEXT_AREA && pending_handle_line_prefix) 25398 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25216 { 25399 {
25217 /* Line numbers should precede the line-prefix or wrap-prefix. */ 25400 /* Line numbers should precede the line-prefix or
25401 wrap-prefix. */
25218 if (line_number_needed) 25402 if (line_number_needed)
25219 maybe_produce_line_number (it); 25403 maybe_produce_line_number (it);
25220 25404
25221 pending_handle_line_prefix = false; 25405 pending_handle_line_prefix = false;
25222 handle_line_prefix (it); 25406 handle_line_prefix (it);
25407 this_line_subject_to_line_prefix
25408 = it->string_from_prefix_prop_p;
25223 } 25409 }
25224 continue; 25410 continue;
25225 } 25411 }
@@ -25240,7 +25426,16 @@ display_line (struct it *it, int cursor_vpos)
25240 if (/* Not a newline. */ 25426 if (/* Not a newline. */
25241 nglyphs > 0 25427 nglyphs > 0
25242 /* Glyphs produced fit entirely in the line. */ 25428 /* Glyphs produced fit entirely in the line. */
25243 && it->current_x < it->last_visible_x) 25429 && (it->current_x < it->last_visible_x
25430 /* Or a line or wrap prefix is in effect, and not
25431 truncating the glyph produced immediately after it
25432 would cause an infinite cycle. */
25433 || (it->line_wrap != TRUNCATE
25434 /* This code is not valid if multiple glyphs were
25435 produced, as some of these glyphs might remain
25436 within this line. */
25437 && nglyphs == 1
25438 && this_line_subject_to_line_prefix)))
25244 { 25439 {
25245 it->hpos += nglyphs; 25440 it->hpos += nglyphs;
25246 row->ascent = max (row->ascent, it->max_ascent); 25441 row->ascent = max (row->ascent, it->max_ascent);
@@ -25291,7 +25486,20 @@ display_line (struct it *it, int cursor_vpos)
25291 && FRAME_WINDOW_P (it->f) 25486 && FRAME_WINDOW_P (it->f)
25292 && (row->reversed_p 25487 && (row->reversed_p
25293 ? WINDOW_LEFT_FRINGE_WIDTH (it->w) 25488 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25294 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) 25489 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25490 /* There is no line prefix, next to which the
25491 iterator _must_ produce a minimum of one actual
25492 glyph. */
25493 && (!this_line_subject_to_line_prefix
25494 /* Or this is the second glyph to be produced
25495 beyond the confines of the line. */
25496 || (i != 0
25497 && (x > it->last_visible_x
25498 || (x == it->last_visible_x
25499 && FRAME_WINDOW_P (it->f)
25500 && (row->reversed_p
25501 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25502 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))))
25295 { 25503 {
25296 /* End of a continued line. */ 25504 /* End of a continued line. */
25297 25505
@@ -25588,24 +25796,23 @@ display_line (struct it *it, int cursor_vpos)
25588 break; 25796 break;
25589 } 25797 }
25590 25798
25591 /* Detect overly-wide wrap-prefixes made of (space ...) display
25592 properties. When such a wrap prefix reaches past the right
25593 margin of the window, we need to avoid the call to
25594 set_iterator_to_next below, so that it->line_wrap is left at
25595 its TRUNCATE value wisely set by handle_line_prefix.
25596 Otherwise, set_iterator_to_next will pop the iterator stack,
25597 restore it->line_wrap, and redisplay might infloop. */
25598 bool overwide_wrap_prefix =
25599 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25600 && it->sp > 0 && it->method == GET_FROM_STRETCH
25601 && it->current_x >= it->last_visible_x
25602 && it->continuation_lines_width > 0
25603 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25604
25605 /* Proceed with next display element. Note that this skips 25799 /* Proceed with next display element. Note that this skips
25606 over lines invisible because of selective display. */ 25800 over lines invisible because of selective display. */
25607 if (!overwide_wrap_prefix) 25801 set_iterator_to_next (it, true);
25608 set_iterator_to_next (it, true); 25802
25803 /* If IT has just finished producing glyphs for the wrap prefix
25804 and is proceeding to the next method, there might not be
25805 sufficient space remaining in this line to accommodate its
25806 glyphs, and one real glyph must be produced to prevent an
25807 infinite loop. Next, clear this flag if such a glyph has
25808 already been produced. */
25809
25810 if (this_line_subject_to_line_prefix == 1
25811 && !it->string_from_prefix_prop_p)
25812 this_line_subject_to_line_prefix = 2;
25813 else if (this_line_subject_to_line_prefix == 2
25814 && !it->string_from_prefix_prop_p)
25815 this_line_subject_to_line_prefix = 0;
25609 25816
25610 /* If we truncate lines, we are done when the last displayed 25817 /* If we truncate lines, we are done when the last displayed
25611 glyphs reach past the right margin of the window. */ 25818 glyphs reach past the right margin of the window. */
@@ -25851,7 +26058,7 @@ display_line (struct it *it, int cursor_vpos)
25851 HPOS) = (0 0). Vertical positions are incremented. As a 26058 HPOS) = (0 0). Vertical positions are incremented. As a
25852 convenience for the caller, IT->glyph_row is set to the next 26059 convenience for the caller, IT->glyph_row is set to the next
25853 row to be used. */ 26060 row to be used. */
25854 it->current_x = it->hpos = 0; 26061 it->wrap_prefix_width = it->current_x = it->hpos = 0;
25855 it->current_y += row->height; 26062 it->current_y += row->height;
25856 /* Restore the first and last visible X if we adjusted them for 26063 /* Restore the first and last visible X if we adjusted them for
25857 current-line hscrolling. */ 26064 current-line hscrolling. */
@@ -26330,7 +26537,7 @@ Value is the new character position of point. */)
26330 { 26537 {
26331 struct text_pos pt; 26538 struct text_pos pt;
26332 struct it it; 26539 struct it it;
26333 int pt_x, target_x, pixel_width, pt_vpos; 26540 int pt_x, pt_wrap_prefix_x, target_x, pixel_width, pt_vpos;
26334 bool at_eol_p; 26541 bool at_eol_p;
26335 bool overshoot_expected = false; 26542 bool overshoot_expected = false;
26336 bool target_is_eol_p = false; 26543 bool target_is_eol_p = false;
@@ -26362,6 +26569,7 @@ Value is the new character position of point. */)
26362 reseat: 26569 reseat:
26363 reseat_at_previous_visible_line_start (&it); 26570 reseat_at_previous_visible_line_start (&it);
26364 it.current_x = it.hpos = it.current_y = it.vpos = 0; 26571 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26572 it.wrap_prefix_width = 0;
26365 if (IT_CHARPOS (it) != PT) 26573 if (IT_CHARPOS (it) != PT)
26366 { 26574 {
26367 move_it_to (&it, overshoot_expected ? PT - 1 : PT, 26575 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
@@ -26380,6 +26588,7 @@ Value is the new character position of point. */)
26380 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS); 26588 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26381 } 26589 }
26382 pt_x = it.current_x; 26590 pt_x = it.current_x;
26591 pt_wrap_prefix_x = it.wrap_prefix_width;
26383 pt_vpos = it.vpos; 26592 pt_vpos = it.vpos;
26384 if (dir > 0 || overshoot_expected) 26593 if (dir > 0 || overshoot_expected)
26385 { 26594 {
@@ -26394,10 +26603,11 @@ Value is the new character position of point. */)
26394 it.glyph_row = NULL; 26603 it.glyph_row = NULL;
26395 PRODUCE_GLYPHS (&it); /* compute it.pixel_width */ 26604 PRODUCE_GLYPHS (&it); /* compute it.pixel_width */
26396 it.glyph_row = row; 26605 it.glyph_row = row;
26397 /* PRODUCE_GLYPHS advances it.current_x, so we must restore 26606 /* PRODUCE_GLYPHS advances it.current_x, so it must be
26398 it, lest it will become out of sync with it's buffer 26607 restored, lest it become out of sync with its buffer
26399 position. */ 26608 position. */
26400 it.current_x = pt_x; 26609 it.current_x = pt_x;
26610 it.wrap_prefix_width = pt_wrap_prefix_x;
26401 } 26611 }
26402 else 26612 else
26403 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it); 26613 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
@@ -26442,6 +26652,7 @@ Value is the new character position of point. */)
26442 it.last_visible_x = DISP_INFINITY; 26652 it.last_visible_x = DISP_INFINITY;
26443 reseat_at_previous_visible_line_start (&it); 26653 reseat_at_previous_visible_line_start (&it);
26444 it.current_x = it.current_y = it.hpos = 0; 26654 it.current_x = it.current_y = it.hpos = 0;
26655 it.wrap_prefix_width = 0;
26445 if (pt_vpos != 0) 26656 if (pt_vpos != 0)
26446 move_it_by_lines (&it, pt_vpos); 26657 move_it_by_lines (&it, pt_vpos);
26447 } 26658 }
@@ -27958,6 +28169,11 @@ are the selected window and the WINDOW's buffer). */)
27958 28169
27959 init_iterator (&it, w, -1, -1, NULL, face_id); 28170 init_iterator (&it, w, -1, -1, NULL, face_id);
27960 28171
28172 /* Make sure `base_line_number` is fresh in case we encounter a `%l`. */
28173 if (current_buffer == XBUFFER ((w)->contents)
28174 && !BASE_LINE_NUMBER_VALID_P (w))
28175 w->base_line_number = 0;
28176
27961 if (no_props) 28177 if (no_props)
27962 { 28178 {
27963 mode_line_target = MODE_LINE_NOPROP; 28179 mode_line_target = MODE_LINE_NOPROP;
@@ -28410,30 +28626,29 @@ decode_mode_spec (struct window *w, register int c, int field_width,
28410 when the buffer's restriction was changed, but the window 28626 when the buffer's restriction was changed, but the window
28411 wasn't yet redisplayed after that. If that happens, we 28627 wasn't yet redisplayed after that. If that happens, we
28412 need to determine a new base line. */ 28628 need to determine a new base line. */
28413 if (!(BUF_BEGV_BYTE (b) <= startpos_byte 28629 if (current_buffer != XBUFFER (w->contents)
28630 || !(BUF_BEGV_BYTE (b) <= startpos_byte
28414 && startpos_byte <= BUF_ZV_BYTE (b))) 28631 && startpos_byte <= BUF_ZV_BYTE (b)))
28415 { 28632 {
28416 startpos = BUF_BEGV (b); 28633 startpos = BUF_BEGV (b);
28417 startpos_byte = BUF_BEGV_BYTE (b); 28634 startpos_byte = BUF_BEGV_BYTE (b);
28418 w->base_line_pos = 0;
28419 w->base_line_number = 0;
28420 } 28635 }
28421 28636
28422 /* If we decided that this buffer isn't suitable for line numbers, 28637 /* If we decided that this buffer isn't suitable for line numbers,
28423 don't forget that too fast. */ 28638 don't forget that too fast.
28639 FIXME: What if `current_buffer != w->contents`? */
28424 if (w->base_line_pos == -1) 28640 if (w->base_line_pos == -1)
28425 goto no_value; 28641 goto no_value;
28426 28642
28427 /* If the buffer is very big, don't waste time. */ 28643 /* If the buffer is very big, don't waste time. */
28428 if (FIXNUMP (Vline_number_display_limit) 28644 if (FIXNUMP (Vline_number_display_limit)
28429 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit)) 28645 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28430 { 28646 goto no_value;
28431 w->base_line_pos = 0;
28432 w->base_line_number = 0;
28433 goto no_value;
28434 }
28435 28647
28436 if (w->base_line_number > 0 28648 /* Callers of `display_mode_element` are in charge of flushing
28649 any stale `base_line_number` cache. */
28650 if (current_buffer == XBUFFER ((w)->contents)
28651 && w->base_line_number > 0
28437 && w->base_line_pos > 0 28652 && w->base_line_pos > 0
28438 && w->base_line_pos <= startpos) 28653 && w->base_line_pos <= startpos)
28439 { 28654 {
@@ -28459,7 +28674,9 @@ decode_mode_spec (struct window *w, register int c, int field_width,
28459 or too far away, or if we did not have one. 28674 or too far away, or if we did not have one.
28460 "Too close" means it's plausible a scroll-down would 28675 "Too close" means it's plausible a scroll-down would
28461 go back past it. */ 28676 go back past it. */
28462 if (startpos == BUF_BEGV (b)) 28677 if (current_buffer != XBUFFER (w->contents))
28678 ; /* The base line is for another buffer, don't touch it! */
28679 else if (startpos == BUF_BEGV (b))
28463 { 28680 {
28464 w->base_line_number = topline; 28681 w->base_line_number = topline;
28465 w->base_line_pos = BUF_BEGV (b); 28682 w->base_line_pos = BUF_BEGV (b);
@@ -28496,6 +28713,12 @@ decode_mode_spec (struct window *w, register int c, int field_width,
28496 goto no_value; 28713 goto no_value;
28497 } 28714 }
28498 28715
28716 /* NOTE: if `clip_changed` is set or if `BEG_UNCHANGED` is
28717 before `position`, this new cached value may get flushed
28718 soon needlessly, because we can't reset `BEG_UNCHANGED` or
28719 `clip_changed` from here (since they reflect the changes
28720 since the last redisplay so they can only be reset from
28721 `mark_window_display_accurate_1`). :-( */
28499 w->base_line_number = topline - nlines; 28722 w->base_line_number = topline - nlines;
28500 w->base_line_pos = BYTE_TO_CHAR (position); 28723 w->base_line_pos = BYTE_TO_CHAR (position);
28501 } 28724 }
@@ -32589,7 +32812,19 @@ gui_produce_glyphs (struct it *it)
32589 if (font->space_width > 0) 32812 if (font->space_width > 0)
32590 { 32813 {
32591 int tab_width = it->tab_width * font->space_width; 32814 int tab_width = it->tab_width * font->space_width;
32592 int x = it->current_x + it->continuation_lines_width; 32815 /* wrap-prefix strings are prepended to continuation
32816 lines, so the width of tab characters inside should
32817 be computed from the start of this screen line rather
32818 than as a product of the total width of the physical
32819 line being wrapped. */
32820 int x = it->current_x + (it->string_from_prefix_prop_p
32821 /* Subtract the width of the
32822 prefix from it->current_x if
32823 it exists. */
32824 ? 0 : (it->continuation_lines_width
32825 ? (it->continuation_lines_width
32826 - it->wrap_prefix_width)
32827 : 0));
32593 int x0 = x; 32828 int x0 = x;
32594 /* Adjust for line numbers, if needed. */ 32829 /* Adjust for line numbers, if needed. */
32595 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) 32830 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
@@ -33060,7 +33295,13 @@ gui_produce_glyphs (struct it *it)
33060 because this isn't true for images with `:ascent 100'. */ 33295 because this isn't true for images with `:ascent 100'. */
33061 eassert (it->ascent >= 0 && it->descent >= 0); 33296 eassert (it->ascent >= 0 && it->descent >= 0);
33062 if (it->area == TEXT_AREA) 33297 if (it->area == TEXT_AREA)
33063 it->current_x += it->pixel_width; 33298 {
33299 it->current_x += it->pixel_width;
33300
33301 if (it->continuation_lines_width
33302 && it->string_from_prefix_prop_p)
33303 it->wrap_prefix_width = it->current_x;
33304 }
33064 33305
33065 if (extra_line_spacing > 0) 33306 if (extra_line_spacing > 0)
33066 { 33307 {
@@ -36219,7 +36460,7 @@ expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36219 /* Use a signed int intermediate value to avoid catastrophic 36460 /* Use a signed int intermediate value to avoid catastrophic
36220 failures due to comparison between signed and unsigned, when 36461 failures due to comparison between signed and unsigned, when
36221 x is negative (can happen for wide images that are hscrolled). */ 36462 x is negative (can happen for wide images that are hscrolled). */
36222 int r_end = r->x + r->width; 36463 int r_end = r->x + (int) r->width;
36223 while (last < end && x < r_end) 36464 while (last < end && x < r_end)
36224 { 36465 {
36225 x += last->pixel_width; 36466 x += last->pixel_width;
@@ -36518,7 +36759,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr)
36518 /* Use a signed int intermediate value to avoid catastrophic 36759 /* Use a signed int intermediate value to avoid catastrophic
36519 failures due to comparison between signed and unsigned, when 36760 failures due to comparison between signed and unsigned, when
36520 y0 or y1 is negative (can happen for tall images). */ 36761 y0 or y1 is negative (can happen for tall images). */
36521 int r_bottom = r.y + r.height; 36762 int r_bottom = r.y + (int) r.height;
36522 36763
36523 /* We must temporarily switch to the window's buffer, in case 36764 /* We must temporarily switch to the window's buffer, in case
36524 the fringe face has been remapped in that buffer's 36765 the fringe face has been remapped in that buffer's
@@ -36565,7 +36806,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr)
36565 /* We must redraw a row overlapping the exposed area. */ 36806 /* We must redraw a row overlapping the exposed area. */
36566 if (y0 < r.y 36807 if (y0 < r.y
36567 ? y0 + row->phys_height > r.y 36808 ? y0 + row->phys_height > r.y
36568 : y0 + row->ascent - row->phys_ascent < r.y +r.height) 36809 : y0 + row->ascent - row->phys_ascent < r.y + (int) r.height)
36569 { 36810 {
36570 if (first_overlapping_row == NULL) 36811 if (first_overlapping_row == NULL)
36571 first_overlapping_row = row; 36812 first_overlapping_row = row;
@@ -36744,7 +36985,7 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36744 const Emacs_Rectangle *upper, *lower; 36985 const Emacs_Rectangle *upper, *lower;
36745 bool intersection_p = false; 36986 bool intersection_p = false;
36746 36987
36747 /* Rearrange so that R1 is the left-most rectangle. */ 36988 /* Rearrange so that left is the left-most rectangle. */
36748 if (r1->x < r2->x) 36989 if (r1->x < r2->x)
36749 left = r1, right = r2; 36990 left = r1, right = r2;
36750 else 36991 else
@@ -36752,13 +36993,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36752 36993
36753 /* X0 of the intersection is right.x0, if this is inside R1, 36994 /* X0 of the intersection is right.x0, if this is inside R1,
36754 otherwise there is no intersection. */ 36995 otherwise there is no intersection. */
36755 if (right->x <= left->x + left->width) 36996 if (right->x <= left->x + (int) left->width)
36756 { 36997 {
36757 result->x = right->x; 36998 result->x = right->x;
36758 36999
36759 /* The right end of the intersection is the minimum of 37000 /* The right end of the intersection is the minimum of
36760 the right ends of left and right. */ 37001 the right ends of left and right. */
36761 result->width = (min (left->x + left->width, right->x + right->width) 37002 result->width = (min (left->x + (int) left->width,
37003 right->x + (int) right->width)
36762 - result->x); 37004 - result->x);
36763 37005
36764 /* Same game for Y. */ 37006 /* Same game for Y. */
@@ -36769,14 +37011,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36769 37011
36770 /* The upper end of the intersection is lower.y0, if this is inside 37012 /* The upper end of the intersection is lower.y0, if this is inside
36771 of upper. Otherwise, there is no intersection. */ 37013 of upper. Otherwise, there is no intersection. */
36772 if (lower->y <= upper->y + upper->height) 37014 if (lower->y <= upper->y + (int) upper->height)
36773 { 37015 {
36774 result->y = lower->y; 37016 result->y = lower->y;
36775 37017
36776 /* The lower end of the intersection is the minimum of the lower 37018 /* The lower end of the intersection is the minimum of the lower
36777 ends of upper and lower. */ 37019 ends of upper and lower. */
36778 result->height = (min (lower->y + lower->height, 37020 result->height = (min (lower->y + (int) lower->height,
36779 upper->y + upper->height) 37021 upper->y + (int) upper->height)
36780 - result->y); 37022 - result->y);
36781 intersection_p = true; 37023 intersection_p = true;
36782 } 37024 }
diff --git a/src/xfaces.c b/src/xfaces.c
index b9a78328661..a558e7328c0 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2245,20 +2245,20 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
2245 2245
2246/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and 2246/* Merge two Lisp face attribute vectors on frame F, FROM and TO, and
2247 store the resulting attributes in TO, which must be already be 2247 store the resulting attributes in TO, which must be already be
2248 completely specified and contain only absolute attributes. 2248 completely specified and contain only absolute attributes. Every
2249 Every specified attribute of FROM overrides the corresponding 2249 specified attribute of FROM overrides the corresponding attribute of
2250 attribute of TO; relative attributes in FROM are merged with the 2250 TO; merge relative attributes in FROM with the absolute value in TO,
2251 absolute value in TO and replace it. NAMED_MERGE_POINTS is used 2251 which attributes also replace it. Use NAMED_MERGE_POINTS internally
2252 internally to detect loops in face inheritance/remapping; it should 2252 to detect loops in face inheritance/remapping; it should be 0 when
2253 be 0 when called from other places. If window W is non-NULL, use W 2253 called from other places. If window W is non-NULL, use W to
2254 to interpret face specifications. */ 2254 interpret face specifications. */
2255static void 2255static void
2256merge_face_vectors (struct window *w, 2256merge_face_vectors (struct window *w,
2257 struct frame *f, const Lisp_Object *from, Lisp_Object *to, 2257 struct frame *f, const Lisp_Object *from, Lisp_Object *to,
2258 struct named_merge_point *named_merge_points) 2258 struct named_merge_point *named_merge_points)
2259{ 2259{
2260 int i; 2260 int i;
2261 Lisp_Object font = Qnil; 2261 Lisp_Object font = Qnil, tospec, adstyle;
2262 2262
2263 /* If FROM inherits from some other faces, merge their attributes into 2263 /* If FROM inherits from some other faces, merge their attributes into
2264 TO before merging FROM's direct attributes. Note that an :inherit 2264 TO before merging FROM's direct attributes. Note that an :inherit
@@ -2318,6 +2318,25 @@ merge_face_vectors (struct window *w,
2318 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (font); 2318 to[LFACE_SLANT_INDEX] = FONT_SLANT_FOR_FACE (font);
2319 if (! NILP (AREF (font, FONT_WIDTH_INDEX))) 2319 if (! NILP (AREF (font, FONT_WIDTH_INDEX)))
2320 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (font); 2320 to[LFACE_SWIDTH_INDEX] = FONT_WIDTH_FOR_FACE (font);
2321
2322 if (!NILP (AREF (font, FONT_ADSTYLE_INDEX)))
2323 {
2324 /* If an adstyle is specified in FROM's font spec, create a
2325 font spec for TO if none exists, and transfer the adstyle
2326 there. */
2327
2328 tospec = to[LFACE_FONT_INDEX];
2329 adstyle = AREF (font, FONT_ADSTYLE_INDEX);
2330
2331 if (!NILP (tospec))
2332 tospec = copy_font_spec (tospec);
2333 else
2334 tospec = Ffont_spec (0, NULL);
2335
2336 to[LFACE_FONT_INDEX] = tospec;
2337 ASET (tospec, FONT_ADSTYLE_INDEX, adstyle);
2338 }
2339
2321 ASET (font, FONT_SIZE_INDEX, Qnil); 2340 ASET (font, FONT_SIZE_INDEX, Qnil);
2322 } 2341 }
2323 2342