diff options
| author | Paul Eggert | 2013-11-04 23:11:24 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-11-04 23:11:24 -0800 |
| commit | df5b49306e8e82e2f18ed3243700c11ca7835750 (patch) | |
| tree | d98fffc7d11d4565b6132e83f54ca3f3c547b1d4 /src | |
| parent | 693698093480628b7438ca0fd1614b00acfd1137 (diff) | |
| download | emacs-df5b49306e8e82e2f18ed3243700c11ca7835750.tar.gz emacs-df5b49306e8e82e2f18ed3243700c11ca7835750.zip | |
Simplify and port recent bool vector changes.
* configure.ac (BITSIZEOF_SIZE_T, SIZEOF_SIZE_T):
New symbols to configure.
* src/alloc.c (ROUNDUP): Move here from lisp.h, since it's now used
only in this file. Use a more-efficient implementation if the
second argument is a power of 2.
(ALIGN): Rewrite in terms of ROUNDUP. Make it a function.
Remove no-longer-necessary compile-time checks.
(bool_vector_exact_payload_bytes): New function.
(bool_vector_payload_bytes): Remove 2nd arg; callers that need
exact payload changed to call the new function. Do not assume
that the arg or result fits in ptrdiff_t.
(bool_vector_fill): New function.
(Fmake_bool_vector): Use it. Don't assume bit counts fit
in ptrdiff_t.
(vroundup_ct): Don't assume arg fits in size_t.
* src/category.c (SET_CATEGORY_SET): Remove. All callers now just
invoke set_category_set.
(set_category_set): 2nd arg is now EMACS_INT and 3rd is now bool.
All callers changed. Use bool_vector_set.
* src/category.h (XCATEGORY_SET): Remove; no longer needed.
(CATEGORY_MEMBER): Now a function. Rewrite in terms of
bool_vector_bitref.
* src/data.c (Faref): Use bool_vector_ref.
(Faset): Use bool_vector_set.
(bits_word_to_host_endian): Don't assume you can shift by CHAR_BIT.
(Fbool_vector_not, Fbool_vector_count_matches)
(Fbool_vector_count_matches_at): Don't assume CHAR_BIT == 8.
* src/fns.c (concat): Use bool_vector_ref.
(Ffillarray): Use bool_vector_fill.
(mapcar1): Use bool_vector_ref.
(sxhash_bool_vector): Hash words, not bytes.
* src/lisp.h (BOOL_VECTOR_BITS_PER_CHAR): Now a macro as well as
a constant, since it's now used in #if.
(bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD): Fall back on
unsigned char on unusual architectures, so that we no longer
assume that the number of bits per bits_word is a power of two or
is a multiple of 8 or of CHAR_BIT.
(Qt): Add forward decl.
(struct Lisp_Bool_Vector): Don't assume EMACS_INT is aligned
at least as strictly as bits_word.
(bool_vector_data, bool_vector_uchar_data): New accessors.
All data structure accesses changed to use them.
(bool_vector_words, bool_vector_bitref, bool_vector_ref)
(bool_vector_set): New functions.
(bool_vector_fill): New decl.
(ROUNDUP): Move to alloc.c as described above.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 46 | ||||
| -rw-r--r-- | src/alloc.c | 108 | ||||
| -rw-r--r-- | src/category.c | 41 | ||||
| -rw-r--r-- | src/category.h | 12 | ||||
| -rw-r--r-- | src/data.c | 51 | ||||
| -rw-r--r-- | src/fns.c | 37 | ||||
| -rw-r--r-- | src/image.c | 4 | ||||
| -rw-r--r-- | src/lisp.h | 87 | ||||
| -rw-r--r-- | src/lread.c | 6 | ||||
| -rw-r--r-- | src/print.c | 2 |
10 files changed, 224 insertions, 170 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index bd5688d868f..9ba39e20432 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,51 @@ | |||
| 1 | 2013-11-05 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2013-11-05 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Simplify and port recent bool vector changes. | ||
| 4 | * alloc.c (ROUNDUP): Move here from lisp.h, since it's now used | ||
| 5 | only in this file. Use a more-efficient implementation if the | ||
| 6 | second argument is a power of 2. | ||
| 7 | (ALIGN): Rewrite in terms of ROUNDUP. Make it a function. | ||
| 8 | Remove no-longer-necessary compile-time checks. | ||
| 9 | (bool_vector_exact_payload_bytes): New function. | ||
| 10 | (bool_vector_payload_bytes): Remove 2nd arg; callers that need | ||
| 11 | exact payload changed to call the new function. Do not assume | ||
| 12 | that the arg or result fits in ptrdiff_t. | ||
| 13 | (bool_vector_fill): New function. | ||
| 14 | (Fmake_bool_vector): Use it. Don't assume bit counts fit | ||
| 15 | in ptrdiff_t. | ||
| 16 | (vroundup_ct): Don't assume arg fits in size_t. | ||
| 17 | * category.c (SET_CATEGORY_SET): Remove. All callers now just | ||
| 18 | invoke set_category_set. | ||
| 19 | (set_category_set): 2nd arg is now EMACS_INT and 3rd is now bool. | ||
| 20 | All callers changed. Use bool_vector_set. | ||
| 21 | * category.h (XCATEGORY_SET): Remove; no longer needed. | ||
| 22 | (CATEGORY_MEMBER): Now a function. Rewrite in terms of | ||
| 23 | bool_vector_bitref. | ||
| 24 | * data.c (Faref): Use bool_vector_ref. | ||
| 25 | (Faset): Use bool_vector_set. | ||
| 26 | (bits_word_to_host_endian): Don't assume you can shift by CHAR_BIT. | ||
| 27 | (Fbool_vector_not, Fbool_vector_count_matches) | ||
| 28 | (Fbool_vector_count_matches_at): Don't assume CHAR_BIT == 8. | ||
| 29 | * fns.c (concat): Use bool_vector_ref. | ||
| 30 | (Ffillarray): Use bool_vector_fill. | ||
| 31 | (mapcar1): Use bool_vector_ref. | ||
| 32 | (sxhash_bool_vector): Hash words, not bytes. | ||
| 33 | * lisp.h (BOOL_VECTOR_BITS_PER_CHAR): Now a macro as well as | ||
| 34 | a constant, since it's now used in #if. | ||
| 35 | (bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD): Fall back on | ||
| 36 | unsigned char on unusual architectures, so that we no longer | ||
| 37 | assume that the number of bits per bits_word is a power of two or | ||
| 38 | is a multiple of 8 or of CHAR_BIT. | ||
| 39 | (Qt): Add forward decl. | ||
| 40 | (struct Lisp_Bool_Vector): Don't assume EMACS_INT is aligned | ||
| 41 | at least as strictly as bits_word. | ||
| 42 | (bool_vector_data, bool_vector_uchar_data): New accessors. | ||
| 43 | All data structure accesses changed to use them. | ||
| 44 | (bool_vector_words, bool_vector_bitref, bool_vector_ref) | ||
| 45 | (bool_vector_set): New functions. | ||
| 46 | (bool_vector_fill): New decl. | ||
| 47 | (ROUNDUP): Move to alloc.c as described above. | ||
| 48 | |||
| 3 | Fix recent gnutls changes. | 49 | Fix recent gnutls changes. |
| 4 | * gnutls.c (Fgnutls_boot): Don't assume C99. | 50 | * gnutls.c (Fgnutls_boot): Don't assume C99. |
| 5 | * process.c (wait_reading_process_output): Fix typo in recent change. | 51 | * process.c (wait_reading_process_output): Fix typo in recent change. |
diff --git a/src/alloc.c b/src/alloc.c index b35f7c4333f..7054083acba 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -361,13 +361,21 @@ static int staticidx; | |||
| 361 | 361 | ||
| 362 | static void *pure_alloc (size_t, int); | 362 | static void *pure_alloc (size_t, int); |
| 363 | 363 | ||
| 364 | /* Return X rounded to the next multiple of Y. Arguments should not | ||
| 365 | have side effects, as they are evaluated more than once. Assume X | ||
| 366 | + Y - 1 does not overflow. Tune for Y being a power of 2. */ | ||
| 364 | 367 | ||
| 365 | /* Value is SZ rounded up to the next multiple of ALIGNMENT. | 368 | #define ROUNDUP(x, y) ((y) & ((y) - 1) \ |
| 366 | ALIGNMENT must be a power of 2. */ | 369 | ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y) \ |
| 370 | : ((x) + (y) - 1) & ~ ((y) - 1)) | ||
| 367 | 371 | ||
| 368 | #define ALIGN(ptr, ALIGNMENT) \ | 372 | /* Return PTR rounded up to the next multiple of ALIGNMENT. */ |
| 369 | ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \ | 373 | |
| 370 | & ~ ((ALIGNMENT) - 1))) | 374 | static void * |
| 375 | ALIGN (void *ptr, int alignment) | ||
| 376 | { | ||
| 377 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); | ||
| 378 | } | ||
| 371 | 379 | ||
| 372 | static void | 380 | static void |
| 373 | XFLOAT_INIT (Lisp_Object f, double n) | 381 | XFLOAT_INIT (Lisp_Object f, double n) |
| @@ -2026,33 +2034,39 @@ INIT must be an integer that represents a character. */) | |||
| 2026 | return val; | 2034 | return val; |
| 2027 | } | 2035 | } |
| 2028 | 2036 | ||
| 2029 | verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD); | 2037 | static EMACS_INT |
| 2030 | verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0); | 2038 | bool_vector_exact_payload_bytes (EMACS_INT nbits) |
| 2031 | |||
| 2032 | static ptrdiff_t | ||
| 2033 | bool_vector_payload_bytes (ptrdiff_t nr_bits, | ||
| 2034 | ptrdiff_t *exact_needed_bytes_out) | ||
| 2035 | { | 2039 | { |
| 2036 | ptrdiff_t exact_needed_bytes; | 2040 | eassume (0 <= nbits); |
| 2037 | ptrdiff_t needed_bytes; | 2041 | return (nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR; |
| 2042 | } | ||
| 2038 | 2043 | ||
| 2039 | eassume (nr_bits >= 0); | 2044 | static EMACS_INT |
| 2045 | bool_vector_payload_bytes (EMACS_INT nbits) | ||
| 2046 | { | ||
| 2047 | EMACS_INT exact_needed_bytes = bool_vector_exact_payload_bytes (nbits); | ||
| 2040 | 2048 | ||
| 2041 | exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT; | 2049 | /* Always allocate at least one machine word of payload so that |
| 2042 | needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT; | 2050 | bool-vector operations in data.c don't need a special case |
| 2051 | for empty vectors. */ | ||
| 2052 | return ROUNDUP (exact_needed_bytes + !exact_needed_bytes, | ||
| 2053 | sizeof (bits_word)); | ||
| 2054 | } | ||
| 2043 | 2055 | ||
| 2044 | if (needed_bytes == 0) | 2056 | void |
| 2057 | bool_vector_fill (Lisp_Object a, Lisp_Object init) | ||
| 2058 | { | ||
| 2059 | EMACS_INT nbits = bool_vector_size (a); | ||
| 2060 | if (0 < nbits) | ||
| 2045 | { | 2061 | { |
| 2046 | /* Always allocate at least one machine word of payload so that | 2062 | unsigned char *data = bool_vector_uchar_data (a); |
| 2047 | bool-vector operations in data.c don't need a special case | 2063 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; |
| 2048 | for empty vectors. */ | 2064 | ptrdiff_t nbytes = ((nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) |
| 2049 | needed_bytes = sizeof (bits_word); | 2065 | / BOOL_VECTOR_BITS_PER_CHAR); |
| 2066 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); | ||
| 2067 | memset (data, pattern, nbytes - 1); | ||
| 2068 | data[nbytes - 1] = pattern & last_mask; | ||
| 2050 | } | 2069 | } |
| 2051 | |||
| 2052 | if (exact_needed_bytes_out != NULL) | ||
| 2053 | *exact_needed_bytes_out = exact_needed_bytes; | ||
| 2054 | |||
| 2055 | return needed_bytes; | ||
| 2056 | } | 2070 | } |
| 2057 | 2071 | ||
| 2058 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | 2072 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, |
| @@ -2060,42 +2074,29 @@ DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | |||
| 2060 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | 2074 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) |
| 2061 | (Lisp_Object length, Lisp_Object init) | 2075 | (Lisp_Object length, Lisp_Object init) |
| 2062 | { | 2076 | { |
| 2063 | register Lisp_Object val; | 2077 | Lisp_Object val; |
| 2064 | struct Lisp_Bool_Vector *p; | 2078 | struct Lisp_Bool_Vector *p; |
| 2065 | ptrdiff_t exact_payload_bytes; | 2079 | EMACS_INT exact_payload_bytes, total_payload_bytes, needed_elements; |
| 2066 | ptrdiff_t total_payload_bytes; | ||
| 2067 | ptrdiff_t needed_elements; | ||
| 2068 | 2080 | ||
| 2069 | CHECK_NATNUM (length); | 2081 | CHECK_NATNUM (length); |
| 2070 | if (PTRDIFF_MAX < XFASTINT (length)) | ||
| 2071 | memory_full (SIZE_MAX); | ||
| 2072 | |||
| 2073 | total_payload_bytes = bool_vector_payload_bytes | ||
| 2074 | (XFASTINT (length), &exact_payload_bytes); | ||
| 2075 | 2082 | ||
| 2076 | eassume (exact_payload_bytes <= total_payload_bytes); | 2083 | exact_payload_bytes = bool_vector_exact_payload_bytes (XFASTINT (length)); |
| 2077 | eassume (0 <= exact_payload_bytes); | 2084 | total_payload_bytes = bool_vector_payload_bytes (XFASTINT (length)); |
| 2078 | 2085 | ||
| 2079 | needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size) | 2086 | needed_elements = ((bool_header_size - header_size + total_payload_bytes |
| 2080 | + total_payload_bytes), | 2087 | + word_size - 1) |
| 2081 | word_size) / word_size; | 2088 | / word_size); |
| 2082 | 2089 | ||
| 2083 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | 2090 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); |
| 2084 | XSETVECTOR (val, p); | 2091 | XSETVECTOR (val, p); |
| 2085 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2092 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2086 | 2093 | ||
| 2087 | p->size = XFASTINT (length); | 2094 | p->size = XFASTINT (length); |
| 2088 | if (exact_payload_bytes) | 2095 | bool_vector_fill (val, init); |
| 2089 | { | ||
| 2090 | memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes); | ||
| 2091 | |||
| 2092 | /* Clear any extraneous bits in the last byte. */ | ||
| 2093 | p->data[exact_payload_bytes - 1] | ||
| 2094 | &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; | ||
| 2095 | } | ||
| 2096 | 2096 | ||
| 2097 | /* Clear padding at the end. */ | 2097 | /* Clear padding at the end. */ |
| 2098 | memset (p->data + exact_payload_bytes, | 2098 | eassume (exact_payload_bytes <= total_payload_bytes); |
| 2099 | memset (bool_vector_uchar_data (val) + exact_payload_bytes, | ||
| 2099 | 0, | 2100 | 0, |
| 2100 | total_payload_bytes - exact_payload_bytes); | 2101 | total_payload_bytes - exact_payload_bytes); |
| 2101 | 2102 | ||
| @@ -2648,7 +2649,7 @@ verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); | |||
| 2648 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | 2649 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); |
| 2649 | 2650 | ||
| 2650 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ | 2651 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ |
| 2651 | #define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size) | 2652 | #define vroundup_ct(x) ROUNDUP (x, roundup_size) |
| 2652 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ | 2653 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ |
| 2653 | #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) | 2654 | #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) |
| 2654 | 2655 | ||
| @@ -2856,11 +2857,8 @@ vector_nbytes (struct Lisp_Vector *v) | |||
| 2856 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | 2857 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) |
| 2857 | { | 2858 | { |
| 2858 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; | 2859 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; |
| 2859 | ptrdiff_t payload_bytes = | 2860 | ptrdiff_t payload_bytes = bool_vector_payload_bytes (bv->size); |
| 2860 | bool_vector_payload_bytes (bv->size, NULL); | 2861 | size = bool_header_size + payload_bytes; |
| 2861 | |||
| 2862 | eassume (payload_bytes >= 0); | ||
| 2863 | size = bool_header_size + ROUNDUP (payload_bytes, word_size); | ||
| 2864 | } | 2862 | } |
| 2865 | else | 2863 | else |
| 2866 | size = (header_size | 2864 | size = (header_size |
diff --git a/src/category.c b/src/category.c index da5e81e4709..80d8b1ca1a2 100644 --- a/src/category.c +++ b/src/category.c | |||
| @@ -55,17 +55,9 @@ bset_category_table (struct buffer *b, Lisp_Object val) | |||
| 55 | static int category_table_version; | 55 | static int category_table_version; |
| 56 | 56 | ||
| 57 | static Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, Qcategory_table_p; | 57 | static Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, Qcategory_table_p; |
| 58 | |||
| 59 | /* Make CATEGORY_SET includes (if VAL is t) or excludes (if VAL is | ||
| 60 | nil) CATEGORY. */ | ||
| 61 | #define SET_CATEGORY_SET(category_set, category, val) \ | ||
| 62 | set_category_set (category_set, category, val) | ||
| 63 | static void set_category_set (Lisp_Object, Lisp_Object, Lisp_Object); | ||
| 64 | 58 | ||
| 65 | /* Category set staff. */ | 59 | /* Category set staff. */ |
| 66 | 60 | ||
| 67 | static Lisp_Object hash_get_category_set (Lisp_Object, Lisp_Object); | ||
| 68 | |||
| 69 | static Lisp_Object | 61 | static Lisp_Object |
| 70 | hash_get_category_set (Lisp_Object table, Lisp_Object category_set) | 62 | hash_get_category_set (Lisp_Object table, Lisp_Object category_set) |
| 71 | { | 63 | { |
| @@ -88,6 +80,13 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set) | |||
| 88 | return category_set; | 80 | return category_set; |
| 89 | } | 81 | } |
| 90 | 82 | ||
| 83 | /* Make CATEGORY_SET include (if VAL) or exclude (if !VAL) CATEGORY. */ | ||
| 84 | |||
| 85 | static void | ||
| 86 | set_category_set (Lisp_Object category_set, EMACS_INT category, bool val) | ||
| 87 | { | ||
| 88 | bool_vector_set (category_set, category, val); | ||
| 89 | } | ||
| 91 | 90 | ||
| 92 | DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0, | 91 | DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0, |
| 93 | doc: /* Return a newly created category-set which contains CATEGORIES. | 92 | doc: /* Return a newly created category-set which contains CATEGORIES. |
| @@ -108,11 +107,11 @@ those categories. */) | |||
| 108 | len = SCHARS (categories); | 107 | len = SCHARS (categories); |
| 109 | while (--len >= 0) | 108 | while (--len >= 0) |
| 110 | { | 109 | { |
| 111 | Lisp_Object category; | 110 | unsigned char cat = SREF (categories, len); |
| 111 | Lisp_Object category = make_number (cat); | ||
| 112 | 112 | ||
| 113 | XSETFASTINT (category, SREF (categories, len)); | ||
| 114 | CHECK_CATEGORY (category); | 113 | CHECK_CATEGORY (category); |
| 115 | SET_CATEGORY_SET (val, category, Qt); | 114 | set_category_set (val, cat, 1); |
| 116 | } | 115 | } |
| 117 | return val; | 116 | return val; |
| 118 | } | 117 | } |
| @@ -334,20 +333,6 @@ The return value is a string containing those same categories. */) | |||
| 334 | return build_string (str); | 333 | return build_string (str); |
| 335 | } | 334 | } |
| 336 | 335 | ||
| 337 | static void | ||
| 338 | set_category_set (Lisp_Object category_set, Lisp_Object category, Lisp_Object val) | ||
| 339 | { | ||
| 340 | do { | ||
| 341 | int idx = XINT (category) / 8; | ||
| 342 | unsigned char bits = 1 << (XINT (category) % 8); | ||
| 343 | |||
| 344 | if (NILP (val)) | ||
| 345 | XCATEGORY_SET (category_set)->data[idx] &= ~bits; | ||
| 346 | else | ||
| 347 | XCATEGORY_SET (category_set)->data[idx] |= bits; | ||
| 348 | } while (0); | ||
| 349 | } | ||
| 350 | |||
| 351 | DEFUN ("modify-category-entry", Fmodify_category_entry, | 336 | DEFUN ("modify-category-entry", Fmodify_category_entry, |
| 352 | Smodify_category_entry, 2, 4, 0, | 337 | Smodify_category_entry, 2, 4, 0, |
| 353 | doc: /* Modify the category set of CHARACTER by adding CATEGORY to it. | 338 | doc: /* Modify the category set of CHARACTER by adding CATEGORY to it. |
| @@ -359,7 +344,7 @@ If optional fourth argument RESET is non-nil, | |||
| 359 | then delete CATEGORY from the category set instead of adding it. */) | 344 | then delete CATEGORY from the category set instead of adding it. */) |
| 360 | (Lisp_Object character, Lisp_Object category, Lisp_Object table, Lisp_Object reset) | 345 | (Lisp_Object character, Lisp_Object category, Lisp_Object table, Lisp_Object reset) |
| 361 | { | 346 | { |
| 362 | Lisp_Object set_value; /* Actual value to be set in category sets. */ | 347 | bool set_value; /* Actual value to be set in category sets. */ |
| 363 | Lisp_Object category_set; | 348 | Lisp_Object category_set; |
| 364 | int start, end; | 349 | int start, end; |
| 365 | int from, to; | 350 | int from, to; |
| @@ -384,7 +369,7 @@ then delete CATEGORY from the category set instead of adding it. */) | |||
| 384 | if (NILP (CATEGORY_DOCSTRING (table, XFASTINT (category)))) | 369 | if (NILP (CATEGORY_DOCSTRING (table, XFASTINT (category)))) |
| 385 | error ("Undefined category: %c", (int) XFASTINT (category)); | 370 | error ("Undefined category: %c", (int) XFASTINT (category)); |
| 386 | 371 | ||
| 387 | set_value = NILP (reset) ? Qt : Qnil; | 372 | set_value = NILP (reset); |
| 388 | 373 | ||
| 389 | while (start <= end) | 374 | while (start <= end) |
| 390 | { | 375 | { |
| @@ -393,7 +378,7 @@ then delete CATEGORY from the category set instead of adding it. */) | |||
| 393 | if (CATEGORY_MEMBER (XFASTINT (category), category_set) != NILP (reset)) | 378 | if (CATEGORY_MEMBER (XFASTINT (category), category_set) != NILP (reset)) |
| 394 | { | 379 | { |
| 395 | category_set = Fcopy_sequence (category_set); | 380 | category_set = Fcopy_sequence (category_set); |
| 396 | SET_CATEGORY_SET (category_set, category, set_value); | 381 | set_category_set (category_set, XFASTINT (category), set_value); |
| 397 | category_set = hash_get_category_set (table, category_set); | 382 | category_set = hash_get_category_set (table, category_set); |
| 398 | char_table_set_range (table, start, to, category_set); | 383 | char_table_set_range (table, start, to, category_set); |
| 399 | } | 384 | } |
diff --git a/src/category.h b/src/category.h index a2eaf010132..ef784c8cbf5 100644 --- a/src/category.h +++ b/src/category.h | |||
| @@ -60,8 +60,6 @@ INLINE_HEADER_BEGIN | |||
| 60 | #define CHECK_CATEGORY(x) \ | 60 | #define CHECK_CATEGORY(x) \ |
| 61 | CHECK_TYPE (CATEGORYP (x), Qcategoryp, x) | 61 | CHECK_TYPE (CATEGORYP (x), Qcategoryp, x) |
| 62 | 62 | ||
| 63 | #define XCATEGORY_SET XBOOL_VECTOR | ||
| 64 | |||
| 65 | #define CATEGORY_SET_P(x) \ | 63 | #define CATEGORY_SET_P(x) \ |
| 66 | (BOOL_VECTOR_P (x) && bool_vector_size (x) == 128) | 64 | (BOOL_VECTOR_P (x) && bool_vector_size (x) == 128) |
| 67 | 65 | ||
| @@ -75,10 +73,12 @@ INLINE_HEADER_BEGIN | |||
| 75 | #define CATEGORY_SET(c) char_category_set (c) | 73 | #define CATEGORY_SET(c) char_category_set (c) |
| 76 | 74 | ||
| 77 | /* Return true if CATEGORY_SET contains CATEGORY. | 75 | /* Return true if CATEGORY_SET contains CATEGORY. |
| 78 | The faster version of `!NILP (Faref (category_set, category))'. */ | 76 | Faster than '!NILP (Faref (category_set, make_number (category)))'. */ |
| 79 | #define CATEGORY_MEMBER(category, category_set) \ | 77 | INLINE bool |
| 80 | ((XCATEGORY_SET (category_set)->data[(category) / 8] \ | 78 | CATEGORY_MEMBER (EMACS_INT category, Lisp_Object category_set) |
| 81 | >> ((category) % 8)) & 1) | 79 | { |
| 80 | return bool_vector_bitref (category_set, category); | ||
| 81 | } | ||
| 82 | 82 | ||
| 83 | /* Return true if category set of CH contains CATEGORY. */ | 83 | /* Return true if category set of CH contains CATEGORY. */ |
| 84 | INLINE bool | 84 | INLINE bool |
diff --git a/src/data.c b/src/data.c index 22d051ef932..4043fbe279b 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2141,13 +2141,9 @@ or a byte-code object. IDX starts at 0. */) | |||
| 2141 | } | 2141 | } |
| 2142 | else if (BOOL_VECTOR_P (array)) | 2142 | else if (BOOL_VECTOR_P (array)) |
| 2143 | { | 2143 | { |
| 2144 | int val; | ||
| 2145 | |||
| 2146 | if (idxval < 0 || idxval >= bool_vector_size (array)) | 2144 | if (idxval < 0 || idxval >= bool_vector_size (array)) |
| 2147 | args_out_of_range (array, idx); | 2145 | args_out_of_range (array, idx); |
| 2148 | 2146 | return bool_vector_ref (array, idxval); | |
| 2149 | val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR]; | ||
| 2150 | return (val & (1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR)) ? Qt : Qnil); | ||
| 2151 | } | 2147 | } |
| 2152 | else if (CHAR_TABLE_P (array)) | 2148 | else if (CHAR_TABLE_P (array)) |
| 2153 | { | 2149 | { |
| @@ -2191,18 +2187,9 @@ bool-vector. IDX starts at 0. */) | |||
| 2191 | } | 2187 | } |
| 2192 | else if (BOOL_VECTOR_P (array)) | 2188 | else if (BOOL_VECTOR_P (array)) |
| 2193 | { | 2189 | { |
| 2194 | int val; | ||
| 2195 | |||
| 2196 | if (idxval < 0 || idxval >= bool_vector_size (array)) | 2190 | if (idxval < 0 || idxval >= bool_vector_size (array)) |
| 2197 | args_out_of_range (array, idx); | 2191 | args_out_of_range (array, idx); |
| 2198 | 2192 | bool_vector_set (array, idxval, !NILP (newelt)); | |
| 2199 | val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR]; | ||
| 2200 | |||
| 2201 | if (! NILP (newelt)) | ||
| 2202 | val |= 1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2203 | else | ||
| 2204 | val &= ~(1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR)); | ||
| 2205 | XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR] = val; | ||
| 2206 | } | 2193 | } |
| 2207 | else if (CHAR_TABLE_P (array)) | 2194 | else if (CHAR_TABLE_P (array)) |
| 2208 | { | 2195 | { |
| @@ -3033,11 +3020,11 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3033 | wrong_length_argument (op1, op2, dest); | 3020 | wrong_length_argument (op1, op2, dest); |
| 3034 | } | 3021 | } |
| 3035 | 3022 | ||
| 3036 | nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD; | 3023 | nr_words = bool_vector_words (nr_bits); |
| 3037 | 3024 | ||
| 3038 | adata = (bits_word *) XBOOL_VECTOR (dest)->data; | 3025 | adata = bool_vector_data (dest); |
| 3039 | bdata = (bits_word *) XBOOL_VECTOR (op1)->data; | 3026 | bdata = bool_vector_data (op1); |
| 3040 | cdata = (bits_word *) XBOOL_VECTOR (op2)->data; | 3027 | cdata = bool_vector_data (op2); |
| 3041 | i = 0; | 3028 | i = 0; |
| 3042 | do | 3029 | do |
| 3043 | { | 3030 | { |
| @@ -3110,8 +3097,9 @@ bits_word_to_host_endian (bits_word val) | |||
| 3110 | bits_word r = 0; | 3097 | bits_word r = 0; |
| 3111 | for (i = 0; i < sizeof val; i++) | 3098 | for (i = 0; i < sizeof val; i++) |
| 3112 | { | 3099 | { |
| 3113 | r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1)); | 3100 | r = ((r << 1 << (CHAR_BIT - 1)) |
| 3114 | val >>= CHAR_BIT; | 3101 | | (val & ((1u << 1 << (CHAR_BIT - 1)) - 1))); |
| 3102 | val = val >> 1 >> (CHAR_BIT - 1); | ||
| 3115 | } | 3103 | } |
| 3116 | return r; | 3104 | return r; |
| 3117 | #endif | 3105 | #endif |
| @@ -3181,7 +3169,6 @@ Return the destination vector. */) | |||
| 3181 | EMACS_INT nr_bits; | 3169 | EMACS_INT nr_bits; |
| 3182 | bits_word *bdata, *adata; | 3170 | bits_word *bdata, *adata; |
| 3183 | ptrdiff_t i; | 3171 | ptrdiff_t i; |
| 3184 | bits_word mword; | ||
| 3185 | 3172 | ||
| 3186 | CHECK_BOOL_VECTOR (a); | 3173 | CHECK_BOOL_VECTOR (a); |
| 3187 | nr_bits = bool_vector_size (a); | 3174 | nr_bits = bool_vector_size (a); |
| @@ -3195,15 +3182,15 @@ Return the destination vector. */) | |||
| 3195 | wrong_length_argument (a, b, Qnil); | 3182 | wrong_length_argument (a, b, Qnil); |
| 3196 | } | 3183 | } |
| 3197 | 3184 | ||
| 3198 | bdata = (bits_word *) XBOOL_VECTOR (b)->data; | 3185 | bdata = bool_vector_data (b); |
| 3199 | adata = (bits_word *) XBOOL_VECTOR (a)->data; | 3186 | adata = bool_vector_data (a); |
| 3200 | 3187 | ||
| 3201 | for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++) | 3188 | for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++) |
| 3202 | bdata[i] = ~adata[i]; | 3189 | bdata[i] = BITS_WORD_MAX & ~adata[i]; |
| 3203 | 3190 | ||
| 3204 | if (nr_bits % BITS_PER_BITS_WORD) | 3191 | if (nr_bits % BITS_PER_BITS_WORD) |
| 3205 | { | 3192 | { |
| 3206 | mword = bits_word_to_host_endian (adata[i]); | 3193 | bits_word mword = bits_word_to_host_endian (adata[i]); |
| 3207 | mword = ~mword; | 3194 | mword = ~mword; |
| 3208 | mword &= bool_vector_spare_mask (nr_bits); | 3195 | mword &= bool_vector_spare_mask (nr_bits); |
| 3209 | bdata[i] = bits_word_to_host_endian (mword); | 3196 | bdata[i] = bits_word_to_host_endian (mword); |
| @@ -3228,8 +3215,8 @@ A must be a bool vector. B is a generalized bool. */) | |||
| 3228 | 3215 | ||
| 3229 | nr_bits = bool_vector_size (a); | 3216 | nr_bits = bool_vector_size (a); |
| 3230 | count = 0; | 3217 | count = 0; |
| 3231 | match = NILP (b) ? -1 : 0; | 3218 | match = NILP (b) ? BITS_WORD_MAX : 0; |
| 3232 | adata = (bits_word *) XBOOL_VECTOR (a)->data; | 3219 | adata = bool_vector_data (a); |
| 3233 | 3220 | ||
| 3234 | for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i) | 3221 | for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i) |
| 3235 | count += popcount_bits_word (adata[i] ^ match); | 3222 | count += popcount_bits_word (adata[i] ^ match); |
| @@ -3269,10 +3256,8 @@ index into the vector. */) | |||
| 3269 | if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */ | 3256 | if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */ |
| 3270 | args_out_of_range (a, i); | 3257 | args_out_of_range (a, i); |
| 3271 | 3258 | ||
| 3272 | adata = (bits_word *) XBOOL_VECTOR (a)->data; | 3259 | adata = bool_vector_data (a); |
| 3273 | 3260 | nr_words = bool_vector_words (nr_bits); | |
| 3274 | nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD; | ||
| 3275 | |||
| 3276 | pos = XFASTINT (i) / BITS_PER_BITS_WORD; | 3261 | pos = XFASTINT (i) / BITS_PER_BITS_WORD; |
| 3277 | offset = XFASTINT (i) % BITS_PER_BITS_WORD; | 3262 | offset = XFASTINT (i) % BITS_PER_BITS_WORD; |
| 3278 | count = 0; | 3263 | count = 0; |
| @@ -3280,7 +3265,7 @@ index into the vector. */) | |||
| 3280 | /* By XORing with twiddle, we transform the problem of "count | 3265 | /* By XORing with twiddle, we transform the problem of "count |
| 3281 | consecutive equal values" into "count the zero bits". The latter | 3266 | consecutive equal values" into "count the zero bits". The latter |
| 3282 | operation usually has hardware support. */ | 3267 | operation usually has hardware support. */ |
| 3283 | twiddle = NILP (b) ? 0 : -1; | 3268 | twiddle = NILP (b) ? 0 : BITS_WORD_MAX; |
| 3284 | 3269 | ||
| 3285 | /* Scan the remainder of the mword at the current offset. */ | 3270 | /* Scan the remainder of the mword at the current offset. */ |
| 3286 | if (pos < nr_words && offset != 0) | 3271 | if (pos < nr_words && offset != 0) |
| @@ -441,8 +441,7 @@ with the original. */) | |||
| 441 | / BOOL_VECTOR_BITS_PER_CHAR); | 441 | / BOOL_VECTOR_BITS_PER_CHAR); |
| 442 | 442 | ||
| 443 | val = Fmake_bool_vector (Flength (arg), Qnil); | 443 | val = Fmake_bool_vector (Flength (arg), Qnil); |
| 444 | memcpy (XBOOL_VECTOR (val)->data, XBOOL_VECTOR (arg)->data, | 444 | memcpy (bool_vector_data (val), bool_vector_data (arg), size_in_chars); |
| 445 | size_in_chars); | ||
| 446 | return val; | 445 | return val; |
| 447 | } | 446 | } |
| 448 | 447 | ||
| @@ -674,12 +673,7 @@ concat (ptrdiff_t nargs, Lisp_Object *args, | |||
| 674 | } | 673 | } |
| 675 | else if (BOOL_VECTOR_P (this)) | 674 | else if (BOOL_VECTOR_P (this)) |
| 676 | { | 675 | { |
| 677 | int byte; | 676 | elt = bool_vector_ref (this, thisindex); |
| 678 | byte = XBOOL_VECTOR (this)->data[thisindex / BOOL_VECTOR_BITS_PER_CHAR]; | ||
| 679 | if (byte & (1 << (thisindex % BOOL_VECTOR_BITS_PER_CHAR))) | ||
| 680 | elt = Qt; | ||
| 681 | else | ||
| 682 | elt = Qnil; | ||
| 683 | thisindex++; | 677 | thisindex++; |
| 684 | } | 678 | } |
| 685 | else | 679 | else |
| @@ -2071,7 +2065,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props) | |||
| 2071 | EMACS_INT size = bool_vector_size (o1); | 2065 | EMACS_INT size = bool_vector_size (o1); |
| 2072 | if (size != bool_vector_size (o2)) | 2066 | if (size != bool_vector_size (o2)) |
| 2073 | return 0; | 2067 | return 0; |
| 2074 | if (memcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data, | 2068 | if (memcmp (bool_vector_data (o1), bool_vector_data (o2), |
| 2075 | ((size + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2069 | ((size + BOOL_VECTOR_BITS_PER_CHAR - 1) |
| 2076 | / BOOL_VECTOR_BITS_PER_CHAR))) | 2070 | / BOOL_VECTOR_BITS_PER_CHAR))) |
| 2077 | return 0; | 2071 | return 0; |
| @@ -2163,19 +2157,7 @@ ARRAY is a vector, string, char-table, or bool-vector. */) | |||
| 2163 | p[idx] = charval; | 2157 | p[idx] = charval; |
| 2164 | } | 2158 | } |
| 2165 | else if (BOOL_VECTOR_P (array)) | 2159 | else if (BOOL_VECTOR_P (array)) |
| 2166 | { | 2160 | bool_vector_fill (array, item); |
| 2167 | unsigned char *p = XBOOL_VECTOR (array)->data; | ||
| 2168 | size = ((bool_vector_size (array) + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 2169 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2170 | |||
| 2171 | if (size) | ||
| 2172 | { | ||
| 2173 | memset (p, ! NILP (item) ? -1 : 0, size); | ||
| 2174 | |||
| 2175 | /* Clear any extraneous bits in the last byte. */ | ||
| 2176 | p[size - 1] &= (1 << (size % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | ||
| 2177 | } | ||
| 2178 | } | ||
| 2179 | else | 2161 | else |
| 2180 | wrong_type_argument (Qarrayp, array); | 2162 | wrong_type_argument (Qarrayp, array); |
| 2181 | return array; | 2163 | return array; |
| @@ -2287,10 +2269,7 @@ mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) | |||
| 2287 | { | 2269 | { |
| 2288 | for (i = 0; i < leni; i++) | 2270 | for (i = 0; i < leni; i++) |
| 2289 | { | 2271 | { |
| 2290 | unsigned char byte; | 2272 | dummy = call1 (fn, bool_vector_ref (seq, i)); |
| 2291 | byte = XBOOL_VECTOR (seq)->data[i / BOOL_VECTOR_BITS_PER_CHAR]; | ||
| 2292 | dummy = (byte & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR))) ? Qt : Qnil; | ||
| 2293 | dummy = call1 (fn, dummy); | ||
| 2294 | if (vals) | 2273 | if (vals) |
| 2295 | vals[i] = dummy; | 2274 | vals[i] = dummy; |
| 2296 | } | 2275 | } |
| @@ -4189,11 +4168,9 @@ sxhash_bool_vector (Lisp_Object vec) | |||
| 4189 | EMACS_UINT hash = size; | 4168 | EMACS_UINT hash = size; |
| 4190 | int i, n; | 4169 | int i, n; |
| 4191 | 4170 | ||
| 4192 | n = min (SXHASH_MAX_LEN, | 4171 | n = min (SXHASH_MAX_LEN, bool_vector_words (size)); |
| 4193 | ((size + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 4194 | / BOOL_VECTOR_BITS_PER_CHAR)); | ||
| 4195 | for (i = 0; i < n; ++i) | 4172 | for (i = 0; i < n; ++i) |
| 4196 | hash = sxhash_combine (hash, XBOOL_VECTOR (vec)->data[i]); | 4173 | hash = sxhash_combine (hash, bool_vector_data (vec)[i]); |
| 4197 | 4174 | ||
| 4198 | return SXHASH_REDUCE (hash); | 4175 | return SXHASH_REDUCE (hash); |
| 4199 | } | 4176 | } |
diff --git a/src/image.c b/src/image.c index 958295c5d09..02565fa7b08 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -3026,13 +3026,13 @@ xbm_load (struct frame *f, struct image *img) | |||
| 3026 | if (STRINGP (line)) | 3026 | if (STRINGP (line)) |
| 3027 | memcpy (p, SDATA (line), nbytes); | 3027 | memcpy (p, SDATA (line), nbytes); |
| 3028 | else | 3028 | else |
| 3029 | memcpy (p, XBOOL_VECTOR (line)->data, nbytes); | 3029 | memcpy (p, bool_vector_data (line), nbytes); |
| 3030 | } | 3030 | } |
| 3031 | } | 3031 | } |
| 3032 | else if (STRINGP (data)) | 3032 | else if (STRINGP (data)) |
| 3033 | bits = SSDATA (data); | 3033 | bits = SSDATA (data); |
| 3034 | else | 3034 | else |
| 3035 | bits = (char *) XBOOL_VECTOR (data)->data; | 3035 | bits = (char *) bool_vector_data (data); |
| 3036 | 3036 | ||
| 3037 | #ifdef HAVE_NTGUI | 3037 | #ifdef HAVE_NTGUI |
| 3038 | { | 3038 | { |
diff --git a/src/lisp.h b/src/lisp.h index f538cec5ed1..863b0842f59 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -82,10 +82,26 @@ typedef unsigned int EMACS_UINT; | |||
| 82 | # endif | 82 | # endif |
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | /* Number of bits to put in each character in the internal representation | ||
| 86 | of bool vectors. This should not vary across implementations. */ | ||
| 87 | enum { BOOL_VECTOR_BITS_PER_CHAR = | ||
| 88 | #define BOOL_VECTOR_BITS_PER_CHAR 8 | ||
| 89 | BOOL_VECTOR_BITS_PER_CHAR | ||
| 90 | }; | ||
| 91 | |||
| 85 | /* An unsigned integer type representing a fixed-length bit sequence, | 92 | /* An unsigned integer type representing a fixed-length bit sequence, |
| 86 | suitable for words in a Lisp bool vector. */ | 93 | suitable for words in a Lisp bool vector. Normally it is size_t |
| 94 | for speed, but it is unsigned char on weird platforms. */ | ||
| 95 | #if (BITSIZEOF_SIZE_T == CHAR_BIT * SIZEOF_SIZE_T \ | ||
| 96 | && BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT) | ||
| 87 | typedef size_t bits_word; | 97 | typedef size_t bits_word; |
| 88 | #define BITS_WORD_MAX SIZE_MAX | 98 | #define BITS_WORD_MAX SIZE_MAX |
| 99 | enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) }; | ||
| 100 | #else | ||
| 101 | typedef unsigned char bits_word; | ||
| 102 | #define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1) | ||
| 103 | enum { BITS_PER_BITS_WORD = BOOL_VECTOR_BITS_PER_CHAR }; | ||
| 104 | #endif | ||
| 89 | 105 | ||
| 90 | /* Number of bits in some machine integer types. */ | 106 | /* Number of bits in some machine integer types. */ |
| 91 | enum | 107 | enum |
| @@ -94,7 +110,6 @@ enum | |||
| 94 | BITS_PER_SHORT = CHAR_BIT * sizeof (short), | 110 | BITS_PER_SHORT = CHAR_BIT * sizeof (short), |
| 95 | BITS_PER_INT = CHAR_BIT * sizeof (int), | 111 | BITS_PER_INT = CHAR_BIT * sizeof (int), |
| 96 | BITS_PER_LONG = CHAR_BIT * sizeof (long int), | 112 | BITS_PER_LONG = CHAR_BIT * sizeof (long int), |
| 97 | BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word), | ||
| 98 | BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) | 113 | BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) |
| 99 | }; | 114 | }; |
| 100 | 115 | ||
| @@ -616,10 +631,6 @@ enum More_Lisp_Bits | |||
| 616 | /* Used to extract pseudovector subtype information. */ | 631 | /* Used to extract pseudovector subtype information. */ |
| 617 | PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS, | 632 | PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS, |
| 618 | PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS, | 633 | PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS, |
| 619 | |||
| 620 | /* Number of bits to put in each character in the internal representation | ||
| 621 | of bool vectors. This should not vary across implementations. */ | ||
| 622 | BOOL_VECTOR_BITS_PER_CHAR = 8 | ||
| 623 | }; | 634 | }; |
| 624 | 635 | ||
| 625 | /* These functions extract various sorts of values from a Lisp_Object. | 636 | /* These functions extract various sorts of values from a Lisp_Object. |
| @@ -777,7 +788,7 @@ extern int char_table_translate (Lisp_Object, int); | |||
| 777 | /* Defined in data.c. */ | 788 | /* Defined in data.c. */ |
| 778 | extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p; | 789 | extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p; |
| 779 | extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil; | 790 | extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil; |
| 780 | extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp; | 791 | extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qt, Qvectorp; |
| 781 | extern Lisp_Object Qbool_vector_p; | 792 | extern Lisp_Object Qbool_vector_p; |
| 782 | extern Lisp_Object Qvector_or_char_table_p, Qwholenump; | 793 | extern Lisp_Object Qvector_or_char_table_p, Qwholenump; |
| 783 | extern Lisp_Object Qwindow; | 794 | extern Lisp_Object Qwindow; |
| @@ -1152,7 +1163,7 @@ STRING_COPYIN (Lisp_Object string, ptrdiff_t index, char const *new, | |||
| 1152 | and PSEUDOVECTORP cast their pointers to struct vectorlike_header *, | 1163 | and PSEUDOVECTORP cast their pointers to struct vectorlike_header *, |
| 1153 | because when two such pointers potentially alias, a compiler won't | 1164 | because when two such pointers potentially alias, a compiler won't |
| 1154 | incorrectly reorder loads and stores to their size fields. See | 1165 | incorrectly reorder loads and stores to their size fields. See |
| 1155 | <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ | 1166 | Bug#8546. */ |
| 1156 | struct vectorlike_header | 1167 | struct vectorlike_header |
| 1157 | { | 1168 | { |
| 1158 | /* The only field contains various pieces of information: | 1169 | /* The only field contains various pieces of information: |
| @@ -1202,7 +1213,7 @@ struct Lisp_Bool_Vector | |||
| 1202 | /* This is the size in bits. */ | 1213 | /* This is the size in bits. */ |
| 1203 | EMACS_INT size; | 1214 | EMACS_INT size; |
| 1204 | /* This contains the actual bits, packed into bytes. */ | 1215 | /* This contains the actual bits, packed into bytes. */ |
| 1205 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; | 1216 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; |
| 1206 | }; | 1217 | }; |
| 1207 | 1218 | ||
| 1208 | INLINE EMACS_INT | 1219 | INLINE EMACS_INT |
| @@ -1213,6 +1224,59 @@ bool_vector_size (Lisp_Object a) | |||
| 1213 | return size; | 1224 | return size; |
| 1214 | } | 1225 | } |
| 1215 | 1226 | ||
| 1227 | INLINE bits_word * | ||
| 1228 | bool_vector_data (Lisp_Object a) | ||
| 1229 | { | ||
| 1230 | return XBOOL_VECTOR (a)->data; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | INLINE unsigned char * | ||
| 1234 | bool_vector_uchar_data (Lisp_Object a) | ||
| 1235 | { | ||
| 1236 | return (unsigned char *) bool_vector_data (a); | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | /* The number of data words in a bool vector with SIZE bits. */ | ||
| 1240 | |||
| 1241 | INLINE EMACS_INT | ||
| 1242 | bool_vector_words (EMACS_INT size) | ||
| 1243 | { | ||
| 1244 | eassume (0 <= size && size <= EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1)); | ||
| 1245 | return (size + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | /* True if A's Ith bit is set. */ | ||
| 1249 | |||
| 1250 | INLINE bool | ||
| 1251 | bool_vector_bitref (Lisp_Object a, EMACS_INT i) | ||
| 1252 | { | ||
| 1253 | eassume (0 <= i && i < bool_vector_size (a)); | ||
| 1254 | return !! (bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR] | ||
| 1255 | & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR))); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | INLINE Lisp_Object | ||
| 1259 | bool_vector_ref (Lisp_Object a, EMACS_INT i) | ||
| 1260 | { | ||
| 1261 | return bool_vector_bitref (a, i) ? Qt : Qnil; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | /* Set A's Ith bit to B. */ | ||
| 1265 | |||
| 1266 | INLINE void | ||
| 1267 | bool_vector_set (Lisp_Object a, EMACS_INT i, bool b) | ||
| 1268 | { | ||
| 1269 | unsigned char *addr; | ||
| 1270 | |||
| 1271 | eassume (0 <= i && i < bool_vector_size (a)); | ||
| 1272 | addr = &bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR]; | ||
| 1273 | |||
| 1274 | if (b) | ||
| 1275 | *addr |= 1 << (i % BOOL_VECTOR_BITS_PER_CHAR); | ||
| 1276 | else | ||
| 1277 | *addr &= ~ (1 << (i % BOOL_VECTOR_BITS_PER_CHAR)); | ||
| 1278 | } | ||
| 1279 | |||
| 1216 | /* Some handy constants for calculating sizes | 1280 | /* Some handy constants for calculating sizes |
| 1217 | and offsets, mostly of vectorlike objects. */ | 1281 | and offsets, mostly of vectorlike objects. */ |
| 1218 | 1282 | ||
| @@ -3526,6 +3590,7 @@ list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h) | |||
| 3526 | make_number (w), make_number (h)); | 3590 | make_number (w), make_number (h)); |
| 3527 | } | 3591 | } |
| 3528 | 3592 | ||
| 3593 | extern void bool_vector_fill (Lisp_Object, Lisp_Object); | ||
| 3529 | extern _Noreturn void string_overflow (void); | 3594 | extern _Noreturn void string_overflow (void); |
| 3530 | extern Lisp_Object make_string (const char *, ptrdiff_t); | 3595 | extern Lisp_Object make_string (const char *, ptrdiff_t); |
| 3531 | extern Lisp_Object make_formatted_string (char *, const char *, ...) | 3596 | extern Lisp_Object make_formatted_string (char *, const char *, ...) |
| @@ -4419,10 +4484,6 @@ functionp (Lisp_Object object) | |||
| 4419 | return 0; | 4484 | return 0; |
| 4420 | } | 4485 | } |
| 4421 | 4486 | ||
| 4422 | /* Round x to the next multiple of y. Does not overflow. Evaluates | ||
| 4423 | arguments repeatedly. */ | ||
| 4424 | #define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0))) | ||
| 4425 | |||
| 4426 | INLINE_HEADER_END | 4487 | INLINE_HEADER_END |
| 4427 | 4488 | ||
| 4428 | #endif /* EMACS_LISP_H */ | 4489 | #endif /* EMACS_LISP_H */ |
diff --git a/src/lread.c b/src/lread.c index 618b0cadb53..7e4f5d38d09 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -2580,6 +2580,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2580 | EMACS_INT size_in_chars | 2580 | EMACS_INT size_in_chars |
| 2581 | = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2581 | = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1) |
| 2582 | / BOOL_VECTOR_BITS_PER_CHAR); | 2582 | / BOOL_VECTOR_BITS_PER_CHAR); |
| 2583 | unsigned char *data; | ||
| 2583 | 2584 | ||
| 2584 | UNREAD (c); | 2585 | UNREAD (c); |
| 2585 | tmp = read1 (readcharfun, pch, first_in_list); | 2586 | tmp = read1 (readcharfun, pch, first_in_list); |
| @@ -2594,10 +2595,11 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2594 | invalid_syntax ("#&..."); | 2595 | invalid_syntax ("#&..."); |
| 2595 | 2596 | ||
| 2596 | val = Fmake_bool_vector (length, Qnil); | 2597 | val = Fmake_bool_vector (length, Qnil); |
| 2597 | memcpy (XBOOL_VECTOR (val)->data, SDATA (tmp), size_in_chars); | 2598 | data = bool_vector_uchar_data (val); |
| 2599 | memcpy (data, SDATA (tmp), size_in_chars); | ||
| 2598 | /* Clear the extraneous bits in the last byte. */ | 2600 | /* Clear the extraneous bits in the last byte. */ |
| 2599 | if (XINT (length) != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR) | 2601 | if (XINT (length) != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR) |
| 2600 | XBOOL_VECTOR (val)->data[size_in_chars - 1] | 2602 | data[size_in_chars - 1] |
| 2601 | &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | 2603 | &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; |
| 2602 | return val; | 2604 | return val; |
| 2603 | } | 2605 | } |
diff --git a/src/print.c b/src/print.c index 965d719f852..6eda6a86fc4 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1726,7 +1726,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1726 | for (i = 0; i < size_in_chars; i++) | 1726 | for (i = 0; i < size_in_chars; i++) |
| 1727 | { | 1727 | { |
| 1728 | QUIT; | 1728 | QUIT; |
| 1729 | c = XBOOL_VECTOR (obj)->data[i]; | 1729 | c = bool_vector_uchar_data (obj)[i]; |
| 1730 | if (c == '\n' && print_escape_newlines) | 1730 | if (c == '\n' && print_escape_newlines) |
| 1731 | { | 1731 | { |
| 1732 | PRINTCHAR ('\\'); | 1732 | PRINTCHAR ('\\'); |