diff options
| author | Stephen Leake | 2019-09-10 03:37:51 -0700 |
|---|---|---|
| committer | Stephen Leake | 2019-09-10 03:37:51 -0700 |
| commit | 3d442312889ef2d14c07282d0aff6199d00cc165 (patch) | |
| tree | 74034ca2dded6ed233d0701b4cb5c10a0b5e9034 /src | |
| parent | ac1a2e260e8ece34500b5879f766b4e54ee57b94 (diff) | |
| parent | 74e9799bd89484b8d15bdd6597c68fc00d07e7f7 (diff) | |
| download | emacs-3d442312889ef2d14c07282d0aff6199d00cc165.tar.gz emacs-3d442312889ef2d14c07282d0aff6199d00cc165.zip | |
Merge commit '74e9799bd89484b8d15bdd6597c68fc00d07e7f7'
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 146 | ||||
| -rw-r--r-- | src/bignum.c | 15 | ||||
| -rw-r--r-- | src/bignum.h | 19 | ||||
| -rw-r--r-- | src/buffer.c | 10 | ||||
| -rw-r--r-- | src/buffer.h | 671 | ||||
| -rw-r--r-- | src/coding.c | 5 | ||||
| -rw-r--r-- | src/composite.c | 7 | ||||
| -rw-r--r-- | src/conf_post.h | 43 | ||||
| -rw-r--r-- | src/data.c | 139 | ||||
| -rw-r--r-- | src/dbusbind.c | 37 | ||||
| -rw-r--r-- | src/emacs.c | 3 | ||||
| -rw-r--r-- | src/floatfns.c | 14 | ||||
| -rw-r--r-- | src/fns.c | 82 | ||||
| -rw-r--r-- | src/font.c | 7 | ||||
| -rw-r--r-- | src/frame.c | 16 | ||||
| -rw-r--r-- | src/ftfont.c | 2 | ||||
| -rw-r--r-- | src/ftfont.h | 1 | ||||
| -rw-r--r-- | src/gnutls.c | 215 | ||||
| -rw-r--r-- | src/image.c | 35 | ||||
| -rw-r--r-- | src/keyboard.c | 4 | ||||
| -rw-r--r-- | src/keymap.c | 4 | ||||
| -rw-r--r-- | src/lisp.h | 10 | ||||
| -rw-r--r-- | src/lread.c | 71 | ||||
| -rw-r--r-- | src/mini-gmp.c | 10 | ||||
| -rw-r--r-- | src/minibuf.c | 3 | ||||
| -rw-r--r-- | src/pdumper.c | 219 | ||||
| -rw-r--r-- | src/pdumper.h | 16 | ||||
| -rw-r--r-- | src/process.c | 104 | ||||
| -rw-r--r-- | src/sound.c | 6 | ||||
| -rw-r--r-- | src/sysdep.c | 6 | ||||
| -rw-r--r-- | src/sysstdio.h | 1 | ||||
| -rw-r--r-- | src/systime.h | 2 | ||||
| -rw-r--r-- | src/timefns.c | 163 | ||||
| -rw-r--r-- | src/w32.c | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 20 | ||||
| -rw-r--r-- | src/xterm.c | 1 |
36 files changed, 1381 insertions, 728 deletions
diff --git a/src/alloc.c b/src/alloc.c index bb8e97f8737..be98cfd5f53 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -297,20 +297,20 @@ static ptrdiff_t pure_bytes_used_non_lisp; | |||
| 297 | 297 | ||
| 298 | static intptr_t garbage_collection_inhibited; | 298 | static intptr_t garbage_collection_inhibited; |
| 299 | 299 | ||
| 300 | /* The GC threshold in bytes, the last time it was calculated | ||
| 301 | from gc-cons-threshold and gc-cons-percentage. */ | ||
| 302 | static intmax_t gc_threshold; | ||
| 303 | |||
| 300 | /* If nonzero, this is a warning delivered by malloc and not yet | 304 | /* If nonzero, this is a warning delivered by malloc and not yet |
| 301 | displayed. */ | 305 | displayed. */ |
| 302 | 306 | ||
| 303 | const char *pending_malloc_warning; | 307 | const char *pending_malloc_warning; |
| 304 | 308 | ||
| 305 | #if 0 /* Normally, pointer sanity only on request... */ | 309 | /* Pointer sanity only on request. FIXME: Code depending on |
| 310 | SUSPICIOUS_OBJECT_CHECKING is obsolete; remove it entirely. */ | ||
| 306 | #ifdef ENABLE_CHECKING | 311 | #ifdef ENABLE_CHECKING |
| 307 | #define SUSPICIOUS_OBJECT_CHECKING 1 | 312 | #define SUSPICIOUS_OBJECT_CHECKING 1 |
| 308 | #endif | 313 | #endif |
| 309 | #endif | ||
| 310 | |||
| 311 | /* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC | ||
| 312 | bug is unresolved. */ | ||
| 313 | #define SUSPICIOUS_OBJECT_CHECKING 1 | ||
| 314 | 314 | ||
| 315 | #ifdef SUSPICIOUS_OBJECT_CHECKING | 315 | #ifdef SUSPICIOUS_OBJECT_CHECKING |
| 316 | struct suspicious_free_record | 316 | struct suspicious_free_record |
| @@ -327,8 +327,8 @@ static int suspicious_free_history_index; | |||
| 327 | static void *find_suspicious_object_in_range (void *begin, void *end); | 327 | static void *find_suspicious_object_in_range (void *begin, void *end); |
| 328 | static void detect_suspicious_free (void *ptr); | 328 | static void detect_suspicious_free (void *ptr); |
| 329 | #else | 329 | #else |
| 330 | # define find_suspicious_object_in_range(begin, end) NULL | 330 | # define find_suspicious_object_in_range(begin, end) ((void *) NULL) |
| 331 | # define detect_suspicious_free(ptr) (void) | 331 | # define detect_suspicious_free(ptr) ((void) 0) |
| 332 | #endif | 332 | #endif |
| 333 | 333 | ||
| 334 | /* Maximum amount of C stack to save when a GC happens. */ | 334 | /* Maximum amount of C stack to save when a GC happens. */ |
| @@ -4621,11 +4621,11 @@ mark_maybe_pointer (void *p) | |||
| 4621 | 4621 | ||
| 4622 | if (pdumper_object_p (p)) | 4622 | if (pdumper_object_p (p)) |
| 4623 | { | 4623 | { |
| 4624 | enum Lisp_Type type = pdumper_find_object_type (p); | 4624 | int type = pdumper_find_object_type (p); |
| 4625 | if (type != PDUMPER_NO_OBJECT) | 4625 | if (pdumper_valid_object_type_p (type)) |
| 4626 | mark_object ((type == Lisp_Symbol) | 4626 | mark_object (type == Lisp_Symbol |
| 4627 | ? make_lisp_symbol(p) | 4627 | ? make_lisp_symbol (p) |
| 4628 | : make_lisp_ptr(p, type)); | 4628 | : make_lisp_ptr (p, type)); |
| 4629 | /* See mark_maybe_object for why we can confidently return. */ | 4629 | /* See mark_maybe_object for why we can confidently return. */ |
| 4630 | return; | 4630 | return; |
| 4631 | } | 4631 | } |
| @@ -5290,9 +5290,10 @@ make_pure_float (double num) | |||
| 5290 | space. */ | 5290 | space. */ |
| 5291 | 5291 | ||
| 5292 | static Lisp_Object | 5292 | static Lisp_Object |
| 5293 | make_pure_bignum (struct Lisp_Bignum *value) | 5293 | make_pure_bignum (Lisp_Object value) |
| 5294 | { | 5294 | { |
| 5295 | size_t i, nlimbs = mpz_size (value->value); | 5295 | mpz_t const *n = xbignum_val (value); |
| 5296 | size_t i, nlimbs = mpz_size (*n); | ||
| 5296 | size_t nbytes = nlimbs * sizeof (mp_limb_t); | 5297 | size_t nbytes = nlimbs * sizeof (mp_limb_t); |
| 5297 | mp_limb_t *pure_limbs; | 5298 | mp_limb_t *pure_limbs; |
| 5298 | mp_size_t new_size; | 5299 | mp_size_t new_size; |
| @@ -5303,10 +5304,10 @@ make_pure_bignum (struct Lisp_Bignum *value) | |||
| 5303 | int limb_alignment = alignof (mp_limb_t); | 5304 | int limb_alignment = alignof (mp_limb_t); |
| 5304 | pure_limbs = pure_alloc (nbytes, - limb_alignment); | 5305 | pure_limbs = pure_alloc (nbytes, - limb_alignment); |
| 5305 | for (i = 0; i < nlimbs; ++i) | 5306 | for (i = 0; i < nlimbs; ++i) |
| 5306 | pure_limbs[i] = mpz_getlimbn (value->value, i); | 5307 | pure_limbs[i] = mpz_getlimbn (*n, i); |
| 5307 | 5308 | ||
| 5308 | new_size = nlimbs; | 5309 | new_size = nlimbs; |
| 5309 | if (mpz_sgn (value->value) < 0) | 5310 | if (mpz_sgn (*n) < 0) |
| 5310 | new_size = -new_size; | 5311 | new_size = -new_size; |
| 5311 | 5312 | ||
| 5312 | mpz_roinit_n (b->value, pure_limbs, new_size); | 5313 | mpz_roinit_n (b->value, pure_limbs, new_size); |
| @@ -5456,7 +5457,7 @@ purecopy (Lisp_Object obj) | |||
| 5456 | return obj; | 5457 | return obj; |
| 5457 | } | 5458 | } |
| 5458 | else if (BIGNUMP (obj)) | 5459 | else if (BIGNUMP (obj)) |
| 5459 | obj = make_pure_bignum (XBIGNUM (obj)); | 5460 | obj = make_pure_bignum (obj); |
| 5460 | else | 5461 | else |
| 5461 | { | 5462 | { |
| 5462 | AUTO_STRING (fmt, "Don't know how to purify: %S"); | 5463 | AUTO_STRING (fmt, "Don't know how to purify: %S"); |
| @@ -5784,6 +5785,77 @@ mark_and_sweep_weak_table_contents (void) | |||
| 5784 | } | 5785 | } |
| 5785 | } | 5786 | } |
| 5786 | 5787 | ||
| 5788 | /* Return the number of bytes to cons between GCs, assuming | ||
| 5789 | gc-cons-threshold is THRESHOLD and gc-cons-percentage is | ||
| 5790 | PERCENTAGE. */ | ||
| 5791 | static intmax_t | ||
| 5792 | consing_threshold (intmax_t threshold, Lisp_Object percentage) | ||
| 5793 | { | ||
| 5794 | if (!NILP (Vmemory_full)) | ||
| 5795 | return memory_full_cons_threshold; | ||
| 5796 | else | ||
| 5797 | { | ||
| 5798 | threshold = max (threshold, GC_DEFAULT_THRESHOLD / 10); | ||
| 5799 | if (FLOATP (percentage)) | ||
| 5800 | { | ||
| 5801 | double tot = (XFLOAT_DATA (percentage) | ||
| 5802 | * total_bytes_of_live_objects ()); | ||
| 5803 | if (threshold < tot) | ||
| 5804 | { | ||
| 5805 | if (tot < INTMAX_MAX) | ||
| 5806 | threshold = tot; | ||
| 5807 | else | ||
| 5808 | threshold = INTMAX_MAX; | ||
| 5809 | } | ||
| 5810 | } | ||
| 5811 | return threshold; | ||
| 5812 | } | ||
| 5813 | } | ||
| 5814 | |||
| 5815 | /* Adjust consing_until_gc, assuming gc-cons-threshold is THRESHOLD and | ||
| 5816 | gc-cons-percentage is PERCENTAGE. */ | ||
| 5817 | static Lisp_Object | ||
| 5818 | bump_consing_until_gc (intmax_t threshold, Lisp_Object percentage) | ||
| 5819 | { | ||
| 5820 | /* If consing_until_gc is negative leave it alone, since this prevents | ||
| 5821 | negative integer overflow and a GC would have been done soon anyway. */ | ||
| 5822 | if (0 <= consing_until_gc) | ||
| 5823 | { | ||
| 5824 | threshold = consing_threshold (threshold, percentage); | ||
| 5825 | intmax_t sum; | ||
| 5826 | if (INT_ADD_WRAPV (consing_until_gc, threshold - gc_threshold, &sum)) | ||
| 5827 | { | ||
| 5828 | /* Scale the threshold down so that consing_until_gc does | ||
| 5829 | not overflow. */ | ||
| 5830 | sum = INTMAX_MAX; | ||
| 5831 | threshold = INTMAX_MAX - consing_until_gc + gc_threshold; | ||
| 5832 | } | ||
| 5833 | consing_until_gc = sum; | ||
| 5834 | gc_threshold = threshold; | ||
| 5835 | } | ||
| 5836 | |||
| 5837 | return Qnil; | ||
| 5838 | } | ||
| 5839 | |||
| 5840 | /* Watch changes to gc-cons-threshold. */ | ||
| 5841 | static Lisp_Object | ||
| 5842 | watch_gc_cons_threshold (Lisp_Object symbol, Lisp_Object newval, | ||
| 5843 | Lisp_Object operation, Lisp_Object where) | ||
| 5844 | { | ||
| 5845 | intmax_t threshold; | ||
| 5846 | if (! (INTEGERP (newval) && integer_to_intmax (newval, &threshold))) | ||
| 5847 | return Qnil; | ||
| 5848 | return bump_consing_until_gc (threshold, Vgc_cons_percentage); | ||
| 5849 | } | ||
| 5850 | |||
| 5851 | /* Watch changes to gc-cons-percentage. */ | ||
| 5852 | static Lisp_Object | ||
| 5853 | watch_gc_cons_percentage (Lisp_Object symbol, Lisp_Object newval, | ||
| 5854 | Lisp_Object operation, Lisp_Object where) | ||
| 5855 | { | ||
| 5856 | return bump_consing_until_gc (gc_cons_threshold, newval); | ||
| 5857 | } | ||
| 5858 | |||
| 5787 | /* Subroutine of Fgarbage_collect that does most of the work. */ | 5859 | /* Subroutine of Fgarbage_collect that does most of the work. */ |
| 5788 | static bool | 5860 | static bool |
| 5789 | garbage_collect_1 (struct gcstat *gcst) | 5861 | garbage_collect_1 (struct gcstat *gcst) |
| @@ -5926,25 +5998,8 @@ garbage_collect_1 (struct gcstat *gcst) | |||
| 5926 | 5998 | ||
| 5927 | unblock_input (); | 5999 | unblock_input (); |
| 5928 | 6000 | ||
| 5929 | if (!NILP (Vmemory_full)) | 6001 | consing_until_gc = gc_threshold |
| 5930 | consing_until_gc = memory_full_cons_threshold; | 6002 | = consing_threshold (gc_cons_threshold, Vgc_cons_percentage); |
| 5931 | else | ||
| 5932 | { | ||
| 5933 | intmax_t threshold = max (gc_cons_threshold, GC_DEFAULT_THRESHOLD / 10); | ||
| 5934 | if (FLOATP (Vgc_cons_percentage)) | ||
| 5935 | { | ||
| 5936 | double tot = (XFLOAT_DATA (Vgc_cons_percentage) | ||
| 5937 | * total_bytes_of_live_objects ()); | ||
| 5938 | if (threshold < tot) | ||
| 5939 | { | ||
| 5940 | if (tot < INTMAX_MAX) | ||
| 5941 | threshold = tot; | ||
| 5942 | else | ||
| 5943 | threshold = INTMAX_MAX; | ||
| 5944 | } | ||
| 5945 | } | ||
| 5946 | consing_until_gc = threshold; | ||
| 5947 | } | ||
| 5948 | 6003 | ||
| 5949 | if (garbage_collection_messages && NILP (Vmemory_full)) | 6004 | if (garbage_collection_messages && NILP (Vmemory_full)) |
| 5950 | { | 6005 | { |
| @@ -7365,6 +7420,7 @@ do hash-consing of the objects allocated to pure space. */); | |||
| 7365 | DEFSYM (Qheap, "heap"); | 7420 | DEFSYM (Qheap, "heap"); |
| 7366 | DEFSYM (QAutomatic_GC, "Automatic GC"); | 7421 | DEFSYM (QAutomatic_GC, "Automatic GC"); |
| 7367 | 7422 | ||
| 7423 | DEFSYM (Qgc_cons_percentage, "gc-cons-percentage"); | ||
| 7368 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); | 7424 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); |
| 7369 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); | 7425 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); |
| 7370 | 7426 | ||
| @@ -7398,6 +7454,22 @@ N should be nonnegative. */); | |||
| 7398 | defsubr (&Smemory_info); | 7454 | defsubr (&Smemory_info); |
| 7399 | defsubr (&Smemory_use_counts); | 7455 | defsubr (&Smemory_use_counts); |
| 7400 | defsubr (&Ssuspicious_object); | 7456 | defsubr (&Ssuspicious_object); |
| 7457 | |||
| 7458 | Lisp_Object watcher; | ||
| 7459 | |||
| 7460 | static union Aligned_Lisp_Subr Swatch_gc_cons_threshold = | ||
| 7461 | {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, | ||
| 7462 | { .a4 = watch_gc_cons_threshold }, | ||
| 7463 | 4, 4, "watch_gc_cons_threshold", 0, 0}}; | ||
| 7464 | XSETSUBR (watcher, &Swatch_gc_cons_threshold.s); | ||
| 7465 | Fadd_variable_watcher (Qgc_cons_threshold, watcher); | ||
| 7466 | |||
| 7467 | static union Aligned_Lisp_Subr Swatch_gc_cons_percentage = | ||
| 7468 | {{{ PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) }, | ||
| 7469 | { .a4 = watch_gc_cons_percentage }, | ||
| 7470 | 4, 4, "watch_gc_cons_percentage", 0, 0}}; | ||
| 7471 | XSETSUBR (watcher, &Swatch_gc_cons_percentage.s); | ||
| 7472 | Fadd_variable_watcher (Qgc_cons_percentage, watcher); | ||
| 7401 | } | 7473 | } |
| 7402 | 7474 | ||
| 7403 | #ifdef HAVE_X_WINDOWS | 7475 | #ifdef HAVE_X_WINDOWS |
diff --git a/src/bignum.c b/src/bignum.c index 3883d3a3944..167b73eee02 100644 --- a/src/bignum.c +++ b/src/bignum.c | |||
| @@ -31,9 +31,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 31 | storage is exhausted. Admittedly this is not ideal. An mpz value | 31 | storage is exhausted. Admittedly this is not ideal. An mpz value |
| 32 | in a temporary is made permanent by mpz_swapping it with a bignum's | 32 | in a temporary is made permanent by mpz_swapping it with a bignum's |
| 33 | value. Although typically at most two temporaries are needed, | 33 | value. Although typically at most two temporaries are needed, |
| 34 | time_arith, rounddiv_q and rounding_driver each need four. */ | 34 | rounddiv_q and rounding_driver both need four and time_arith needs |
| 35 | five. */ | ||
| 35 | 36 | ||
| 36 | mpz_t mpz[4]; | 37 | mpz_t mpz[5]; |
| 37 | 38 | ||
| 38 | static void * | 39 | static void * |
| 39 | xrealloc_for_gmp (void *ptr, size_t ignore, size_t size) | 40 | xrealloc_for_gmp (void *ptr, size_t ignore, size_t size) |
| @@ -62,7 +63,7 @@ init_bignum (void) | |||
| 62 | double | 63 | double |
| 63 | bignum_to_double (Lisp_Object n) | 64 | bignum_to_double (Lisp_Object n) |
| 64 | { | 65 | { |
| 65 | return mpz_get_d_rounded (XBIGNUM (n)->value); | 66 | return mpz_get_d_rounded (*xbignum_val (n)); |
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | /* Return D, converted to a Lisp integer. Discard any fraction. | 69 | /* Return D, converted to a Lisp integer. Discard any fraction. |
| @@ -263,13 +264,13 @@ intmax_t | |||
| 263 | bignum_to_intmax (Lisp_Object x) | 264 | bignum_to_intmax (Lisp_Object x) |
| 264 | { | 265 | { |
| 265 | intmax_t i; | 266 | intmax_t i; |
| 266 | return mpz_to_intmax (XBIGNUM (x)->value, &i) ? i : 0; | 267 | return mpz_to_intmax (*xbignum_val (x), &i) ? i : 0; |
| 267 | } | 268 | } |
| 268 | uintmax_t | 269 | uintmax_t |
| 269 | bignum_to_uintmax (Lisp_Object x) | 270 | bignum_to_uintmax (Lisp_Object x) |
| 270 | { | 271 | { |
| 271 | uintmax_t i; | 272 | uintmax_t i; |
| 272 | return mpz_to_uintmax (XBIGNUM (x)->value, &i) ? i : 0; | 273 | return mpz_to_uintmax (*xbignum_val (x), &i) ? i : 0; |
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | /* Yield an upper bound on the buffer size needed to contain a C | 276 | /* Yield an upper bound on the buffer size needed to contain a C |
| @@ -283,7 +284,7 @@ mpz_bufsize (mpz_t const num, int base) | |||
| 283 | ptrdiff_t | 284 | ptrdiff_t |
| 284 | bignum_bufsize (Lisp_Object num, int base) | 285 | bignum_bufsize (Lisp_Object num, int base) |
| 285 | { | 286 | { |
| 286 | return mpz_bufsize (XBIGNUM (num)->value, base); | 287 | return mpz_bufsize (*xbignum_val (num), base); |
| 287 | } | 288 | } |
| 288 | 289 | ||
| 289 | /* Convert NUM to a nearest double, as opposed to mpz_get_d which | 290 | /* Convert NUM to a nearest double, as opposed to mpz_get_d which |
| @@ -317,7 +318,7 @@ ptrdiff_t | |||
| 317 | bignum_to_c_string (char *buf, ptrdiff_t size, Lisp_Object num, int base) | 318 | bignum_to_c_string (char *buf, ptrdiff_t size, Lisp_Object num, int base) |
| 318 | { | 319 | { |
| 319 | eassert (bignum_bufsize (num, abs (base)) == size); | 320 | eassert (bignum_bufsize (num, abs (base)) == size); |
| 320 | mpz_get_str (buf, base, XBIGNUM (num)->value); | 321 | mpz_get_str (buf, base, *xbignum_val (num)); |
| 321 | ptrdiff_t n = size - 2; | 322 | ptrdiff_t n = size - 2; |
| 322 | return !buf[n - 1] ? n - 1 : n + !!buf[n]; | 323 | return !buf[n - 1] ? n - 1 : n + !!buf[n]; |
| 323 | } | 324 | } |
diff --git a/src/bignum.h b/src/bignum.h index a9c7a0a09a8..bf7b3669537 100644 --- a/src/bignum.h +++ b/src/bignum.h | |||
| @@ -41,7 +41,7 @@ struct Lisp_Bignum | |||
| 41 | mpz_t value; | 41 | mpz_t value; |
| 42 | } GCALIGNED_STRUCT; | 42 | } GCALIGNED_STRUCT; |
| 43 | 43 | ||
| 44 | extern mpz_t mpz[4]; | 44 | extern mpz_t mpz[5]; |
| 45 | 45 | ||
| 46 | extern void init_bignum (void); | 46 | extern void init_bignum (void); |
| 47 | extern Lisp_Object make_integer_mpz (void); | 47 | extern Lisp_Object make_integer_mpz (void); |
| @@ -80,6 +80,19 @@ mpz_set_uintmax (mpz_t result, uintmax_t v) | |||
| 80 | mpz_set_uintmax_slow (result, v); | 80 | mpz_set_uintmax_slow (result, v); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /* Return a pointer to the mpz_t value represented by the bignum I. | ||
| 84 | It is const because the value should not change. */ | ||
| 85 | INLINE mpz_t const * | ||
| 86 | bignum_val (struct Lisp_Bignum const *i) | ||
| 87 | { | ||
| 88 | return &i->value; | ||
| 89 | } | ||
| 90 | INLINE mpz_t const * | ||
| 91 | xbignum_val (Lisp_Object i) | ||
| 92 | { | ||
| 93 | return bignum_val (XBIGNUM (i)); | ||
| 94 | } | ||
| 95 | |||
| 83 | /* Return a pointer to an mpz_t that is equal to the Lisp integer I. | 96 | /* Return a pointer to an mpz_t that is equal to the Lisp integer I. |
| 84 | If I is a bignum this returns a pointer to I's representation; | 97 | If I is a bignum this returns a pointer to I's representation; |
| 85 | otherwise this sets *TMP to I's value and returns TMP. */ | 98 | otherwise this sets *TMP to I's value and returns TMP. */ |
| @@ -91,7 +104,7 @@ bignum_integer (mpz_t *tmp, Lisp_Object i) | |||
| 91 | mpz_set_intmax (*tmp, XFIXNUM (i)); | 104 | mpz_set_intmax (*tmp, XFIXNUM (i)); |
| 92 | return tmp; | 105 | return tmp; |
| 93 | } | 106 | } |
| 94 | return &XBIGNUM (i)->value; | 107 | return xbignum_val (i); |
| 95 | } | 108 | } |
| 96 | 109 | ||
| 97 | /* Set RESULT to the value stored in the Lisp integer I. If I is a | 110 | /* Set RESULT to the value stored in the Lisp integer I. If I is a |
| @@ -103,7 +116,7 @@ mpz_set_integer (mpz_t result, Lisp_Object i) | |||
| 103 | if (FIXNUMP (i)) | 116 | if (FIXNUMP (i)) |
| 104 | mpz_set_intmax (result, XFIXNUM (i)); | 117 | mpz_set_intmax (result, XFIXNUM (i)); |
| 105 | else | 118 | else |
| 106 | mpz_set (result, XBIGNUM (i)->value); | 119 | mpz_set (result, *xbignum_val (i)); |
| 107 | } | 120 | } |
| 108 | 121 | ||
| 109 | INLINE_HEADER_END | 122 | INLINE_HEADER_END |
diff --git a/src/buffer.c b/src/buffer.c index ea785bbcd70..77e8b6bb779 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -105,7 +105,7 @@ static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS]; | |||
| 105 | 105 | ||
| 106 | /* Number of per-buffer variables used. */ | 106 | /* Number of per-buffer variables used. */ |
| 107 | 107 | ||
| 108 | int last_per_buffer_idx; | 108 | static int last_per_buffer_idx; |
| 109 | 109 | ||
| 110 | static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, | 110 | static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, |
| 111 | bool after, Lisp_Object arg1, | 111 | bool after, Lisp_Object arg1, |
| @@ -655,6 +655,12 @@ set_buffer_overlays_after (struct buffer *b, struct Lisp_Overlay *o) | |||
| 655 | b->overlays_after = o; | 655 | b->overlays_after = o; |
| 656 | } | 656 | } |
| 657 | 657 | ||
| 658 | bool | ||
| 659 | valid_per_buffer_idx (int idx) | ||
| 660 | { | ||
| 661 | return 0 <= idx && idx < last_per_buffer_idx; | ||
| 662 | } | ||
| 663 | |||
| 658 | /* Clone per-buffer values of buffer FROM. | 664 | /* Clone per-buffer values of buffer FROM. |
| 659 | 665 | ||
| 660 | Buffer TO gets the same per-buffer values as FROM, with the | 666 | Buffer TO gets the same per-buffer values as FROM, with the |
| @@ -4568,7 +4574,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after, | |||
| 4568 | prop_i = copy[i++]; | 4574 | prop_i = copy[i++]; |
| 4569 | overlay_i = copy[i++]; | 4575 | overlay_i = copy[i++]; |
| 4570 | /* It is possible that the recorded overlay has been deleted | 4576 | /* It is possible that the recorded overlay has been deleted |
| 4571 | (which makes it's markers' buffers be nil), or that (due to | 4577 | (which makes its markers' buffers be nil), or that (due to |
| 4572 | some bug) it belongs to a different buffer. Only run this | 4578 | some bug) it belongs to a different buffer. Only run this |
| 4573 | hook if the overlay belongs to the current buffer. */ | 4579 | hook if the overlay belongs to the current buffer. */ |
| 4574 | if (XMARKER (OVERLAY_START (overlay_i))->buffer == current_buffer) | 4580 | if (XMARKER (OVERLAY_START (overlay_i))->buffer == current_buffer) |
diff --git a/src/buffer.h b/src/buffer.h index 2080a6f40b7..82d9350bfc2 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -31,12 +31,11 @@ INLINE_HEADER_BEGIN | |||
| 31 | 31 | ||
| 32 | /* Accessing the parameters of the current buffer. */ | 32 | /* Accessing the parameters of the current buffer. */ |
| 33 | 33 | ||
| 34 | /* These macros come in pairs, one for the char position | 34 | /* These constants and macros come in pairs, one for the char position |
| 35 | and one for the byte position. */ | 35 | and one for the byte position. */ |
| 36 | 36 | ||
| 37 | /* Position of beginning of buffer. */ | 37 | /* Position of beginning of buffer. */ |
| 38 | #define BEG (1) | 38 | enum { BEG = 1, BEG_BYTE = BEG }; |
| 39 | #define BEG_BYTE (BEG) | ||
| 40 | 39 | ||
| 41 | /* Position of beginning of accessible range of buffer. */ | 40 | /* Position of beginning of accessible range of buffer. */ |
| 42 | #define BEGV (current_buffer->begv) | 41 | #define BEGV (current_buffer->begv) |
| @@ -96,59 +95,7 @@ INLINE_HEADER_BEGIN | |||
| 96 | 95 | ||
| 97 | /* Modification count as of last visit or save. */ | 96 | /* Modification count as of last visit or save. */ |
| 98 | #define SAVE_MODIFF (current_buffer->text->save_modiff) | 97 | #define SAVE_MODIFF (current_buffer->text->save_modiff) |
| 99 | |||
| 100 | /* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return | ||
| 101 | the max (resp. min) p such that | ||
| 102 | |||
| 103 | BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */ | ||
| 104 | |||
| 105 | #define BUFFER_CEILING_OF(BYTEPOS) \ | ||
| 106 | (((BYTEPOS) < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1) | ||
| 107 | #define BUFFER_FLOOR_OF(BYTEPOS) \ | ||
| 108 | (BEGV <= GPT && GPT_BYTE <= (BYTEPOS) ? GPT_BYTE : BEGV_BYTE) | ||
| 109 | 98 | ||
| 110 | /* Similar macros to operate on a specified buffer. | ||
| 111 | Note that many of these evaluate the buffer argument more than once. */ | ||
| 112 | |||
| 113 | /* Position of beginning of buffer. */ | ||
| 114 | #define BUF_BEG(buf) (BEG) | ||
| 115 | #define BUF_BEG_BYTE(buf) (BEG_BYTE) | ||
| 116 | |||
| 117 | /* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] macros cannot | ||
| 118 | be used for assignment; use SET_BUF_* macros below for that. */ | ||
| 119 | |||
| 120 | /* Position of beginning of accessible range of buffer. */ | ||
| 121 | #define BUF_BEGV(buf) \ | ||
| 122 | (buf == current_buffer ? BEGV \ | ||
| 123 | : NILP (BVAR (buf, begv_marker)) ? buf->begv \ | ||
| 124 | : marker_position (BVAR (buf, begv_marker))) | ||
| 125 | |||
| 126 | #define BUF_BEGV_BYTE(buf) \ | ||
| 127 | (buf == current_buffer ? BEGV_BYTE \ | ||
| 128 | : NILP (BVAR (buf, begv_marker)) ? buf->begv_byte \ | ||
| 129 | : marker_byte_position (BVAR (buf, begv_marker))) | ||
| 130 | |||
| 131 | /* Position of point in buffer. */ | ||
| 132 | #define BUF_PT(buf) \ | ||
| 133 | (buf == current_buffer ? PT \ | ||
| 134 | : NILP (BVAR (buf, pt_marker)) ? buf->pt \ | ||
| 135 | : marker_position (BVAR (buf, pt_marker))) | ||
| 136 | |||
| 137 | #define BUF_PT_BYTE(buf) \ | ||
| 138 | (buf == current_buffer ? PT_BYTE \ | ||
| 139 | : NILP (BVAR (buf, pt_marker)) ? buf->pt_byte \ | ||
| 140 | : marker_byte_position (BVAR (buf, pt_marker))) | ||
| 141 | |||
| 142 | /* Position of end of accessible range of buffer. */ | ||
| 143 | #define BUF_ZV(buf) \ | ||
| 144 | (buf == current_buffer ? ZV \ | ||
| 145 | : NILP (BVAR (buf, zv_marker)) ? buf->zv \ | ||
| 146 | : marker_position (BVAR (buf, zv_marker))) | ||
| 147 | |||
| 148 | #define BUF_ZV_BYTE(buf) \ | ||
| 149 | (buf == current_buffer ? ZV_BYTE \ | ||
| 150 | : NILP (BVAR (buf, zv_marker)) ? buf->zv_byte \ | ||
| 151 | : marker_byte_position (BVAR (buf, zv_marker))) | ||
| 152 | 99 | ||
| 153 | /* Position of gap in buffer. */ | 100 | /* Position of gap in buffer. */ |
| 154 | #define BUF_GPT(buf) ((buf)->text->gpt) | 101 | #define BUF_GPT(buf) ((buf)->text->gpt) |
| @@ -161,15 +108,6 @@ INLINE_HEADER_BEGIN | |||
| 161 | /* Address of beginning of buffer. */ | 108 | /* Address of beginning of buffer. */ |
| 162 | #define BUF_BEG_ADDR(buf) ((buf)->text->beg) | 109 | #define BUF_BEG_ADDR(buf) ((buf)->text->beg) |
| 163 | 110 | ||
| 164 | /* Address of beginning of gap of buffer. */ | ||
| 165 | #define BUF_GPT_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte - BEG_BYTE) | ||
| 166 | |||
| 167 | /* Address of end of buffer. */ | ||
| 168 | #define BUF_Z_ADDR(buf) ((buf)->text->beg + (buf)->text->gap_size + (buf)->text->z_byte - BEG_BYTE) | ||
| 169 | |||
| 170 | /* Address of end of gap in buffer. */ | ||
| 171 | #define BUF_GAP_END_ADDR(buf) ((buf)->text->beg + (buf)->text->gpt_byte + (buf)->text->gap_size - BEG_BYTE) | ||
| 172 | |||
| 173 | /* Size of gap. */ | 111 | /* Size of gap. */ |
| 174 | #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size) | 112 | #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size) |
| 175 | 113 | ||
| @@ -209,43 +147,8 @@ INLINE_HEADER_BEGIN | |||
| 209 | BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer) | 147 | BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer) |
| 210 | #define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer) | 148 | #define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer) |
| 211 | #define END_UNCHANGED BUF_END_UNCHANGED (current_buffer) | 149 | #define END_UNCHANGED BUF_END_UNCHANGED (current_buffer) |
| 212 | |||
| 213 | /* Compute how many characters at the top and bottom of BUF are | ||
| 214 | unchanged when the range START..END is modified. This computation | ||
| 215 | must be done each time BUF is modified. */ | ||
| 216 | |||
| 217 | #define BUF_COMPUTE_UNCHANGED(buf, start, end) \ | ||
| 218 | do \ | ||
| 219 | { \ | ||
| 220 | if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf) \ | ||
| 221 | && (BUF_OVERLAY_UNCHANGED_MODIFIED (buf) \ | ||
| 222 | == BUF_OVERLAY_MODIFF (buf))) \ | ||
| 223 | { \ | ||
| 224 | BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \ | ||
| 225 | BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \ | ||
| 226 | } \ | ||
| 227 | else \ | ||
| 228 | { \ | ||
| 229 | if (BUF_Z (buf) - (end) < BUF_END_UNCHANGED (buf)) \ | ||
| 230 | BUF_END_UNCHANGED (buf) = BUF_Z (buf) - (end); \ | ||
| 231 | if ((start) - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf)) \ | ||
| 232 | BUF_BEG_UNCHANGED (buf) = (start) - BUF_BEG (buf); \ | ||
| 233 | } \ | ||
| 234 | } \ | ||
| 235 | while (false) | ||
| 236 | |||
| 237 | 150 | ||
| 238 | /* Macros to set PT in the current buffer, or another buffer. */ | 151 | /* Functions to set PT in the current buffer, or another buffer. */ |
| 239 | |||
| 240 | #define SET_PT(position) (set_point (position)) | ||
| 241 | #define TEMP_SET_PT(position) (temp_set_point (current_buffer, (position))) | ||
| 242 | |||
| 243 | #define SET_PT_BOTH(position, byte) (set_point_both (position, byte)) | ||
| 244 | #define TEMP_SET_PT_BOTH(position, byte) \ | ||
| 245 | (temp_set_point_both (current_buffer, (position), (byte))) | ||
| 246 | |||
| 247 | #define BUF_TEMP_SET_PT(buffer, position) \ | ||
| 248 | (temp_set_point ((buffer), (position))) | ||
| 249 | 152 | ||
| 250 | extern void set_point (ptrdiff_t); | 153 | extern void set_point (ptrdiff_t); |
| 251 | extern void temp_set_point (struct buffer *, ptrdiff_t); | 154 | extern void temp_set_point (struct buffer *, ptrdiff_t); |
| @@ -255,39 +158,32 @@ extern void temp_set_point_both (struct buffer *, | |||
| 255 | extern void set_point_from_marker (Lisp_Object); | 158 | extern void set_point_from_marker (Lisp_Object); |
| 256 | extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); | 159 | extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); |
| 257 | 160 | ||
| 161 | INLINE void | ||
| 162 | SET_PT (ptrdiff_t position) | ||
| 163 | { | ||
| 164 | set_point (position); | ||
| 165 | } | ||
| 166 | INLINE void | ||
| 167 | TEMP_SET_PT (ptrdiff_t position) | ||
| 168 | { | ||
| 169 | temp_set_point (current_buffer, position); | ||
| 170 | } | ||
| 171 | INLINE void | ||
| 172 | SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte) | ||
| 173 | { | ||
| 174 | set_point_both (position, byte); | ||
| 175 | } | ||
| 176 | INLINE void | ||
| 177 | TEMP_SET_PT_BOTH (ptrdiff_t position, ptrdiff_t byte) | ||
| 178 | { | ||
| 179 | temp_set_point_both (current_buffer, position, byte); | ||
| 180 | } | ||
| 181 | INLINE void | ||
| 182 | BUF_TEMP_SET_PT (struct buffer *buffer, ptrdiff_t position) | ||
| 183 | { | ||
| 184 | temp_set_point (buffer, position); | ||
| 185 | } | ||
| 258 | 186 | ||
| 259 | /* Macros for setting the BEGV, ZV or PT of a given buffer. | ||
| 260 | |||
| 261 | The ..._BOTH macros take both a charpos and a bytepos, | ||
| 262 | which must correspond to each other. | ||
| 263 | |||
| 264 | The macros without ..._BOTH take just a charpos, | ||
| 265 | and compute the bytepos from it. */ | ||
| 266 | |||
| 267 | #define SET_BUF_BEGV(buf, charpos) \ | ||
| 268 | ((buf)->begv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \ | ||
| 269 | (buf)->begv = (charpos)) | ||
| 270 | |||
| 271 | #define SET_BUF_ZV(buf, charpos) \ | ||
| 272 | ((buf)->zv_byte = buf_charpos_to_bytepos ((buf), (charpos)), \ | ||
| 273 | (buf)->zv = (charpos)) | ||
| 274 | |||
| 275 | #define SET_BUF_BEGV_BOTH(buf, charpos, byte) \ | ||
| 276 | ((buf)->begv = (charpos), \ | ||
| 277 | (buf)->begv_byte = (byte)) | ||
| 278 | |||
| 279 | #define SET_BUF_ZV_BOTH(buf, charpos, byte) \ | ||
| 280 | ((buf)->zv = (charpos), \ | ||
| 281 | (buf)->zv_byte = (byte)) | ||
| 282 | |||
| 283 | #define SET_BUF_PT_BOTH(buf, charpos, byte) \ | ||
| 284 | ((buf)->pt = (charpos), \ | ||
| 285 | (buf)->pt_byte = (byte)) | ||
| 286 | |||
| 287 | /* Macros to access a character or byte in the current buffer, | ||
| 288 | or convert between a byte position and an address. | ||
| 289 | These macros do not check that the position is in range. */ | ||
| 290 | |||
| 291 | /* Maximum number of bytes in a buffer. | 187 | /* Maximum number of bytes in a buffer. |
| 292 | A buffer cannot contain more bytes than a 1-origin fixnum can represent, | 188 | A buffer cannot contain more bytes than a 1-origin fixnum can represent, |
| 293 | nor can it be so large that C pointer arithmetic stops working. | 189 | nor can it be so large that C pointer arithmetic stops working. |
| @@ -298,115 +194,21 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t); | |||
| 298 | /* Maximum gap size after compact_buffer, in bytes. Also | 194 | /* Maximum gap size after compact_buffer, in bytes. Also |
| 299 | used in make_gap_larger to get some extra reserved space. */ | 195 | used in make_gap_larger to get some extra reserved space. */ |
| 300 | 196 | ||
| 301 | #define GAP_BYTES_DFL 2000 | 197 | enum { GAP_BYTES_DFL = 2000 }; |
| 302 | 198 | ||
| 303 | /* Minimum gap size after compact_buffer, in bytes. Also | 199 | /* Minimum gap size after compact_buffer, in bytes. Also |
| 304 | used in make_gap_smaller to avoid too small gap size. */ | 200 | used in make_gap_smaller to avoid too small gap size. */ |
| 305 | 201 | ||
| 306 | #define GAP_BYTES_MIN 20 | 202 | enum { GAP_BYTES_MIN = 20 }; |
| 307 | |||
| 308 | /* Return the address of byte position N in current buffer. */ | ||
| 309 | |||
| 310 | #define BYTE_POS_ADDR(n) \ | ||
| 311 | (((n) >= GPT_BYTE ? GAP_SIZE : 0) + (n) + BEG_ADDR - BEG_BYTE) | ||
| 312 | |||
| 313 | /* Return the address of char position N. */ | ||
| 314 | |||
| 315 | #define CHAR_POS_ADDR(n) \ | ||
| 316 | (((n) >= GPT ? GAP_SIZE : 0) \ | ||
| 317 | + buf_charpos_to_bytepos (current_buffer, n) \ | ||
| 318 | + BEG_ADDR - BEG_BYTE) | ||
| 319 | |||
| 320 | /* Convert a character position to a byte position. */ | ||
| 321 | |||
| 322 | #define CHAR_TO_BYTE(charpos) \ | ||
| 323 | (buf_charpos_to_bytepos (current_buffer, charpos)) | ||
| 324 | |||
| 325 | /* Convert a byte position to a character position. */ | ||
| 326 | |||
| 327 | #define BYTE_TO_CHAR(bytepos) \ | ||
| 328 | (buf_bytepos_to_charpos (current_buffer, bytepos)) | ||
| 329 | 203 | ||
| 330 | /* For those very rare cases where you may have a "random" pointer into | 204 | /* For those very rare cases where you may have a "random" pointer into |
| 331 | the middle of a multibyte char, this moves to the next boundary. */ | 205 | the middle of a multibyte char, this moves to the next boundary. */ |
| 332 | extern ptrdiff_t advance_to_char_boundary (ptrdiff_t byte_pos); | 206 | extern ptrdiff_t advance_to_char_boundary (ptrdiff_t byte_pos); |
| 333 | 207 | ||
| 334 | /* Convert PTR, the address of a byte in the buffer, into a byte position. */ | 208 | /* Return the byte at byte position N. |
| 335 | 209 | Do not check that the position is in range. */ | |
| 336 | #define PTR_BYTE_POS(ptr) \ | ||
| 337 | ((ptr) - (current_buffer)->text->beg \ | ||
| 338 | - (ptr - (current_buffer)->text->beg <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) \ | ||
| 339 | + BEG_BYTE) | ||
| 340 | |||
| 341 | /* Return character at byte position POS. See the caveat WARNING for | ||
| 342 | FETCH_MULTIBYTE_CHAR below. */ | ||
| 343 | |||
| 344 | #define FETCH_CHAR(pos) \ | ||
| 345 | (!NILP (BVAR (current_buffer, enable_multibyte_characters)) \ | ||
| 346 | ? FETCH_MULTIBYTE_CHAR ((pos)) \ | ||
| 347 | : FETCH_BYTE ((pos))) | ||
| 348 | |||
| 349 | /* Return the byte at byte position N. */ | ||
| 350 | 210 | ||
| 351 | #define FETCH_BYTE(n) *(BYTE_POS_ADDR ((n))) | 211 | #define FETCH_BYTE(n) *(BYTE_POS_ADDR ((n))) |
| 352 | |||
| 353 | /* Return character at byte position POS. If the current buffer is unibyte | ||
| 354 | and the character is not ASCII, make the returning character | ||
| 355 | multibyte. */ | ||
| 356 | |||
| 357 | #define FETCH_CHAR_AS_MULTIBYTE(pos) \ | ||
| 358 | (!NILP (BVAR (current_buffer, enable_multibyte_characters)) \ | ||
| 359 | ? FETCH_MULTIBYTE_CHAR ((pos)) \ | ||
| 360 | : UNIBYTE_TO_CHAR (FETCH_BYTE ((pos)))) | ||
| 361 | |||
| 362 | |||
| 363 | /* Macros for accessing a character or byte, | ||
| 364 | or converting between byte positions and addresses, | ||
| 365 | in a specified buffer. */ | ||
| 366 | |||
| 367 | /* Return the address of character at byte position POS in buffer BUF. | ||
| 368 | Note that both arguments can be computed more than once. */ | ||
| 369 | |||
| 370 | #define BUF_BYTE_ADDRESS(buf, pos) \ | ||
| 371 | ((buf)->text->beg + (pos) - BEG_BYTE \ | ||
| 372 | + ((pos) >= (buf)->text->gpt_byte ? (buf)->text->gap_size : 0)) | ||
| 373 | |||
| 374 | /* Return the address of character at char position POS in buffer BUF. | ||
| 375 | Note that both arguments can be computed more than once. */ | ||
| 376 | |||
| 377 | #define BUF_CHAR_ADDRESS(buf, pos) \ | ||
| 378 | ((buf)->text->beg + buf_charpos_to_bytepos ((buf), (pos)) - BEG_BYTE \ | ||
| 379 | + ((pos) >= (buf)->text->gpt ? (buf)->text->gap_size : 0)) | ||
| 380 | |||
| 381 | /* Convert PTR, the address of a char in buffer BUF, | ||
| 382 | into a character position. */ | ||
| 383 | |||
| 384 | #define BUF_PTR_BYTE_POS(buf, ptr) \ | ||
| 385 | ((ptr) - (buf)->text->beg \ | ||
| 386 | - (ptr - (buf)->text->beg <= BUF_GPT_BYTE (buf) - BEG_BYTE \ | ||
| 387 | ? 0 : BUF_GAP_SIZE ((buf))) \ | ||
| 388 | + BEG_BYTE) | ||
| 389 | |||
| 390 | /* Return the character at byte position POS in buffer BUF. */ | ||
| 391 | |||
| 392 | #define BUF_FETCH_CHAR(buf, pos) \ | ||
| 393 | (!NILP (buf->enable_multibyte_characters) \ | ||
| 394 | ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ | ||
| 395 | : BUF_FETCH_BYTE ((buf), (pos))) | ||
| 396 | |||
| 397 | /* Return character at byte position POS in buffer BUF. If BUF is | ||
| 398 | unibyte and the character is not ASCII, make the returning | ||
| 399 | character multibyte. */ | ||
| 400 | |||
| 401 | #define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \ | ||
| 402 | (! NILP (BVAR ((buf), enable_multibyte_characters)) \ | ||
| 403 | ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ | ||
| 404 | : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos)))) | ||
| 405 | |||
| 406 | /* Return the byte at byte position N in buffer BUF. */ | ||
| 407 | |||
| 408 | #define BUF_FETCH_BYTE(buf, n) \ | ||
| 409 | *(BUF_BYTE_ADDRESS ((buf), (n))) | ||
| 410 | 212 | ||
| 411 | /* Define the actual buffer data structures. */ | 213 | /* Define the actual buffer data structures. */ |
| 412 | 214 | ||
| @@ -482,6 +284,13 @@ struct buffer_text | |||
| 482 | 284 | ||
| 483 | #define BVAR(buf, field) ((buf)->field ## _) | 285 | #define BVAR(buf, field) ((buf)->field ## _) |
| 484 | 286 | ||
| 287 | /* Max number of builtin per-buffer variables. */ | ||
| 288 | enum { MAX_PER_BUFFER_VARS = 50 }; | ||
| 289 | |||
| 290 | /* Special values for struct buffer.modtime. */ | ||
| 291 | enum { NONEXISTENT_MODTIME_NSECS = -1 }; | ||
| 292 | enum { UNKNOWN_MODTIME_NSECS = -2 }; | ||
| 293 | |||
| 485 | /* This is the structure that the buffer Lisp object points to. */ | 294 | /* This is the structure that the buffer Lisp object points to. */ |
| 486 | 295 | ||
| 487 | struct buffer | 296 | struct buffer |
| @@ -796,7 +605,6 @@ struct buffer | |||
| 796 | for a buffer-local variable is stored in that variable's slot | 605 | for a buffer-local variable is stored in that variable's slot |
| 797 | in buffer_local_flags as a Lisp integer. If the index is -1, | 606 | in buffer_local_flags as a Lisp integer. If the index is -1, |
| 798 | this means the variable is always local in all buffers. */ | 607 | this means the variable is always local in all buffers. */ |
| 799 | #define MAX_PER_BUFFER_VARS 50 | ||
| 800 | char local_flags[MAX_PER_BUFFER_VARS]; | 608 | char local_flags[MAX_PER_BUFFER_VARS]; |
| 801 | 609 | ||
| 802 | /* Set to the modtime of the visited file when read or written. | 610 | /* Set to the modtime of the visited file when read or written. |
| @@ -804,8 +612,6 @@ struct buffer | |||
| 804 | visited file was nonexistent. modtime.tv_nsec == | 612 | visited file was nonexistent. modtime.tv_nsec == |
| 805 | UNKNOWN_MODTIME_NSECS means visited file modtime unknown; | 613 | UNKNOWN_MODTIME_NSECS means visited file modtime unknown; |
| 806 | in no case complain about any mismatch on next save attempt. */ | 614 | in no case complain about any mismatch on next save attempt. */ |
| 807 | #define NONEXISTENT_MODTIME_NSECS (-1) | ||
| 808 | #define UNKNOWN_MODTIME_NSECS (-2) | ||
| 809 | struct timespec modtime; | 615 | struct timespec modtime; |
| 810 | 616 | ||
| 811 | /* Size of the file when modtime was set. This is used to detect the | 617 | /* Size of the file when modtime was set. This is used to detect the |
| @@ -1018,49 +824,281 @@ bset_width_table (struct buffer *b, Lisp_Object val) | |||
| 1018 | b->width_table_ = val; | 824 | b->width_table_ = val; |
| 1019 | } | 825 | } |
| 1020 | 826 | ||
| 827 | /* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return | ||
| 828 | the max (resp. min) p such that | ||
| 829 | |||
| 830 | BYTE_POS_ADDR (p) - BYTE_POS_ADDR (n) == p - n */ | ||
| 831 | |||
| 832 | INLINE ptrdiff_t | ||
| 833 | BUFFER_CEILING_OF (ptrdiff_t bytepos) | ||
| 834 | { | ||
| 835 | return (bytepos < GPT_BYTE && GPT < ZV ? GPT_BYTE : ZV_BYTE) - 1; | ||
| 836 | } | ||
| 837 | |||
| 838 | INLINE ptrdiff_t | ||
| 839 | BUFFER_FLOOR_OF (ptrdiff_t bytepos) | ||
| 840 | { | ||
| 841 | return BEGV <= GPT && GPT_BYTE <= bytepos ? GPT_BYTE : BEGV_BYTE; | ||
| 842 | } | ||
| 843 | |||
| 844 | /* The BUF_BEGV[_BYTE], BUF_ZV[_BYTE], and BUF_PT[_BYTE] functions cannot | ||
| 845 | be used for assignment; use SET_BUF_* functions below for that. */ | ||
| 846 | |||
| 847 | /* Position of beginning of accessible range of buffer. */ | ||
| 848 | INLINE ptrdiff_t | ||
| 849 | BUF_BEGV (struct buffer *buf) | ||
| 850 | { | ||
| 851 | return (buf == current_buffer ? BEGV | ||
| 852 | : NILP (BVAR (buf, begv_marker)) ? buf->begv | ||
| 853 | : marker_position (BVAR (buf, begv_marker))); | ||
| 854 | } | ||
| 855 | |||
| 856 | INLINE ptrdiff_t | ||
| 857 | BUF_BEGV_BYTE (struct buffer *buf) | ||
| 858 | { | ||
| 859 | return (buf == current_buffer ? BEGV_BYTE | ||
| 860 | : NILP (BVAR (buf, begv_marker)) ? buf->begv_byte | ||
| 861 | : marker_byte_position (BVAR (buf, begv_marker))); | ||
| 862 | } | ||
| 863 | |||
| 864 | /* Position of point in buffer. */ | ||
| 865 | INLINE ptrdiff_t | ||
| 866 | BUF_PT (struct buffer *buf) | ||
| 867 | { | ||
| 868 | return (buf == current_buffer ? PT | ||
| 869 | : NILP (BVAR (buf, pt_marker)) ? buf->pt | ||
| 870 | : marker_position (BVAR (buf, pt_marker))); | ||
| 871 | } | ||
| 872 | |||
| 873 | INLINE ptrdiff_t | ||
| 874 | BUF_PT_BYTE (struct buffer *buf) | ||
| 875 | { | ||
| 876 | return (buf == current_buffer ? PT_BYTE | ||
| 877 | : NILP (BVAR (buf, pt_marker)) ? buf->pt_byte | ||
| 878 | : marker_byte_position (BVAR (buf, pt_marker))); | ||
| 879 | } | ||
| 880 | |||
| 881 | /* Position of end of accessible range of buffer. */ | ||
| 882 | INLINE ptrdiff_t | ||
| 883 | BUF_ZV (struct buffer *buf) | ||
| 884 | { | ||
| 885 | return (buf == current_buffer ? ZV | ||
| 886 | : NILP (BVAR (buf, zv_marker)) ? buf->zv | ||
| 887 | : marker_position (BVAR (buf, zv_marker))); | ||
| 888 | } | ||
| 889 | |||
| 890 | INLINE ptrdiff_t | ||
| 891 | BUF_ZV_BYTE (struct buffer *buf) | ||
| 892 | { | ||
| 893 | return (buf == current_buffer ? ZV_BYTE | ||
| 894 | : NILP (BVAR (buf, zv_marker)) ? buf->zv_byte | ||
| 895 | : marker_byte_position (BVAR (buf, zv_marker))); | ||
| 896 | } | ||
| 897 | |||
| 898 | /* Similar functions to operate on a specified buffer. */ | ||
| 899 | |||
| 900 | /* Position of beginning of buffer. */ | ||
| 901 | INLINE ptrdiff_t | ||
| 902 | BUF_BEG (struct buffer *buf) | ||
| 903 | { | ||
| 904 | return BEG; | ||
| 905 | } | ||
| 906 | |||
| 907 | INLINE ptrdiff_t | ||
| 908 | BUF_BEG_BYTE (struct buffer *buf) | ||
| 909 | { | ||
| 910 | return BEG_BYTE; | ||
| 911 | } | ||
| 912 | |||
| 913 | /* Address of beginning of gap of buffer. */ | ||
| 914 | INLINE unsigned char * | ||
| 915 | BUF_GPT_ADDR (struct buffer *buf) | ||
| 916 | { | ||
| 917 | return buf->text->beg + buf->text->gpt_byte - BEG_BYTE; | ||
| 918 | } | ||
| 919 | |||
| 920 | /* Address of end of buffer. */ | ||
| 921 | INLINE unsigned char * | ||
| 922 | BUF_Z_ADDR (struct buffer *buf) | ||
| 923 | { | ||
| 924 | return buf->text->beg + buf->text->gap_size + buf->text->z_byte - BEG_BYTE; | ||
| 925 | } | ||
| 926 | |||
| 927 | /* Address of end of gap in buffer. */ | ||
| 928 | INLINE unsigned char * | ||
| 929 | BUF_GAP_END_ADDR (struct buffer *buf) | ||
| 930 | { | ||
| 931 | return buf->text->beg + buf->text->gpt_byte + buf->text->gap_size - BEG_BYTE; | ||
| 932 | } | ||
| 933 | |||
| 934 | /* Compute how many characters at the top and bottom of BUF are | ||
| 935 | unchanged when the range START..END is modified. This computation | ||
| 936 | must be done each time BUF is modified. */ | ||
| 937 | |||
| 938 | INLINE void | ||
| 939 | BUF_COMPUTE_UNCHANGED (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) | ||
| 940 | { | ||
| 941 | if (BUF_UNCHANGED_MODIFIED (buf) == BUF_MODIFF (buf) | ||
| 942 | && (BUF_OVERLAY_UNCHANGED_MODIFIED (buf) | ||
| 943 | == BUF_OVERLAY_MODIFF (buf))) | ||
| 944 | { | ||
| 945 | buf->text->beg_unchanged = start - BUF_BEG (buf); | ||
| 946 | buf->text->end_unchanged = BUF_Z (buf) - (end); | ||
| 947 | } | ||
| 948 | else | ||
| 949 | { | ||
| 950 | if (BUF_Z (buf) - end < BUF_END_UNCHANGED (buf)) | ||
| 951 | buf->text->end_unchanged = BUF_Z (buf) - end; | ||
| 952 | if (start - BUF_BEG (buf) < BUF_BEG_UNCHANGED (buf)) | ||
| 953 | buf->text->beg_unchanged = start - BUF_BEG (buf); | ||
| 954 | } | ||
| 955 | } | ||
| 956 | |||
| 957 | /* Functions for setting the BEGV, ZV or PT of a given buffer. | ||
| 958 | |||
| 959 | The ..._BOTH functions take both a charpos and a bytepos, | ||
| 960 | which must correspond to each other. | ||
| 961 | |||
| 962 | The functions without ..._BOTH take just a charpos, | ||
| 963 | and compute the bytepos from it. */ | ||
| 964 | |||
| 965 | INLINE void | ||
| 966 | SET_BUF_BEGV (struct buffer *buf, ptrdiff_t charpos) | ||
| 967 | { | ||
| 968 | buf->begv_byte = buf_charpos_to_bytepos (buf, charpos); | ||
| 969 | buf->begv = charpos; | ||
| 970 | } | ||
| 971 | |||
| 972 | INLINE void | ||
| 973 | SET_BUF_ZV (struct buffer *buf, ptrdiff_t charpos) | ||
| 974 | { | ||
| 975 | buf->zv_byte = buf_charpos_to_bytepos (buf, charpos); | ||
| 976 | buf->zv = charpos; | ||
| 977 | } | ||
| 978 | |||
| 979 | INLINE void | ||
| 980 | SET_BUF_BEGV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) | ||
| 981 | { | ||
| 982 | buf->begv = charpos; | ||
| 983 | buf->begv_byte = byte; | ||
| 984 | } | ||
| 985 | |||
| 986 | INLINE void | ||
| 987 | SET_BUF_ZV_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) | ||
| 988 | { | ||
| 989 | buf->zv = charpos; | ||
| 990 | buf->zv_byte = byte; | ||
| 991 | } | ||
| 992 | |||
| 993 | INLINE void | ||
| 994 | SET_BUF_PT_BOTH (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t byte) | ||
| 995 | { | ||
| 996 | buf->pt = charpos; | ||
| 997 | buf->pt_byte = byte; | ||
| 998 | } | ||
| 999 | |||
| 1000 | /* Functions to access a character or byte in the current buffer, | ||
| 1001 | or convert between a byte position and an address. | ||
| 1002 | These functions do not check that the position is in range. */ | ||
| 1003 | |||
| 1004 | /* Return the address of byte position N in current buffer. */ | ||
| 1005 | |||
| 1006 | INLINE unsigned char * | ||
| 1007 | BYTE_POS_ADDR (ptrdiff_t n) | ||
| 1008 | { | ||
| 1009 | return (n < GPT_BYTE ? 0 : GAP_SIZE) + n + BEG_ADDR - BEG_BYTE; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | /* Return the address of char position N. */ | ||
| 1013 | |||
| 1014 | INLINE unsigned char * | ||
| 1015 | CHAR_POS_ADDR (ptrdiff_t n) | ||
| 1016 | { | ||
| 1017 | return ((n < GPT ? 0 : GAP_SIZE) | ||
| 1018 | + buf_charpos_to_bytepos (current_buffer, n) | ||
| 1019 | + BEG_ADDR - BEG_BYTE); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | /* Convert a character position to a byte position. */ | ||
| 1023 | |||
| 1024 | INLINE ptrdiff_t | ||
| 1025 | CHAR_TO_BYTE (ptrdiff_t charpos) | ||
| 1026 | { | ||
| 1027 | return buf_charpos_to_bytepos (current_buffer, charpos); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | /* Convert a byte position to a character position. */ | ||
| 1031 | |||
| 1032 | INLINE ptrdiff_t | ||
| 1033 | BYTE_TO_CHAR (ptrdiff_t bytepos) | ||
| 1034 | { | ||
| 1035 | return buf_bytepos_to_charpos (current_buffer, bytepos); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | /* Convert PTR, the address of a byte in the buffer, into a byte position. */ | ||
| 1039 | |||
| 1040 | INLINE ptrdiff_t | ||
| 1041 | PTR_BYTE_POS (unsigned char const *ptr) | ||
| 1042 | { | ||
| 1043 | ptrdiff_t byte = ptr - current_buffer->text->beg; | ||
| 1044 | return byte - (byte <= GPT_BYTE - BEG_BYTE ? 0 : GAP_SIZE) + BEG_BYTE; | ||
| 1045 | } | ||
| 1046 | |||
| 1021 | /* Number of Lisp_Objects at the beginning of struct buffer. | 1047 | /* Number of Lisp_Objects at the beginning of struct buffer. |
| 1022 | If you add, remove, or reorder Lisp_Objects within buffer | 1048 | If you add, remove, or reorder Lisp_Objects within buffer |
| 1023 | structure, make sure that this is still correct. */ | 1049 | structure, make sure that this is still correct. */ |
| 1024 | 1050 | ||
| 1025 | #define BUFFER_LISP_SIZE \ | 1051 | enum { BUFFER_LISP_SIZE = PSEUDOVECSIZE (struct buffer, |
| 1026 | PSEUDOVECSIZE (struct buffer, cursor_in_non_selected_windows_) | 1052 | cursor_in_non_selected_windows_) }; |
| 1027 | 1053 | ||
| 1028 | /* Allocated size of the struct buffer part beyond leading | 1054 | /* Allocated size of the struct buffer part beyond leading |
| 1029 | Lisp_Objects, in word_size units. */ | 1055 | Lisp_Objects, in word_size units. */ |
| 1030 | 1056 | ||
| 1031 | #define BUFFER_REST_SIZE (VECSIZE (struct buffer) - BUFFER_LISP_SIZE) | 1057 | enum { BUFFER_REST_SIZE = VECSIZE (struct buffer) - BUFFER_LISP_SIZE }; |
| 1032 | 1058 | ||
| 1033 | /* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE | 1059 | /* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE |
| 1034 | is required for GC, but BUFFER_REST_SIZE is set up just to be consistent | 1060 | is required for GC, but BUFFER_REST_SIZE is set up just to be consistent |
| 1035 | with other pseudovectors. */ | 1061 | with other pseudovectors. */ |
| 1036 | 1062 | ||
| 1037 | #define BUFFER_PVEC_INIT(b) \ | 1063 | INLINE void |
| 1038 | XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE) | 1064 | BUFFER_PVEC_INIT (struct buffer *b) |
| 1065 | { | ||
| 1066 | XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE); | ||
| 1067 | } | ||
| 1039 | 1068 | ||
| 1040 | /* Convenient check whether buffer B is live. */ | 1069 | /* Convenient check whether buffer B is live. */ |
| 1041 | 1070 | ||
| 1042 | #define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name))) | 1071 | INLINE bool |
| 1072 | BUFFER_LIVE_P (struct buffer *b) | ||
| 1073 | { | ||
| 1074 | return !NILP (BVAR (b, name)); | ||
| 1075 | } | ||
| 1043 | 1076 | ||
| 1044 | /* Convenient check whether buffer B is hidden (i.e. its name | 1077 | /* Convenient check whether buffer B is hidden (i.e. its name |
| 1045 | starts with a space). Caller must ensure that B is live. */ | 1078 | starts with a space). Caller must ensure that B is live. */ |
| 1046 | 1079 | ||
| 1047 | #define BUFFER_HIDDEN_P(b) (SREF (BVAR (b, name), 0) == ' ') | 1080 | INLINE bool |
| 1081 | BUFFER_HIDDEN_P (struct buffer *b) | ||
| 1082 | { | ||
| 1083 | return SREF (BVAR (b, name), 0) == ' '; | ||
| 1084 | } | ||
| 1048 | 1085 | ||
| 1049 | /* Verify indirection counters. */ | 1086 | /* Verify indirection counters. */ |
| 1050 | 1087 | ||
| 1051 | #define BUFFER_CHECK_INDIRECTION(b) \ | 1088 | INLINE void |
| 1052 | do { \ | 1089 | BUFFER_CHECK_INDIRECTION (struct buffer *b) |
| 1053 | if (BUFFER_LIVE_P (b)) \ | 1090 | { |
| 1054 | { \ | 1091 | if (BUFFER_LIVE_P (b)) |
| 1055 | if (b->base_buffer) \ | 1092 | { |
| 1056 | { \ | 1093 | if (b->base_buffer) |
| 1057 | eassert (b->indirections == -1); \ | 1094 | { |
| 1058 | eassert (b->base_buffer->indirections > 0); \ | 1095 | eassert (b->indirections == -1); |
| 1059 | } \ | 1096 | eassert (b->base_buffer->indirections > 0); |
| 1060 | else \ | 1097 | } |
| 1061 | eassert (b->indirections >= 0); \ | 1098 | else |
| 1062 | } \ | 1099 | eassert (b->indirections >= 0); |
| 1063 | } while (false) | 1100 | } |
| 1101 | } | ||
| 1064 | 1102 | ||
| 1065 | /* Chain of all buffers, including killed ones. */ | 1103 | /* Chain of all buffers, including killed ones. */ |
| 1066 | 1104 | ||
| @@ -1157,7 +1195,9 @@ record_unwind_current_buffer (void) | |||
| 1157 | 1195 | ||
| 1158 | /* Get overlays at POSN into array OVERLAYS with NOVERLAYS elements. | 1196 | /* Get overlays at POSN into array OVERLAYS with NOVERLAYS elements. |
| 1159 | If NEXTP is non-NULL, return next overlay there. | 1197 | If NEXTP is non-NULL, return next overlay there. |
| 1160 | See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. */ | 1198 | See overlay_at arg CHANGE_REQ for meaning of CHRQ arg. |
| 1199 | This macro might evaluate its args multiple times, | ||
| 1200 | and it treat some args as lvalues. */ | ||
| 1161 | 1201 | ||
| 1162 | #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ | 1202 | #define GET_OVERLAYS_AT(posn, overlays, noverlays, nextp, chrq) \ |
| 1163 | do { \ | 1203 | do { \ |
| @@ -1207,6 +1247,10 @@ buffer_has_overlays (void) | |||
| 1207 | { | 1247 | { |
| 1208 | return current_buffer->overlays_before || current_buffer->overlays_after; | 1248 | return current_buffer->overlays_before || current_buffer->overlays_after; |
| 1209 | } | 1249 | } |
| 1250 | |||
| 1251 | /* Functions for accessing a character or byte, | ||
| 1252 | or converting between byte positions and addresses, | ||
| 1253 | in a specified buffer. */ | ||
| 1210 | 1254 | ||
| 1211 | /* Return character code of multi-byte form at byte position POS. If POS | 1255 | /* Return character code of multi-byte form at byte position POS. If POS |
| 1212 | doesn't point the head of valid multi-byte form, only the byte at | 1256 | doesn't point the head of valid multi-byte form, only the byte at |
| @@ -1232,6 +1276,80 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos) | |||
| 1232 | return STRING_CHAR (p); | 1276 | return STRING_CHAR (p); |
| 1233 | } | 1277 | } |
| 1234 | 1278 | ||
| 1279 | /* Return character at byte position POS. | ||
| 1280 | If the current buffer is unibyte and the character is not ASCII, | ||
| 1281 | make the returning character multibyte. */ | ||
| 1282 | |||
| 1283 | INLINE int | ||
| 1284 | FETCH_CHAR_AS_MULTIBYTE (ptrdiff_t pos) | ||
| 1285 | { | ||
| 1286 | return (!NILP (BVAR (current_buffer, enable_multibyte_characters)) | ||
| 1287 | ? FETCH_MULTIBYTE_CHAR (pos) | ||
| 1288 | : UNIBYTE_TO_CHAR (FETCH_BYTE (pos))); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | /* Return character at byte position POS. | ||
| 1292 | See the caveat WARNING for FETCH_MULTIBYTE_CHAR above. */ | ||
| 1293 | |||
| 1294 | INLINE int | ||
| 1295 | FETCH_CHAR (ptrdiff_t pos) | ||
| 1296 | { | ||
| 1297 | return (!NILP (BVAR (current_buffer, enable_multibyte_characters)) | ||
| 1298 | ? FETCH_MULTIBYTE_CHAR (pos) | ||
| 1299 | : FETCH_BYTE (pos)); | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | /* Return the address of character at byte position POS in buffer BUF. | ||
| 1303 | Note that both arguments can be computed more than once. */ | ||
| 1304 | |||
| 1305 | INLINE unsigned char * | ||
| 1306 | BUF_BYTE_ADDRESS (struct buffer *buf, ptrdiff_t pos) | ||
| 1307 | { | ||
| 1308 | return (buf->text->beg + pos - BEG_BYTE | ||
| 1309 | + (pos < buf->text->gpt_byte ? 0 : buf->text->gap_size)); | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | /* Return the address of character at char position POS in buffer BUF. | ||
| 1313 | Note that both arguments can be computed more than once. */ | ||
| 1314 | |||
| 1315 | INLINE unsigned char * | ||
| 1316 | BUF_CHAR_ADDRESS (struct buffer *buf, ptrdiff_t pos) | ||
| 1317 | { | ||
| 1318 | return (buf->text->beg + buf_charpos_to_bytepos (buf, pos) - BEG_BYTE | ||
| 1319 | + (pos < buf->text->gpt ? 0 : buf->text->gap_size)); | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | /* Convert PTR, the address of a char in buffer BUF, | ||
| 1323 | into a character position. */ | ||
| 1324 | |||
| 1325 | INLINE ptrdiff_t | ||
| 1326 | BUF_PTR_BYTE_POS (struct buffer *buf, unsigned char *ptr) | ||
| 1327 | { | ||
| 1328 | ptrdiff_t byte = ptr - buf->text->beg; | ||
| 1329 | return (byte - (byte <= BUF_GPT_BYTE (buf) - BEG_BYTE ? 0 : BUF_GAP_SIZE (buf)) | ||
| 1330 | + BEG_BYTE); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | /* Return the byte at byte position N in buffer BUF. */ | ||
| 1334 | |||
| 1335 | INLINE unsigned char | ||
| 1336 | BUF_FETCH_BYTE (struct buffer *buf, ptrdiff_t n) | ||
| 1337 | { | ||
| 1338 | return *BUF_BYTE_ADDRESS (buf, n); | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | /* Return character at byte position POS in buffer BUF. If BUF is | ||
| 1342 | unibyte and the character is not ASCII, make the returning | ||
| 1343 | character multibyte. */ | ||
| 1344 | |||
| 1345 | INLINE int | ||
| 1346 | BUF_FETCH_CHAR_AS_MULTIBYTE (struct buffer *buf, ptrdiff_t pos) | ||
| 1347 | { | ||
| 1348 | return (! NILP (BVAR (buf, enable_multibyte_characters)) | ||
| 1349 | ? BUF_FETCH_MULTIBYTE_CHAR (buf, pos) | ||
| 1350 | : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE (buf, pos))); | ||
| 1351 | } | ||
| 1352 | |||
| 1235 | /* Return number of windows showing B. */ | 1353 | /* Return number of windows showing B. */ |
| 1236 | 1354 | ||
| 1237 | INLINE int | 1355 | INLINE int |
| @@ -1260,18 +1378,17 @@ buffer_window_count (struct buffer *b) | |||
| 1260 | /* Return the actual buffer position for the marker P. | 1378 | /* Return the actual buffer position for the marker P. |
| 1261 | We assume you know which buffer it's pointing into. */ | 1379 | We assume you know which buffer it's pointing into. */ |
| 1262 | 1380 | ||
| 1263 | #define OVERLAY_POSITION(P) \ | 1381 | INLINE ptrdiff_t |
| 1264 | (MARKERP (P) ? marker_position (P) : (emacs_abort (), 0)) | 1382 | OVERLAY_POSITION (Lisp_Object p) |
| 1383 | { | ||
| 1384 | return marker_position (p); | ||
| 1385 | } | ||
| 1265 | 1386 | ||
| 1266 | 1387 | ||
| 1267 | /*********************************************************************** | 1388 | /*********************************************************************** |
| 1268 | Buffer-local Variables | 1389 | Buffer-local Variables |
| 1269 | ***********************************************************************/ | 1390 | ***********************************************************************/ |
| 1270 | 1391 | ||
| 1271 | /* Number of per-buffer variables used. */ | ||
| 1272 | |||
| 1273 | extern int last_per_buffer_idx; | ||
| 1274 | |||
| 1275 | /* Return the offset in bytes of member VAR of struct buffer | 1392 | /* Return the offset in bytes of member VAR of struct buffer |
| 1276 | from the start of a buffer structure. */ | 1393 | from the start of a buffer structure. */ |
| 1277 | 1394 | ||
| @@ -1296,23 +1413,27 @@ extern int last_per_buffer_idx; | |||
| 1296 | #define PER_BUFFER_VAR_IDX(VAR) \ | 1413 | #define PER_BUFFER_VAR_IDX(VAR) \ |
| 1297 | PER_BUFFER_IDX (PER_BUFFER_VAR_OFFSET (VAR)) | 1414 | PER_BUFFER_IDX (PER_BUFFER_VAR_OFFSET (VAR)) |
| 1298 | 1415 | ||
| 1416 | extern bool valid_per_buffer_idx (int); | ||
| 1417 | |||
| 1299 | /* Value is true if the variable with index IDX has a local value | 1418 | /* Value is true if the variable with index IDX has a local value |
| 1300 | in buffer B. */ | 1419 | in buffer B. */ |
| 1301 | 1420 | ||
| 1302 | #define PER_BUFFER_VALUE_P(B, IDX) \ | 1421 | INLINE bool |
| 1303 | (((IDX) < 0 || IDX >= last_per_buffer_idx) \ | 1422 | PER_BUFFER_VALUE_P (struct buffer *b, int idx) |
| 1304 | ? (emacs_abort (), false) \ | 1423 | { |
| 1305 | : ((B)->local_flags[IDX] != 0)) | 1424 | eassert (valid_per_buffer_idx (idx)); |
| 1425 | return b->local_flags[idx]; | ||
| 1426 | } | ||
| 1306 | 1427 | ||
| 1307 | /* Set whether per-buffer variable with index IDX has a buffer-local | 1428 | /* Set whether per-buffer variable with index IDX has a buffer-local |
| 1308 | value in buffer B. VAL zero means it hasn't. */ | 1429 | value in buffer B. VAL zero means it hasn't. */ |
| 1309 | 1430 | ||
| 1310 | #define SET_PER_BUFFER_VALUE_P(B, IDX, VAL) \ | 1431 | INLINE void |
| 1311 | do { \ | 1432 | SET_PER_BUFFER_VALUE_P (struct buffer *b, int idx, bool val) |
| 1312 | if ((IDX) < 0 || (IDX) >= last_per_buffer_idx) \ | 1433 | { |
| 1313 | emacs_abort (); \ | 1434 | eassert (valid_per_buffer_idx (idx)); |
| 1314 | (B)->local_flags[IDX] = (VAL); \ | 1435 | b->local_flags[idx] = val; |
| 1315 | } while (false) | 1436 | } |
| 1316 | 1437 | ||
| 1317 | /* Return the index value of the per-buffer variable at offset OFFSET | 1438 | /* Return the index value of the per-buffer variable at offset OFFSET |
| 1318 | in the buffer structure. | 1439 | in the buffer structure. |
| @@ -1332,11 +1453,13 @@ extern int last_per_buffer_idx; | |||
| 1332 | new buffer. | 1453 | new buffer. |
| 1333 | 1454 | ||
| 1334 | If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is | 1455 | If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is |
| 1335 | zero, that is a bug */ | 1456 | zero, that is a bug. */ |
| 1336 | 1457 | ||
| 1337 | 1458 | INLINE int | |
| 1338 | #define PER_BUFFER_IDX(OFFSET) \ | 1459 | PER_BUFFER_IDX (ptrdiff_t offset) |
| 1339 | XFIXNUM (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_flags)) | 1460 | { |
| 1461 | return XFIXNUM (*(Lisp_Object *) (offset + (char *) &buffer_local_flags)); | ||
| 1462 | } | ||
| 1340 | 1463 | ||
| 1341 | /* Functions to get and set default value of the per-buffer | 1464 | /* Functions to get and set default value of the per-buffer |
| 1342 | variable at offset OFFSET in the buffer structure. */ | 1465 | variable at offset OFFSET in the buffer structure. */ |
diff --git a/src/coding.c b/src/coding.c index 2ddd34eb7b6..c0408fbce48 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -9842,7 +9842,10 @@ encode_string_utf_8 (Lisp_Object string, Lisp_Object buffer, | |||
| 9842 | If BUFFER is Qnil, return a multibyte string from the decoded result. | 9842 | If BUFFER is Qnil, return a multibyte string from the decoded result. |
| 9843 | As a special case, return STRING itself in the following cases: | 9843 | As a special case, return STRING itself in the following cases: |
| 9844 | 1. STRING contains only ASCII characters. | 9844 | 1. STRING contains only ASCII characters. |
| 9845 | 2. NOCOPY, and STRING contains only valid UTF-8 sequences. | 9845 | 2. NOCOPY is true, and STRING contains only valid UTF-8 sequences. |
| 9846 | |||
| 9847 | For maximum speed, always specify NOCOPY true when STRING is | ||
| 9848 | guaranteed to contain only valid UTF-8 sequences. | ||
| 9846 | 9849 | ||
| 9847 | HANDLE-8-BIT and HANDLE-OVER-UNI specify how to handle a invalid | 9850 | HANDLE-8-BIT and HANDLE-OVER-UNI specify how to handle a invalid |
| 9848 | byte sequence. The former is for an 1-byte invalid sequence that | 9851 | byte sequence. The former is for an 1-byte invalid sequence that |
diff --git a/src/composite.c b/src/composite.c index a6606d5fc45..efbd055cef2 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -919,16 +919,17 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, | |||
| 919 | } | 919 | } |
| 920 | 920 | ||
| 921 | /* 1 iff the character C is composable. Characters of general | 921 | /* 1 iff the character C is composable. Characters of general |
| 922 | category Z? or C? are not composable except for ZWNJ and ZWJ. */ | 922 | category Z? or C? are not composable except for ZWNJ and ZWJ, |
| 923 | and characters of category Zs. */ | ||
| 923 | 924 | ||
| 924 | static bool | 925 | static bool |
| 925 | char_composable_p (int c) | 926 | char_composable_p (int c) |
| 926 | { | 927 | { |
| 927 | Lisp_Object val; | 928 | Lisp_Object val; |
| 928 | return (c > ' ' | 929 | return (c >= ' ' |
| 929 | && (c == ZERO_WIDTH_NON_JOINER || c == ZERO_WIDTH_JOINER | 930 | && (c == ZERO_WIDTH_NON_JOINER || c == ZERO_WIDTH_JOINER |
| 930 | || (val = CHAR_TABLE_REF (Vunicode_category_table, c), | 931 | || (val = CHAR_TABLE_REF (Vunicode_category_table, c), |
| 931 | (FIXNUMP (val) && (XFIXNUM (val) <= UNICODE_CATEGORY_So))))); | 932 | (FIXNUMP (val) && (XFIXNUM (val) <= UNICODE_CATEGORY_Zs))))); |
| 932 | } | 933 | } |
| 933 | 934 | ||
| 934 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and | 935 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and |
diff --git a/src/conf_post.h b/src/conf_post.h index 4af1ba9331f..43f98620a4b 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -373,8 +373,13 @@ extern int emacs_setenv_TZ (char const *); | |||
| 373 | #undef noinline | 373 | #undef noinline |
| 374 | #endif | 374 | #endif |
| 375 | 375 | ||
| 376 | /* Use Gnulib's extern-inline module for extern inline functions. | 376 | /* INLINE marks functions defined in Emacs-internal C headers. |
| 377 | An include file foo.h should prepend FOO_INLINE to function | 377 | INLINE is implemented via C99-style 'extern inline' if Emacs is built |
| 378 | with -DEMACS_EXTERN_INLINE; otherwise it is implemented via 'static'. | ||
| 379 | EMACS_EXTERN_INLINE is no longer the default, as 'static' seems to | ||
| 380 | have better performance with GCC. | ||
| 381 | |||
| 382 | An include file foo.h should prepend INLINE to function | ||
| 378 | definitions, with the following overall pattern: | 383 | definitions, with the following overall pattern: |
| 379 | 384 | ||
| 380 | [#include any other .h files first.] | 385 | [#include any other .h files first.] |
| @@ -399,20 +404,40 @@ extern int emacs_setenv_TZ (char const *); | |||
| 399 | For Emacs, this is done by having emacs.c first '#define INLINE | 404 | For Emacs, this is done by having emacs.c first '#define INLINE |
| 400 | EXTERN_INLINE' and then include every .h file that uses INLINE. | 405 | EXTERN_INLINE' and then include every .h file that uses INLINE. |
| 401 | 406 | ||
| 402 | The INLINE_HEADER_BEGIN and INLINE_HEADER_END suppress bogus | 407 | The INLINE_HEADER_BEGIN and INLINE_HEADER_END macros suppress bogus |
| 403 | warnings in some GCC versions; see ../m4/extern-inline.m4. | 408 | warnings in some GCC versions; see ../m4/extern-inline.m4. */ |
| 409 | |||
| 410 | #ifdef EMACS_EXTERN_INLINE | ||
| 411 | |||
| 412 | /* Use Gnulib's extern-inline module for extern inline functions. | ||
| 404 | 413 | ||
| 405 | C99 compilers compile functions like 'incr' as C99-style extern | 414 | C99 compilers compile functions like 'incr' as C99-style extern |
| 406 | inline functions. Buggy GCC implementations do something similar with | 415 | inline functions. Buggy GCC implementations do something similar with |
| 407 | GNU-specific keywords. Buggy non-GCC compilers use static | 416 | GNU-specific keywords. Buggy non-GCC compilers use static |
| 408 | functions, which bloats the code but is good enough. */ | 417 | functions, which bloats the code but is good enough. */ |
| 409 | 418 | ||
| 410 | #ifndef INLINE | 419 | # ifndef INLINE |
| 411 | # define INLINE _GL_INLINE | 420 | # define INLINE _GL_INLINE |
| 421 | # endif | ||
| 422 | # define EXTERN_INLINE _GL_EXTERN_INLINE | ||
| 423 | # define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN | ||
| 424 | # define INLINE_HEADER_END _GL_INLINE_HEADER_END | ||
| 425 | |||
| 426 | #else | ||
| 427 | |||
| 428 | /* Use 'static' instead of 'extern inline' because 'static' typically | ||
| 429 | has better performance for Emacs. Do not use the 'inline' keyword, | ||
| 430 | as modern compilers inline automatically. ATTRIBUTE_UNUSED | ||
| 431 | pacifies gcc -Wunused-function. */ | ||
| 432 | |||
| 433 | # ifndef INLINE | ||
| 434 | # define INLINE EXTERN_INLINE | ||
| 435 | # endif | ||
| 436 | # define EXTERN_INLINE static ATTRIBUTE_UNUSED | ||
| 437 | # define INLINE_HEADER_BEGIN | ||
| 438 | # define INLINE_HEADER_END | ||
| 439 | |||
| 412 | #endif | 440 | #endif |
| 413 | #define EXTERN_INLINE _GL_EXTERN_INLINE | ||
| 414 | #define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN | ||
| 415 | #define INLINE_HEADER_END _GL_INLINE_HEADER_END | ||
| 416 | 441 | ||
| 417 | /* 'int x UNINIT;' is equivalent to 'int x;', except it cajoles GCC | 442 | /* 'int x UNINIT;' is equivalent to 'int x;', except it cajoles GCC |
| 418 | into not warning incorrectly about use of an uninitialized variable. */ | 443 | into not warning incorrectly about use of an uninitialized variable. */ |
diff --git a/src/data.c b/src/data.c index cf9f8e56133..1d9222e75a7 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -525,7 +525,7 @@ DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0, | |||
| 525 | (Lisp_Object object) | 525 | (Lisp_Object object) |
| 526 | { | 526 | { |
| 527 | return ((FIXNUMP (object) ? 0 <= XFIXNUM (object) | 527 | return ((FIXNUMP (object) ? 0 <= XFIXNUM (object) |
| 528 | : BIGNUMP (object) && 0 <= mpz_sgn (XBIGNUM (object)->value)) | 528 | : BIGNUMP (object) && 0 <= mpz_sgn (*xbignum_val (object))) |
| 529 | ? Qt : Qnil); | 529 | ? Qt : Qnil); |
| 530 | } | 530 | } |
| 531 | 531 | ||
| @@ -771,10 +771,7 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, | |||
| 771 | if (AUTOLOADP (function)) | 771 | if (AUTOLOADP (function)) |
| 772 | Fput (symbol, Qautoload, XCDR (function)); | 772 | Fput (symbol, Qautoload, XCDR (function)); |
| 773 | 773 | ||
| 774 | /* Convert to eassert or remove after GC bug is found. In the | 774 | eassert (valid_lisp_object_p (definition)); |
| 775 | meantime, check unconditionally, at a slight perf hit. */ | ||
| 776 | if (! valid_lisp_object_p (definition)) | ||
| 777 | emacs_abort (); | ||
| 778 | 775 | ||
| 779 | set_symbol_function (symbol, definition); | 776 | set_symbol_function (symbol, definition); |
| 780 | 777 | ||
| @@ -2481,7 +2478,7 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2481 | else if (isnan (f1)) | 2478 | else if (isnan (f1)) |
| 2482 | lt = eq = gt = false; | 2479 | lt = eq = gt = false; |
| 2483 | else | 2480 | else |
| 2484 | i2 = mpz_cmp_d (XBIGNUM (num2)->value, f1); | 2481 | i2 = mpz_cmp_d (*xbignum_val (num2), f1); |
| 2485 | } | 2482 | } |
| 2486 | else if (FIXNUMP (num1)) | 2483 | else if (FIXNUMP (num1)) |
| 2487 | { | 2484 | { |
| @@ -2502,7 +2499,7 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2502 | i2 = XFIXNUM (num2); | 2499 | i2 = XFIXNUM (num2); |
| 2503 | } | 2500 | } |
| 2504 | else | 2501 | else |
| 2505 | i2 = mpz_sgn (XBIGNUM (num2)->value); | 2502 | i2 = mpz_sgn (*xbignum_val (num2)); |
| 2506 | } | 2503 | } |
| 2507 | else if (FLOATP (num2)) | 2504 | else if (FLOATP (num2)) |
| 2508 | { | 2505 | { |
| @@ -2510,12 +2507,12 @@ arithcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2510 | if (isnan (f2)) | 2507 | if (isnan (f2)) |
| 2511 | lt = eq = gt = false; | 2508 | lt = eq = gt = false; |
| 2512 | else | 2509 | else |
| 2513 | i1 = mpz_cmp_d (XBIGNUM (num1)->value, f2); | 2510 | i1 = mpz_cmp_d (*xbignum_val (num1), f2); |
| 2514 | } | 2511 | } |
| 2515 | else if (FIXNUMP (num2)) | 2512 | else if (FIXNUMP (num2)) |
| 2516 | i1 = mpz_sgn (XBIGNUM (num1)->value); | 2513 | i1 = mpz_sgn (*xbignum_val (num1)); |
| 2517 | else | 2514 | else |
| 2518 | i1 = mpz_cmp (XBIGNUM (num1)->value, XBIGNUM (num2)->value); | 2515 | i1 = mpz_cmp (*xbignum_val (num1), *xbignum_val (num2)); |
| 2519 | 2516 | ||
| 2520 | if (eq) | 2517 | if (eq) |
| 2521 | { | 2518 | { |
| @@ -3005,7 +3002,7 @@ usage: (- &optional NUMBER-OR-MARKER &rest MORE-NUMBERS-OR-MARKERS) */) | |||
| 3005 | return make_int (-XFIXNUM (a)); | 3002 | return make_int (-XFIXNUM (a)); |
| 3006 | if (FLOATP (a)) | 3003 | if (FLOATP (a)) |
| 3007 | return make_float (-XFLOAT_DATA (a)); | 3004 | return make_float (-XFLOAT_DATA (a)); |
| 3008 | mpz_neg (mpz[0], XBIGNUM (a)->value); | 3005 | mpz_neg (mpz[0], *xbignum_val (a)); |
| 3009 | return make_integer_mpz (); | 3006 | return make_integer_mpz (); |
| 3010 | } | 3007 | } |
| 3011 | return arith_driver (Asub, nargs, args, a); | 3008 | return arith_driver (Asub, nargs, args, a); |
| @@ -3058,58 +3055,67 @@ usage: (/ NUMBER &rest DIVISORS) */) | |||
| 3058 | return arith_driver (Adiv, nargs, args, a); | 3055 | return arith_driver (Adiv, nargs, args, a); |
| 3059 | } | 3056 | } |
| 3060 | 3057 | ||
| 3061 | DEFUN ("%", Frem, Srem, 2, 2, 0, | 3058 | /* Return NUM % DEN (or NUM mod DEN, if MODULO). NUM and DEN must be |
| 3062 | doc: /* Return remainder of X divided by Y. | 3059 | integers. */ |
| 3063 | Both must be integers or markers. */) | 3060 | static Lisp_Object |
| 3064 | (register Lisp_Object x, Lisp_Object y) | 3061 | integer_remainder (Lisp_Object num, Lisp_Object den, bool modulo) |
| 3065 | { | ||
| 3066 | CHECK_INTEGER_COERCE_MARKER (x); | ||
| 3067 | CHECK_INTEGER_COERCE_MARKER (y); | ||
| 3068 | |||
| 3069 | /* A bignum can never be 0, so don't check that case. */ | ||
| 3070 | if (EQ (y, make_fixnum (0))) | ||
| 3071 | xsignal0 (Qarith_error); | ||
| 3072 | |||
| 3073 | if (FIXNUMP (x) && FIXNUMP (y)) | ||
| 3074 | return make_fixnum (XFIXNUM (x) % XFIXNUM (y)); | ||
| 3075 | else | ||
| 3076 | { | ||
| 3077 | mpz_tdiv_r (mpz[0], | ||
| 3078 | *bignum_integer (&mpz[0], x), | ||
| 3079 | *bignum_integer (&mpz[1], y)); | ||
| 3080 | return make_integer_mpz (); | ||
| 3081 | } | ||
| 3082 | } | ||
| 3083 | |||
| 3084 | /* Return X mod Y. Both must be integers and Y must be nonzero. */ | ||
| 3085 | Lisp_Object | ||
| 3086 | integer_mod (Lisp_Object x, Lisp_Object y) | ||
| 3087 | { | 3062 | { |
| 3088 | if (FIXNUMP (x) && FIXNUMP (y)) | 3063 | if (FIXNUMP (den)) |
| 3089 | { | 3064 | { |
| 3090 | EMACS_INT i1 = XFIXNUM (x), i2 = XFIXNUM (y); | 3065 | EMACS_INT d = XFIXNUM (den); |
| 3066 | if (d == 0) | ||
| 3067 | xsignal0 (Qarith_error); | ||
| 3091 | 3068 | ||
| 3092 | i1 %= i2; | 3069 | EMACS_INT r; |
| 3070 | bool have_r = false; | ||
| 3071 | if (FIXNUMP (num)) | ||
| 3072 | { | ||
| 3073 | r = XFIXNUM (num) % d; | ||
| 3074 | have_r = true; | ||
| 3075 | } | ||
| 3076 | else if (eabs (d) <= ULONG_MAX) | ||
| 3077 | { | ||
| 3078 | mpz_t const *n = xbignum_val (num); | ||
| 3079 | bool neg_n = mpz_sgn (*n) < 0; | ||
| 3080 | r = mpz_tdiv_ui (*n, eabs (d)); | ||
| 3081 | if (neg_n) | ||
| 3082 | r = -r; | ||
| 3083 | have_r = true; | ||
| 3084 | } | ||
| 3093 | 3085 | ||
| 3094 | /* If the "remainder" comes out with the wrong sign, fix it. */ | 3086 | if (have_r) |
| 3095 | if (i2 < 0 ? i1 > 0 : i1 < 0) | 3087 | { |
| 3096 | i1 += i2; | 3088 | /* If MODULO and the remainder has the wrong sign, fix it. */ |
| 3089 | if (modulo && (d < 0 ? r > 0 : r < 0)) | ||
| 3090 | r += d; | ||
| 3097 | 3091 | ||
| 3098 | return make_fixnum (i1); | 3092 | return make_fixnum (r); |
| 3093 | } | ||
| 3099 | } | 3094 | } |
| 3100 | else | ||
| 3101 | { | ||
| 3102 | mpz_t const *ym = bignum_integer (&mpz[1], y); | ||
| 3103 | bool neg_y = mpz_sgn (*ym) < 0; | ||
| 3104 | mpz_mod (mpz[0], *bignum_integer (&mpz[0], x), *ym); | ||
| 3105 | 3095 | ||
| 3106 | /* Fix the sign if needed. */ | 3096 | mpz_t const *d = bignum_integer (&mpz[1], den); |
| 3107 | int sgn_r = mpz_sgn (mpz[0]); | 3097 | mpz_t *r = &mpz[0]; |
| 3108 | if (neg_y ? sgn_r > 0 : sgn_r < 0) | 3098 | mpz_tdiv_r (*r, *bignum_integer (&mpz[0], num), *d); |
| 3109 | mpz_add (mpz[0], mpz[0], *ym); | ||
| 3110 | 3099 | ||
| 3111 | return make_integer_mpz (); | 3100 | if (modulo) |
| 3101 | { | ||
| 3102 | /* If the remainder has the wrong sign, fix it. */ | ||
| 3103 | int sgn_r = mpz_sgn (*r); | ||
| 3104 | if (mpz_sgn (*d) < 0 ? sgn_r > 0 : sgn_r < 0) | ||
| 3105 | mpz_add (*r, *r, *d); | ||
| 3112 | } | 3106 | } |
| 3107 | |||
| 3108 | return make_integer_mpz (); | ||
| 3109 | } | ||
| 3110 | |||
| 3111 | DEFUN ("%", Frem, Srem, 2, 2, 0, | ||
| 3112 | doc: /* Return remainder of X divided by Y. | ||
| 3113 | Both must be integers or markers. */) | ||
| 3114 | (register Lisp_Object x, Lisp_Object y) | ||
| 3115 | { | ||
| 3116 | CHECK_INTEGER_COERCE_MARKER (x); | ||
| 3117 | CHECK_INTEGER_COERCE_MARKER (y); | ||
| 3118 | return integer_remainder (x, y, false); | ||
| 3113 | } | 3119 | } |
| 3114 | 3120 | ||
| 3115 | DEFUN ("mod", Fmod, Smod, 2, 2, 0, | 3121 | DEFUN ("mod", Fmod, Smod, 2, 2, 0, |
| @@ -3120,12 +3126,9 @@ Both X and Y must be numbers or markers. */) | |||
| 3120 | { | 3126 | { |
| 3121 | CHECK_NUMBER_COERCE_MARKER (x); | 3127 | CHECK_NUMBER_COERCE_MARKER (x); |
| 3122 | CHECK_NUMBER_COERCE_MARKER (y); | 3128 | CHECK_NUMBER_COERCE_MARKER (y); |
| 3123 | 3129 | if (FLOATP (x) || FLOATP (y)) | |
| 3124 | /* A bignum can never be 0, so don't check that case. */ | 3130 | return fmod_float (x, y); |
| 3125 | if (EQ (y, make_fixnum (0))) | 3131 | return integer_remainder (x, y, true); |
| 3126 | xsignal0 (Qarith_error); | ||
| 3127 | |||
| 3128 | return (FLOATP (x) || FLOATP (y) ? fmod_float : integer_mod) (x, y); | ||
| 3129 | } | 3132 | } |
| 3130 | 3133 | ||
| 3131 | static Lisp_Object | 3134 | static Lisp_Object |
| @@ -3214,7 +3217,7 @@ representation. */) | |||
| 3214 | 3217 | ||
| 3215 | if (BIGNUMP (value)) | 3218 | if (BIGNUMP (value)) |
| 3216 | { | 3219 | { |
| 3217 | mpz_t *nonneg = &XBIGNUM (value)->value; | 3220 | mpz_t const *nonneg = xbignum_val (value); |
| 3218 | if (mpz_sgn (*nonneg) < 0) | 3221 | if (mpz_sgn (*nonneg) < 0) |
| 3219 | { | 3222 | { |
| 3220 | mpz_com (mpz[0], *nonneg); | 3223 | mpz_com (mpz[0], *nonneg); |
| @@ -3245,10 +3248,10 @@ In this case, the sign bit is duplicated. */) | |||
| 3245 | { | 3248 | { |
| 3246 | if (EQ (value, make_fixnum (0))) | 3249 | if (EQ (value, make_fixnum (0))) |
| 3247 | return value; | 3250 | return value; |
| 3248 | if (mpz_sgn (XBIGNUM (count)->value) < 0) | 3251 | if (mpz_sgn (*xbignum_val (count)) < 0) |
| 3249 | { | 3252 | { |
| 3250 | EMACS_INT v = (FIXNUMP (value) ? XFIXNUM (value) | 3253 | EMACS_INT v = (FIXNUMP (value) ? XFIXNUM (value) |
| 3251 | : mpz_sgn (XBIGNUM (value)->value)); | 3254 | : mpz_sgn (*xbignum_val (value))); |
| 3252 | return make_fixnum (v < 0 ? -1 : 0); | 3255 | return make_fixnum (v < 0 ? -1 : 0); |
| 3253 | } | 3256 | } |
| 3254 | overflow_error (); | 3257 | overflow_error (); |
| @@ -3291,8 +3294,8 @@ expt_integer (Lisp_Object x, Lisp_Object y) | |||
| 3291 | if (TYPE_RANGED_FIXNUMP (unsigned long, y)) | 3294 | if (TYPE_RANGED_FIXNUMP (unsigned long, y)) |
| 3292 | exp = XFIXNUM (y); | 3295 | exp = XFIXNUM (y); |
| 3293 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (y) | 3296 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (y) |
| 3294 | && mpz_fits_ulong_p (XBIGNUM (y)->value)) | 3297 | && mpz_fits_ulong_p (*xbignum_val (y))) |
| 3295 | exp = mpz_get_ui (XBIGNUM (y)->value); | 3298 | exp = mpz_get_ui (*xbignum_val (y)); |
| 3296 | else | 3299 | else |
| 3297 | overflow_error (); | 3300 | overflow_error (); |
| 3298 | 3301 | ||
| @@ -3311,7 +3314,7 @@ Markers are converted to integers. */) | |||
| 3311 | return make_int (XFIXNUM (number) + 1); | 3314 | return make_int (XFIXNUM (number) + 1); |
| 3312 | if (FLOATP (number)) | 3315 | if (FLOATP (number)) |
| 3313 | return (make_float (1.0 + XFLOAT_DATA (number))); | 3316 | return (make_float (1.0 + XFLOAT_DATA (number))); |
| 3314 | mpz_add_ui (mpz[0], XBIGNUM (number)->value, 1); | 3317 | mpz_add_ui (mpz[0], *xbignum_val (number), 1); |
| 3315 | return make_integer_mpz (); | 3318 | return make_integer_mpz (); |
| 3316 | } | 3319 | } |
| 3317 | 3320 | ||
| @@ -3326,7 +3329,7 @@ Markers are converted to integers. */) | |||
| 3326 | return make_int (XFIXNUM (number) - 1); | 3329 | return make_int (XFIXNUM (number) - 1); |
| 3327 | if (FLOATP (number)) | 3330 | if (FLOATP (number)) |
| 3328 | return (make_float (-1.0 + XFLOAT_DATA (number))); | 3331 | return (make_float (-1.0 + XFLOAT_DATA (number))); |
| 3329 | mpz_sub_ui (mpz[0], XBIGNUM (number)->value, 1); | 3332 | mpz_sub_ui (mpz[0], *xbignum_val (number), 1); |
| 3330 | return make_integer_mpz (); | 3333 | return make_integer_mpz (); |
| 3331 | } | 3334 | } |
| 3332 | 3335 | ||
| @@ -3337,7 +3340,7 @@ DEFUN ("lognot", Flognot, Slognot, 1, 1, 0, | |||
| 3337 | CHECK_INTEGER (number); | 3340 | CHECK_INTEGER (number); |
| 3338 | if (FIXNUMP (number)) | 3341 | if (FIXNUMP (number)) |
| 3339 | return make_fixnum (~XFIXNUM (number)); | 3342 | return make_fixnum (~XFIXNUM (number)); |
| 3340 | mpz_com (mpz[0], XBIGNUM (number)->value); | 3343 | mpz_com (mpz[0], *xbignum_val (number)); |
| 3341 | return make_integer_mpz (); | 3344 | return make_integer_mpz (); |
| 3342 | } | 3345 | } |
| 3343 | 3346 | ||
diff --git a/src/dbusbind.c b/src/dbusbind.c index 90ba461c6bc..7f4c8717f42 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -728,22 +728,27 @@ xd_append_arg (int dtype, Lisp_Object object, DBusMessageIter *iter) | |||
| 728 | strcpy (signature, DBUS_TYPE_STRING_AS_STRING); | 728 | strcpy (signature, DBUS_TYPE_STRING_AS_STRING); |
| 729 | 729 | ||
| 730 | else | 730 | else |
| 731 | /* If the element type is DBUS_TYPE_SIGNATURE, and this is | 731 | { |
| 732 | the only element, the value of this element is used as | 732 | /* If the element type is DBUS_TYPE_SIGNATURE, and this is |
| 733 | the array's element signature. */ | 733 | the only element, the value of this element is used as |
| 734 | if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)) | 734 | the array's element signature. */ |
| 735 | == DBUS_TYPE_SIGNATURE) | 735 | if (CONSP (object) && (XD_OBJECT_TO_DBUS_TYPE (XCAR (object)) |
| 736 | && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object))) | 736 | == DBUS_TYPE_SIGNATURE)) |
| 737 | && NILP (CDR_SAFE (XD_NEXT_VALUE (object)))) | 737 | { |
| 738 | { | 738 | Lisp_Object val = XD_NEXT_VALUE (object); |
| 739 | lispstpcpy (signature, CAR_SAFE (XD_NEXT_VALUE (object))); | 739 | if (CONSP (val) && STRINGP (XCAR (val)) && NILP (XCDR (val)) |
| 740 | object = CDR_SAFE (XD_NEXT_VALUE (object)); | 740 | && SBYTES (XCAR (val)) < DBUS_MAXIMUM_SIGNATURE_LENGTH) |
| 741 | } | 741 | { |
| 742 | 742 | lispstpcpy (signature, XCAR (val)); | |
| 743 | else | 743 | object = Qnil; |
| 744 | xd_signature (signature, | 744 | } |
| 745 | XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)), | 745 | } |
| 746 | dtype, CAR_SAFE (XD_NEXT_VALUE (object))); | 746 | |
| 747 | if (!NILP (object)) | ||
| 748 | xd_signature (signature, | ||
| 749 | XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)), | ||
| 750 | dtype, CAR_SAFE (XD_NEXT_VALUE (object))); | ||
| 751 | } | ||
| 747 | 752 | ||
| 748 | XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature, | 753 | XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature, |
| 749 | XD_OBJECT_TO_STRING (object)); | 754 | XD_OBJECT_TO_STRING (object)); |
diff --git a/src/emacs.c b/src/emacs.c index cc5818393a3..53572d7f0c8 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -2084,8 +2084,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 2084 | 2084 | ||
| 2085 | /* Enter editor command loop. This never returns. */ | 2085 | /* Enter editor command loop. This never returns. */ |
| 2086 | Frecursive_edit (); | 2086 | Frecursive_edit (); |
| 2087 | /* NOTREACHED */ | 2087 | eassume (false); |
| 2088 | return 0; | ||
| 2089 | } | 2088 | } |
| 2090 | 2089 | ||
| 2091 | /* Sort the args so we can find the most important ones | 2090 | /* Sort the args so we can find the most important ones |
diff --git a/src/floatfns.c b/src/floatfns.c index a913aad5aac..9049185307c 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -48,6 +48,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 48 | 48 | ||
| 49 | #include <count-leading-zeros.h> | 49 | #include <count-leading-zeros.h> |
| 50 | 50 | ||
| 51 | /* Emacs needs proper handling of +/-inf; correct printing as well as | ||
| 52 | important packages depend on it. Make sure the user didn't specify | ||
| 53 | -ffinite-math-only, either directly or implicitly with -Ofast or | ||
| 54 | -ffast-math. */ | ||
| 55 | #if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ | ||
| 56 | #error Emacs cannot be built with -ffinite-math-only | ||
| 57 | #endif | ||
| 58 | |||
| 51 | /* Check that X is a floating point number. */ | 59 | /* Check that X is a floating point number. */ |
| 52 | 60 | ||
| 53 | static void | 61 | static void |
| @@ -268,9 +276,9 @@ DEFUN ("abs", Fabs, Sabs, 1, 1, 0, | |||
| 268 | } | 276 | } |
| 269 | else | 277 | else |
| 270 | { | 278 | { |
| 271 | if (mpz_sgn (XBIGNUM (arg)->value) < 0) | 279 | if (mpz_sgn (*xbignum_val (arg)) < 0) |
| 272 | { | 280 | { |
| 273 | mpz_neg (mpz[0], XBIGNUM (arg)->value); | 281 | mpz_neg (mpz[0], *xbignum_val (arg)); |
| 274 | arg = make_integer_mpz (); | 282 | arg = make_integer_mpz (); |
| 275 | } | 283 | } |
| 276 | } | 284 | } |
| @@ -315,7 +323,7 @@ This is the same as the exponent of a float. */) | |||
| 315 | value = ivalue - 1; | 323 | value = ivalue - 1; |
| 316 | } | 324 | } |
| 317 | else if (!FIXNUMP (arg)) | 325 | else if (!FIXNUMP (arg)) |
| 318 | value = mpz_sizeinbase (XBIGNUM (arg)->value, 2) - 1; | 326 | value = mpz_sizeinbase (*xbignum_val (arg), 2) - 1; |
| 319 | else | 327 | else |
| 320 | { | 328 | { |
| 321 | EMACS_INT i = XFIXNUM (arg); | 329 | EMACS_INT i = XFIXNUM (arg); |
| @@ -47,7 +47,6 @@ static void sort_vector_copy (Lisp_Object, ptrdiff_t, | |||
| 47 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; | 47 | enum equal_kind { EQUAL_NO_QUIT, EQUAL_PLAIN, EQUAL_INCLUDING_PROPERTIES }; |
| 48 | static bool internal_equal (Lisp_Object, Lisp_Object, | 48 | static bool internal_equal (Lisp_Object, Lisp_Object, |
| 49 | enum equal_kind, int, Lisp_Object); | 49 | enum equal_kind, int, Lisp_Object); |
| 50 | static EMACS_UINT sxhash_bignum (struct Lisp_Bignum *); | ||
| 51 | 50 | ||
| 52 | DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, | 51 | DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0, |
| 53 | doc: /* Return the argument unchanged. */ | 52 | doc: /* Return the argument unchanged. */ |
| @@ -1444,7 +1443,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0, | |||
| 1444 | } | 1443 | } |
| 1445 | else | 1444 | else |
| 1446 | { | 1445 | { |
| 1447 | if (mpz_sgn (XBIGNUM (n)->value) < 0) | 1446 | if (mpz_sgn (*xbignum_val (n)) < 0) |
| 1448 | return tail; | 1447 | return tail; |
| 1449 | num = large_num; | 1448 | num = large_num; |
| 1450 | } | 1449 | } |
| @@ -1482,11 +1481,11 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0, | |||
| 1482 | CYCLE_LENGTH. */ | 1481 | CYCLE_LENGTH. */ |
| 1483 | /* Add N mod CYCLE_LENGTH to NUM. */ | 1482 | /* Add N mod CYCLE_LENGTH to NUM. */ |
| 1484 | if (cycle_length <= ULONG_MAX) | 1483 | if (cycle_length <= ULONG_MAX) |
| 1485 | num += mpz_tdiv_ui (XBIGNUM (n)->value, cycle_length); | 1484 | num += mpz_tdiv_ui (*xbignum_val (n), cycle_length); |
| 1486 | else | 1485 | else |
| 1487 | { | 1486 | { |
| 1488 | mpz_set_intmax (mpz[0], cycle_length); | 1487 | mpz_set_intmax (mpz[0], cycle_length); |
| 1489 | mpz_tdiv_r (mpz[0], XBIGNUM (n)->value, mpz[0]); | 1488 | mpz_tdiv_r (mpz[0], *xbignum_val (n), mpz[0]); |
| 1490 | intptr_t iz; | 1489 | intptr_t iz; |
| 1491 | mpz_export (&iz, NULL, -1, sizeof iz, 0, 0, mpz[0]); | 1490 | mpz_export (&iz, NULL, -1, sizeof iz, 0, 0, mpz[0]); |
| 1492 | num += iz; | 1491 | num += iz; |
| @@ -1595,7 +1594,7 @@ The value is actually the tail of LIST whose car is ELT. */) | |||
| 1595 | { | 1594 | { |
| 1596 | Lisp_Object tem = XCAR (tail); | 1595 | Lisp_Object tem = XCAR (tail); |
| 1597 | if (BIGNUMP (tem) | 1596 | if (BIGNUMP (tem) |
| 1598 | && mpz_cmp (XBIGNUM (elt)->value, XBIGNUM (tem)->value) == 0) | 1597 | && mpz_cmp (*xbignum_val (elt), *xbignum_val (tem)) == 0) |
| 1599 | return tail; | 1598 | return tail; |
| 1600 | } | 1599 | } |
| 1601 | } | 1600 | } |
| @@ -2307,7 +2306,7 @@ This differs from numeric comparison: (eql 0.0 -0.0) returns nil and | |||
| 2307 | return FLOATP (obj2) && same_float (obj1, obj2) ? Qt : Qnil; | 2306 | return FLOATP (obj2) && same_float (obj1, obj2) ? Qt : Qnil; |
| 2308 | else if (BIGNUMP (obj1)) | 2307 | else if (BIGNUMP (obj1)) |
| 2309 | return ((BIGNUMP (obj2) | 2308 | return ((BIGNUMP (obj2) |
| 2310 | && mpz_cmp (XBIGNUM (obj1)->value, XBIGNUM (obj2)->value) == 0) | 2309 | && mpz_cmp (*xbignum_val (obj1), *xbignum_val (obj2)) == 0) |
| 2311 | ? Qt : Qnil); | 2310 | ? Qt : Qnil); |
| 2312 | else | 2311 | else |
| 2313 | return EQ (obj1, obj2) ? Qt : Qnil; | 2312 | return EQ (obj1, obj2) ? Qt : Qnil; |
| @@ -2437,7 +2436,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, | |||
| 2437 | if (ASIZE (o2) != size) | 2436 | if (ASIZE (o2) != size) |
| 2438 | return false; | 2437 | return false; |
| 2439 | if (BIGNUMP (o1)) | 2438 | if (BIGNUMP (o1)) |
| 2440 | return mpz_cmp (XBIGNUM (o1)->value, XBIGNUM (o2)->value) == 0; | 2439 | return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; |
| 2441 | if (OVERLAYP (o1)) | 2440 | if (OVERLAYP (o1)) |
| 2442 | { | 2441 | { |
| 2443 | if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), | 2442 | if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2), |
| @@ -2951,9 +2950,12 @@ suppressed. */) | |||
| 2951 | But not more than once in any file, | 2950 | But not more than once in any file, |
| 2952 | and not when we aren't loading or reading from a file. */ | 2951 | and not when we aren't loading or reading from a file. */ |
| 2953 | if (!from_file) | 2952 | if (!from_file) |
| 2954 | for (tem = Vcurrent_load_list; CONSP (tem); tem = XCDR (tem)) | 2953 | { |
| 2955 | if (NILP (XCDR (tem)) && STRINGP (XCAR (tem))) | 2954 | Lisp_Object tail = Vcurrent_load_list; |
| 2956 | from_file = 1; | 2955 | FOR_EACH_TAIL_SAFE (tail) |
| 2956 | if (NILP (XCDR (tail)) && STRINGP (XCAR (tail))) | ||
| 2957 | from_file = true; | ||
| 2958 | } | ||
| 2957 | 2959 | ||
| 2958 | if (from_file) | 2960 | if (from_file) |
| 2959 | { | 2961 | { |
| @@ -3278,11 +3280,11 @@ static ptrdiff_t base64_encode_1 (const char *, char *, ptrdiff_t, bool, bool, | |||
| 3278 | static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, bool, | 3280 | static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, bool, |
| 3279 | bool, ptrdiff_t *); | 3281 | bool, ptrdiff_t *); |
| 3280 | 3282 | ||
| 3281 | Lisp_Object base64_encode_region_1 (Lisp_Object, Lisp_Object, bool, | 3283 | static Lisp_Object base64_encode_region_1 (Lisp_Object, Lisp_Object, bool, |
| 3282 | bool, bool); | 3284 | bool, bool); |
| 3283 | 3285 | ||
| 3284 | Lisp_Object base64_encode_string_1(Lisp_Object, bool, | 3286 | static Lisp_Object base64_encode_string_1 (Lisp_Object, bool, |
| 3285 | bool, bool); | 3287 | bool, bool); |
| 3286 | 3288 | ||
| 3287 | 3289 | ||
| 3288 | DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region, | 3290 | DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region, |
| @@ -3293,7 +3295,7 @@ Optional third argument NO-LINE-BREAK means do not break long lines | |||
| 3293 | into shorter lines. */) | 3295 | into shorter lines. */) |
| 3294 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_line_break) | 3296 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_line_break) |
| 3295 | { | 3297 | { |
| 3296 | return base64_encode_region_1(beg, end, NILP (no_line_break), true, false); | 3298 | return base64_encode_region_1 (beg, end, NILP (no_line_break), true, false); |
| 3297 | } | 3299 | } |
| 3298 | 3300 | ||
| 3299 | 3301 | ||
| @@ -3306,10 +3308,10 @@ Optional second argument NO-PAD means do not add padding char =. | |||
| 3306 | This produces the URL variant of base 64 encoding defined in RFC 4648. */) | 3308 | This produces the URL variant of base 64 encoding defined in RFC 4648. */) |
| 3307 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_pad) | 3309 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_pad) |
| 3308 | { | 3310 | { |
| 3309 | return base64_encode_region_1(beg, end, false, NILP(no_pad), true); | 3311 | return base64_encode_region_1 (beg, end, false, NILP(no_pad), true); |
| 3310 | } | 3312 | } |
| 3311 | 3313 | ||
| 3312 | Lisp_Object | 3314 | static Lisp_Object |
| 3313 | base64_encode_region_1 (Lisp_Object beg, Lisp_Object end, bool line_break, | 3315 | base64_encode_region_1 (Lisp_Object beg, Lisp_Object end, bool line_break, |
| 3314 | bool pad, bool base64url) | 3316 | bool pad, bool base64url) |
| 3315 | { | 3317 | { |
| @@ -3374,11 +3376,11 @@ into shorter lines. */) | |||
| 3374 | (Lisp_Object string, Lisp_Object no_line_break) | 3376 | (Lisp_Object string, Lisp_Object no_line_break) |
| 3375 | { | 3377 | { |
| 3376 | 3378 | ||
| 3377 | return base64_encode_string_1(string, NILP (no_line_break), true, false); | 3379 | return base64_encode_string_1 (string, NILP (no_line_break), true, false); |
| 3378 | } | 3380 | } |
| 3379 | 3381 | ||
| 3380 | DEFUN ("base64url-encode-string", Fbase64url_encode_string, Sbase64url_encode_string, | 3382 | DEFUN ("base64url-encode-string", Fbase64url_encode_string, |
| 3381 | 1, 2, 0, | 3383 | Sbase64url_encode_string, 1, 2, 0, |
| 3382 | doc: /* Base64url-encode STRING and return the result. | 3384 | doc: /* Base64url-encode STRING and return the result. |
| 3383 | Optional second argument NO-PAD means do not add padding char =. | 3385 | Optional second argument NO-PAD means do not add padding char =. |
| 3384 | 3386 | ||
| @@ -3386,12 +3388,12 @@ This produces the URL variant of base 64 encoding defined in RFC 4648. */) | |||
| 3386 | (Lisp_Object string, Lisp_Object no_pad) | 3388 | (Lisp_Object string, Lisp_Object no_pad) |
| 3387 | { | 3389 | { |
| 3388 | 3390 | ||
| 3389 | return base64_encode_string_1(string, false, NILP(no_pad), true); | 3391 | return base64_encode_string_1 (string, false, NILP(no_pad), true); |
| 3390 | } | 3392 | } |
| 3391 | 3393 | ||
| 3392 | Lisp_Object | 3394 | static Lisp_Object |
| 3393 | base64_encode_string_1(Lisp_Object string, bool line_break, | 3395 | base64_encode_string_1 (Lisp_Object string, bool line_break, |
| 3394 | bool pad, bool base64url) | 3396 | bool pad, bool base64url) |
| 3395 | { | 3397 | { |
| 3396 | ptrdiff_t allength, length, encoded_length; | 3398 | ptrdiff_t allength, length, encoded_length; |
| 3397 | char *encoded; | 3399 | char *encoded; |
| @@ -3508,9 +3510,7 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3508 | { | 3510 | { |
| 3509 | *e++ = b64_value_to_char[value]; | 3511 | *e++ = b64_value_to_char[value]; |
| 3510 | if (pad) | 3512 | if (pad) |
| 3511 | { | 3513 | *e++ = '='; |
| 3512 | *e++ = '='; | ||
| 3513 | } | ||
| 3514 | break; | 3514 | break; |
| 3515 | } | 3515 | } |
| 3516 | 3516 | ||
| @@ -4196,21 +4196,20 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) | |||
| 4196 | new_size); | 4196 | new_size); |
| 4197 | ptrdiff_t next_size = ASIZE (next); | 4197 | ptrdiff_t next_size = ASIZE (next); |
| 4198 | for (ptrdiff_t i = old_size; i < next_size - 1; i++) | 4198 | for (ptrdiff_t i = old_size; i < next_size - 1; i++) |
| 4199 | gc_aset (next, i, make_fixnum (i + 1)); | 4199 | ASET (next, i, make_fixnum (i + 1)); |
| 4200 | gc_aset (next, next_size - 1, make_fixnum (-1)); | 4200 | ASET (next, next_size - 1, make_fixnum (-1)); |
| 4201 | ptrdiff_t index_size = hash_index_size (h, next_size); | ||
| 4202 | 4201 | ||
| 4203 | /* Build the new&larger key_and_value vector, making sure the new | 4202 | /* Build the new&larger key_and_value vector, making sure the new |
| 4204 | fields are initialized to `unbound`. */ | 4203 | fields are initialized to `unbound`. */ |
| 4205 | Lisp_Object key_and_value | 4204 | Lisp_Object key_and_value |
| 4206 | = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size), | 4205 | = larger_vecalloc (h->key_and_value, 2 * (next_size - old_size), |
| 4207 | 2 * next_size); | 4206 | 2 * next_size); |
| 4208 | for (ptrdiff_t i = ASIZE (h->key_and_value); | 4207 | for (ptrdiff_t i = 2 * old_size; i < 2 * next_size; i++) |
| 4209 | i < ASIZE (key_and_value); i++) | ||
| 4210 | ASET (key_and_value, i, Qunbound); | 4208 | ASET (key_and_value, i, Qunbound); |
| 4211 | 4209 | ||
| 4212 | Lisp_Object hash = larger_vector (h->hash, next_size - old_size, | 4210 | Lisp_Object hash = larger_vector (h->hash, next_size - old_size, |
| 4213 | next_size); | 4211 | next_size); |
| 4212 | ptrdiff_t index_size = hash_index_size (h, next_size); | ||
| 4214 | h->index = make_vector (index_size, make_fixnum (-1)); | 4213 | h->index = make_vector (index_size, make_fixnum (-1)); |
| 4215 | h->key_and_value = key_and_value; | 4214 | h->key_and_value = key_and_value; |
| 4216 | h->hash = hash; | 4215 | h->hash = hash; |
| @@ -4402,17 +4401,17 @@ hash_clear (struct Lisp_Hash_Table *h) | |||
| 4402 | { | 4401 | { |
| 4403 | if (h->count > 0) | 4402 | if (h->count > 0) |
| 4404 | { | 4403 | { |
| 4405 | ptrdiff_t i, size = HASH_TABLE_SIZE (h); | 4404 | ptrdiff_t size = HASH_TABLE_SIZE (h); |
| 4406 | 4405 | if (!hash_rehash_needed_p (h)) | |
| 4407 | for (i = 0; i < size; ++i) | 4406 | memclear (XVECTOR (h->hash)->contents, size * word_size); |
| 4407 | for (ptrdiff_t i = 0; i < size; i++) | ||
| 4408 | { | 4408 | { |
| 4409 | set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); | 4409 | set_hash_next_slot (h, i, i < size - 1 ? i + 1 : -1); |
| 4410 | set_hash_key_slot (h, i, Qunbound); | 4410 | set_hash_key_slot (h, i, Qunbound); |
| 4411 | set_hash_value_slot (h, i, Qnil); | 4411 | set_hash_value_slot (h, i, Qnil); |
| 4412 | set_hash_hash_slot (h, i, Qnil); | ||
| 4413 | } | 4412 | } |
| 4414 | 4413 | ||
| 4415 | for (i = 0; i < ASIZE (h->index); ++i) | 4414 | for (ptrdiff_t i = 0; i < ASIZE (h->index); i++) |
| 4416 | ASET (h->index, i, make_fixnum (-1)); | 4415 | ASET (h->index, i, make_fixnum (-1)); |
| 4417 | 4416 | ||
| 4418 | h->next_free = 0; | 4417 | h->next_free = 0; |
| @@ -4640,13 +4639,14 @@ sxhash_bool_vector (Lisp_Object vec) | |||
| 4640 | /* Return a hash for a bignum. */ | 4639 | /* Return a hash for a bignum. */ |
| 4641 | 4640 | ||
| 4642 | static EMACS_UINT | 4641 | static EMACS_UINT |
| 4643 | sxhash_bignum (struct Lisp_Bignum *bignum) | 4642 | sxhash_bignum (Lisp_Object bignum) |
| 4644 | { | 4643 | { |
| 4645 | size_t i, nlimbs = mpz_size (bignum->value); | 4644 | mpz_t const *n = xbignum_val (bignum); |
| 4645 | size_t i, nlimbs = mpz_size (*n); | ||
| 4646 | EMACS_UINT hash = 0; | 4646 | EMACS_UINT hash = 0; |
| 4647 | 4647 | ||
| 4648 | for (i = 0; i < nlimbs; ++i) | 4648 | for (i = 0; i < nlimbs; ++i) |
| 4649 | hash = sxhash_combine (hash, mpz_getlimbn (bignum->value, i)); | 4649 | hash = sxhash_combine (hash, mpz_getlimbn (*n, i)); |
| 4650 | 4650 | ||
| 4651 | return SXHASH_REDUCE (hash); | 4651 | return SXHASH_REDUCE (hash); |
| 4652 | } | 4652 | } |
| @@ -4680,7 +4680,7 @@ sxhash (Lisp_Object obj, int depth) | |||
| 4680 | /* This can be everything from a vector to an overlay. */ | 4680 | /* This can be everything from a vector to an overlay. */ |
| 4681 | case Lisp_Vectorlike: | 4681 | case Lisp_Vectorlike: |
| 4682 | if (BIGNUMP (obj)) | 4682 | if (BIGNUMP (obj)) |
| 4683 | hash = sxhash_bignum (XBIGNUM (obj)); | 4683 | hash = sxhash_bignum (obj); |
| 4684 | else if (VECTORP (obj) || RECORDP (obj)) | 4684 | else if (VECTORP (obj) || RECORDP (obj)) |
| 4685 | /* According to the CL HyperSpec, two arrays are equal only if | 4685 | /* According to the CL HyperSpec, two arrays are equal only if |
| 4686 | they are `eq', except for strings and bit-vectors. In | 4686 | they are `eq', except for strings and bit-vectors. In |
diff --git a/src/font.c b/src/font.c index ce85e0bb4ad..935dd64e648 100644 --- a/src/font.c +++ b/src/font.c | |||
| @@ -5509,7 +5509,14 @@ and cannot switch to a smaller font for those characters, set | |||
| 5509 | this variable non-nil. | 5509 | this variable non-nil. |
| 5510 | Disabling compaction of font caches might enlarge the Emacs memory | 5510 | Disabling compaction of font caches might enlarge the Emacs memory |
| 5511 | footprint in sessions that use lots of different fonts. */); | 5511 | footprint in sessions that use lots of different fonts. */); |
| 5512 | |||
| 5513 | #ifdef WINDOWSNT | ||
| 5514 | /* Compacting font caches causes slow redisplay on Windows with many | ||
| 5515 | large fonts, so we disable it by default. */ | ||
| 5516 | inhibit_compacting_font_caches = 1; | ||
| 5517 | #else | ||
| 5512 | inhibit_compacting_font_caches = 0; | 5518 | inhibit_compacting_font_caches = 0; |
| 5519 | #endif | ||
| 5513 | 5520 | ||
| 5514 | DEFVAR_BOOL ("xft-ignore-color-fonts", | 5521 | DEFVAR_BOOL ("xft-ignore-color-fonts", |
| 5515 | Vxft_ignore_color_fonts, | 5522 | Vxft_ignore_color_fonts, |
diff --git a/src/frame.c b/src/frame.c index 50a7f138b81..1d42d0cb4de 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -3492,7 +3492,7 @@ DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_widt | |||
| 3492 | } | 3492 | } |
| 3493 | 3493 | ||
| 3494 | DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, | 3494 | DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, |
| 3495 | "(list (selected-frame) current-prefix-arg)", | 3495 | "(list (selected-frame) (prefix-numeric-value current-prefix-arg))", |
| 3496 | doc: /* Set text height of frame FRAME to HEIGHT lines. | 3496 | doc: /* Set text height of frame FRAME to HEIGHT lines. |
| 3497 | Optional third arg PRETEND non-nil means that redisplay should use | 3497 | Optional third arg PRETEND non-nil means that redisplay should use |
| 3498 | HEIGHT lines but that the idea of the actual height of the frame should | 3498 | HEIGHT lines but that the idea of the actual height of the frame should |
| @@ -3521,7 +3521,7 @@ currenly selected frame will be set to this height. */) | |||
| 3521 | } | 3521 | } |
| 3522 | 3522 | ||
| 3523 | DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, | 3523 | DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, |
| 3524 | "(list (selected-frame) current-prefix-arg)", | 3524 | "(list (selected-frame) (prefix-numeric-value current-prefix-arg))", |
| 3525 | doc: /* Set text width of frame FRAME to WIDTH columns. | 3525 | doc: /* Set text width of frame FRAME to WIDTH columns. |
| 3526 | Optional third arg PRETEND non-nil means that redisplay should use WIDTH | 3526 | Optional third arg PRETEND non-nil means that redisplay should use WIDTH |
| 3527 | columns but that the idea of the actual width of the frame should not | 3527 | columns but that the idea of the actual width of the frame should not |
| @@ -5327,9 +5327,11 @@ or a list (- N) meaning -N pixels relative to bottom/right corner. | |||
| 5327 | On Nextstep, this just calls `ns-parse-geometry'. */) | 5327 | On Nextstep, this just calls `ns-parse-geometry'. */) |
| 5328 | (Lisp_Object string) | 5328 | (Lisp_Object string) |
| 5329 | { | 5329 | { |
| 5330 | int geometry, x, y; | 5330 | /* x and y don't need initialization, as they are not accessed |
| 5331 | unless XParseGeometry sets them, in which case it always returns | ||
| 5332 | a non-zero value. */ | ||
| 5333 | int x UNINIT, y UNINIT; | ||
| 5331 | unsigned int width, height; | 5334 | unsigned int width, height; |
| 5332 | Lisp_Object result; | ||
| 5333 | 5335 | ||
| 5334 | CHECK_STRING (string); | 5336 | CHECK_STRING (string); |
| 5335 | 5337 | ||
| @@ -5337,9 +5339,9 @@ On Nextstep, this just calls `ns-parse-geometry'. */) | |||
| 5337 | if (strchr (SSDATA (string), ' ') != NULL) | 5339 | if (strchr (SSDATA (string), ' ') != NULL) |
| 5338 | return call1 (Qns_parse_geometry, string); | 5340 | return call1 (Qns_parse_geometry, string); |
| 5339 | #endif | 5341 | #endif |
| 5340 | geometry = XParseGeometry (SSDATA (string), | 5342 | int geometry = XParseGeometry (SSDATA (string), |
| 5341 | &x, &y, &width, &height); | 5343 | &x, &y, &width, &height); |
| 5342 | result = Qnil; | 5344 | Lisp_Object result = Qnil; |
| 5343 | if (geometry & XValue) | 5345 | if (geometry & XValue) |
| 5344 | { | 5346 | { |
| 5345 | Lisp_Object element; | 5347 | Lisp_Object element; |
diff --git a/src/ftfont.c b/src/ftfont.c index 16b18de6867..77a4cf5de5c 100644 --- a/src/ftfont.c +++ b/src/ftfont.c | |||
| @@ -433,7 +433,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for) | |||
| 433 | return cache; | 433 | return cache; |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | FcCharSet * | 436 | static FcCharSet * |
| 437 | ftfont_get_fc_charset (Lisp_Object entity) | 437 | ftfont_get_fc_charset (Lisp_Object entity) |
| 438 | { | 438 | { |
| 439 | Lisp_Object val, cache; | 439 | Lisp_Object val, cache; |
diff --git a/src/ftfont.h b/src/ftfont.h index b2280e9aab9..f771dc159b0 100644 --- a/src/ftfont.h +++ b/src/ftfont.h | |||
| @@ -41,7 +41,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 41 | #endif /* HAVE_M17N_FLT */ | 41 | #endif /* HAVE_M17N_FLT */ |
| 42 | #endif /* HAVE_LIBOTF */ | 42 | #endif /* HAVE_LIBOTF */ |
| 43 | 43 | ||
| 44 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); | ||
| 45 | extern void ftfont_fix_match (FcPattern *, FcPattern *); | 44 | extern void ftfont_fix_match (FcPattern *, FcPattern *); |
| 46 | extern void ftfont_add_rendering_parameters (FcPattern *, Lisp_Object); | 45 | extern void ftfont_add_rendering_parameters (FcPattern *, Lisp_Object); |
| 47 | extern FcPattern *ftfont_entity_pattern (Lisp_Object, int); | 46 | extern FcPattern *ftfont_entity_pattern (Lisp_Object, int); |
diff --git a/src/gnutls.c b/src/gnutls.c index 267ba9aba35..d43534b5ae1 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -44,6 +44,14 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 44 | # define HAVE_GNUTLS_EXT__DUMBFW | 44 | # define HAVE_GNUTLS_EXT__DUMBFW |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | #if GNUTLS_VERSION_NUMBER >= 0x030400 | ||
| 48 | # define HAVE_GNUTLS_ETM_STATUS | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #if GNUTLS_VERSION_NUMBER < 0x030600 | ||
| 52 | # define HAVE_GNUTLS_COMPRESSION_GET | ||
| 53 | #endif | ||
| 54 | |||
| 47 | /* gnutls_mac_get_nonce_size was added in GnuTLS 3.2.0, but was | 55 | /* gnutls_mac_get_nonce_size was added in GnuTLS 3.2.0, but was |
| 48 | exported only since 3.3.0. */ | 56 | exported only since 3.3.0. */ |
| 49 | #if GNUTLS_VERSION_NUMBER >= 0x030300 | 57 | #if GNUTLS_VERSION_NUMBER >= 0x030300 |
| @@ -159,6 +167,8 @@ DEF_DLL_FN (int, gnutls_x509_crt_check_hostname, | |||
| 159 | DEF_DLL_FN (int, gnutls_x509_crt_check_issuer, | 167 | DEF_DLL_FN (int, gnutls_x509_crt_check_issuer, |
| 160 | (gnutls_x509_crt_t, gnutls_x509_crt_t)); | 168 | (gnutls_x509_crt_t, gnutls_x509_crt_t)); |
| 161 | DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t)); | 169 | DEF_DLL_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t)); |
| 170 | DEF_DLL_FN (int, gnutls_x509_crt_export, | ||
| 171 | (gnutls_x509_crt_t, gnutls_x509_crt_fmt_t, void *, size_t *)); | ||
| 162 | DEF_DLL_FN (int, gnutls_x509_crt_import, | 172 | DEF_DLL_FN (int, gnutls_x509_crt_import, |
| 163 | (gnutls_x509_crt_t, const gnutls_datum_t *, | 173 | (gnutls_x509_crt_t, const gnutls_datum_t *, |
| 164 | gnutls_x509_crt_fmt_t)); | 174 | gnutls_x509_crt_fmt_t)); |
| @@ -180,6 +190,9 @@ DEF_DLL_FN (int, gnutls_x509_crt_get_dn, | |||
| 180 | (gnutls_x509_crt_t, char *, size_t *)); | 190 | (gnutls_x509_crt_t, char *, size_t *)); |
| 181 | DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm, | 191 | DEF_DLL_FN (int, gnutls_x509_crt_get_pk_algorithm, |
| 182 | (gnutls_x509_crt_t, unsigned int *)); | 192 | (gnutls_x509_crt_t, unsigned int *)); |
| 193 | DEF_DLL_FN (int, gnutls_x509_crt_print, | ||
| 194 | (gnutls_x509_crt_t, gnutls_certificate_print_formats_t, | ||
| 195 | gnutls_datum_t *)); | ||
| 183 | DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name, | 196 | DEF_DLL_FN (const char *, gnutls_pk_algorithm_get_name, |
| 184 | (gnutls_pk_algorithm_t)); | 197 | (gnutls_pk_algorithm_t)); |
| 185 | DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param, | 198 | DEF_DLL_FN (int, gnutls_pk_bits_to_sec_param, |
| @@ -208,6 +221,13 @@ DEF_DLL_FN (const char *, gnutls_cipher_get_name, | |||
| 208 | (gnutls_cipher_algorithm_t)); | 221 | (gnutls_cipher_algorithm_t)); |
| 209 | DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t)); | 222 | DEF_DLL_FN (gnutls_mac_algorithm_t, gnutls_mac_get, (gnutls_session_t)); |
| 210 | DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t)); | 223 | DEF_DLL_FN (const char *, gnutls_mac_get_name, (gnutls_mac_algorithm_t)); |
| 224 | #ifdef HAVE_GNUTLS_COMPRESSION_GET | ||
| 225 | DEF_DLL_FN (gnutls_compression_method_t, gnutls_compression_get, | ||
| 226 | (gnutls_session_t)); | ||
| 227 | DEF_DLL_FN (const char *, gnutls_compression_get_name, | ||
| 228 | (gnutls_compression_method_t)); | ||
| 229 | #endif | ||
| 230 | DEF_DLL_FN (unsigned, gnutls_safe_renegotiation_status, (gnutls_session_t)); | ||
| 211 | 231 | ||
| 212 | # ifdef HAVE_GNUTLS3 | 232 | # ifdef HAVE_GNUTLS3 |
| 213 | DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t)); | 233 | DEF_DLL_FN (int, gnutls_rnd, (gnutls_rnd_level_t, void *, size_t)); |
| @@ -250,6 +270,9 @@ DEF_DLL_FN (int, gnutls_aead_cipher_decrypt, | |||
| 250 | (gnutls_aead_cipher_hd_t, const void *, size_t, const void *, | 270 | (gnutls_aead_cipher_hd_t, const void *, size_t, const void *, |
| 251 | size_t, size_t, const void *, size_t, void *, size_t *)); | 271 | size_t, size_t, const void *, size_t, void *, size_t *)); |
| 252 | # endif | 272 | # endif |
| 273 | # ifdef HAVE_GNUTLS_ETM_STATUS | ||
| 274 | DEF_DLL_FN (unsigned, gnutls_session_etm_status, (gnutls_session_t)); | ||
| 275 | # endif | ||
| 253 | DEF_DLL_FN (int, gnutls_hmac_init, | 276 | DEF_DLL_FN (int, gnutls_hmac_init, |
| 254 | (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t)); | 277 | (gnutls_hmac_hd_t *, gnutls_mac_algorithm_t, const void *, size_t)); |
| 255 | DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t)); | 278 | DEF_DLL_FN (int, gnutls_hmac_get_len, (gnutls_mac_algorithm_t)); |
| @@ -267,6 +290,7 @@ DEF_DLL_FN (const char *, gnutls_ext_get_name, (unsigned int)); | |||
| 267 | # endif | 290 | # endif |
| 268 | # endif /* HAVE_GNUTLS3 */ | 291 | # endif /* HAVE_GNUTLS3 */ |
| 269 | 292 | ||
| 293 | static gnutls_free_function *gnutls_free_func; | ||
| 270 | 294 | ||
| 271 | static bool | 295 | static bool |
| 272 | init_gnutls_functions (void) | 296 | init_gnutls_functions (void) |
| @@ -322,6 +346,7 @@ init_gnutls_functions (void) | |||
| 322 | LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname); | 346 | LOAD_DLL_FN (library, gnutls_x509_crt_check_hostname); |
| 323 | LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer); | 347 | LOAD_DLL_FN (library, gnutls_x509_crt_check_issuer); |
| 324 | LOAD_DLL_FN (library, gnutls_x509_crt_deinit); | 348 | LOAD_DLL_FN (library, gnutls_x509_crt_deinit); |
| 349 | LOAD_DLL_FN (library, gnutls_x509_crt_export); | ||
| 325 | LOAD_DLL_FN (library, gnutls_x509_crt_import); | 350 | LOAD_DLL_FN (library, gnutls_x509_crt_import); |
| 326 | LOAD_DLL_FN (library, gnutls_x509_crt_init); | 351 | LOAD_DLL_FN (library, gnutls_x509_crt_init); |
| 327 | LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint); | 352 | LOAD_DLL_FN (library, gnutls_x509_crt_get_fingerprint); |
| @@ -332,6 +357,7 @@ init_gnutls_functions (void) | |||
| 332 | LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time); | 357 | LOAD_DLL_FN (library, gnutls_x509_crt_get_expiration_time); |
| 333 | LOAD_DLL_FN (library, gnutls_x509_crt_get_dn); | 358 | LOAD_DLL_FN (library, gnutls_x509_crt_get_dn); |
| 334 | LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm); | 359 | LOAD_DLL_FN (library, gnutls_x509_crt_get_pk_algorithm); |
| 360 | LOAD_DLL_FN (library, gnutls_x509_crt_print); | ||
| 335 | LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name); | 361 | LOAD_DLL_FN (library, gnutls_pk_algorithm_get_name); |
| 336 | LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param); | 362 | LOAD_DLL_FN (library, gnutls_pk_bits_to_sec_param); |
| 337 | LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id); | 363 | LOAD_DLL_FN (library, gnutls_x509_crt_get_issuer_unique_id); |
| @@ -349,6 +375,11 @@ init_gnutls_functions (void) | |||
| 349 | LOAD_DLL_FN (library, gnutls_cipher_get_name); | 375 | LOAD_DLL_FN (library, gnutls_cipher_get_name); |
| 350 | LOAD_DLL_FN (library, gnutls_mac_get); | 376 | LOAD_DLL_FN (library, gnutls_mac_get); |
| 351 | LOAD_DLL_FN (library, gnutls_mac_get_name); | 377 | LOAD_DLL_FN (library, gnutls_mac_get_name); |
| 378 | # ifdef HAVE_GNUTLS_COMPRESSION_GET | ||
| 379 | LOAD_DLL_FN (library, gnutls_compression_get); | ||
| 380 | LOAD_DLL_FN (library, gnutls_compression_get_name); | ||
| 381 | # endif | ||
| 382 | LOAD_DLL_FN (library, gnutls_safe_renegotiation_status); | ||
| 352 | # ifdef HAVE_GNUTLS3 | 383 | # ifdef HAVE_GNUTLS3 |
| 353 | LOAD_DLL_FN (library, gnutls_rnd); | 384 | LOAD_DLL_FN (library, gnutls_rnd); |
| 354 | LOAD_DLL_FN (library, gnutls_mac_list); | 385 | LOAD_DLL_FN (library, gnutls_mac_list); |
| @@ -380,6 +411,9 @@ init_gnutls_functions (void) | |||
| 380 | LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt); | 411 | LOAD_DLL_FN (library, gnutls_aead_cipher_encrypt); |
| 381 | LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt); | 412 | LOAD_DLL_FN (library, gnutls_aead_cipher_decrypt); |
| 382 | # endif | 413 | # endif |
| 414 | # ifdef HAVE_GNUTLS_ETM_STATUS | ||
| 415 | LOAD_DLL_FN (library, gnutls_session_etm_status); | ||
| 416 | # endif | ||
| 383 | LOAD_DLL_FN (library, gnutls_hmac_init); | 417 | LOAD_DLL_FN (library, gnutls_hmac_init); |
| 384 | LOAD_DLL_FN (library, gnutls_hmac_get_len); | 418 | LOAD_DLL_FN (library, gnutls_hmac_get_len); |
| 385 | LOAD_DLL_FN (library, gnutls_hmac); | 419 | LOAD_DLL_FN (library, gnutls_hmac); |
| @@ -395,6 +429,13 @@ init_gnutls_functions (void) | |||
| 395 | # endif | 429 | # endif |
| 396 | # endif /* HAVE_GNUTLS3 */ | 430 | # endif /* HAVE_GNUTLS3 */ |
| 397 | 431 | ||
| 432 | /* gnutls_free is a variable inside GnuTLS, whose value is the | ||
| 433 | "free" function. So it needs special handling. */ | ||
| 434 | gnutls_free_func = (gnutls_free_function *) GetProcAddress (library, | ||
| 435 | "gnutls_free"); | ||
| 436 | if (!gnutls_free_func) | ||
| 437 | return false; | ||
| 438 | |||
| 398 | max_log_level = clip_to_bounds (INT_MIN, global_gnutls_log_level, INT_MAX); | 439 | max_log_level = clip_to_bounds (INT_MIN, global_gnutls_log_level, INT_MAX); |
| 399 | { | 440 | { |
| 400 | Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from)); | 441 | Lisp_Object name = CAR_SAFE (Fget (Qgnutls, QCloaded_from)); |
| @@ -437,6 +478,11 @@ init_gnutls_functions (void) | |||
| 437 | # define gnutls_kx_get_name fn_gnutls_kx_get_name | 478 | # define gnutls_kx_get_name fn_gnutls_kx_get_name |
| 438 | # define gnutls_mac_get fn_gnutls_mac_get | 479 | # define gnutls_mac_get fn_gnutls_mac_get |
| 439 | # define gnutls_mac_get_name fn_gnutls_mac_get_name | 480 | # define gnutls_mac_get_name fn_gnutls_mac_get_name |
| 481 | # ifdef HAVE_GNUTLS_COMPRESSION_GET | ||
| 482 | # define gnutls_compression_get fn_gnutls_compression_get | ||
| 483 | # define gnutls_compression_get_name fn_gnutls_compression_get_name | ||
| 484 | # endif | ||
| 485 | # define gnutls_safe_renegotiation_status fn_gnutls_safe_renegotiation_status | ||
| 440 | # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name | 486 | # define gnutls_pk_algorithm_get_name fn_gnutls_pk_algorithm_get_name |
| 441 | # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param | 487 | # define gnutls_pk_bits_to_sec_param fn_gnutls_pk_bits_to_sec_param |
| 442 | # define gnutls_priority_set_direct fn_gnutls_priority_set_direct | 488 | # define gnutls_priority_set_direct fn_gnutls_priority_set_direct |
| @@ -456,6 +502,7 @@ init_gnutls_functions (void) | |||
| 456 | # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname | 502 | # define gnutls_x509_crt_check_hostname fn_gnutls_x509_crt_check_hostname |
| 457 | # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer | 503 | # define gnutls_x509_crt_check_issuer fn_gnutls_x509_crt_check_issuer |
| 458 | # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit | 504 | # define gnutls_x509_crt_deinit fn_gnutls_x509_crt_deinit |
| 505 | # define gnutls_x509_crt_export fn_gnutls_x509_crt_export | ||
| 459 | # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time | 506 | # define gnutls_x509_crt_get_activation_time fn_gnutls_x509_crt_get_activation_time |
| 460 | # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn | 507 | # define gnutls_x509_crt_get_dn fn_gnutls_x509_crt_get_dn |
| 461 | # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time | 508 | # define gnutls_x509_crt_get_expiration_time fn_gnutls_x509_crt_get_expiration_time |
| @@ -464,6 +511,7 @@ init_gnutls_functions (void) | |||
| 464 | # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id | 511 | # define gnutls_x509_crt_get_issuer_unique_id fn_gnutls_x509_crt_get_issuer_unique_id |
| 465 | # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id | 512 | # define gnutls_x509_crt_get_key_id fn_gnutls_x509_crt_get_key_id |
| 466 | # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm | 513 | # define gnutls_x509_crt_get_pk_algorithm fn_gnutls_x509_crt_get_pk_algorithm |
| 514 | # define gnutls_x509_crt_print fn_gnutls_x509_crt_print | ||
| 467 | # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial | 515 | # define gnutls_x509_crt_get_serial fn_gnutls_x509_crt_get_serial |
| 468 | # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm | 516 | # define gnutls_x509_crt_get_signature_algorithm fn_gnutls_x509_crt_get_signature_algorithm |
| 469 | # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id | 517 | # define gnutls_x509_crt_get_subject_unique_id fn_gnutls_x509_crt_get_subject_unique_id |
| @@ -501,6 +549,9 @@ init_gnutls_functions (void) | |||
| 501 | # define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init | 549 | # define gnutls_aead_cipher_init fn_gnutls_aead_cipher_init |
| 502 | # define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit | 550 | # define gnutls_aead_cipher_deinit fn_gnutls_aead_cipher_deinit |
| 503 | # endif | 551 | # endif |
| 552 | # ifdef HAVE_GNUTLS_ETM_STATUS | ||
| 553 | # define gnutls_session_etm_status fn_gnutls_session_etm_status | ||
| 554 | # endif | ||
| 504 | # define gnutls_hmac_init fn_gnutls_hmac_init | 555 | # define gnutls_hmac_init fn_gnutls_hmac_init |
| 505 | # define gnutls_hmac_get_len fn_gnutls_hmac_get_len | 556 | # define gnutls_hmac_get_len fn_gnutls_hmac_get_len |
| 506 | # define gnutls_hmac fn_gnutls_hmac | 557 | # define gnutls_hmac fn_gnutls_hmac |
| @@ -516,6 +567,11 @@ init_gnutls_functions (void) | |||
| 516 | # endif | 567 | # endif |
| 517 | # endif /* HAVE_GNUTLS3 */ | 568 | # endif /* HAVE_GNUTLS3 */ |
| 518 | 569 | ||
| 570 | /* gnutls_free_func is a data pointer to a variable which holds an | ||
| 571 | address of a function. We use #undef because MinGW64 defines | ||
| 572 | gnutls_free as a macro as well in the GnuTLS headers. */ | ||
| 573 | # undef gnutls_free | ||
| 574 | # define gnutls_free (*gnutls_free_func) | ||
| 519 | 575 | ||
| 520 | /* This wrapper is called from fns.c, which doesn't know about the | 576 | /* This wrapper is called from fns.c, which doesn't know about the |
| 521 | LOAD_DLL_FN stuff above. */ | 577 | LOAD_DLL_FN stuff above. */ |
| @@ -1041,7 +1097,35 @@ gnutls_hex_string (unsigned char *buf, ptrdiff_t buf_size, const char *prefix) | |||
| 1041 | } | 1097 | } |
| 1042 | 1098 | ||
| 1043 | static Lisp_Object | 1099 | static Lisp_Object |
| 1044 | gnutls_certificate_details (gnutls_x509_crt_t cert) | 1100 | emacs_gnutls_certificate_export_pem (gnutls_x509_crt_t cert) |
| 1101 | { | ||
| 1102 | size_t size = 0; | ||
| 1103 | int err = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, NULL, &size); | ||
| 1104 | check_memory_full (err); | ||
| 1105 | |||
| 1106 | if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) | ||
| 1107 | { | ||
| 1108 | USE_SAFE_ALLOCA; | ||
| 1109 | char *buf = SAFE_ALLOCA (size); | ||
| 1110 | err = gnutls_x509_crt_export (cert, GNUTLS_X509_FMT_PEM, buf, &size); | ||
| 1111 | check_memory_full (err); | ||
| 1112 | |||
| 1113 | if (err < GNUTLS_E_SUCCESS) | ||
| 1114 | error ("GnuTLS certificate export error: %s", | ||
| 1115 | emacs_gnutls_strerror (err)); | ||
| 1116 | |||
| 1117 | Lisp_Object result = build_string (buf); | ||
| 1118 | SAFE_FREE (); | ||
| 1119 | return result; | ||
| 1120 | } | ||
| 1121 | else if (err < GNUTLS_E_SUCCESS) | ||
| 1122 | error ("GnuTLS certificate export error: %s", emacs_gnutls_strerror (err)); | ||
| 1123 | |||
| 1124 | return Qnil; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static Lisp_Object | ||
| 1128 | emacs_gnutls_certificate_details (gnutls_x509_crt_t cert) | ||
| 1045 | { | 1129 | { |
| 1046 | Lisp_Object res = Qnil; | 1130 | Lisp_Object res = Qnil; |
| 1047 | int err; | 1131 | int err; |
| @@ -1209,6 +1293,10 @@ gnutls_certificate_details (gnutls_x509_crt_t cert) | |||
| 1209 | xfree (buf); | 1293 | xfree (buf); |
| 1210 | } | 1294 | } |
| 1211 | 1295 | ||
| 1296 | /* PEM */ | ||
| 1297 | res = nconc2 (res, list2 (intern (":pem"), | ||
| 1298 | emacs_gnutls_certificate_export_pem(cert))); | ||
| 1299 | |||
| 1212 | return res; | 1300 | return res; |
| 1213 | } | 1301 | } |
| 1214 | 1302 | ||
| @@ -1246,6 +1334,29 @@ DEFUN ("gnutls-peer-status-warning-describe", Fgnutls_peer_status_warning_descri | |||
| 1246 | if (EQ (status_symbol, intern (":no-host-match"))) | 1334 | if (EQ (status_symbol, intern (":no-host-match"))) |
| 1247 | return build_string ("certificate host does not match hostname"); | 1335 | return build_string ("certificate host does not match hostname"); |
| 1248 | 1336 | ||
| 1337 | if (EQ (status_symbol, intern (":signature-failure"))) | ||
| 1338 | return build_string ("certificate signature could not be verified"); | ||
| 1339 | |||
| 1340 | if (EQ (status_symbol, intern (":revocation-data-superseded"))) | ||
| 1341 | return build_string ("certificate revocation data are old and have been " | ||
| 1342 | "superseded"); | ||
| 1343 | |||
| 1344 | if (EQ (status_symbol, intern (":revocation-data-issued-in-future"))) | ||
| 1345 | return build_string ("certificate revocation data have a future issue date"); | ||
| 1346 | |||
| 1347 | if (EQ (status_symbol, intern (":signer-constraints-failure"))) | ||
| 1348 | return build_string ("certificate signer constraints were violated"); | ||
| 1349 | |||
| 1350 | if (EQ (status_symbol, intern (":purpose-mismatch"))) | ||
| 1351 | return build_string ("certificate does not match the intended purpose"); | ||
| 1352 | |||
| 1353 | if (EQ (status_symbol, intern (":missing-ocsp-status"))) | ||
| 1354 | return build_string ("certificate requires the server to send a OCSP " | ||
| 1355 | "certificate status, but no status was received"); | ||
| 1356 | |||
| 1357 | if (EQ (status_symbol, intern (":invalid-ocsp-status"))) | ||
| 1358 | return build_string ("the received OCSP certificate status is invalid"); | ||
| 1359 | |||
| 1249 | return Qnil; | 1360 | return Qnil; |
| 1250 | } | 1361 | } |
| 1251 | 1362 | ||
| @@ -1297,6 +1408,35 @@ returned as the :certificate entry. */) | |||
| 1297 | if (verification & GNUTLS_CERT_EXPIRED) | 1408 | if (verification & GNUTLS_CERT_EXPIRED) |
| 1298 | warnings = Fcons (intern (":expired"), warnings); | 1409 | warnings = Fcons (intern (":expired"), warnings); |
| 1299 | 1410 | ||
| 1411 | #if GNUTLS_VERSION_NUMBER >= 0x030100 | ||
| 1412 | if (verification & GNUTLS_CERT_SIGNATURE_FAILURE) | ||
| 1413 | warnings = Fcons (intern (":signature-failure"), warnings); | ||
| 1414 | |||
| 1415 | # if GNUTLS_VERSION_NUMBER >= 0x030114 | ||
| 1416 | if (verification & GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED) | ||
| 1417 | warnings = Fcons (intern (":revocation-data-superseded"), warnings); | ||
| 1418 | |||
| 1419 | if (verification & GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE) | ||
| 1420 | warnings = Fcons (intern (":revocation-data-issued-in-future"), warnings); | ||
| 1421 | |||
| 1422 | if (verification & GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE) | ||
| 1423 | warnings = Fcons (intern (":signer-constraints-failure"), warnings); | ||
| 1424 | |||
| 1425 | # if GNUTLS_VERSION_NUMBER >= 0x030400 | ||
| 1426 | if (verification & GNUTLS_CERT_PURPOSE_MISMATCH) | ||
| 1427 | warnings = Fcons (intern (":purpose-mismatch"), warnings); | ||
| 1428 | |||
| 1429 | # if GNUTLS_VERSION_NUMBER >= 0x030501 | ||
| 1430 | if (verification & GNUTLS_CERT_MISSING_OCSP_STATUS) | ||
| 1431 | warnings = Fcons (intern (":missing-ocsp-status"), warnings); | ||
| 1432 | |||
| 1433 | if (verification & GNUTLS_CERT_INVALID_OCSP_STATUS) | ||
| 1434 | warnings = Fcons (intern (":invalid-ocsp-status"), warnings); | ||
| 1435 | # endif | ||
| 1436 | # endif | ||
| 1437 | # endif | ||
| 1438 | #endif | ||
| 1439 | |||
| 1300 | if (XPROCESS (proc)->gnutls_extra_peer_verification & | 1440 | if (XPROCESS (proc)->gnutls_extra_peer_verification & |
| 1301 | CERTIFICATE_NOT_MATCHING) | 1441 | CERTIFICATE_NOT_MATCHING) |
| 1302 | warnings = Fcons (intern (":no-host-match"), warnings); | 1442 | warnings = Fcons (intern (":no-host-match"), warnings); |
| @@ -1319,7 +1459,7 @@ returned as the :certificate entry. */) | |||
| 1319 | 1459 | ||
| 1320 | /* Return all the certificates in a list. */ | 1460 | /* Return all the certificates in a list. */ |
| 1321 | for (int i = 0; i < XPROCESS (proc)->gnutls_certificates_length; i++) | 1461 | for (int i = 0; i < XPROCESS (proc)->gnutls_certificates_length; i++) |
| 1322 | certs = nconc2 (certs, list1 (gnutls_certificate_details | 1462 | certs = nconc2 (certs, list1 (emacs_gnutls_certificate_details |
| 1323 | (XPROCESS (proc)->gnutls_certificates[i]))); | 1463 | (XPROCESS (proc)->gnutls_certificates[i]))); |
| 1324 | 1464 | ||
| 1325 | result = nconc2 (result, list2 (intern (":certificates"), certs)); | 1465 | result = nconc2 (result, list2 (intern (":certificates"), certs)); |
| @@ -1347,10 +1487,10 @@ returned as the :certificate entry. */) | |||
| 1347 | (gnutls_kx_get (state))))); | 1487 | (gnutls_kx_get (state))))); |
| 1348 | 1488 | ||
| 1349 | /* Protocol name. */ | 1489 | /* Protocol name. */ |
| 1490 | gnutls_protocol_t proto = gnutls_protocol_get_version (state); | ||
| 1350 | result = nconc2 | 1491 | result = nconc2 |
| 1351 | (result, list2 (intern (":protocol"), | 1492 | (result, list2 (intern (":protocol"), |
| 1352 | build_string (gnutls_protocol_get_name | 1493 | build_string (gnutls_protocol_get_name (proto)))); |
| 1353 | (gnutls_protocol_get_version (state))))); | ||
| 1354 | 1494 | ||
| 1355 | /* Cipher name. */ | 1495 | /* Cipher name. */ |
| 1356 | result = nconc2 | 1496 | result = nconc2 |
| @@ -1364,6 +1504,26 @@ returned as the :certificate entry. */) | |||
| 1364 | build_string (gnutls_mac_get_name | 1504 | build_string (gnutls_mac_get_name |
| 1365 | (gnutls_mac_get (state))))); | 1505 | (gnutls_mac_get (state))))); |
| 1366 | 1506 | ||
| 1507 | /* Compression name. */ | ||
| 1508 | #ifdef HAVE_GNUTLS_COMPRESSION_GET | ||
| 1509 | result = nconc2 | ||
| 1510 | (result, list2 (intern (":compression"), | ||
| 1511 | build_string (gnutls_compression_get_name | ||
| 1512 | (gnutls_compression_get (state))))); | ||
| 1513 | #endif | ||
| 1514 | |||
| 1515 | /* Encrypt-then-MAC. */ | ||
| 1516 | #ifdef HAVE_GNUTLS_ETM_STATUS | ||
| 1517 | result = nconc2 | ||
| 1518 | (result, list2 (intern (":encrypt-then-mac"), | ||
| 1519 | gnutls_session_etm_status (state) ? Qt : Qnil)); | ||
| 1520 | #endif | ||
| 1521 | |||
| 1522 | /* Renegotiation Indication */ | ||
| 1523 | if (proto <= GNUTLS_TLS1_2) | ||
| 1524 | result = nconc2 | ||
| 1525 | (result, list2 (intern (":safe-renegotiation"), | ||
| 1526 | gnutls_safe_renegotiation_status (state) ? Qt : Qnil)); | ||
| 1367 | 1527 | ||
| 1368 | return result; | 1528 | return result; |
| 1369 | } | 1529 | } |
| @@ -1425,6 +1585,52 @@ boot_error (struct Lisp_Process *p, const char *m, ...) | |||
| 1425 | va_end (ap); | 1585 | va_end (ap); |
| 1426 | } | 1586 | } |
| 1427 | 1587 | ||
| 1588 | DEFUN ("gnutls-format-certificate", Fgnutls_format_certificate, | ||
| 1589 | Sgnutls_format_certificate, 1, 1, 0, | ||
| 1590 | doc: /* Format a X.509 certificate to a string. | ||
| 1591 | |||
| 1592 | Given a PEM-encoded X.509 certificate CERT, returns a human-readable | ||
| 1593 | string representation. */) | ||
| 1594 | (Lisp_Object cert) | ||
| 1595 | { | ||
| 1596 | CHECK_STRING (cert); | ||
| 1597 | |||
| 1598 | int err; | ||
| 1599 | gnutls_x509_crt_t crt; | ||
| 1600 | |||
| 1601 | err = gnutls_x509_crt_init (&crt); | ||
| 1602 | check_memory_full (err); | ||
| 1603 | if (err < GNUTLS_E_SUCCESS) | ||
| 1604 | error ("gnutls-format-certificate error: %s", emacs_gnutls_strerror (err)); | ||
| 1605 | |||
| 1606 | gnutls_datum_t crt_data = { SDATA (cert), strlen (SSDATA (cert)) }; | ||
| 1607 | err = gnutls_x509_crt_import (crt, &crt_data, GNUTLS_X509_FMT_PEM); | ||
| 1608 | check_memory_full (err); | ||
| 1609 | if (err < GNUTLS_E_SUCCESS) | ||
| 1610 | { | ||
| 1611 | gnutls_x509_crt_deinit (crt); | ||
| 1612 | error ("gnutls-format-certificate error: %s", | ||
| 1613 | emacs_gnutls_strerror (err)); | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | gnutls_datum_t out; | ||
| 1617 | err = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &out); | ||
| 1618 | check_memory_full (err); | ||
| 1619 | if (err < GNUTLS_E_SUCCESS) | ||
| 1620 | { | ||
| 1621 | gnutls_x509_crt_deinit (crt); | ||
| 1622 | error ("gnutls-format-certificate error: %s", | ||
| 1623 | emacs_gnutls_strerror (err)); | ||
| 1624 | } | ||
| 1625 | |||
| 1626 | Lisp_Object result = make_string_from_bytes ((char *) out.data, out.size, | ||
| 1627 | out.size); | ||
| 1628 | gnutls_free (out.data); | ||
| 1629 | gnutls_x509_crt_deinit (crt); | ||
| 1630 | |||
| 1631 | return result; | ||
| 1632 | } | ||
| 1633 | |||
| 1428 | Lisp_Object | 1634 | Lisp_Object |
| 1429 | gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist) | 1635 | gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist) |
| 1430 | { | 1636 | { |
| @@ -2706,6 +2912,7 @@ syms_of_gnutls (void) | |||
| 2706 | defsubr (&Sgnutls_bye); | 2912 | defsubr (&Sgnutls_bye); |
| 2707 | defsubr (&Sgnutls_peer_status); | 2913 | defsubr (&Sgnutls_peer_status); |
| 2708 | defsubr (&Sgnutls_peer_status_warning_describe); | 2914 | defsubr (&Sgnutls_peer_status_warning_describe); |
| 2915 | defsubr (&Sgnutls_format_certificate); | ||
| 2709 | 2916 | ||
| 2710 | #ifdef HAVE_GNUTLS3 | 2917 | #ifdef HAVE_GNUTLS3 |
| 2711 | defsubr (&Sgnutls_ciphers); | 2918 | defsubr (&Sgnutls_ciphers); |
diff --git a/src/image.c b/src/image.c index 81d8cb4e2b2..fe7bd90b051 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -6234,7 +6234,10 @@ DEF_DLL_FN (void, png_read_info, (png_structp, png_infop)); | |||
| 6234 | DEF_DLL_FN (png_uint_32, png_get_IHDR, | 6234 | DEF_DLL_FN (png_uint_32, png_get_IHDR, |
| 6235 | (png_structp, png_infop, png_uint_32 *, png_uint_32 *, | 6235 | (png_structp, png_infop, png_uint_32 *, png_uint_32 *, |
| 6236 | int *, int *, int *, int *, int *)); | 6236 | int *, int *, int *, int *, int *)); |
| 6237 | DEF_DLL_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32)); | 6237 | # ifdef PNG_tRNS_SUPPORTED |
| 6238 | DEF_DLL_FN (png_uint_32, png_get_tRNS, (png_structp, png_infop, png_bytep *, | ||
| 6239 | int *, png_color_16p *)); | ||
| 6240 | # endif | ||
| 6238 | DEF_DLL_FN (void, png_set_strip_16, (png_structp)); | 6241 | DEF_DLL_FN (void, png_set_strip_16, (png_structp)); |
| 6239 | DEF_DLL_FN (void, png_set_expand, (png_structp)); | 6242 | DEF_DLL_FN (void, png_set_expand, (png_structp)); |
| 6240 | DEF_DLL_FN (void, png_set_gray_to_rgb, (png_structp)); | 6243 | DEF_DLL_FN (void, png_set_gray_to_rgb, (png_structp)); |
| @@ -6273,7 +6276,9 @@ init_png_functions (void) | |||
| 6273 | LOAD_DLL_FN (library, png_set_sig_bytes); | 6276 | LOAD_DLL_FN (library, png_set_sig_bytes); |
| 6274 | LOAD_DLL_FN (library, png_read_info); | 6277 | LOAD_DLL_FN (library, png_read_info); |
| 6275 | LOAD_DLL_FN (library, png_get_IHDR); | 6278 | LOAD_DLL_FN (library, png_get_IHDR); |
| 6276 | LOAD_DLL_FN (library, png_get_valid); | 6279 | # ifdef PNG_tRNS_SUPPORTED |
| 6280 | LOAD_DLL_FN (library, png_get_tRNS); | ||
| 6281 | # endif | ||
| 6277 | LOAD_DLL_FN (library, png_set_strip_16); | 6282 | LOAD_DLL_FN (library, png_set_strip_16); |
| 6278 | LOAD_DLL_FN (library, png_set_expand); | 6283 | LOAD_DLL_FN (library, png_set_expand); |
| 6279 | LOAD_DLL_FN (library, png_set_gray_to_rgb); | 6284 | LOAD_DLL_FN (library, png_set_gray_to_rgb); |
| @@ -6304,7 +6309,7 @@ init_png_functions (void) | |||
| 6304 | # undef png_get_IHDR | 6309 | # undef png_get_IHDR |
| 6305 | # undef png_get_io_ptr | 6310 | # undef png_get_io_ptr |
| 6306 | # undef png_get_rowbytes | 6311 | # undef png_get_rowbytes |
| 6307 | # undef png_get_valid | 6312 | # undef png_get_tRNS |
| 6308 | # undef png_longjmp | 6313 | # undef png_longjmp |
| 6309 | # undef png_read_end | 6314 | # undef png_read_end |
| 6310 | # undef png_read_image | 6315 | # undef png_read_image |
| @@ -6329,7 +6334,7 @@ init_png_functions (void) | |||
| 6329 | # define png_get_IHDR fn_png_get_IHDR | 6334 | # define png_get_IHDR fn_png_get_IHDR |
| 6330 | # define png_get_io_ptr fn_png_get_io_ptr | 6335 | # define png_get_io_ptr fn_png_get_io_ptr |
| 6331 | # define png_get_rowbytes fn_png_get_rowbytes | 6336 | # define png_get_rowbytes fn_png_get_rowbytes |
| 6332 | # define png_get_valid fn_png_get_valid | 6337 | # define png_get_tRNS fn_png_get_tRNS |
| 6333 | # define png_longjmp fn_png_longjmp | 6338 | # define png_longjmp fn_png_longjmp |
| 6334 | # define png_read_end fn_png_read_end | 6339 | # define png_read_end fn_png_read_end |
| 6335 | # define png_read_image fn_png_read_image | 6340 | # define png_read_image fn_png_read_image |
| @@ -6589,10 +6594,22 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6589 | 6594 | ||
| 6590 | /* If image contains simply transparency data, we prefer to | 6595 | /* If image contains simply transparency data, we prefer to |
| 6591 | construct a clipping mask. */ | 6596 | construct a clipping mask. */ |
| 6592 | if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) | 6597 | transparent_p = false; |
| 6593 | transparent_p = 1; | 6598 | # ifdef PNG_tRNS_SUPPORTED |
| 6594 | else | 6599 | png_bytep trans_alpha; |
| 6595 | transparent_p = 0; | 6600 | int num_trans; |
| 6601 | if (png_get_tRNS (png_ptr, info_ptr, &trans_alpha, &num_trans, NULL)) | ||
| 6602 | { | ||
| 6603 | transparent_p = true; | ||
| 6604 | if (trans_alpha) | ||
| 6605 | for (int i = 0; i < num_trans; i++) | ||
| 6606 | if (0 < trans_alpha[i] && trans_alpha[i] < 255) | ||
| 6607 | { | ||
| 6608 | transparent_p = false; | ||
| 6609 | break; | ||
| 6610 | } | ||
| 6611 | } | ||
| 6612 | # endif | ||
| 6596 | 6613 | ||
| 6597 | /* This function is easier to write if we only have to handle | 6614 | /* This function is easier to write if we only have to handle |
| 6598 | one data format: RGB or RGBA with 8 bits per channel. Let's | 6615 | one data format: RGB or RGBA with 8 bits per channel. Let's |
| @@ -6680,7 +6697,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) | |||
| 6680 | /* Create an image and pixmap serving as mask if the PNG image | 6697 | /* Create an image and pixmap serving as mask if the PNG image |
| 6681 | contains an alpha channel. */ | 6698 | contains an alpha channel. */ |
| 6682 | if (channels == 4 | 6699 | if (channels == 4 |
| 6683 | && !transparent_p | 6700 | && transparent_p |
| 6684 | && !image_create_x_image_and_pixmap (f, img, width, height, 1, | 6701 | && !image_create_x_image_and_pixmap (f, img, width, height, 1, |
| 6685 | &mask_img, 1)) | 6702 | &mask_img, 1)) |
| 6686 | { | 6703 | { |
diff --git a/src/keyboard.c b/src/keyboard.c index 30686a25898..1b9a603ca17 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -8304,6 +8304,10 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item) | |||
| 8304 | AUTO_STRING (end, ")"); | 8304 | AUTO_STRING (end, ")"); |
| 8305 | Lisp_Object orig = PROP (TOOL_BAR_ITEM_HELP); | 8305 | Lisp_Object orig = PROP (TOOL_BAR_ITEM_HELP); |
| 8306 | Lisp_Object desc = Fkey_description (keys, Qnil); | 8306 | Lisp_Object desc = Fkey_description (keys, Qnil); |
| 8307 | |||
| 8308 | if (NILP (orig)) | ||
| 8309 | orig = PROP (TOOL_BAR_ITEM_CAPTION); | ||
| 8310 | |||
| 8307 | set_prop (TOOL_BAR_ITEM_HELP, CALLN (Fconcat, orig, beg, desc, end)); | 8311 | set_prop (TOOL_BAR_ITEM_HELP, CALLN (Fconcat, orig, beg, desc, end)); |
| 8308 | } | 8312 | } |
| 8309 | 8313 | ||
diff --git a/src/keymap.c b/src/keymap.c index 6762915f70c..b1e09a92f20 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -3371,12 +3371,10 @@ describe_vector (Lisp_Object vector, Lisp_Object prefix, Lisp_Object args, | |||
| 3371 | 3371 | ||
| 3372 | if (!keymap_p) | 3372 | if (!keymap_p) |
| 3373 | { | 3373 | { |
| 3374 | /* Call Fkey_description first, to avoid GC bug for the other string. */ | ||
| 3375 | if (!NILP (prefix) && XFIXNAT (Flength (prefix)) > 0) | 3374 | if (!NILP (prefix) && XFIXNAT (Flength (prefix)) > 0) |
| 3376 | { | 3375 | { |
| 3377 | Lisp_Object tem = Fkey_description (prefix, Qnil); | ||
| 3378 | AUTO_STRING (space, " "); | 3376 | AUTO_STRING (space, " "); |
| 3379 | elt_prefix = concat2 (tem, space); | 3377 | elt_prefix = concat2 (Fkey_description (prefix, Qnil), space); |
| 3380 | } | 3378 | } |
| 3381 | prefix = Qnil; | 3379 | prefix = Qnil; |
| 3382 | } | 3380 | } |
diff --git a/src/lisp.h b/src/lisp.h index 56ad99b8e39..a7b19ab576e 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2307,7 +2307,7 @@ struct Lisp_Hash_Table | |||
| 2307 | weakness of the table. */ | 2307 | weakness of the table. */ |
| 2308 | Lisp_Object weak; | 2308 | Lisp_Object weak; |
| 2309 | 2309 | ||
| 2310 | /* Vector of hash codes. | 2310 | /* Vector of hash codes, or nil if the table needs rehashing. |
| 2311 | If the I-th entry is unused, then hash[I] should be nil. */ | 2311 | If the I-th entry is unused, then hash[I] should be nil. */ |
| 2312 | Lisp_Object hash; | 2312 | Lisp_Object hash; |
| 2313 | 2313 | ||
| @@ -2327,8 +2327,7 @@ struct Lisp_Hash_Table | |||
| 2327 | 'index' are special and are either ignored by the GC or traced in | 2327 | 'index' are special and are either ignored by the GC or traced in |
| 2328 | a special way (e.g. because of weakness). */ | 2328 | a special way (e.g. because of weakness). */ |
| 2329 | 2329 | ||
| 2330 | /* Number of key/value entries in the table. This number is | 2330 | /* Number of key/value entries in the table. */ |
| 2331 | negated if the table needs rehashing. */ | ||
| 2332 | ptrdiff_t count; | 2331 | ptrdiff_t count; |
| 2333 | 2332 | ||
| 2334 | /* Index of first free entry in free list, or -1 if none. */ | 2333 | /* Index of first free entry in free list, or -1 if none. */ |
| @@ -2413,7 +2412,9 @@ HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx) | |||
| 2413 | INLINE ptrdiff_t | 2412 | INLINE ptrdiff_t |
| 2414 | HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h) | 2413 | HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h) |
| 2415 | { | 2414 | { |
| 2416 | return ASIZE (h->next); | 2415 | ptrdiff_t size = ASIZE (h->next); |
| 2416 | eassume (0 < size); | ||
| 2417 | return size; | ||
| 2417 | } | 2418 | } |
| 2418 | 2419 | ||
| 2419 | void hash_table_rehash (struct Lisp_Hash_Table *h); | 2420 | void hash_table_rehash (struct Lisp_Hash_Table *h); |
| @@ -3614,7 +3615,6 @@ extern void set_default_internal (Lisp_Object, Lisp_Object, | |||
| 3614 | extern Lisp_Object expt_integer (Lisp_Object, Lisp_Object); | 3615 | extern Lisp_Object expt_integer (Lisp_Object, Lisp_Object); |
| 3615 | extern void syms_of_data (void); | 3616 | extern void syms_of_data (void); |
| 3616 | extern void swap_in_global_binding (struct Lisp_Symbol *); | 3617 | extern void swap_in_global_binding (struct Lisp_Symbol *); |
| 3617 | extern Lisp_Object integer_mod (Lisp_Object, Lisp_Object); | ||
| 3618 | 3618 | ||
| 3619 | /* Defined in cmds.c */ | 3619 | /* Defined in cmds.c */ |
| 3620 | extern void syms_of_cmds (void); | 3620 | extern void syms_of_cmds (void); |
diff --git a/src/lread.c b/src/lread.c index 1bfbf5aa865..6ae7a0d8ba0 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -1064,18 +1064,13 @@ required. | |||
| 1064 | This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) | 1064 | This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) |
| 1065 | (void) | 1065 | (void) |
| 1066 | { | 1066 | { |
| 1067 | Lisp_Object lst = Qnil, suffixes = Vload_suffixes, suffix, ext; | 1067 | Lisp_Object lst = Qnil, suffixes = Vload_suffixes; |
| 1068 | while (CONSP (suffixes)) | 1068 | FOR_EACH_TAIL (suffixes) |
| 1069 | { | 1069 | { |
| 1070 | Lisp_Object exts = Vload_file_rep_suffixes; | 1070 | Lisp_Object exts = Vload_file_rep_suffixes; |
| 1071 | suffix = XCAR (suffixes); | 1071 | Lisp_Object suffix = XCAR (suffixes); |
| 1072 | suffixes = XCDR (suffixes); | 1072 | FOR_EACH_TAIL (exts) |
| 1073 | while (CONSP (exts)) | 1073 | lst = Fcons (concat2 (suffix, XCAR (exts)), lst); |
| 1074 | { | ||
| 1075 | ext = XCAR (exts); | ||
| 1076 | exts = XCDR (exts); | ||
| 1077 | lst = Fcons (concat2 (suffix, ext), lst); | ||
| 1078 | } | ||
| 1079 | } | 1074 | } |
| 1080 | return Fnreverse (lst); | 1075 | return Fnreverse (lst); |
| 1081 | } | 1076 | } |
| @@ -1290,8 +1285,8 @@ Return t if the file exists and loads successfully. */) | |||
| 1290 | the general case; the second load may do something different. */ | 1285 | the general case; the second load may do something different. */ |
| 1291 | { | 1286 | { |
| 1292 | int load_count = 0; | 1287 | int load_count = 0; |
| 1293 | Lisp_Object tem; | 1288 | Lisp_Object tem = Vloads_in_progress; |
| 1294 | for (tem = Vloads_in_progress; CONSP (tem); tem = XCDR (tem)) | 1289 | FOR_EACH_TAIL_SAFE (tem) |
| 1295 | if (!NILP (Fequal (found, XCAR (tem))) && (++load_count > 3)) | 1290 | if (!NILP (Fequal (found, XCAR (tem))) && (++load_count > 3)) |
| 1296 | signal_error ("Recursive load", Fcons (found, Vloads_in_progress)); | 1291 | signal_error ("Recursive load", Fcons (found, Vloads_in_progress)); |
| 1297 | record_unwind_protect (record_load_unwind, Vloads_in_progress); | 1292 | record_unwind_protect (record_load_unwind, Vloads_in_progress); |
| @@ -1611,7 +1606,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1611 | 1606 | ||
| 1612 | CHECK_STRING (str); | 1607 | CHECK_STRING (str); |
| 1613 | 1608 | ||
| 1614 | for (tail = suffixes; CONSP (tail); tail = XCDR (tail)) | 1609 | tail = suffixes; |
| 1610 | FOR_EACH_TAIL_SAFE (tail) | ||
| 1615 | { | 1611 | { |
| 1616 | CHECK_STRING_CAR (tail); | 1612 | CHECK_STRING_CAR (tail); |
| 1617 | max_suffix_len = max (max_suffix_len, | 1613 | max_suffix_len = max (max_suffix_len, |
| @@ -1625,12 +1621,17 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1625 | 1621 | ||
| 1626 | absolute = complete_filename_p (str); | 1622 | absolute = complete_filename_p (str); |
| 1627 | 1623 | ||
| 1624 | AUTO_LIST1 (just_use_str, Qnil); | ||
| 1625 | if (NILP (path)) | ||
| 1626 | path = just_use_str; | ||
| 1627 | |||
| 1628 | /* Go through all entries in the path and see whether we find the | 1628 | /* Go through all entries in the path and see whether we find the |
| 1629 | executable. */ | 1629 | executable. */ |
| 1630 | do { | 1630 | FOR_EACH_TAIL_SAFE (path) |
| 1631 | { | ||
| 1631 | ptrdiff_t baselen, prefixlen; | 1632 | ptrdiff_t baselen, prefixlen; |
| 1632 | 1633 | ||
| 1633 | if (NILP (path)) | 1634 | if (EQ (path, just_use_str)) |
| 1634 | filename = str; | 1635 | filename = str; |
| 1635 | else | 1636 | else |
| 1636 | filename = Fexpand_file_name (str, XCAR (path)); | 1637 | filename = Fexpand_file_name (str, XCAR (path)); |
| @@ -1663,8 +1664,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1663 | memcpy (fn, SDATA (filename) + prefixlen, baselen); | 1664 | memcpy (fn, SDATA (filename) + prefixlen, baselen); |
| 1664 | 1665 | ||
| 1665 | /* Loop over suffixes. */ | 1666 | /* Loop over suffixes. */ |
| 1666 | for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes; | 1667 | AUTO_LIST1 (empty_string_only, empty_unibyte_string); |
| 1667 | CONSP (tail); tail = XCDR (tail)) | 1668 | tail = NILP (suffixes) ? empty_string_only : suffixes; |
| 1669 | FOR_EACH_TAIL_SAFE (tail) | ||
| 1668 | { | 1670 | { |
| 1669 | Lisp_Object suffix = XCAR (tail); | 1671 | Lisp_Object suffix = XCAR (tail); |
| 1670 | ptrdiff_t fnlen, lsuffix = SBYTES (suffix); | 1672 | ptrdiff_t fnlen, lsuffix = SBYTES (suffix); |
| @@ -1808,10 +1810,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1808 | } | 1810 | } |
| 1809 | } | 1811 | } |
| 1810 | } | 1812 | } |
| 1811 | if (absolute || NILP (path)) | 1813 | if (absolute) |
| 1812 | break; | 1814 | break; |
| 1813 | path = XCDR (path); | 1815 | } |
| 1814 | } while (CONSP (path)); | ||
| 1815 | 1816 | ||
| 1816 | SAFE_FREE (); | 1817 | SAFE_FREE (); |
| 1817 | errno = last_errno; | 1818 | errno = last_errno; |
| @@ -1838,7 +1839,7 @@ build_load_history (Lisp_Object filename, bool entire) | |||
| 1838 | tail = Vload_history; | 1839 | tail = Vload_history; |
| 1839 | prev = Qnil; | 1840 | prev = Qnil; |
| 1840 | 1841 | ||
| 1841 | while (CONSP (tail)) | 1842 | FOR_EACH_TAIL (tail) |
| 1842 | { | 1843 | { |
| 1843 | tem = XCAR (tail); | 1844 | tem = XCAR (tail); |
| 1844 | 1845 | ||
| @@ -1861,22 +1862,19 @@ build_load_history (Lisp_Object filename, bool entire) | |||
| 1861 | { | 1862 | { |
| 1862 | tem2 = Vcurrent_load_list; | 1863 | tem2 = Vcurrent_load_list; |
| 1863 | 1864 | ||
| 1864 | while (CONSP (tem2)) | 1865 | FOR_EACH_TAIL (tem2) |
| 1865 | { | 1866 | { |
| 1866 | newelt = XCAR (tem2); | 1867 | newelt = XCAR (tem2); |
| 1867 | 1868 | ||
| 1868 | if (NILP (Fmember (newelt, tem))) | 1869 | if (NILP (Fmember (newelt, tem))) |
| 1869 | Fsetcar (tail, Fcons (XCAR (tem), | 1870 | Fsetcar (tail, Fcons (XCAR (tem), |
| 1870 | Fcons (newelt, XCDR (tem)))); | 1871 | Fcons (newelt, XCDR (tem)))); |
| 1871 | |||
| 1872 | tem2 = XCDR (tem2); | ||
| 1873 | maybe_quit (); | 1872 | maybe_quit (); |
| 1874 | } | 1873 | } |
| 1875 | } | 1874 | } |
| 1876 | } | 1875 | } |
| 1877 | else | 1876 | else |
| 1878 | prev = tail; | 1877 | prev = tail; |
| 1879 | tail = XCDR (tail); | ||
| 1880 | maybe_quit (); | 1878 | maybe_quit (); |
| 1881 | } | 1879 | } |
| 1882 | 1880 | ||
| @@ -1918,10 +1916,9 @@ readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand) | |||
| 1918 | if (EQ (CAR_SAFE (val), Qprogn)) | 1916 | if (EQ (CAR_SAFE (val), Qprogn)) |
| 1919 | { | 1917 | { |
| 1920 | Lisp_Object subforms = XCDR (val); | 1918 | Lisp_Object subforms = XCDR (val); |
| 1921 | 1919 | val = Qnil; | |
| 1922 | for (val = Qnil; CONSP (subforms); subforms = XCDR (subforms)) | 1920 | FOR_EACH_TAIL (subforms) |
| 1923 | val = readevalloop_eager_expand_eval (XCAR (subforms), | 1921 | val = readevalloop_eager_expand_eval (XCAR (subforms), macroexpand); |
| 1924 | macroexpand); | ||
| 1925 | } | 1922 | } |
| 1926 | else | 1923 | else |
| 1927 | val = eval_sub (call2 (macroexpand, val, Qt)); | 1924 | val = eval_sub (call2 (macroexpand, val, Qt)); |
| @@ -2588,7 +2585,8 @@ read_escape (Lisp_Object readcharfun, bool stringp) | |||
| 2588 | want. */ | 2585 | want. */ |
| 2589 | int digit = char_hexdigit (c); | 2586 | int digit = char_hexdigit (c); |
| 2590 | if (digit < 0) | 2587 | if (digit < 0) |
| 2591 | error ("Non-hex digit used for Unicode escape"); | 2588 | error ("Non-hex character used for Unicode escape: %c (%d)", |
| 2589 | c, c); | ||
| 2592 | i = (i << 4) + digit; | 2590 | i = (i << 4) + digit; |
| 2593 | } | 2591 | } |
| 2594 | if (i > 0x10FFFF) | 2592 | if (i > 0x10FFFF) |
| @@ -2861,16 +2859,19 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2861 | /* Now use params to make a new hash table and fill it. */ | 2859 | /* Now use params to make a new hash table and fill it. */ |
| 2862 | ht = Fmake_hash_table (param_count, params); | 2860 | ht = Fmake_hash_table (param_count, params); |
| 2863 | 2861 | ||
| 2864 | while (CONSP (data)) | 2862 | Lisp_Object last = data; |
| 2865 | { | 2863 | FOR_EACH_TAIL_SAFE (data) |
| 2864 | { | ||
| 2866 | key = XCAR (data); | 2865 | key = XCAR (data); |
| 2867 | data = XCDR (data); | 2866 | data = XCDR (data); |
| 2868 | if (!CONSP (data)) | 2867 | if (!CONSP (data)) |
| 2869 | error ("Odd number of elements in hash table data"); | 2868 | break; |
| 2870 | val = XCAR (data); | 2869 | val = XCAR (data); |
| 2871 | data = XCDR (data); | 2870 | last = XCDR (data); |
| 2872 | Fputhash (key, val, ht); | 2871 | Fputhash (key, val, ht); |
| 2873 | } | 2872 | } |
| 2873 | if (!NILP (last)) | ||
| 2874 | error ("Hash table data is not a list of even length"); | ||
| 2874 | 2875 | ||
| 2875 | return ht; | 2876 | return ht; |
| 2876 | } | 2877 | } |
diff --git a/src/mini-gmp.c b/src/mini-gmp.c index 88b71c3f9a6..e92e7cf9c72 100644 --- a/src/mini-gmp.c +++ b/src/mini-gmp.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | Contributed to the GNU project by Niels Möller | 3 | Contributed to the GNU project by Niels Möller |
| 4 | 4 | ||
| 5 | Copyright 1991-1997, 1999-2018 Free Software Foundation, Inc. | 5 | Copyright 1991-1997, 1999-2019 Free Software Foundation, Inc. |
| 6 | 6 | ||
| 7 | This file is part of the GNU MP Library. | 7 | This file is part of the GNU MP Library. |
| 8 | 8 | ||
| @@ -295,7 +295,7 @@ gmp_default_alloc (size_t size) | |||
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | static void * | 297 | static void * |
| 298 | gmp_default_realloc (void *old, size_t old_size, size_t new_size) | 298 | gmp_default_realloc (void *old, size_t unused_old_size, size_t new_size) |
| 299 | { | 299 | { |
| 300 | void * p; | 300 | void * p; |
| 301 | 301 | ||
| @@ -308,7 +308,7 @@ gmp_default_realloc (void *old, size_t old_size, size_t new_size) | |||
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | static void | 310 | static void |
| 311 | gmp_default_free (void *p, size_t size) | 311 | gmp_default_free (void *p, size_t unused_size) |
| 312 | { | 312 | { |
| 313 | free (p); | 313 | free (p); |
| 314 | } | 314 | } |
| @@ -1595,7 +1595,7 @@ mpz_get_ui (const mpz_t u) | |||
| 1595 | int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; | 1595 | int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; |
| 1596 | unsigned long r = 0; | 1596 | unsigned long r = 0; |
| 1597 | mp_size_t n = GMP_ABS (u->_mp_size); | 1597 | mp_size_t n = GMP_ABS (u->_mp_size); |
| 1598 | n = GMP_MIN (n, 1 + (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS); | 1598 | n = GMP_MIN (n, 1 + (mp_size_t) (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS); |
| 1599 | while (--n >= 0) | 1599 | while (--n >= 0) |
| 1600 | r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n]; | 1600 | r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n]; |
| 1601 | return r; | 1601 | return r; |
| @@ -3499,7 +3499,7 @@ gmp_stronglucas (const mpz_t x, mpz_t Qk) | |||
| 3499 | b0 = mpz_scan0 (n, 0); | 3499 | b0 = mpz_scan0 (n, 0); |
| 3500 | 3500 | ||
| 3501 | /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */ | 3501 | /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */ |
| 3502 | Q = (D & 2) ? (D >> 2) + 1 : -(long) (D >> 2); | 3502 | Q = (D & 2) ? (long) (D >> 2) + 1 : -(long) (D >> 2); |
| 3503 | 3503 | ||
| 3504 | if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */ | 3504 | if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */ |
| 3505 | while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */ | 3505 | while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */ |
diff --git a/src/minibuf.c b/src/minibuf.c index 14a0dbe762c..f6cf47f1f28 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -169,7 +169,8 @@ string_to_object (Lisp_Object val, Lisp_Object defalt) | |||
| 169 | { | 169 | { |
| 170 | int c = SREF (val, i); | 170 | int c = SREF (val, i); |
| 171 | if (c != ' ' && c != '\t' && c != '\n') | 171 | if (c != ' ' && c != '\t' && c != '\n') |
| 172 | error ("Trailing garbage following expression"); | 172 | xsignal1 (Qinvalid_read_syntax, |
| 173 | build_string ("Trailing garbage following expression")); | ||
| 173 | } | 174 | } |
| 174 | } | 175 | } |
| 175 | 176 | ||
diff --git a/src/pdumper.c b/src/pdumper.c index 326a346a632..98090238b1a 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -105,8 +105,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 105 | # define VM_SUPPORTED 0 | 105 | # define VM_SUPPORTED 0 |
| 106 | #endif | 106 | #endif |
| 107 | 107 | ||
| 108 | #define DANGEROUS 0 | ||
| 109 | |||
| 110 | /* PDUMPER_CHECK_REHASHING being true causes the portable dumper to | 108 | /* PDUMPER_CHECK_REHASHING being true causes the portable dumper to |
| 111 | check, for each hash table it dumps, that the hash table means the | 109 | check, for each hash table it dumps, that the hash table means the |
| 112 | same thing after rehashing. */ | 110 | same thing after rehashing. */ |
| @@ -129,7 +127,11 @@ verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object)); | |||
| 129 | verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); | 127 | verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); |
| 130 | verify (CHAR_BIT == 8); | 128 | verify (CHAR_BIT == 8); |
| 131 | 129 | ||
| 132 | #define DIVIDE_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) | 130 | static size_t |
| 131 | divide_round_up (size_t x, size_t y) | ||
| 132 | { | ||
| 133 | return (x + y - 1) / y; | ||
| 134 | } | ||
| 133 | 135 | ||
| 134 | static const char dump_magic[16] = { | 136 | static const char dump_magic[16] = { |
| 135 | 'D', 'U', 'M', 'P', 'E', 'D', | 137 | 'D', 'U', 'M', 'P', 'E', 'D', |
| @@ -235,9 +237,12 @@ enum emacs_reloc_type | |||
| 235 | RELOC_EMACS_EMACS_LV, | 237 | RELOC_EMACS_EMACS_LV, |
| 236 | }; | 238 | }; |
| 237 | 239 | ||
| 238 | #define EMACS_RELOC_TYPE_BITS 3 | 240 | enum |
| 239 | #define EMACS_RELOC_LENGTH_BITS \ | 241 | { |
| 240 | (sizeof (dump_off) * CHAR_BIT - EMACS_RELOC_TYPE_BITS) | 242 | EMACS_RELOC_TYPE_BITS = 3, |
| 243 | EMACS_RELOC_LENGTH_BITS = (sizeof (dump_off) * CHAR_BIT | ||
| 244 | - EMACS_RELOC_TYPE_BITS) | ||
| 245 | }; | ||
| 241 | 246 | ||
| 242 | struct emacs_reloc | 247 | struct emacs_reloc |
| 243 | { | 248 | { |
| @@ -274,19 +279,22 @@ struct dump_table_locator | |||
| 274 | dump_off nr_entries; | 279 | dump_off nr_entries; |
| 275 | }; | 280 | }; |
| 276 | 281 | ||
| 277 | #define DUMP_RELOC_TYPE_BITS 5 | 282 | enum |
| 278 | verify (RELOC_DUMP_TO_EMACS_LV + 8 < (1 << DUMP_RELOC_TYPE_BITS)); | 283 | { |
| 284 | DUMP_RELOC_TYPE_BITS = 5, | ||
| 285 | DUMP_RELOC_ALIGNMENT_BITS = 2, | ||
| 279 | 286 | ||
| 280 | #define DUMP_RELOC_ALIGNMENT_BITS 2 | 287 | /* Minimum alignment required by dump file format. */ |
| 281 | #define DUMP_RELOC_OFFSET_BITS \ | 288 | DUMP_RELOCATION_ALIGNMENT = 1 << DUMP_RELOC_ALIGNMENT_BITS, |
| 282 | (sizeof (dump_off) * CHAR_BIT - DUMP_RELOC_TYPE_BITS) | ||
| 283 | 289 | ||
| 284 | /* Minimum alignment required by dump file format. */ | 290 | /* The alignment granularity (in bytes) for objects we store in the |
| 285 | #define DUMP_RELOCATION_ALIGNMENT (1<<DUMP_RELOC_ALIGNMENT_BITS) | 291 | dump. Always suitable for heap objects; may be more aligned. */ |
| 292 | DUMP_ALIGNMENT = max (GCALIGNMENT, DUMP_RELOCATION_ALIGNMENT), | ||
| 293 | |||
| 294 | DUMP_RELOC_OFFSET_BITS = sizeof (dump_off) * CHAR_BIT - DUMP_RELOC_TYPE_BITS | ||
| 295 | }; | ||
| 286 | 296 | ||
| 287 | /* The alignment granularity (in bytes) for objects we store in the | 297 | verify (RELOC_DUMP_TO_EMACS_LV + 8 < (1 << DUMP_RELOC_TYPE_BITS)); |
| 288 | dump. Always suitable for heap objects; may be more aligned. */ | ||
| 289 | #define DUMP_ALIGNMENT (max (GCALIGNMENT, DUMP_RELOCATION_ALIGNMENT)) | ||
| 290 | verify (DUMP_ALIGNMENT >= GCALIGNMENT); | 298 | verify (DUMP_ALIGNMENT >= GCALIGNMENT); |
| 291 | 299 | ||
| 292 | struct dump_reloc | 300 | struct dump_reloc |
| @@ -572,23 +580,17 @@ enum dump_object_special_offset | |||
| 572 | }; | 580 | }; |
| 573 | 581 | ||
| 574 | /* Weights for score scores for object non-locality. */ | 582 | /* Weights for score scores for object non-locality. */ |
| 575 | enum link_weight_enum | ||
| 576 | { | ||
| 577 | WEIGHT_NONE_VALUE = 0, | ||
| 578 | WEIGHT_NORMAL_VALUE = 1000, | ||
| 579 | WEIGHT_STRONG_VALUE = 1200, | ||
| 580 | }; | ||
| 581 | 583 | ||
| 582 | struct link_weight | 584 | struct link_weight |
| 583 | { | 585 | { |
| 584 | /* Wrapped in a struct to break unwanted implicit conversion. */ | 586 | /* Wrapped in a struct to break unwanted implicit conversion. */ |
| 585 | enum link_weight_enum value; | 587 | int value; |
| 586 | }; | 588 | }; |
| 587 | 589 | ||
| 588 | #define LINK_WEIGHT_LITERAL(x) ((struct link_weight){.value=(x)}) | 590 | static struct link_weight const |
| 589 | #define WEIGHT_NONE LINK_WEIGHT_LITERAL (WEIGHT_NONE_VALUE) | 591 | WEIGHT_NONE = { .value = 0 }, |
| 590 | #define WEIGHT_NORMAL LINK_WEIGHT_LITERAL (WEIGHT_NORMAL_VALUE) | 592 | WEIGHT_NORMAL = { .value = 1000 }, |
| 591 | #define WEIGHT_STRONG LINK_WEIGHT_LITERAL (WEIGHT_STRONG_VALUE) | 593 | WEIGHT_STRONG = { .value = 1200 }; |
| 592 | 594 | ||
| 593 | 595 | ||
| 594 | /* Dump file creation */ | 596 | /* Dump file creation */ |
| @@ -628,35 +630,27 @@ dump_set_have_current_referrer (struct dump_context *ctx, bool have) | |||
| 628 | #endif | 630 | #endif |
| 629 | } | 631 | } |
| 630 | 632 | ||
| 631 | /* Remember the reason objects are enqueued. | 633 | /* Return true if if objects should be enqueued in CTX to refer to an |
| 634 | object that the caller should store into CTX->current_referrer. | ||
| 632 | 635 | ||
| 633 | Until DUMP_CLEAR_REFERRER is called, any objects enqueued are being | 636 | Until dump_clear_referrer is called, any objects enqueued are being |
| 634 | enqueued because OBJECT refers to them. It is not legal to enqueue | 637 | enqueued because the object refers to them. It is not valid to |
| 635 | objects without a referer set. We check this constraint | 638 | enqueue objects without a referrer set. We check this constraint |
| 636 | at runtime. | 639 | at runtime. |
| 637 | 640 | ||
| 638 | It is illegal to call DUMP_SET_REFERRER twice without an | 641 | It is invalid to call dump_set_referrer twice without an |
| 639 | intervening call to DUMP_CLEAR_REFERRER. | 642 | intervening call to dump_clear_referrer. */ |
| 640 | 643 | static bool | |
| 641 | Define as a macro so we can avoid evaluating OBJECT | 644 | dump_set_referrer (struct dump_context *ctx) |
| 642 | if we dont want referrer tracking. */ | 645 | { |
| 643 | #define DUMP_SET_REFERRER(ctx, object) \ | 646 | eassert (!ctx->have_current_referrer); |
| 644 | do \ | 647 | dump_set_have_current_referrer (ctx, true); |
| 645 | { \ | 648 | return dump_tracking_referrers_p (ctx); |
| 646 | struct dump_context *_ctx = (ctx); \ | 649 | } |
| 647 | eassert (!_ctx->have_current_referrer); \ | 650 | |
| 648 | dump_set_have_current_referrer (_ctx, true); \ | 651 | /* Unset the referrer that dump_set_referrer prepared for. */ |
| 649 | if (dump_tracking_referrers_p (_ctx)) \ | ||
| 650 | ctx->current_referrer = (object); \ | ||
| 651 | } \ | ||
| 652 | while (0) | ||
| 653 | |||
| 654 | /* Unset the referer that DUMP_SET_REFERRER set. | ||
| 655 | |||
| 656 | Named with upper-case letters for symmetry with | ||
| 657 | DUMP_SET_REFERRER. */ | ||
| 658 | static void | 652 | static void |
| 659 | DUMP_CLEAR_REFERRER (struct dump_context *ctx) | 653 | dump_clear_referrer (struct dump_context *ctx) |
| 660 | { | 654 | { |
| 661 | eassert (ctx->have_current_referrer); | 655 | eassert (ctx->have_current_referrer); |
| 662 | dump_set_have_current_referrer (ctx, false); | 656 | dump_set_have_current_referrer (ctx, false); |
| @@ -732,34 +726,36 @@ dump_object_self_representing_p (Lisp_Object object) | |||
| 732 | return FIXNUMP (object) || dump_builtin_symbol_p (object); | 726 | return FIXNUMP (object) || dump_builtin_symbol_p (object); |
| 733 | } | 727 | } |
| 734 | 728 | ||
| 735 | #define DEFINE_FROMLISP_FUNC(fn, type) \ | 729 | static intmax_t |
| 736 | static type \ | 730 | intmax_t_from_lisp (Lisp_Object value) |
| 737 | fn (Lisp_Object value) \ | 731 | { |
| 738 | { \ | 732 | intmax_t n; |
| 739 | ALLOW_IMPLICIT_CONVERSION; \ | 733 | bool ok = integer_to_intmax (value, &n); |
| 740 | if (FIXNUMP (value)) \ | 734 | eassert (ok); |
| 741 | return XFIXNUM (value); \ | 735 | return n; |
| 742 | eassert (BIGNUMP (value)); \ | 736 | } |
| 743 | type result; \ | ||
| 744 | if (TYPE_SIGNED (type)) \ | ||
| 745 | result = bignum_to_intmax (value); \ | ||
| 746 | else \ | ||
| 747 | result = bignum_to_uintmax (value); \ | ||
| 748 | DISALLOW_IMPLICIT_CONVERSION; \ | ||
| 749 | return result; \ | ||
| 750 | } | ||
| 751 | 737 | ||
| 752 | #define DEFINE_TOLISP_FUNC(fn, type) \ | 738 | static Lisp_Object |
| 753 | static Lisp_Object \ | 739 | intmax_t_to_lisp (intmax_t value) |
| 754 | fn (type value) \ | 740 | { |
| 755 | { \ | 741 | return INT_TO_INTEGER (value); |
| 756 | return INT_TO_INTEGER (value); \ | 742 | } |
| 757 | } | 743 | |
| 744 | static dump_off | ||
| 745 | dump_off_from_lisp (Lisp_Object value) | ||
| 746 | { | ||
| 747 | intmax_t n = intmax_t_from_lisp (value); | ||
| 748 | eassert (DUMP_OFF_MIN <= n && n <= DUMP_OFF_MAX); | ||
| 749 | ALLOW_IMPLICIT_CONVERSION; | ||
| 750 | return n; | ||
| 751 | DISALLOW_IMPLICIT_CONVERSION; | ||
| 752 | } | ||
| 758 | 753 | ||
| 759 | DEFINE_FROMLISP_FUNC (intmax_t_from_lisp, intmax_t) | 754 | static Lisp_Object |
| 760 | DEFINE_TOLISP_FUNC (intmax_t_to_lisp, intmax_t) | 755 | dump_off_to_lisp (dump_off value) |
| 761 | DEFINE_FROMLISP_FUNC (dump_off_from_lisp, dump_off) | 756 | { |
| 762 | DEFINE_TOLISP_FUNC (dump_off_to_lisp, dump_off) | 757 | return INT_TO_INTEGER (value); |
| 758 | } | ||
| 763 | 759 | ||
| 764 | static void | 760 | static void |
| 765 | dump_write (struct dump_context *ctx, const void *buf, dump_off nbyte) | 761 | dump_write (struct dump_context *ctx, const void *buf, dump_off nbyte) |
| @@ -1731,9 +1727,10 @@ dump_root_visitor (Lisp_Object const *root_ptr, enum gc_root_type type, | |||
| 1731 | eassert (dump_builtin_symbol_p (value)); | 1727 | eassert (dump_builtin_symbol_p (value)); |
| 1732 | /* Remember to dump the object itself later along with all the | 1728 | /* Remember to dump the object itself later along with all the |
| 1733 | rest of the copied-to-Emacs objects. */ | 1729 | rest of the copied-to-Emacs objects. */ |
| 1734 | DUMP_SET_REFERRER (ctx, build_string ("built-in symbol list")); | 1730 | if (dump_set_referrer (ctx)) |
| 1731 | ctx->current_referrer = build_string ("built-in symbol list"); | ||
| 1735 | dump_enqueue_object (ctx, value, WEIGHT_NONE); | 1732 | dump_enqueue_object (ctx, value, WEIGHT_NONE); |
| 1736 | DUMP_CLEAR_REFERRER (ctx); | 1733 | dump_clear_referrer (ctx); |
| 1737 | } | 1734 | } |
| 1738 | else | 1735 | else |
| 1739 | { | 1736 | { |
| @@ -1743,9 +1740,11 @@ dump_root_visitor (Lisp_Object const *root_ptr, enum gc_root_type type, | |||
| 1743 | ctx->staticpro_table); | 1740 | ctx->staticpro_table); |
| 1744 | if (root_ptr != &Vinternal_interpreter_environment) | 1741 | if (root_ptr != &Vinternal_interpreter_environment) |
| 1745 | { | 1742 | { |
| 1746 | DUMP_SET_REFERRER (ctx, dump_ptr_referrer ("emacs root", root_ptr)); | 1743 | if (dump_set_referrer (ctx)) |
| 1744 | ctx->current_referrer | ||
| 1745 | = dump_ptr_referrer ("emacs root", root_ptr); | ||
| 1747 | dump_emacs_reloc_to_lv (ctx, root_ptr, *root_ptr); | 1746 | dump_emacs_reloc_to_lv (ctx, root_ptr, *root_ptr); |
| 1748 | DUMP_CLEAR_REFERRER (ctx); | 1747 | dump_clear_referrer (ctx); |
| 1749 | } | 1748 | } |
| 1750 | } | 1749 | } |
| 1751 | } | 1750 | } |
| @@ -1759,7 +1758,7 @@ dump_roots (struct dump_context *ctx) | |||
| 1759 | visit_static_gc_roots (visitor); | 1758 | visit_static_gc_roots (visitor); |
| 1760 | } | 1759 | } |
| 1761 | 1760 | ||
| 1762 | #define PDUMPER_MAX_OBJECT_SIZE 2048 | 1761 | enum { PDUMPER_MAX_OBJECT_SIZE = 2048 }; |
| 1763 | 1762 | ||
| 1764 | static dump_off | 1763 | static dump_off |
| 1765 | field_relpos (const void *in_start, const void *in_field) | 1764 | field_relpos (const void *in_start, const void *in_field) |
| @@ -1788,11 +1787,7 @@ cpyptr (void *out, const void *in) | |||
| 1788 | 1787 | ||
| 1789 | /* Convenience macro for regular assignment. */ | 1788 | /* Convenience macro for regular assignment. */ |
| 1790 | #define DUMP_FIELD_COPY(out, in, name) \ | 1789 | #define DUMP_FIELD_COPY(out, in, name) \ |
| 1791 | do \ | 1790 | ((out)->name = (in)->name) |
| 1792 | { \ | ||
| 1793 | (out)->name = (in)->name; \ | ||
| 1794 | } \ | ||
| 1795 | while (0) | ||
| 1796 | 1791 | ||
| 1797 | static void | 1792 | static void |
| 1798 | dump_field_lv_or_rawptr (struct dump_context *ctx, | 1793 | dump_field_lv_or_rawptr (struct dump_context *ctx, |
| @@ -1848,6 +1843,7 @@ dump_field_lv_or_rawptr (struct dump_context *ctx, | |||
| 1848 | intptr_t out_value; | 1843 | intptr_t out_value; |
| 1849 | dump_off out_field_offset = ctx->obj_offset + relpos; | 1844 | dump_off out_field_offset = ctx->obj_offset + relpos; |
| 1850 | dump_off target_offset = dump_recall_object (ctx, value); | 1845 | dump_off target_offset = dump_recall_object (ctx, value); |
| 1846 | enum { DANGEROUS = false }; | ||
| 1851 | if (DANGEROUS | 1847 | if (DANGEROUS |
| 1852 | && target_offset > 0 && dump_object_emacs_ptr (value) == NULL) | 1848 | && target_offset > 0 && dump_object_emacs_ptr (value) == NULL) |
| 1853 | { | 1849 | { |
| @@ -2211,7 +2207,7 @@ dump_bignum (struct dump_context *ctx, Lisp_Object object) | |||
| 2211 | const struct Lisp_Bignum *bignum = XBIGNUM (object); | 2207 | const struct Lisp_Bignum *bignum = XBIGNUM (object); |
| 2212 | START_DUMP_PVEC (ctx, &bignum->header, struct Lisp_Bignum, out); | 2208 | START_DUMP_PVEC (ctx, &bignum->header, struct Lisp_Bignum, out); |
| 2213 | verify (sizeof (out->value) >= sizeof (struct bignum_reload_info)); | 2209 | verify (sizeof (out->value) >= sizeof (struct bignum_reload_info)); |
| 2214 | dump_field_fixup_later (ctx, out, bignum, &bignum->value); | 2210 | dump_field_fixup_later (ctx, out, bignum, xbignum_val (object)); |
| 2215 | dump_off bignum_offset = finish_dump_pvec (ctx, &out->header); | 2211 | dump_off bignum_offset = finish_dump_pvec (ctx, &out->header); |
| 2216 | if (ctx->flags.dump_object_contents) | 2212 | if (ctx->flags.dump_object_contents) |
| 2217 | { | 2213 | { |
| @@ -2408,7 +2404,8 @@ dump_pre_dump_symbol (struct dump_context *ctx, struct Lisp_Symbol *symbol) | |||
| 2408 | { | 2404 | { |
| 2409 | Lisp_Object symbol_lv = make_lisp_symbol (symbol); | 2405 | Lisp_Object symbol_lv = make_lisp_symbol (symbol); |
| 2410 | eassert (!dump_recall_symbol_aux (ctx, symbol_lv)); | 2406 | eassert (!dump_recall_symbol_aux (ctx, symbol_lv)); |
| 2411 | DUMP_SET_REFERRER (ctx, symbol_lv); | 2407 | if (dump_set_referrer (ctx)) |
| 2408 | ctx->current_referrer = symbol_lv; | ||
| 2412 | switch (symbol->u.s.redirect) | 2409 | switch (symbol->u.s.redirect) |
| 2413 | { | 2410 | { |
| 2414 | case SYMBOL_LOCALIZED: | 2411 | case SYMBOL_LOCALIZED: |
| @@ -2422,7 +2419,7 @@ dump_pre_dump_symbol (struct dump_context *ctx, struct Lisp_Symbol *symbol) | |||
| 2422 | default: | 2419 | default: |
| 2423 | break; | 2420 | break; |
| 2424 | } | 2421 | } |
| 2425 | DUMP_CLEAR_REFERRER (ctx); | 2422 | dump_clear_referrer (ctx); |
| 2426 | } | 2423 | } |
| 2427 | 2424 | ||
| 2428 | static dump_off | 2425 | static dump_off |
| @@ -2443,13 +2440,14 @@ dump_symbol (struct dump_context *ctx, | |||
| 2443 | { | 2440 | { |
| 2444 | eassert (offset == DUMP_OBJECT_ON_NORMAL_QUEUE | 2441 | eassert (offset == DUMP_OBJECT_ON_NORMAL_QUEUE |
| 2445 | || offset == DUMP_OBJECT_NOT_SEEN); | 2442 | || offset == DUMP_OBJECT_NOT_SEEN); |
| 2446 | DUMP_CLEAR_REFERRER (ctx); | 2443 | dump_clear_referrer (ctx); |
| 2447 | struct dump_flags old_flags = ctx->flags; | 2444 | struct dump_flags old_flags = ctx->flags; |
| 2448 | ctx->flags.dump_object_contents = false; | 2445 | ctx->flags.dump_object_contents = false; |
| 2449 | ctx->flags.defer_symbols = false; | 2446 | ctx->flags.defer_symbols = false; |
| 2450 | dump_object (ctx, object); | 2447 | dump_object (ctx, object); |
| 2451 | ctx->flags = old_flags; | 2448 | ctx->flags = old_flags; |
| 2452 | DUMP_SET_REFERRER (ctx, object); | 2449 | if (dump_set_referrer (ctx)) |
| 2450 | ctx->current_referrer = object; | ||
| 2453 | 2451 | ||
| 2454 | offset = DUMP_OBJECT_ON_SYMBOL_QUEUE; | 2452 | offset = DUMP_OBJECT_ON_SYMBOL_QUEUE; |
| 2455 | dump_remember_object (ctx, object, offset); | 2453 | dump_remember_object (ctx, object, offset); |
| @@ -2696,7 +2694,7 @@ dump_hash_table (struct dump_context *ctx, | |||
| 2696 | Lisp_Object object, | 2694 | Lisp_Object object, |
| 2697 | dump_off offset) | 2695 | dump_off offset) |
| 2698 | { | 2696 | { |
| 2699 | #if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_BB1ACF756E | 2697 | #if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_12AFBF47AF |
| 2700 | # error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h." | 2698 | # error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h." |
| 2701 | #endif | 2699 | #endif |
| 2702 | const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object); | 2700 | const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object); |
| @@ -3118,7 +3116,8 @@ dump_object (struct dump_context *ctx, Lisp_Object object) | |||
| 3118 | } | 3116 | } |
| 3119 | 3117 | ||
| 3120 | /* Object needs to be dumped. */ | 3118 | /* Object needs to be dumped. */ |
| 3121 | DUMP_SET_REFERRER (ctx, object); | 3119 | if (dump_set_referrer (ctx)) |
| 3120 | ctx->current_referrer = object; | ||
| 3122 | switch (XTYPE (object)) | 3121 | switch (XTYPE (object)) |
| 3123 | { | 3122 | { |
| 3124 | case Lisp_String: | 3123 | case Lisp_String: |
| @@ -3142,7 +3141,7 @@ dump_object (struct dump_context *ctx, Lisp_Object object) | |||
| 3142 | default: | 3141 | default: |
| 3143 | emacs_abort (); | 3142 | emacs_abort (); |
| 3144 | } | 3143 | } |
| 3145 | DUMP_CLEAR_REFERRER (ctx); | 3144 | dump_clear_referrer (ctx); |
| 3146 | 3145 | ||
| 3147 | /* offset can be < 0 if we've deferred an object. */ | 3146 | /* offset can be < 0 if we've deferred an object. */ |
| 3148 | if (ctx->flags.dump_object_contents && offset > DUMP_OBJECT_NOT_SEEN) | 3147 | if (ctx->flags.dump_object_contents && offset > DUMP_OBJECT_NOT_SEEN) |
| @@ -3397,19 +3396,18 @@ dump_cold_buffer (struct dump_context *ctx, Lisp_Object data) | |||
| 3397 | static void | 3396 | static void |
| 3398 | dump_cold_bignum (struct dump_context *ctx, Lisp_Object object) | 3397 | dump_cold_bignum (struct dump_context *ctx, Lisp_Object object) |
| 3399 | { | 3398 | { |
| 3400 | const struct Lisp_Bignum *bignum = XBIGNUM (object); | 3399 | mpz_t const *n = xbignum_val (object); |
| 3401 | size_t sz_nlimbs = mpz_size (bignum->value); | 3400 | size_t sz_nlimbs = mpz_size (*n); |
| 3402 | eassert (sz_nlimbs < DUMP_OFF_MAX); | 3401 | eassert (sz_nlimbs < DUMP_OFF_MAX); |
| 3403 | dump_align_output (ctx, alignof (mp_limb_t)); | 3402 | dump_align_output (ctx, alignof (mp_limb_t)); |
| 3404 | dump_off nlimbs = (dump_off) sz_nlimbs; | 3403 | dump_off nlimbs = (dump_off) sz_nlimbs; |
| 3405 | Lisp_Object descriptor | 3404 | Lisp_Object descriptor |
| 3406 | = list2 (dump_off_to_lisp (ctx->offset), | 3405 | = list2 (dump_off_to_lisp (ctx->offset), |
| 3407 | dump_off_to_lisp ((mpz_sgn (bignum->value) < 0 | 3406 | dump_off_to_lisp (mpz_sgn (*n) < 0 ? -nlimbs : nlimbs)); |
| 3408 | ? -nlimbs : nlimbs))); | ||
| 3409 | Fputhash (object, descriptor, ctx->bignum_data); | 3407 | Fputhash (object, descriptor, ctx->bignum_data); |
| 3410 | for (mp_size_t i = 0; i < nlimbs; ++i) | 3408 | for (mp_size_t i = 0; i < nlimbs; ++i) |
| 3411 | { | 3409 | { |
| 3412 | mp_limb_t limb = mpz_getlimbn (bignum->value, i); | 3410 | mp_limb_t limb = mpz_getlimbn (*n, i); |
| 3413 | dump_write (ctx, &limb, sizeof (limb)); | 3411 | dump_write (ctx, &limb, sizeof (limb)); |
| 3414 | } | 3412 | } |
| 3415 | } | 3413 | } |
| @@ -3508,9 +3506,10 @@ dump_drain_user_remembered_data_hot (struct dump_context *ctx) | |||
| 3508 | read_ptr_raw_and_lv (mem, type, &value, &lv); | 3506 | read_ptr_raw_and_lv (mem, type, &value, &lv); |
| 3509 | if (value != NULL) | 3507 | if (value != NULL) |
| 3510 | { | 3508 | { |
| 3511 | DUMP_SET_REFERRER (ctx, dump_ptr_referrer ("user data", mem)); | 3509 | if (dump_set_referrer (ctx)) |
| 3510 | ctx->current_referrer = dump_ptr_referrer ("user data", mem); | ||
| 3512 | dump_enqueue_object (ctx, lv, WEIGHT_NONE); | 3511 | dump_enqueue_object (ctx, lv, WEIGHT_NONE); |
| 3513 | DUMP_CLEAR_REFERRER (ctx); | 3512 | dump_clear_referrer (ctx); |
| 3514 | } | 3513 | } |
| 3515 | } | 3514 | } |
| 3516 | } | 3515 | } |
| @@ -4735,7 +4734,7 @@ dump_mmap_release_vm (struct dump_memory_map *map) | |||
| 4735 | static bool | 4734 | static bool |
| 4736 | needs_mmap_retry_p (void) | 4735 | needs_mmap_retry_p (void) |
| 4737 | { | 4736 | { |
| 4738 | #if defined (CYGWIN) || VM_SUPPORTED == VM_MS_WINDOWS | 4737 | #if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS || defined _AIX |
| 4739 | return true; | 4738 | return true; |
| 4740 | #else | 4739 | #else |
| 4741 | return false; | 4740 | return false; |
| @@ -4878,7 +4877,7 @@ dump_bitset_init (struct dump_bitset *bitset, size_t number_bits) | |||
| 4878 | { | 4877 | { |
| 4879 | int xword_size = sizeof (bitset->bits[0]); | 4878 | int xword_size = sizeof (bitset->bits[0]); |
| 4880 | int bits_per_word = xword_size * CHAR_BIT; | 4879 | int bits_per_word = xword_size * CHAR_BIT; |
| 4881 | ptrdiff_t words_needed = DIVIDE_ROUND_UP (number_bits, bits_per_word); | 4880 | ptrdiff_t words_needed = divide_round_up (number_bits, bits_per_word); |
| 4882 | bitset->number_words = words_needed; | 4881 | bitset->number_words = words_needed; |
| 4883 | bitset->bits = calloc (words_needed, xword_size); | 4882 | bitset->bits = calloc (words_needed, xword_size); |
| 4884 | return bitset->bits != NULL; | 4883 | return bitset->bits != NULL; |
| @@ -5058,7 +5057,7 @@ pdumper_cold_object_p_impl (const void *obj) | |||
| 5058 | return offset >= dump_private.header.cold_start; | 5057 | return offset >= dump_private.header.cold_start; |
| 5059 | } | 5058 | } |
| 5060 | 5059 | ||
| 5061 | enum Lisp_Type | 5060 | int |
| 5062 | pdumper_find_object_type_impl (const void *obj) | 5061 | pdumper_find_object_type_impl (const void *obj) |
| 5063 | { | 5062 | { |
| 5064 | eassert (pdumper_object_p (obj)); | 5063 | eassert (pdumper_object_p (obj)); |
| @@ -5068,7 +5067,7 @@ pdumper_find_object_type_impl (const void *obj) | |||
| 5068 | const struct dump_reloc *reloc = | 5067 | const struct dump_reloc *reloc = |
| 5069 | dump_find_relocation (&dump_private.header.object_starts, offset); | 5068 | dump_find_relocation (&dump_private.header.object_starts, offset); |
| 5070 | return (reloc != NULL && dump_reloc_get_offset (*reloc) == offset) | 5069 | return (reloc != NULL && dump_reloc_get_offset (*reloc) == offset) |
| 5071 | ? (enum Lisp_Type) reloc->type | 5070 | ? reloc->type |
| 5072 | : PDUMPER_NO_OBJECT; | 5071 | : PDUMPER_NO_OBJECT; |
| 5073 | } | 5072 | } |
| 5074 | 5073 | ||
| @@ -5205,8 +5204,8 @@ dump_do_dump_relocation (const uintptr_t dump_base, | |||
| 5205 | { | 5204 | { |
| 5206 | struct Lisp_Bignum *bignum = dump_ptr (dump_base, reloc_offset); | 5205 | struct Lisp_Bignum *bignum = dump_ptr (dump_base, reloc_offset); |
| 5207 | struct bignum_reload_info reload_info; | 5206 | struct bignum_reload_info reload_info; |
| 5208 | verify (sizeof (reload_info) <= sizeof (bignum->value)); | 5207 | verify (sizeof (reload_info) <= sizeof (*bignum_val (bignum))); |
| 5209 | memcpy (&reload_info, &bignum->value, sizeof (reload_info)); | 5208 | memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info)); |
| 5210 | const mp_limb_t *limbs = | 5209 | const mp_limb_t *limbs = |
| 5211 | dump_ptr (dump_base, reload_info.data_location); | 5210 | dump_ptr (dump_base, reload_info.data_location); |
| 5212 | mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs); | 5211 | mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs); |
| @@ -5421,7 +5420,7 @@ pdumper_load (const char *dump_filename) | |||
| 5421 | 5420 | ||
| 5422 | err = PDUMPER_LOAD_ERROR; | 5421 | err = PDUMPER_LOAD_ERROR; |
| 5423 | mark_bits_needed = | 5422 | mark_bits_needed = |
| 5424 | DIVIDE_ROUND_UP (header->discardable_start, DUMP_ALIGNMENT); | 5423 | divide_round_up (header->discardable_start, DUMP_ALIGNMENT); |
| 5425 | if (!dump_bitset_init (&mark_bits, mark_bits_needed)) | 5424 | if (!dump_bitset_init (&mark_bits, mark_bits_needed)) |
| 5426 | goto out; | 5425 | goto out; |
| 5427 | 5426 | ||
diff --git a/src/pdumper.h b/src/pdumper.h index 5d1e9c3aea3..83c094f3caa 100644 --- a/src/pdumper.h +++ b/src/pdumper.h | |||
| @@ -24,7 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 24 | 24 | ||
| 25 | INLINE_HEADER_BEGIN | 25 | INLINE_HEADER_BEGIN |
| 26 | 26 | ||
| 27 | #define PDUMPER_NO_OBJECT ((enum Lisp_Type) -1) | 27 | enum { PDUMPER_NO_OBJECT = -1 }; |
| 28 | 28 | ||
| 29 | /* Indicate in source code that we're deliberately relying on pdumper | 29 | /* Indicate in source code that we're deliberately relying on pdumper |
| 30 | not preserving the given value. Compiles to nothing --- for humans | 30 | not preserving the given value. Compiles to nothing --- for humans |
| @@ -170,12 +170,12 @@ pdumper_cold_object_p (const void *obj) | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | 172 | ||
| 173 | extern enum Lisp_Type pdumper_find_object_type_impl (const void *obj); | 173 | extern int pdumper_find_object_type_impl (const void *obj); |
| 174 | 174 | ||
| 175 | /* Return the type of the dumped object that starts at OBJ. It is a | 175 | /* Return the type of the dumped object that starts at OBJ. It is a |
| 176 | programming error to call this routine for an OBJ for which | 176 | programming error to call this routine for an OBJ for which |
| 177 | pdumper_object_p would return false. */ | 177 | pdumper_object_p would return false. */ |
| 178 | INLINE _GL_ATTRIBUTE_CONST enum Lisp_Type | 178 | INLINE _GL_ATTRIBUTE_CONST int |
| 179 | pdumper_find_object_type (const void *obj) | 179 | pdumper_find_object_type (const void *obj) |
| 180 | { | 180 | { |
| 181 | #ifdef HAVE_PDUMPER | 181 | #ifdef HAVE_PDUMPER |
| @@ -186,6 +186,14 @@ pdumper_find_object_type (const void *obj) | |||
| 186 | #endif | 186 | #endif |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | /* Return true if TYPE is that of a Lisp object. | ||
| 190 | PDUMPER_NO_OBJECT is invalid. */ | ||
| 191 | INLINE bool | ||
| 192 | pdumper_valid_object_type_p (int type) | ||
| 193 | { | ||
| 194 | return 0 <= type; | ||
| 195 | } | ||
| 196 | |||
| 189 | /* Return whether OBJ points exactly to the start of some object in | 197 | /* Return whether OBJ points exactly to the start of some object in |
| 190 | the loaded dump image. It is a programming error to call this | 198 | the loaded dump image. It is a programming error to call this |
| 191 | routine for an OBJ for which pdumper_object_p would return | 199 | routine for an OBJ for which pdumper_object_p would return |
| @@ -194,7 +202,7 @@ INLINE _GL_ATTRIBUTE_CONST bool | |||
| 194 | pdumper_object_p_precise (const void *obj) | 202 | pdumper_object_p_precise (const void *obj) |
| 195 | { | 203 | { |
| 196 | #ifdef HAVE_PDUMPER | 204 | #ifdef HAVE_PDUMPER |
| 197 | return pdumper_find_object_type (obj) != PDUMPER_NO_OBJECT; | 205 | return pdumper_valid_object_type_p (pdumper_find_object_type (obj)); |
| 198 | #else | 206 | #else |
| 199 | (void) obj; | 207 | (void) obj; |
| 200 | emacs_abort (); | 208 | emacs_abort (); |
diff --git a/src/process.c b/src/process.c index 066edbc83d6..372277a953d 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -276,6 +276,10 @@ static int read_process_output (Lisp_Object, int); | |||
| 276 | static void create_pty (Lisp_Object); | 276 | static void create_pty (Lisp_Object); |
| 277 | static void exec_sentinel (Lisp_Object, Lisp_Object); | 277 | static void exec_sentinel (Lisp_Object, Lisp_Object); |
| 278 | 278 | ||
| 279 | static Lisp_Object | ||
| 280 | network_lookup_address_info_1 (Lisp_Object host, const char *service, | ||
| 281 | struct addrinfo *hints, struct addrinfo **res); | ||
| 282 | |||
| 279 | /* Number of bits set in connect_wait_mask. */ | 283 | /* Number of bits set in connect_wait_mask. */ |
| 280 | static int num_pending_connects; | 284 | static int num_pending_connects; |
| 281 | 285 | ||
| @@ -4106,7 +4110,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 4106 | if (!NILP (host)) | 4110 | if (!NILP (host)) |
| 4107 | { | 4111 | { |
| 4108 | struct addrinfo *res, *lres; | 4112 | struct addrinfo *res, *lres; |
| 4109 | int ret; | 4113 | Lisp_Object msg; |
| 4110 | 4114 | ||
| 4111 | maybe_quit (); | 4115 | maybe_quit (); |
| 4112 | 4116 | ||
| @@ -4115,20 +4119,9 @@ usage: (make-network-process &rest ARGS) */) | |||
| 4115 | hints.ai_family = family; | 4119 | hints.ai_family = family; |
| 4116 | hints.ai_socktype = socktype; | 4120 | hints.ai_socktype = socktype; |
| 4117 | 4121 | ||
| 4118 | ret = getaddrinfo (SSDATA (host), portstring, &hints, &res); | 4122 | msg = network_lookup_address_info_1 (host, portstring, &hints, &res); |
| 4119 | if (ret) | 4123 | if (!EQ (msg, Qt)) |
| 4120 | #ifdef HAVE_GAI_STRERROR | 4124 | error ("%s", SSDATA (msg)); |
| 4121 | { | ||
| 4122 | synchronize_system_messages_locale (); | ||
| 4123 | char const *str = gai_strerror (ret); | ||
| 4124 | if (! NILP (Vlocale_coding_system)) | ||
| 4125 | str = SSDATA (code_convert_string_norecord | ||
| 4126 | (build_string (str), Vlocale_coding_system, 0)); | ||
| 4127 | error ("%s/%s %s", SSDATA (host), portstring, str); | ||
| 4128 | } | ||
| 4129 | #else | ||
| 4130 | error ("%s/%s getaddrinfo error %d", SSDATA (host), portstring, ret); | ||
| 4131 | #endif | ||
| 4132 | 4125 | ||
| 4133 | for (lres = res; lres; lres = lres->ai_next) | 4126 | for (lres = res; lres; lres = lres->ai_next) |
| 4134 | addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); | 4127 | addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); |
| @@ -4576,6 +4569,86 @@ Data that is unavailable is returned as nil. */) | |||
| 4576 | #endif | 4569 | #endif |
| 4577 | } | 4570 | } |
| 4578 | 4571 | ||
| 4572 | static Lisp_Object | ||
| 4573 | network_lookup_address_info_1 (Lisp_Object host, const char *service, | ||
| 4574 | struct addrinfo *hints, struct addrinfo **res) | ||
| 4575 | { | ||
| 4576 | Lisp_Object msg = Qt; | ||
| 4577 | int ret; | ||
| 4578 | |||
| 4579 | if (STRING_MULTIBYTE (host) && SBYTES (host) != SCHARS (host)) | ||
| 4580 | error ("Non-ASCII hostname %s detected, please use puny-encode-domain", | ||
| 4581 | SSDATA (host)); | ||
| 4582 | ret = getaddrinfo (SSDATA (host), service, hints, res); | ||
| 4583 | if (ret) | ||
| 4584 | { | ||
| 4585 | if (service == NULL) | ||
| 4586 | service = "0"; | ||
| 4587 | #ifdef HAVE_GAI_STRERROR | ||
| 4588 | synchronize_system_messages_locale (); | ||
| 4589 | char const *str = gai_strerror (ret); | ||
| 4590 | if (! NILP (Vlocale_coding_system)) | ||
| 4591 | str = SSDATA (code_convert_string_norecord | ||
| 4592 | (build_string (str), Vlocale_coding_system, 0)); | ||
| 4593 | AUTO_STRING (format, "%s/%s %s"); | ||
| 4594 | msg = CALLN (Fformat, format, host, build_string (service), | ||
| 4595 | build_string (str)); | ||
| 4596 | #else | ||
| 4597 | AUTO_STRING (format, "%s/%s getaddrinfo error %d"); | ||
| 4598 | msg = CALLN (Fformat, format, host, build_string (service), | ||
| 4599 | make_int (ret)); | ||
| 4600 | #endif | ||
| 4601 | } | ||
| 4602 | return msg; | ||
| 4603 | } | ||
| 4604 | |||
| 4605 | DEFUN ("network-lookup-address-info", Fnetwork_lookup_address_info, | ||
| 4606 | Snetwork_lookup_address_info, 1, 2, 0, | ||
| 4607 | doc: /* Look up ip address info of NAME. | ||
| 4608 | Optional parameter FAMILY controls whether to look up IPv4 or IPv6 | ||
| 4609 | addresses. The default of nil means both, symbol `ipv4' means IPv4 | ||
| 4610 | only, symbol `ipv6' means IPv6 only. Returns a list of addresses, or | ||
| 4611 | nil if none were found. Each address is a vector of integers. */) | ||
| 4612 | (Lisp_Object name, Lisp_Object family) | ||
| 4613 | { | ||
| 4614 | Lisp_Object addresses = Qnil; | ||
| 4615 | Lisp_Object msg = Qnil; | ||
| 4616 | |||
| 4617 | struct addrinfo *res, *lres; | ||
| 4618 | struct addrinfo hints; | ||
| 4619 | |||
| 4620 | memset (&hints, 0, sizeof hints); | ||
| 4621 | if (EQ (family, Qnil)) | ||
| 4622 | hints.ai_family = AF_UNSPEC; | ||
| 4623 | else if (EQ (family, Qipv4)) | ||
| 4624 | hints.ai_family = AF_INET; | ||
| 4625 | else if (EQ (family, Qipv6)) | ||
| 4626 | #ifdef AF_INET6 | ||
| 4627 | hints.ai_family = AF_INET6; | ||
| 4628 | #else | ||
| 4629 | /* If we don't support IPv6, querying will never work anyway */ | ||
| 4630 | return addresses; | ||
| 4631 | #endif | ||
| 4632 | else | ||
| 4633 | error ("Unsupported lookup type"); | ||
| 4634 | hints.ai_socktype = SOCK_DGRAM; | ||
| 4635 | |||
| 4636 | msg = network_lookup_address_info_1 (name, NULL, &hints, &res); | ||
| 4637 | if (!EQ (msg, Qt)) | ||
| 4638 | message ("%s", SSDATA(msg)); | ||
| 4639 | else | ||
| 4640 | { | ||
| 4641 | for (lres = res; lres; lres = lres->ai_next) | ||
| 4642 | addresses = Fcons (conv_sockaddr_to_lisp (lres->ai_addr, | ||
| 4643 | lres->ai_addrlen), | ||
| 4644 | addresses); | ||
| 4645 | addresses = Fnreverse (addresses); | ||
| 4646 | |||
| 4647 | freeaddrinfo (res); | ||
| 4648 | } | ||
| 4649 | return addresses; | ||
| 4650 | } | ||
| 4651 | |||
| 4579 | /* Turn off input and output for process PROC. */ | 4652 | /* Turn off input and output for process PROC. */ |
| 4580 | 4653 | ||
| 4581 | static void | 4654 | static void |
| @@ -8345,6 +8418,7 @@ returns non-`nil'. */); | |||
| 8345 | defsubr (&Sset_network_process_option); | 8418 | defsubr (&Sset_network_process_option); |
| 8346 | defsubr (&Smake_network_process); | 8419 | defsubr (&Smake_network_process); |
| 8347 | defsubr (&Sformat_network_address); | 8420 | defsubr (&Sformat_network_address); |
| 8421 | defsubr (&Snetwork_lookup_address_info); | ||
| 8348 | defsubr (&Snetwork_interface_list); | 8422 | defsubr (&Snetwork_interface_list); |
| 8349 | defsubr (&Snetwork_interface_info); | 8423 | defsubr (&Snetwork_interface_info); |
| 8350 | #ifdef DATAGRAM_SOCKETS | 8424 | #ifdef DATAGRAM_SOCKETS |
diff --git a/src/sound.c b/src/sound.c index 4ba826e82c4..44d4cbc6d56 100644 --- a/src/sound.c +++ b/src/sound.c | |||
| @@ -72,12 +72,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 72 | #include <soundcard.h> | 72 | #include <soundcard.h> |
| 73 | #endif | 73 | #endif |
| 74 | #ifdef HAVE_ALSA | 74 | #ifdef HAVE_ALSA |
| 75 | #ifdef ALSA_SUBDIR_INCLUDE | ||
| 76 | #include <alsa/asoundlib.h> | 75 | #include <alsa/asoundlib.h> |
| 77 | #else | 76 | #endif |
| 78 | #include <asoundlib.h> | ||
| 79 | #endif /* ALSA_SUBDIR_INCLUDE */ | ||
| 80 | #endif /* HAVE_ALSA */ | ||
| 81 | 77 | ||
| 82 | /* END: Non Windows Includes */ | 78 | /* END: Non Windows Includes */ |
| 83 | 79 | ||
diff --git a/src/sysdep.c b/src/sysdep.c index f7478253a35..aa18ee22fd5 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -2810,12 +2810,6 @@ errputc (int c) | |||
| 2810 | } | 2810 | } |
| 2811 | 2811 | ||
| 2812 | void | 2812 | void |
| 2813 | verrprintf (char const *fmt, va_list ap) | ||
| 2814 | { | ||
| 2815 | vfprintf (errstream (), fmt, ap); | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | void | ||
| 2819 | errwrite (void const *buf, ptrdiff_t nbuf) | 2813 | errwrite (void const *buf, ptrdiff_t nbuf) |
| 2820 | { | 2814 | { |
| 2821 | fwrite_unlocked (buf, 1, nbuf, errstream ()); | 2815 | fwrite_unlocked (buf, 1, nbuf, errstream ()); |
diff --git a/src/sysstdio.h b/src/sysstdio.h index f402bd633d4..1e1180a4d31 100644 --- a/src/sysstdio.h +++ b/src/sysstdio.h | |||
| @@ -28,7 +28,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | 28 | ||
| 29 | extern FILE *emacs_fopen (char const *, char const *); | 29 | extern FILE *emacs_fopen (char const *, char const *); |
| 30 | extern void errputc (int); | 30 | extern void errputc (int); |
| 31 | extern void verrprintf (char const *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); | ||
| 32 | extern void errwrite (void const *, ptrdiff_t); | 31 | extern void errwrite (void const *, ptrdiff_t); |
| 33 | extern void close_output_streams (void); | 32 | extern void close_output_streams (void); |
| 34 | 33 | ||
diff --git a/src/systime.h b/src/systime.h index 125b2f1385e..2f783efcfca 100644 --- a/src/systime.h +++ b/src/systime.h | |||
| @@ -41,6 +41,8 @@ typedef unsigned long Time; | |||
| 41 | #endif | 41 | #endif |
| 42 | 42 | ||
| 43 | #include <sys/time.h> /* for 'struct timeval' */ | 43 | #include <sys/time.h> /* for 'struct timeval' */ |
| 44 | |||
| 45 | #undef hz /* AIX <sys/param.h> #defines this. */ | ||
| 44 | 46 | ||
| 45 | /* Emacs uses struct timespec to represent nonnegative temporal intervals. | 47 | /* Emacs uses struct timespec to represent nonnegative temporal intervals. |
| 46 | 48 | ||
diff --git a/src/timefns.c b/src/timefns.c index 2d545a4f905..c1e3141c4cf 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -91,7 +91,7 @@ static Lisp_Object timespec_hz; | |||
| 91 | #define TRILLION 1000000000000 | 91 | #define TRILLION 1000000000000 |
| 92 | #if FIXNUM_OVERFLOW_P (TRILLION) | 92 | #if FIXNUM_OVERFLOW_P (TRILLION) |
| 93 | static Lisp_Object trillion; | 93 | static Lisp_Object trillion; |
| 94 | # define ztrillion (XBIGNUM (trillion)->value) | 94 | # define ztrillion (*xbignum_val (trillion)) |
| 95 | #else | 95 | #else |
| 96 | # define trillion make_fixnum (TRILLION) | 96 | # define trillion make_fixnum (TRILLION) |
| 97 | # if ULONG_MAX < TRILLION || !FASTER_TIMEFNS | 97 | # if ULONG_MAX < TRILLION || !FASTER_TIMEFNS |
| @@ -99,6 +99,22 @@ mpz_t ztrillion; | |||
| 99 | # endif | 99 | # endif |
| 100 | #endif | 100 | #endif |
| 101 | 101 | ||
| 102 | /* True if the nonzero Lisp integer HZ divides evenly into a trillion. */ | ||
| 103 | static bool | ||
| 104 | trillion_factor (Lisp_Object hz) | ||
| 105 | { | ||
| 106 | if (FASTER_TIMEFNS) | ||
| 107 | { | ||
| 108 | if (FIXNUMP (hz)) | ||
| 109 | return TRILLION % XFIXNUM (hz) == 0; | ||
| 110 | if (!FIXNUM_OVERFLOW_P (TRILLION)) | ||
| 111 | return false; | ||
| 112 | } | ||
| 113 | verify (TRILLION <= INTMAX_MAX); | ||
| 114 | intmax_t ihz; | ||
| 115 | return integer_to_intmax (hz, &ihz) && TRILLION % ihz == 0; | ||
| 116 | } | ||
| 117 | |||
| 102 | /* Return a struct timeval that is roughly equivalent to T. | 118 | /* Return a struct timeval that is roughly equivalent to T. |
| 103 | Use the least timeval not less than T. | 119 | Use the least timeval not less than T. |
| 104 | Return an extremal value if the result would overflow. */ | 120 | Return an extremal value if the result would overflow. */ |
| @@ -391,16 +407,36 @@ decode_float_time (double t, struct lisp_time *result) | |||
| 391 | else | 407 | else |
| 392 | { | 408 | { |
| 393 | int exponent = ilogb (t); | 409 | int exponent = ilogb (t); |
| 394 | if (exponent == FP_ILOGBNAN) | 410 | int scale; |
| 395 | return EINVAL; | 411 | if (exponent < DBL_MANT_DIG) |
| 396 | 412 | { | |
| 397 | /* An enormous or infinite T would make SCALE < 0 which would make | 413 | if (exponent < DBL_MIN_EXP - 1) |
| 398 | HZ < 1, which the (TICKS . HZ) representation does not allow. */ | 414 | { |
| 399 | if (DBL_MANT_DIG - 1 < exponent) | 415 | if (exponent == FP_ILOGBNAN |
| 400 | return EOVERFLOW; | 416 | && (FP_ILOGBNAN != FP_ILOGB0 || isnan (t))) |
| 401 | 417 | return EINVAL; | |
| 402 | /* min so we don't scale tiny numbers as if they were normalized. */ | 418 | /* T is tiny. SCALE must be less than FLT_RADIX_POWER_SIZE, |
| 403 | int scale = min (DBL_MANT_DIG - 1 - exponent, flt_radix_power_size - 1); | 419 | as otherwise T would be scaled as if it were normalized. */ |
| 420 | scale = flt_radix_power_size - 1; | ||
| 421 | } | ||
| 422 | else | ||
| 423 | { | ||
| 424 | /* The typical case. */ | ||
| 425 | scale = DBL_MANT_DIG - 1 - exponent; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | else if (exponent < INT_MAX) | ||
| 429 | { | ||
| 430 | /* T is finite but so large that HZ would be less than 1 if | ||
| 431 | T's precision were represented exactly. SCALE must be | ||
| 432 | nonnegative, as the (TICKS . HZ) representation requires | ||
| 433 | HZ to be at least 1. So use SCALE = 0, which converts T to | ||
| 434 | (T . 1), which is the exact numeric value with too-large HZ, | ||
| 435 | which is typically better than signaling overflow. */ | ||
| 436 | scale = 0; | ||
| 437 | } | ||
| 438 | else | ||
| 439 | return FP_ILOGBNAN == INT_MAX && isnan (t) ? EINVAL : EOVERFLOW; | ||
| 404 | 440 | ||
| 405 | double scaled = scalbn (t, scale); | 441 | double scaled = scalbn (t, scale); |
| 406 | eassert (trunc (scaled) == scaled); | 442 | eassert (trunc (scaled) == scaled); |
| @@ -498,7 +534,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) | |||
| 498 | return make_int (ticks / XFIXNUM (t.hz) | 534 | return make_int (ticks / XFIXNUM (t.hz) |
| 499 | - (ticks % XFIXNUM (t.hz) < 0)); | 535 | - (ticks % XFIXNUM (t.hz) < 0)); |
| 500 | } | 536 | } |
| 501 | else if (! (BIGNUMP (hz) && 0 < mpz_sgn (XBIGNUM (hz)->value))) | 537 | else if (! (BIGNUMP (hz) && 0 < mpz_sgn (*xbignum_val (hz)))) |
| 502 | invalid_hz (hz); | 538 | invalid_hz (hz); |
| 503 | 539 | ||
| 504 | mpz_mul (mpz[0], | 540 | mpz_mul (mpz[0], |
| @@ -661,18 +697,10 @@ enum timeform | |||
| 661 | TIMEFORM_HI_LO_US, /* seconds plus microseconds (HI LO US) */ | 697 | TIMEFORM_HI_LO_US, /* seconds plus microseconds (HI LO US) */ |
| 662 | TIMEFORM_NIL, /* current time in nanoseconds */ | 698 | TIMEFORM_NIL, /* current time in nanoseconds */ |
| 663 | TIMEFORM_HI_LO_US_PS, /* seconds plus micro and picoseconds (HI LO US PS) */ | 699 | TIMEFORM_HI_LO_US_PS, /* seconds plus micro and picoseconds (HI LO US PS) */ |
| 664 | /* These two should be last; see timeform_sub_ps_p. */ | ||
| 665 | TIMEFORM_FLOAT, /* time as a float */ | 700 | TIMEFORM_FLOAT, /* time as a float */ |
| 666 | TIMEFORM_TICKS_HZ /* fractional time: HI is ticks, LO is ticks per second */ | 701 | TIMEFORM_TICKS_HZ /* fractional time: HI is ticks, LO is ticks per second */ |
| 667 | }; | 702 | }; |
| 668 | 703 | ||
| 669 | /* True if Lisp times of form FORM can express sub-picosecond timestamps. */ | ||
| 670 | static bool | ||
| 671 | timeform_sub_ps_p (enum timeform form) | ||
| 672 | { | ||
| 673 | return TIMEFORM_FLOAT <= form; | ||
| 674 | } | ||
| 675 | |||
| 676 | /* From the valid form FORM and the time components HIGH, LOW, USEC | 704 | /* From the valid form FORM and the time components HIGH, LOW, USEC |
| 677 | and PSEC, generate the corresponding time value. If LOW is | 705 | and PSEC, generate the corresponding time value. If LOW is |
| 678 | floating point, the other components should be zero and FORM should | 706 | floating point, the other components should be zero and FORM should |
| @@ -878,6 +906,7 @@ lisp_to_timespec (struct lisp_time t) | |||
| 878 | struct timespec result = invalid_timespec (); | 906 | struct timespec result = invalid_timespec (); |
| 879 | int ns; | 907 | int ns; |
| 880 | mpz_t *q = &mpz[0]; | 908 | mpz_t *q = &mpz[0]; |
| 909 | mpz_t const *qt = q; | ||
| 881 | 910 | ||
| 882 | if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) | 911 | if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) |
| 883 | { | 912 | { |
| @@ -896,7 +925,7 @@ lisp_to_timespec (struct lisp_time t) | |||
| 896 | return result; | 925 | return result; |
| 897 | } | 926 | } |
| 898 | else | 927 | else |
| 899 | ns = mpz_fdiv_q_ui (*q, XBIGNUM (t.ticks)->value, TIMESPEC_HZ); | 928 | ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ); |
| 900 | } | 929 | } |
| 901 | else if (FASTER_TIMEFNS && EQ (t.hz, make_fixnum (1))) | 930 | else if (FASTER_TIMEFNS && EQ (t.hz, make_fixnum (1))) |
| 902 | { | 931 | { |
| @@ -913,7 +942,7 @@ lisp_to_timespec (struct lisp_time t) | |||
| 913 | return result; | 942 | return result; |
| 914 | } | 943 | } |
| 915 | else | 944 | else |
| 916 | q = &XBIGNUM (t.ticks)->value; | 945 | qt = xbignum_val (t.ticks); |
| 917 | } | 946 | } |
| 918 | else | 947 | else |
| 919 | { | 948 | { |
| @@ -925,7 +954,7 @@ lisp_to_timespec (struct lisp_time t) | |||
| 925 | /* With some versions of MinGW, tv_sec is a 64-bit type, whereas | 954 | /* With some versions of MinGW, tv_sec is a 64-bit type, whereas |
| 926 | time_t is a 32-bit type. */ | 955 | time_t is a 32-bit type. */ |
| 927 | time_t sec; | 956 | time_t sec; |
| 928 | if (mpz_time (*q, &sec)) | 957 | if (mpz_time (*qt, &sec)) |
| 929 | { | 958 | { |
| 930 | result.tv_sec = sec; | 959 | result.tv_sec = sec; |
| 931 | result.tv_nsec = ns; | 960 | result.tv_nsec = ns; |
| @@ -1010,7 +1039,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract) | |||
| 1010 | if (eabs (XFIXNUM (b)) <= ULONG_MAX) | 1039 | if (eabs (XFIXNUM (b)) <= ULONG_MAX) |
| 1011 | { | 1040 | { |
| 1012 | ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui) | 1041 | ((XFIXNUM (b) < 0) == subtract ? mpz_add_ui : mpz_sub_ui) |
| 1013 | (mpz[0], XBIGNUM (a)->value, eabs (XFIXNUM (b))); | 1042 | (mpz[0], *xbignum_val (a), eabs (XFIXNUM (b))); |
| 1014 | mpz_done = true; | 1043 | mpz_done = true; |
| 1015 | } | 1044 | } |
| 1016 | } | 1045 | } |
| @@ -1060,9 +1089,14 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) | |||
| 1060 | else | 1089 | else |
| 1061 | { | 1090 | { |
| 1062 | /* The plan is to decompose ta into na/da and tb into nb/db. | 1091 | /* The plan is to decompose ta into na/da and tb into nb/db. |
| 1063 | Start by computing da and db. */ | 1092 | Start by computing da and db, their minimum (which will be |
| 1093 | needed later) and the iticks temporary that will become | ||
| 1094 | available once only their minimum is needed. */ | ||
| 1064 | mpz_t const *da = bignum_integer (&mpz[1], ta.hz); | 1095 | mpz_t const *da = bignum_integer (&mpz[1], ta.hz); |
| 1065 | mpz_t const *db = bignum_integer (&mpz[2], tb.hz); | 1096 | mpz_t const *db = bignum_integer (&mpz[2], tb.hz); |
| 1097 | bool da_lt_db = mpz_cmp (*da, *db) < 0; | ||
| 1098 | mpz_t const *hzmin = da_lt_db ? da : db; | ||
| 1099 | mpz_t *iticks = &mpz[da_lt_db + 1]; | ||
| 1066 | 1100 | ||
| 1067 | /* The plan is to compute (na * (db/g) + nb * (da/g)) / lcm (da, db) | 1101 | /* The plan is to compute (na * (db/g) + nb * (da/g)) / lcm (da, db) |
| 1068 | where g = gcd (da, db). Start by computing g. */ | 1102 | where g = gcd (da, db). Start by computing g. */ |
| @@ -1070,34 +1104,83 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) | |||
| 1070 | mpz_gcd (*g, *da, *db); | 1104 | mpz_gcd (*g, *da, *db); |
| 1071 | 1105 | ||
| 1072 | /* fa = da/g, fb = db/g. */ | 1106 | /* fa = da/g, fb = db/g. */ |
| 1073 | mpz_t *fa = &mpz[1], *fb = &mpz[3]; | 1107 | mpz_t *fa = &mpz[4], *fb = &mpz[3]; |
| 1074 | mpz_tdiv_q (*fa, *da, *g); | 1108 | mpz_divexact (*fa, *da, *g); |
| 1075 | mpz_tdiv_q (*fb, *db, *g); | 1109 | mpz_divexact (*fb, *db, *g); |
| 1110 | |||
| 1111 | /* ihz = fa * db. This is equal to lcm (da, db). */ | ||
| 1112 | mpz_t *ihz = &mpz[0]; | ||
| 1113 | mpz_mul (*ihz, *fa, *db); | ||
| 1114 | |||
| 1115 | /* When warning about obsolete timestamps, if the smaller | ||
| 1116 | denominator comes from a non-(TICKS . HZ) timestamp and could | ||
| 1117 | generate a (TICKS . HZ) timestamp that would look obsolete, | ||
| 1118 | arrange for the result to have a higher HZ to avoid a | ||
| 1119 | spurious warning by a later consumer of this function's | ||
| 1120 | returned value. */ | ||
| 1121 | verify (1 << LO_TIME_BITS <= ULONG_MAX); | ||
| 1122 | if (WARN_OBSOLETE_TIMESTAMPS | ||
| 1123 | && (da_lt_db ? aform : bform) == TIMEFORM_FLOAT | ||
| 1124 | && (da_lt_db ? bform : aform) != TIMEFORM_TICKS_HZ | ||
| 1125 | && mpz_cmp_ui (*hzmin, 1) > 0 | ||
| 1126 | && mpz_cmp_ui (*hzmin, 1 << LO_TIME_BITS) < 0) | ||
| 1127 | { | ||
| 1128 | mpz_t *hzmin1 = &mpz[2 - da_lt_db]; | ||
| 1129 | mpz_set_ui (*hzmin1, 1 << LO_TIME_BITS); | ||
| 1130 | hzmin = hzmin1; | ||
| 1131 | } | ||
| 1076 | 1132 | ||
| 1077 | /* FIXME: Maybe omit need for extra temp by computing fa * db here? */ | 1133 | /* iticks = (fb * na) OP (fa * nb), where OP is + or -. */ |
| 1134 | mpz_t const *na = bignum_integer (iticks, ta.ticks); | ||
| 1135 | mpz_mul (*iticks, *fb, *na); | ||
| 1136 | mpz_t const *nb = bignum_integer (&mpz[3], tb.ticks); | ||
| 1137 | (subtract ? mpz_submul : mpz_addmul) (*iticks, *fa, *nb); | ||
| 1138 | |||
| 1139 | /* Normalize iticks/ihz by dividing both numerator and | ||
| 1140 | denominator by ig = gcd (iticks, ihz). However, if that | ||
| 1141 | would cause the denominator to become less than hzmin, | ||
| 1142 | rescale the denominator upwards from its ordinary value by | ||
| 1143 | multiplying numerator and denominator so that the denominator | ||
| 1144 | becomes at least hzmin. This rescaling avoids returning a | ||
| 1145 | timestamp that is less precise than both a and b, or a | ||
| 1146 | timestamp that looks obsolete when that might be a problem. */ | ||
| 1147 | mpz_t *ig = &mpz[3]; | ||
| 1148 | mpz_gcd (*ig, *iticks, *ihz); | ||
| 1149 | |||
| 1150 | if (!FASTER_TIMEFNS || mpz_cmp_ui (*ig, 1) > 0) | ||
| 1151 | { | ||
| 1152 | mpz_divexact (*iticks, *iticks, *ig); | ||
| 1153 | mpz_divexact (*ihz, *ihz, *ig); | ||
| 1078 | 1154 | ||
| 1079 | /* hz = fa * db. This is equal to lcm (da, db). */ | 1155 | if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) |
| 1080 | mpz_mul (mpz[0], *fa, *db); | 1156 | { |
| 1157 | /* Rescale straightforwardly. Although this might not | ||
| 1158 | yield the minimal denominator that preserves numeric | ||
| 1159 | value and is at least hzmin, calculating such a | ||
| 1160 | denominator would be too expensive because it would | ||
| 1161 | require testing multisets of factors of lcm (da, db). */ | ||
| 1162 | mpz_t *rescale = &mpz[3]; | ||
| 1163 | mpz_cdiv_q (*rescale, *hzmin, *ihz); | ||
| 1164 | mpz_mul (*iticks, *iticks, *rescale); | ||
| 1165 | mpz_mul (*ihz, *ihz, *rescale); | ||
| 1166 | } | ||
| 1167 | } | ||
| 1081 | hz = make_integer_mpz (); | 1168 | hz = make_integer_mpz (); |
| 1082 | 1169 | mpz_swap (mpz[0], *iticks); | |
| 1083 | /* ticks = (fb * na) OPER (fa * nb), where OPER is + or -. | ||
| 1084 | OP is the multiply-add or multiply-sub form of OPER. */ | ||
| 1085 | mpz_t const *na = bignum_integer (&mpz[0], ta.ticks); | ||
| 1086 | mpz_mul (mpz[0], *fb, *na); | ||
| 1087 | mpz_t const *nb = bignum_integer (&mpz[3], tb.ticks); | ||
| 1088 | (subtract ? mpz_submul : mpz_addmul) (mpz[0], *fa, *nb); | ||
| 1089 | ticks = make_integer_mpz (); | 1170 | ticks = make_integer_mpz (); |
| 1090 | } | 1171 | } |
| 1091 | 1172 | ||
| 1092 | /* Return an integer if the timestamp resolution is 1, | 1173 | /* Return an integer if the timestamp resolution is 1, |
| 1093 | otherwise the (TICKS . HZ) form if !CURRENT_TIME_LIST or if | 1174 | otherwise the (TICKS . HZ) form if !CURRENT_TIME_LIST or if |
| 1094 | either input form supports timestamps that cannot be expressed | 1175 | either input used (TICKS . HZ) form or the result can't be expressed |
| 1095 | exactly in (HI LO US PS) form, otherwise the (HI LO US PS) form | 1176 | exactly in (HI LO US PS) form, otherwise the (HI LO US PS) form |
| 1096 | for backward compatibility. */ | 1177 | for backward compatibility. */ |
| 1097 | return (EQ (hz, make_fixnum (1)) | 1178 | return (EQ (hz, make_fixnum (1)) |
| 1098 | ? ticks | 1179 | ? ticks |
| 1099 | : (!CURRENT_TIME_LIST | 1180 | : (!CURRENT_TIME_LIST |
| 1100 | || timeform_sub_ps_p (aform) || timeform_sub_ps_p (bform)) | 1181 | || aform == TIMEFORM_TICKS_HZ |
| 1182 | || bform == TIMEFORM_TICKS_HZ | ||
| 1183 | || !trillion_factor (hz)) | ||
| 1101 | ? Fcons (ticks, hz) | 1184 | ? Fcons (ticks, hz) |
| 1102 | : ticks_hz_list4 (ticks, hz)); | 1185 | : ticks_hz_list4 (ticks, hz)); |
| 1103 | } | 1186 | } |
| @@ -3918,7 +3918,7 @@ logon_network_drive (const char *path) | |||
| 3918 | return; | 3918 | return; |
| 3919 | 3919 | ||
| 3920 | n_slashes = 2; | 3920 | n_slashes = 2; |
| 3921 | strncpy (share, path, MAX_UTF8_PATH); | 3921 | strncpy (share, path, MAX_UTF8_PATH - 1); |
| 3922 | /* Truncate to just server and share name. */ | 3922 | /* Truncate to just server and share name. */ |
| 3923 | for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++) | 3923 | for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++) |
| 3924 | { | 3924 | { |
diff --git a/src/xdisp.c b/src/xdisp.c index af772bdef28..94f969f37cf 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -184,7 +184,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 184 | infrequently. These include the face of the characters, whether | 184 | infrequently. These include the face of the characters, whether |
| 185 | text is invisible, the object (buffer or display or overlay string) | 185 | text is invisible, the object (buffer or display or overlay string) |
| 186 | being iterated, character composition info, etc. For any given | 186 | being iterated, character composition info, etc. For any given |
| 187 | buffer or string position, these sources of information that | 187 | buffer or string position, the sources of information that |
| 188 | affects the display can be determined by calling the appropriate | 188 | affects the display can be determined by calling the appropriate |
| 189 | primitives, such as Fnext_single_property_change, but both these | 189 | primitives, such as Fnext_single_property_change, but both these |
| 190 | calls and the processing of their return values is relatively | 190 | calls and the processing of their return values is relatively |
| @@ -214,7 +214,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 214 | string's interval tree to determine where the text properties | 214 | string's interval tree to determine where the text properties |
| 215 | change, finds the next position where overlays and character | 215 | change, finds the next position where overlays and character |
| 216 | composition can change, and stores in stop_charpos the closest | 216 | composition can change, and stores in stop_charpos the closest |
| 217 | position where any of these factors should be reconsider. | 217 | position where any of these factors should be reconsidered. |
| 218 | 218 | ||
| 219 | Producing glyphs. | 219 | Producing glyphs. |
| 220 | 220 | ||
| @@ -13509,7 +13509,8 @@ hscroll_window_tree (Lisp_Object window) | |||
| 13509 | get glyph rows whose start and end have zero buffer | 13509 | get glyph rows whose start and end have zero buffer |
| 13510 | positions, which we cannot handle below. Just skip | 13510 | positions, which we cannot handle below. Just skip |
| 13511 | such windows. */ | 13511 | such windows. */ |
| 13512 | && CHARPOS (cursor_row->start.pos) >= BUF_BEG (w->contents) | 13512 | && (CHARPOS (cursor_row->start.pos) |
| 13513 | >= BUF_BEG (XBUFFER (w->contents))) | ||
| 13513 | /* For left-to-right rows, hscroll when cursor is either | 13514 | /* For left-to-right rows, hscroll when cursor is either |
| 13514 | (i) inside the right hscroll margin, or (ii) if it is | 13515 | (i) inside the right hscroll margin, or (ii) if it is |
| 13515 | inside the left margin and the window is already | 13516 | inside the left margin and the window is already |
| @@ -20463,7 +20464,7 @@ append_space_for_newline (struct it *it, bool default_face_p) | |||
| 20463 | static void | 20464 | static void |
| 20464 | extend_face_to_end_of_line (struct it *it) | 20465 | extend_face_to_end_of_line (struct it *it) |
| 20465 | { | 20466 | { |
| 20466 | struct face *face, *default_face; | 20467 | struct face *face; |
| 20467 | struct frame *f = it->f; | 20468 | struct frame *f = it->f; |
| 20468 | 20469 | ||
| 20469 | /* If line is already filled, do nothing. Non window-system frames | 20470 | /* If line is already filled, do nothing. Non window-system frames |
| @@ -20481,10 +20482,6 @@ extend_face_to_end_of_line (struct it *it) | |||
| 20481 | || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)) | 20482 | || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)) |
| 20482 | return; | 20483 | return; |
| 20483 | 20484 | ||
| 20484 | /* The default face, possibly remapped. */ | ||
| 20485 | default_face = | ||
| 20486 | FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID)); | ||
| 20487 | |||
| 20488 | /* Face extension extends the background and box of IT->face_id | 20485 | /* Face extension extends the background and box of IT->face_id |
| 20489 | to the end of the line. If the background equals the background | 20486 | to the end of the line. If the background equals the background |
| 20490 | of the frame, we don't have to do anything. */ | 20487 | of the frame, we don't have to do anything. */ |
| @@ -20517,7 +20514,14 @@ extend_face_to_end_of_line (struct it *it) | |||
| 20517 | it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil); | 20514 | it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil); |
| 20518 | } | 20515 | } |
| 20519 | 20516 | ||
| 20517 | /* The default face, possibly remapped. */ | ||
| 20518 | struct face *default_face = | ||
| 20519 | FACE_FROM_ID (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID)); | ||
| 20520 | |||
| 20520 | #ifdef HAVE_WINDOW_SYSTEM | 20521 | #ifdef HAVE_WINDOW_SYSTEM |
| 20522 | if (default_face == NULL) | ||
| 20523 | error ("extend_face_to_end_of_line: default_face is not set!"); | ||
| 20524 | |||
| 20521 | if (FRAME_WINDOW_P (f)) | 20525 | if (FRAME_WINDOW_P (f)) |
| 20522 | { | 20526 | { |
| 20523 | /* If the row is empty, add a space with the current face of IT, | 20527 | /* If the row is empty, add a space with the current face of IT, |
diff --git a/src/xterm.c b/src/xterm.c index 0d224063d76..b761eaf4d11 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -10044,7 +10044,6 @@ For details, see etc/PROBLEMS.\n", | |||
| 10044 | { | 10044 | { |
| 10045 | fprintf (stderr, "%s\n", error_msg); | 10045 | fprintf (stderr, "%s\n", error_msg); |
| 10046 | Fkill_emacs (make_fixnum (70)); | 10046 | Fkill_emacs (make_fixnum (70)); |
| 10047 | /* NOTREACHED */ | ||
| 10048 | } | 10047 | } |
| 10049 | 10048 | ||
| 10050 | totally_unblock_input (); | 10049 | totally_unblock_input (); |