aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-11-04 23:11:24 -0800
committerPaul Eggert2013-11-04 23:11:24 -0800
commitdf5b49306e8e82e2f18ed3243700c11ca7835750 (patch)
treed98fffc7d11d4565b6132e83f54ca3f3c547b1d4 /src
parent693698093480628b7438ca0fd1614b00acfd1137 (diff)
downloademacs-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/ChangeLog46
-rw-r--r--src/alloc.c108
-rw-r--r--src/category.c41
-rw-r--r--src/category.h12
-rw-r--r--src/data.c51
-rw-r--r--src/fns.c37
-rw-r--r--src/image.c4
-rw-r--r--src/lisp.h87
-rw-r--r--src/lread.c6
-rw-r--r--src/print.c2
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 @@
12013-11-05 Paul Eggert <eggert@cs.ucla.edu> 12013-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
362static void *pure_alloc (size_t, int); 362static 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))) 374static void *
375ALIGN (void *ptr, int alignment)
376{
377 return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
378}
371 379
372static void 380static void
373XFLOAT_INIT (Lisp_Object f, double n) 381XFLOAT_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
2029verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD); 2037static EMACS_INT
2030verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0); 2038bool_vector_exact_payload_bytes (EMACS_INT nbits)
2031
2032static ptrdiff_t
2033bool_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); 2044static EMACS_INT
2045bool_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) 2056void
2057bool_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
2058DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, 2072DEFUN ("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,
2060LENGTH must be a number. INIT matters only in whether it is t or nil. */) 2074LENGTH 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);
2648verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); 2649verify (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)
55static int category_table_version; 55static int category_table_version;
56 56
57static Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, Qcategory_table_p; 57static 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)
63static void set_category_set (Lisp_Object, Lisp_Object, Lisp_Object);
64 58
65/* Category set staff. */ 59/* Category set staff. */
66 60
67static Lisp_Object hash_get_category_set (Lisp_Object, Lisp_Object);
68
69static Lisp_Object 61static Lisp_Object
70hash_get_category_set (Lisp_Object table, Lisp_Object category_set) 62hash_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
85static void
86set_category_set (Lisp_Object category_set, EMACS_INT category, bool val)
87{
88 bool_vector_set (category_set, category, val);
89}
91 90
92DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0, 91DEFUN ("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
337static void
338set_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
351DEFUN ("modify-category-entry", Fmodify_category_entry, 336DEFUN ("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,
359then delete CATEGORY from the category set instead of adding it. */) 344then 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) \ 77INLINE bool
80 ((XCATEGORY_SET (category_set)->data[(category) / 8] \ 78CATEGORY_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. */
84INLINE bool 84INLINE 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)
diff --git a/src/fns.c b/src/fns.c
index 93f2eee0666..44b70af6eb5 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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. */
87enum { 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)
87typedef size_t bits_word; 97typedef size_t bits_word;
88#define BITS_WORD_MAX SIZE_MAX 98#define BITS_WORD_MAX SIZE_MAX
99enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) };
100#else
101typedef unsigned char bits_word;
102#define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1)
103enum { 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. */
91enum 107enum
@@ -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. */
778extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p; 789extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p;
779extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil; 790extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
780extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp; 791extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qt, Qvectorp;
781extern Lisp_Object Qbool_vector_p; 792extern Lisp_Object Qbool_vector_p;
782extern Lisp_Object Qvector_or_char_table_p, Qwholenump; 793extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
783extern Lisp_Object Qwindow; 794extern 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. */
1156struct vectorlike_header 1167struct 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
1208INLINE EMACS_INT 1219INLINE EMACS_INT
@@ -1213,6 +1224,59 @@ bool_vector_size (Lisp_Object a)
1213 return size; 1224 return size;
1214} 1225}
1215 1226
1227INLINE bits_word *
1228bool_vector_data (Lisp_Object a)
1229{
1230 return XBOOL_VECTOR (a)->data;
1231}
1232
1233INLINE unsigned char *
1234bool_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
1241INLINE EMACS_INT
1242bool_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
1250INLINE bool
1251bool_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
1258INLINE Lisp_Object
1259bool_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
1266INLINE void
1267bool_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
3593extern void bool_vector_fill (Lisp_Object, Lisp_Object);
3529extern _Noreturn void string_overflow (void); 3594extern _Noreturn void string_overflow (void);
3530extern Lisp_Object make_string (const char *, ptrdiff_t); 3595extern Lisp_Object make_string (const char *, ptrdiff_t);
3531extern Lisp_Object make_formatted_string (char *, const char *, ...) 3596extern 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
4426INLINE_HEADER_END 4487INLINE_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 ('\\');