diff options
| author | Andrea Corallo | 2024-02-28 20:47:57 +0100 |
|---|---|---|
| committer | Andrea Corallo | 2024-02-28 20:47:57 +0100 |
| commit | 1fbe56c32761efdc8d268df80a97a9102d00e109 (patch) | |
| tree | 8d8e76c8ae43c79ef9d76b0f97c12607567664b9 /src | |
| parent | 6de60f33ed5cc438e20400aee83e1e2032773811 (diff) | |
| parent | 05195e129fc933db32c9e08a155a94bfa4d75b54 (diff) | |
| download | emacs-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.c | 48 | ||||
| -rw-r--r-- | src/android.c | 81 | ||||
| -rw-r--r-- | src/android.h | 9 | ||||
| -rw-r--r-- | src/androidfns.c | 106 | ||||
| -rw-r--r-- | src/androidselect.c | 20 | ||||
| -rw-r--r-- | src/androidterm.c | 4 | ||||
| -rw-r--r-- | src/androidvfs.c | 32 | ||||
| -rw-r--r-- | src/buffer.c | 64 | ||||
| -rw-r--r-- | src/buffer.h | 2 | ||||
| -rw-r--r-- | src/bytecode.c | 84 | ||||
| -rw-r--r-- | src/ccl.c | 7 | ||||
| -rw-r--r-- | src/comp.c | 6 | ||||
| -rw-r--r-- | src/conf_post.h | 4 | ||||
| -rw-r--r-- | src/data.c | 58 | ||||
| -rw-r--r-- | src/dispextern.h | 10 | ||||
| -rw-r--r-- | src/doc.c | 58 | ||||
| -rw-r--r-- | src/editfns.c | 85 | ||||
| -rw-r--r-- | src/emacs.c | 4 | ||||
| -rw-r--r-- | src/eval.c | 61 | ||||
| -rw-r--r-- | src/fileio.c | 10 | ||||
| -rw-r--r-- | src/fns.c | 207 | ||||
| -rw-r--r-- | src/inotify.c | 10 | ||||
| -rw-r--r-- | src/keyboard.c | 26 | ||||
| -rw-r--r-- | src/lisp.h | 311 | ||||
| -rw-r--r-- | src/lread.c | 498 | ||||
| -rw-r--r-- | src/macfont.m | 96 | ||||
| -rw-r--r-- | src/marker.c | 2 | ||||
| -rw-r--r-- | src/minibuf.c | 110 | ||||
| -rw-r--r-- | src/pdumper.c | 68 | ||||
| -rw-r--r-- | src/pgtkterm.c | 4 | ||||
| -rw-r--r-- | src/print.c | 29 | ||||
| -rw-r--r-- | src/process.c | 33 | ||||
| -rw-r--r-- | src/sfnt.c | 10 | ||||
| -rw-r--r-- | src/sfnt.h | 2 | ||||
| -rw-r--r-- | src/sfntfont.c | 6 | ||||
| -rw-r--r-- | src/term.c | 21 | ||||
| -rw-r--r-- | src/textconv.c | 10 | ||||
| -rw-r--r-- | src/thread.c | 39 | ||||
| -rw-r--r-- | src/thread.h | 11 | ||||
| -rw-r--r-- | src/timefns.c | 12 | ||||
| -rw-r--r-- | src/treesit.c | 4 | ||||
| -rw-r--r-- | src/verbose.mk.in | 29 | ||||
| -rw-r--r-- | src/window.c | 11 | ||||
| -rw-r--r-- | src/xdisp.c | 594 | ||||
| -rw-r--r-- | src/xfaces.c | 35 |
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. */ |
| 370 | static ptrdiff_t hash_table_allocated_bytes = 0; | 370 | static 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. */ |
| 5637 | void * | 5647 | void * |
| 5638 | hash_table_alloc_bytes (ptrdiff_t nbytes) | 5648 | hash_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 | ||
| 117 | struct android_emacs_cursor | 120 | struct 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. */ |
| 153 | JNIEnv *android_java_env; | 156 | JNIEnv *android_java_env; |
| 154 | 157 | ||
| 158 | #ifdef THREADS_ENABLED | ||
| 159 | |||
| 160 | /* The Java VM new threads attach to. */ | ||
| 161 | JavaVM *android_jvm; | ||
| 162 | |||
| 163 | #endif /* THREADS_ENABLED */ | ||
| 164 | |||
| 155 | /* The EmacsGC class. */ | 165 | /* The EmacsGC class. */ |
| 156 | static jclass emacs_gc_class; | 166 | static 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. */ |
| 497 | static sem_t android_query_sem; | 507 | static sem_t android_query_sem; |
| 498 | 508 | ||
| 509 | /* ID of the Emacs thread. */ | ||
| 510 | static 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 | |||
| 584 | static 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 | |||
| 2496 | NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env, | 2519 | NATIVE_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, | |||
| 2504 | JNIEXPORT jboolean JNICALL | 2529 | JNIEXPORT jboolean JNICALL |
| 2505 | NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object) | 2530 | NATIVE_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 | |||
| 2607 | NATIVE_NAME (notifyPixelsChanged) (JNIEnv *env, jobject object, | 2634 | NATIVE_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) | |||
| 2660 | JNIEXPORT void JNICALL | 2689 | JNIEXPORT void JNICALL |
| 2661 | NATIVE_NAME (setupSystemThread) (void) | 2690 | NATIVE_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 | ||
| 5659 | bool | ||
| 5660 | android_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 | |||
| 5629 | void | 5674 | void |
| 5630 | android_set_dont_focus_on_map (android_window handle, | 5675 | android_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 | ||
| 6704 | static void | 6749 | void |
| 6705 | android_check_query (void) | 6750 | android_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); | |||
| 103 | extern int android_get_mm_width (void); | 105 | extern int android_get_mm_width (void); |
| 104 | extern int android_get_mm_height (void); | 106 | extern int android_get_mm_height (void); |
| 105 | extern bool android_detect_mouse (void); | 107 | extern bool android_detect_mouse (void); |
| 108 | extern bool android_detect_keyboard (void); | ||
| 106 | 109 | ||
| 107 | extern void android_set_dont_focus_on_map (android_window, bool); | 110 | extern void android_set_dont_focus_on_map (android_window, bool); |
| 108 | extern void android_set_dont_accept_focus (android_window, bool); | 111 | extern 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 | ||
| 231 | extern void android_check_query (void); | ||
| 228 | extern void android_check_query_urgent (void); | 232 | extern void android_check_query_urgent (void); |
| 229 | extern int android_run_in_emacs_thread (void (*) (void *), void *); | 233 | extern int android_run_in_emacs_thread (void (*) (void *), void *); |
| 230 | extern void android_write_event (union android_event *); | 234 | extern 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 | ||
| 298 | extern JNIEnv *android_java_env; | 303 | extern JNIEnv *android_java_env; |
| 299 | 304 | ||
| 305 | #ifdef THREADS_ENABLED | ||
| 306 | extern JavaVM *android_jvm; | ||
| 307 | #endif /* THREADS_ENABLED */ | ||
| 308 | |||
| 300 | /* The EmacsService object. */ | 309 | /* The EmacsService object. */ |
| 301 | extern jobject emacs_service; | 310 | extern 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 | ||
| 2530 | DEFUN ("android-detect-keyboard", Fandroid_detect_keyboard, | ||
| 2531 | Sandroid_detect_keyboard, 0, 0, 0, | ||
| 2532 | doc: /* Return whether a keyboard is connected. | ||
| 2533 | Return non-nil if a key is connected to this computer, or nil | ||
| 2534 | if 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 | |||
| 2479 | DEFUN ("android-toggle-on-screen-keyboard", | 2549 | DEFUN ("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 | ||
| 240 | DEFUN ("android-browse-url", Fandroid_browse_url, | 240 | DEFUN ("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. |
| 243 | URL-encoded URL with a scheme specified unless SEND is non-nil. | 243 | |
| 244 | Signal an error upon failure. | 244 | URL should be a URL-encoded URL with a scheme specified unless SEND is |
| 245 | non-nil. Signal an error upon failure. | ||
| 245 | 246 | ||
| 246 | If SEND is nil, start a program that is able to display the URL, such | 247 | If SEND is nil, start a program that is able to display the URL, such |
| 247 | as a web browser. Otherwise, try to share URL using programs such as | 248 | as a web browser. Otherwise, try to share URL using programs such as |
| 248 | email clients. */) | 249 | email clients. |
| 250 | |||
| 251 | If URL is a file URI, convert it into a `content' address accessible to | ||
| 252 | other programs. Files inside the /content or /assets directories cannot | ||
| 253 | be opened through such addresses, which this function does not provide | ||
| 254 | for. 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) | |||
| 1018 | static const char * | 1018 | static const char * |
| 1019 | android_scan_directory_tree (char *file, size_t *limit_return) | 1019 | android_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; | |||
| 6319 | JNIEXPORT jint JNICALL | 6317 | JNIEXPORT jint JNICALL |
| 6320 | NATIVE_NAME (safSyncAndReadInput) (JNIEnv *env, jobject object) | 6318 | NATIVE_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) | |||
| 6340 | JNIEXPORT void JNICALL | 6340 | JNIEXPORT void JNICALL |
| 6341 | NATIVE_NAME (safSync) (JNIEnv *env, jobject object) | 6341 | NATIVE_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) | |||
| 6347 | JNIEXPORT void JNICALL | 6349 | JNIEXPORT void JNICALL |
| 6348 | NATIVE_NAME (safPostRequest) (JNIEnv *env, jobject object) | 6350 | NATIVE_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 | ||
| 6353 | JNIEXPORT jboolean JNICALL | 6357 | JNIEXPORT jboolean JNICALL |
| 6354 | NATIVE_NAME (ftruncate) (JNIEnv *env, jobject object, jint fd) | 6358 | NATIVE_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 | ||
| 3005 | ptrdiff_t | 3005 | static ptrdiff_t |
| 3006 | overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend, | 3006 | overlays_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. */ |
| 3154 | Lisp_Object | 3147 | bool |
| 3155 | disable_line_numbers_overlay_at_eob (void) | 3148 | disable_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 *); | |||
| 1174 | extern void reset_buffer (struct buffer *); | 1174 | extern void reset_buffer (struct buffer *); |
| 1175 | extern void compact_buffer (struct buffer *); | 1175 | extern void compact_buffer (struct buffer *); |
| 1176 | extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); | 1176 | extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); |
| 1177 | extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **, | ||
| 1178 | ptrdiff_t *, bool, bool, ptrdiff_t *); | ||
| 1179 | extern ptrdiff_t previous_overlay_change (ptrdiff_t); | 1177 | extern ptrdiff_t previous_overlay_change (ptrdiff_t); |
| 1180 | extern ptrdiff_t next_overlay_change (ptrdiff_t); | 1178 | extern ptrdiff_t next_overlay_change (ptrdiff_t); |
| 1181 | extern ptrdiff_t sort_overlays (Lisp_Object *, ptrdiff_t, struct window *); | 1179 | extern 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; |
| @@ -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 | ||
| 4862 | DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file, | 4862 | DEFUN ("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 | ||
| 800 | DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0, | 799 | DEFUN ("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 | ||
| 808 | DEFUN ("remove-pos-from-symbol", Fremove_pos_from_symbol, | 807 | DEFUN ("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 | |||
| 823 | the position will be taken. */) | 822 | the 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. */ |
| @@ -357,6 +357,20 @@ reread_doc_file (Lisp_Object file) | |||
| 357 | return 1; | 357 | return 1; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | DEFUN ("documentation-stringp", Fdocumentation_stringp, Sdocumentation_stringp, | ||
| 361 | 1, 1, 0, | ||
| 362 | doc: /* Return non-nil if OBJECT is a well-formed docstring object. | ||
| 363 | OBJECT 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 | |||
| 360 | DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0, | 374 | DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0, |
| 361 | doc: /* Return the documentation string of FUNCTION. | 375 | doc: /* Return the documentation string of FUNCTION. |
| 362 | Unless a non-nil second argument RAW is given, the | 376 | Unless 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 | |||
| 282 | static ptrdiff_t | ||
| 283 | overlays_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 | |||
| 293 | DEFUN ("get-pos-property", Fget_pos_property, Sget_pos_property, 2, 3, 0, | 275 | DEFUN ("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. |
| 295 | Almost identical to `get-char-property' except for the following difference: | 277 | Almost 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 | |||
| 3128 | static Lisp_Object | ||
| 3129 | fetch_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 | |||
| 3138 | static Lisp_Object | 3125 | static Lisp_Object |
| 3139 | apply_lambda (Lisp_Object fun, Lisp_Object args, specpdl_ref count) | 3126 | apply_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 | ||
| 3414 | DEFUN ("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 |
| @@ -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. */) | |||
| 3211 | Lisp_Object | 3209 | Lisp_Object |
| 3212 | do_yes_or_no_p (Lisp_Object prompt) | 3210 | do_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 | ||
| 3217 | DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0, | 3215 | DEFUN ("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) | |||
| 4291 | static void | 4289 | static void |
| 4292 | set_hash_index_slot (struct Lisp_Hash_Table *h, ptrdiff_t idx, ptrdiff_t val) | 4290 | set_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) | |||
| 4392 | static ptrdiff_t | 4390 | static ptrdiff_t |
| 4393 | HASH_INDEX (struct Lisp_Hash_Table *h, ptrdiff_t idx) | 4391 | HASH_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. */ | ||
| 4456 | static inline hash_hash_t | ||
| 4457 | reduce_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 | |||
| 4465 | static EMACS_INT | 4453 | static EMACS_INT |
| 4466 | sxhash_eq (Lisp_Object key) | 4454 | sxhash_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 | ||
| 4473 | static EMACS_INT | 4460 | static 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. */ |
| 4531 | static ptrdiff_t | 4518 | static int |
| 4532 | hash_index_size (ptrdiff_t size) | 4519 | compute_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, | |||
| 4633 | static Lisp_Object | 4608 | static Lisp_Object |
| 4634 | copy_hash_table (struct Lisp_Hash_Table *h1) | 4609 | copy_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. */ |
| 4668 | static inline ptrdiff_t | 4639 | static inline ptrdiff_t |
| 4669 | hash_index_index (struct Lisp_Hash_Table *h, hash_hash_t hash) | 4640 | hash_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, | |||
| 4976 | bool | 4949 | bool |
| 4977 | sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p) | 4950 | sweep_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. */ | ||
| 5377 | static struct hash_table_test * | 5383 | static struct hash_table_test * |
| 5378 | get_hash_table_user_test (Lisp_Object test) | 5384 | get_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. |
| 13227 | The value may be integer or floating point. | 13239 | The value may be integer or floating point. |
| 13228 | If the value is zero, don't echo at all. */); | 13240 | If 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. | ||
| 13245 | When non-nil, a reference to `C-h' is printed after echoed | ||
| 13246 | keystrokes. */); | ||
| 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. |
| 13233 | The reason for polling is to make C-g work to stop a running program. | 13251 | The 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 */ | ||
| 521 | enum Lisp_Type | 491 | enum 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 | |||
| 1121 | INLINE bool | 1092 | INLINE bool |
| 1122 | PSEUDOVECTORP (Lisp_Object a, int code) | 1093 | PSEUDOVECTORP (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 | ||
| 1127 | INLINE bool | 1101 | INLINE bool |
| @@ -1137,9 +1111,10 @@ INLINE bool | |||
| 1137 | } | 1111 | } |
| 1138 | 1112 | ||
| 1139 | INLINE bool | 1113 | INLINE bool |
| 1140 | (SYMBOLP) (Lisp_Object x) | 1114 | SYMBOLP (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 | ||
| 1145 | INLINE struct Lisp_Symbol_With_Pos * | 1120 | INLINE 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 | ||
| 1127 | INLINE Lisp_Object | ||
| 1128 | XSYMBOL_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 | |||
| 1135 | INLINE Lisp_Object | ||
| 1136 | XSYMBOL_WITH_POS_POS (Lisp_Object a) | ||
| 1137 | { | ||
| 1138 | return XSYMBOL_WITH_POS (a)->pos; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | INLINE Lisp_Object | ||
| 1142 | maybe_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 | |||
| 1152 | INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED | 1148 | INLINE struct Lisp_Symbol * ATTRIBUTE_NO_SANITIZE_UNDEFINED |
| 1153 | XBARE_SYMBOL (Lisp_Object a) | 1149 | XBARE_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. */ | ||
| 1357 | INLINE 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. */ |
| 1365 | INLINE bool | 1353 | INLINE bool |
| 1366 | (EQ) (Lisp_Object x, Lisp_Object y) | 1354 | EQ (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 | ||
| 1371 | INLINE intmax_t | 1362 | INLINE 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 | ||
| 1512 | INLINE struct Lisp_Cons * | 1502 | INLINE struct Lisp_Cons * |
| 1513 | (XCONS) (Lisp_Object a) | 1503 | XCONS (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 | ||
| 2299 | INLINE Lisp_Object | 2290 | INLINE Lisp_Object |
| 2300 | (SYMBOL_VAL) (struct Lisp_Symbol *sym) | 2291 | SYMBOL_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 | ||
| 2305 | INLINE struct Lisp_Symbol * | 2297 | INLINE struct Lisp_Symbol * |
| @@ -2322,9 +2314,10 @@ SYMBOL_FWD (struct Lisp_Symbol *sym) | |||
| 2322 | } | 2314 | } |
| 2323 | 2315 | ||
| 2324 | INLINE void | 2316 | INLINE void |
| 2325 | (SET_SYMBOL_VAL) (struct Lisp_Symbol *sym, Lisp_Object v) | 2317 | SET_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 | ||
| 2330 | INLINE void | 2323 | INLINE 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 | |||
| 2390 | struct 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 | |||
| 2403 | INLINE bool | ||
| 2404 | OBARRAYP (Lisp_Object a) | ||
| 2405 | { | ||
| 2406 | return PSEUDOVECTORP (a, PVEC_OBARRAY); | ||
| 2407 | } | ||
| 2408 | |||
| 2409 | INLINE struct Lisp_Obarray * | ||
| 2410 | XOBARRAY (Lisp_Object a) | ||
| 2411 | { | ||
| 2412 | eassert (OBARRAYP (a)); | ||
| 2413 | return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Obarray); | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | INLINE void | ||
| 2417 | CHECK_OBARRAY (Lisp_Object x) | ||
| 2418 | { | ||
| 2419 | CHECK_TYPE (OBARRAYP (x), Qobarrayp, x); | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | INLINE Lisp_Object | ||
| 2423 | make_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 | |||
| 2429 | INLINE ptrdiff_t | ||
| 2430 | obarray_size (const struct Lisp_Obarray *o) | ||
| 2431 | { | ||
| 2432 | return (ptrdiff_t)1 << o->size_bits; | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | Lisp_Object check_obarray_slow (Lisp_Object); | ||
| 2436 | |||
| 2437 | /* Return an obarray object from OBARRAY or signal an error. */ | ||
| 2438 | INLINE Lisp_Object | ||
| 2439 | check_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. */ | ||
| 2446 | typedef 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 | |||
| 2453 | INLINE obarray_iter_t | ||
| 2454 | make_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. */ | ||
| 2461 | INLINE bool | ||
| 2462 | obarray_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. */ | ||
| 2480 | INLINE void | ||
| 2481 | obarray_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. */ | ||
| 2487 | INLINE Lisp_Object | ||
| 2488 | obarray_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) \ | 2672 | INLINE Lisp_Object |
| 2567 | XSETPSEUDOVECTOR (VAR, PTR, PVEC_HASH_TABLE) | 2673 | make_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. */ |
| 2570 | INLINE Lisp_Object | 2680 | INLINE 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. */ | ||
| 2711 | INLINE ptrdiff_t | ||
| 2712 | hash_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. */ |
| 2601 | INLINE hash_hash_t | 2718 | INLINE hash_hash_t |
| 2602 | hash_from_key (struct Lisp_Hash_Table *h, Lisp_Object key) | 2719 | hash_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. */ | ||
| 2782 | INLINE hash_hash_t | ||
| 2783 | reduce_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. */ | ||
| 2792 | INLINE ptrdiff_t | ||
| 2793 | knuth_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 | |||
| 2664 | struct Lisp_Marker | 2803 | struct 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 | ||
| 2842 | INLINE Lisp_Object | ||
| 2843 | SYMBOL_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 | |||
| 2850 | INLINE Lisp_Object | ||
| 2851 | SYMBOL_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 | |||
| 2858 | INLINE bool | 2981 | INLINE bool |
| 2859 | USER_PTRP (Lisp_Object x) | 2982 | USER_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. */ |
| 4599 | extern Lisp_Object check_obarray (Lisp_Object); | ||
| 4600 | extern Lisp_Object intern_1 (const char *, ptrdiff_t); | 4722 | extern Lisp_Object intern_1 (const char *, ptrdiff_t); |
| 4601 | extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t); | 4723 | extern Lisp_Object intern_c_string_1 (const char *, ptrdiff_t); |
| 4602 | extern Lisp_Object intern_driver (Lisp_Object, Lisp_Object, Lisp_Object); | 4724 | extern 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. */ |
| 4804 | extern bool mouse_face_overlay_overlaps (Lisp_Object); | 4926 | extern bool mouse_face_overlay_overlaps (Lisp_Object); |
| 4805 | extern Lisp_Object disable_line_numbers_overlay_at_eob (void); | 4927 | extern bool disable_line_numbers_overlay_at_eob (void); |
| 4806 | extern AVOID nsberror (Lisp_Object); | 4928 | extern AVOID nsberror (Lisp_Object); |
| 4807 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool); | 4929 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool); |
| 4808 | extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); | 4930 | extern 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. */ |
| 5031 | extern int daemon_type; | 5153 | extern 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 */ |
| 5035 | extern void *w32_daemon_event; | 5158 | extern 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 | ||
| 2376 | static void | 2382 | static 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 | ||
| 3492 | static Lisp_Object get_lazy_string (Lisp_Object val); | ||
| 3493 | |||
| 3484 | static Lisp_Object | 3494 | static Lisp_Object |
| 3485 | bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | 3495 | bytecode_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 | ||
| 4876 | static size_t oblookup_last_bucket_number; | 4887 | static size_t oblookup_last_bucket_number; |
| 4877 | 4888 | ||
| 4878 | /* Get an error if OBARRAY is not an obarray. | 4889 | static 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. */ | ||
| 4881 | Lisp_Object | 4892 | Lisp_Object |
| 4882 | check_obarray (Lisp_Object obarray) | 4893 | check_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 | ||
| 4917 | static 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 */ | ||
| 4899 | static Lisp_Object | 4922 | static Lisp_Object |
| 4900 | intern_sym (Lisp_Object sym, Lisp_Object obarray, Lisp_Object index) | 4923 | intern_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) | |||
| 4926 | Lisp_Object | 4953 | Lisp_Object |
| 4927 | intern_driver (Lisp_Object string, Lisp_Object obarray, Lisp_Object index) | 4954 | intern_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. */ | ||
| 5170 | static ptrdiff_t | ||
| 5171 | obarray_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) */) | |||
| 5152 | Lisp_Object | 5184 | Lisp_Object |
| 5153 | oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff_t size_byte) | 5185 | oblookup (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 | ||
| 5250 | void | 5274 | static struct Lisp_Obarray * |
| 5251 | map_obarray (Lisp_Object obarray, void (*fn) (Lisp_Object, Lisp_Object), Lisp_Object arg) | 5275 | allocate_obarray (void) |
| 5276 | { | ||
| 5277 | return ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Obarray, PVEC_OBARRAY); | ||
| 5278 | } | ||
| 5279 | |||
| 5280 | static Lisp_Object | ||
| 5281 | make_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 | |||
| 5293 | enum { | ||
| 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 | |||
| 5300 | static void | ||
| 5301 | grow_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 | |||
| 5343 | DEFUN ("obarray-make", Fobarray_make, Sobarray_make, 0, 1, 0, | ||
| 5344 | doc: /* Return a new obarray of size SIZE. | ||
| 5345 | The obarray will grow to accommodate any number of symbols; the size, if | ||
| 5346 | given, 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 | |||
| 5363 | DEFUN ("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 | |||
| 5370 | DEFUN ("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 | |||
| 5395 | void | ||
| 5396 | map_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 | ||
| 5270 | static void | 5404 | static 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 | 5422 | DEFUN ("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 | ||
| 5290 | void | 5449 | void |
| 5291 | init_obarray_once (void) | 5450 | init_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! */ | ||
| 5335 | void | ||
| 5336 | defalias (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 | |||
| 5348 | defvar_int (struct Lisp_Intfwd const *i_fwd, char const *namestring) | 5497 | defvar_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 | |||
| 5358 | defvar_bool (struct Lisp_Boolfwd const *b_fwd, char const *namestring) | 5507 | defvar_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 | |||
| 5373 | defvar_lisp_nopro (struct Lisp_Objfwd const *o_fwd, char const *namestring) | 5522 | defvar_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 | ||
| 5381 | void | 5530 | void |
| @@ -5392,9 +5541,9 @@ void | |||
| 5392 | defvar_kboard (struct Lisp_Kboard_Objfwd const *ko_fwd, char const *namestring) | 5541 | defvar_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. |
| 5694 | Order is reverse chronological. | 5847 | Order is reverse chronological. |
| 5695 | This variable is obsolete as of Emacs 28.1 and should not be used. */); | 5848 | This 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. |
| 6008 | Only valid during macro-expansion. Internal use only. */); | 6161 | Only 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: | |||
| 2059 | the values STRING, PREDICATE and `lambda'. */) | 2029 | the 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) | |||
| 2719 | static dump_off | 2719 | static dump_off |
| 2720 | dump_hash_table (struct dump_context *ctx, Lisp_Object object) | 2720 | dump_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 | ||
| 2751 | static dump_off | 2751 | static dump_off |
| 2752 | dump_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 | |||
| 2774 | static dump_off | ||
| 2775 | dump_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 | |||
| 2796 | static dump_off | ||
| 2752 | dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) | 2797 | dump_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. |
| 2930 | The Lisp printer uses this vector to detect Lisp objects referenced more | 2940 | The Lisp printer uses this vector to detect Lisp objects referenced more |
| 2931 | than once. | 2941 | than once. If an entry contains a number, then the corresponding key is |
| 2942 | referenced more than once: a positive sign indicates that it's already been | ||
| 2943 | printed, and the absolute value indicates the number to use when printing. | ||
| 2944 | If an entry contains a string, that string is printed instead. | ||
| 2932 | 2945 | ||
| 2933 | When you bind `print-continuous-numbering' to t, you should probably | 2946 | When you bind `print-continuous-numbering' to t, you should probably |
| 2934 | also bind `print-number-table' to nil. This ensures that the value of | 2947 | also 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 | |||
| 5218 | static int | ||
| 5219 | android_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, | |||
| 3275 | static Lisp_Object | 3275 | static Lisp_Object |
| 3276 | treesit_traverse_get_predicate (Lisp_Object thing, Lisp_Object language) | 3276 | treesit_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 | ||
| 56 | AM_V_AR = @$(info $ AR $@) | 56 | . := |
| 57 | AM_V_AR = @$(info $. AR $@) | ||
| 57 | AM_V_at = @ | 58 | AM_V_at = @ |
| 58 | AM_V_CC = @$(info $ CC $@) | 59 | AM_V_CC = @$(info $. CC $@) |
| 59 | AM_V_CXX = @$(info $ CXX $@) | 60 | AM_V_CXX = @$(info $. CXX $@) |
| 60 | AM_V_CCLD = @$(info $ CCLD $@) | 61 | AM_V_CCLD = @$(info $. CCLD $@) |
| 61 | AM_V_CXXLD = @$(info $ CXXLD $@) | 62 | AM_V_CXXLD = @$(info $. CXXLD $@) |
| 62 | 63 | ||
| 63 | ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--) | 64 | ifeq ($(HAVE_NATIVE_COMP)-$(NATIVE_DISABLED)-$(ANCIENT),yes--) |
| 64 | ifneq (,$(have_working_info)) | 65 | ifneq (,$(have_working_info)) |
| 65 | AM_V_ELC = @$(info $ ELC+ELN $@) | 66 | AM_V_ELC = @$(info $. ELC+ELN $@) |
| 66 | AM_V_ELN = @$(info $ ELN $@) | 67 | AM_V_ELN = @$(info $. ELN $@) |
| 67 | else | 68 | else |
| 68 | AM_V_ELC = @echo " ELC+ELN " $@; | 69 | AM_V_ELC = @echo " ELC+ELN " $@; |
| 69 | AM_V_ELN = @echo " ELN " $@; | 70 | AM_V_ELN = @echo " ELN " $@; |
| 70 | endif | 71 | endif |
| 71 | else | 72 | else |
| 72 | ifneq (,$(have_working_info)) | 73 | ifneq (,$(have_working_info)) |
| 73 | AM_V_ELC = @$(info $ ELC $@) | 74 | AM_V_ELC = @$(info $. ELC $@) |
| 74 | else | 75 | else |
| 75 | AM_V_ELC = @echo " ELC " $@; | 76 | AM_V_ELC = @echo " ELC " $@; |
| 76 | endif | 77 | endif |
| 77 | AM_V_ELN = | 78 | AM_V_ELN = |
| 78 | endif | 79 | endif |
| 79 | 80 | ||
| 80 | AM_V_GEN = @$(info $ GEN $@) | 81 | AM_V_GEN = @$(info $. GEN $@) |
| 81 | AM_V_GLOBALS = @$(info $ GEN globals.h) | 82 | AM_V_GLOBALS = @$(info $. GEN globals.h) |
| 82 | AM_V_NO_PD = --no-print-directory | 83 | AM_V_NO_PD = --no-print-directory |
| 83 | AM_V_RC = @$(info $ RC $@) | 84 | AM_V_RC = @$(info $. RC $@) |
| 84 | 85 | ||
| 85 | # These are used for the Android port. | 86 | # These are used for the Android port. |
| 86 | AM_V_JAVAC = @$(info $ JAVAC $@) | 87 | AM_V_JAVAC = @$(info $. JAVAC $@) |
| 87 | AM_V_D8 = @$(info $ D8 $@) | 88 | AM_V_D8 = @$(info $. D8 $@) |
| 88 | AM_V_AAPT = @$(info $ AAPT $@) | 89 | AM_V_AAPT = @$(info $. AAPT $@) |
| 89 | AM_V_SILENT = @ | 90 | AM_V_SILENT = @ |
| 90 | endif | 91 | endif |
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 | |||
| 18685 | static int | 18868 | static int |
| 18686 | try_scrolling (Lisp_Object window, bool just_this_one_p, | 18869 | try_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. */ |
| 2255 | static void | 2255 | static void |
| 2256 | merge_face_vectors (struct window *w, | 2256 | merge_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 | ||