diff options
| author | Paul Eggert | 2013-06-21 13:11:44 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-06-21 13:11:44 -0700 |
| commit | fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc (patch) | |
| tree | 7b1836faca02f39413afec531c2ae467898523f5 /src | |
| parent | cad5d1cb5af7210154814b60825576d14740158f (diff) | |
| download | emacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.tar.gz emacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.zip | |
Use C99-style flexible array members if available.
This avoids some subtle aliasing issues, which typically
aren't a problem with GCC but may be a problem elsewhere.
* lib-src/ebrowse.c (struct member, struct alias, struct sym):
Use FLEXIBLE_ARRAY_MEMBER.
(add_sym, add_member, make_namespace, register_namespace_alias):
Use offsetof (struct, flex_array_member), not sizeof (struct), as
that ports better to pre-C99 non-GCC.
* src/alloc.c (sdata): New typedef, replacing the old struct sdata.
It is a struct if GC_CHECK_STRING_BYTES, a union otherwise.
In either case, it uses a flexible array member rather than
the old struct hack. All uses changed.
(SDATA_NBYTES, sweep_strings) [!GC_CHECK_STRING_BYTES]:
Adjust to sdata reorganization.
* src/alloc.c (VBLOCK_BYTES_MIN, allocate_vectorlike, Fgarbage_collect):
Use offsetof (struct, flex_array_member), not sizeof (struct), as
that ports better to pre-C99 non-GCC.
* src/chartab.c (Fmake_char_table, make_sub_char_table, copy_char_table):
Use CHAR_TABLE_STANDARD_SLOTS rather than its definition,
as the latter has changed.
* src/conf_post.h (FLEXIBLE_ARRAY_MEMBER): Move here from w32.c,
and port better to pre-C99 GCC.
* src/image.c (struct xpm_cached_color):
* src/lisp.h (struct Lisp_Vector, struct Lisp_Bool_Vector)
(struct Lisp_Char_Table, struct Lisp_Sub_Char_Table):
Use FLEXIBLE_ARRAY_MEMBER.
* src/lisp.h (string_bytes) [GC_CHECK_STRING_BYTES]:
Move decl to top level so it gets checked against implementation.
(CHAR_TABLE_STANDARD_SLOTS): Adjust to struct Lisp_Char_Table change.
* src/w32.c (FLEXIBLE_ARRAY_MEMBER): Move to conf_post.h.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 28 | ||||
| -rw-r--r-- | src/alloc.c | 80 | ||||
| -rw-r--r-- | src/chartab.c | 6 | ||||
| -rw-r--r-- | src/conf_post.h | 11 | ||||
| -rw-r--r-- | src/image.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 16 | ||||
| -rw-r--r-- | src/w32.c | 6 |
7 files changed, 99 insertions, 50 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 4e52f5b2818..4821f5fb7eb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,31 @@ | |||
| 1 | 2013-06-21 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Use C99-style flexible array members if available. | ||
| 4 | This avoids some subtle aliasing issues, which typically | ||
| 5 | aren't a problem with GCC but may be a problem elsewhere. | ||
| 6 | * alloc.c (sdata): New typedef, replacing the old struct sdata. | ||
| 7 | It is a struct if GC_CHECK_STRING_BYTES, a union otherwise. | ||
| 8 | In either case, it uses a flexible array member rather than | ||
| 9 | the old struct hack. All uses changed. | ||
| 10 | (SDATA_NBYTES, sweep_strings) [!GC_CHECK_STRING_BYTES]: | ||
| 11 | Adjust to sdata reorganization. | ||
| 12 | * alloc.c (VBLOCK_BYTES_MIN, allocate_vectorlike, Fgarbage_collect): | ||
| 13 | Use offsetof (struct, flex_array_member), not sizeof (struct), as | ||
| 14 | that ports better to pre-C99 non-GCC. | ||
| 15 | * chartab.c (Fmake_char_table, make_sub_char_table, copy_char_table): | ||
| 16 | Use CHAR_TABLE_STANDARD_SLOTS rather than its definition, | ||
| 17 | as the latter has changed. | ||
| 18 | * conf_post.h (FLEXIBLE_ARRAY_MEMBER): Move here from w32.c, | ||
| 19 | and port better to pre-C99 GCC. | ||
| 20 | * image.c (struct xpm_cached_color): | ||
| 21 | * lisp.h (struct Lisp_Vector, struct Lisp_Bool_Vector) | ||
| 22 | (struct Lisp_Char_Table, struct Lisp_Sub_Char_Table): | ||
| 23 | Use FLEXIBLE_ARRAY_MEMBER. | ||
| 24 | * lisp.h (string_bytes) [GC_CHECK_STRING_BYTES]: | ||
| 25 | Move decl to top level so it gets checked against implementation. | ||
| 26 | (CHAR_TABLE_STANDARD_SLOTS): Adjust to struct Lisp_Char_Table change. | ||
| 27 | * w32.c (FLEXIBLE_ARRAY_MEMBER): Move to conf_post.h. | ||
| 28 | |||
| 1 | 2013-06-20 Paul Eggert <eggert@cs.ucla.edu> | 29 | 2013-06-20 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 30 | ||
| 3 | * syntax.c: Integer cleanups. | 31 | * syntax.c: Integer cleanups. |
diff --git a/src/alloc.c b/src/alloc.c index d277dd2419b..eaef0d4b797 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1260,7 +1260,7 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1260 | When a Lisp_String is freed during GC, it is put back on | 1260 | When a Lisp_String is freed during GC, it is put back on |
| 1261 | string_free_list, and its `data' member and its sdata's `string' | 1261 | string_free_list, and its `data' member and its sdata's `string' |
| 1262 | pointer is set to null. The size of the string is recorded in the | 1262 | pointer is set to null. The size of the string is recorded in the |
| 1263 | `u.nbytes' member of the sdata. So, sdata structures that are no | 1263 | `n.nbytes' member of the sdata. So, sdata structures that are no |
| 1264 | longer used, can be easily recognized, and it's easy to compact the | 1264 | longer used, can be easily recognized, and it's easy to compact the |
| 1265 | sblocks of small strings which we do in compact_small_strings. */ | 1265 | sblocks of small strings which we do in compact_small_strings. */ |
| 1266 | 1266 | ||
| @@ -1274,10 +1274,12 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1274 | 1274 | ||
| 1275 | #define LARGE_STRING_BYTES 1024 | 1275 | #define LARGE_STRING_BYTES 1024 |
| 1276 | 1276 | ||
| 1277 | /* Structure describing string memory sub-allocated from an sblock. | 1277 | /* Struct or union describing string memory sub-allocated from an sblock. |
| 1278 | This is where the contents of Lisp strings are stored. */ | 1278 | This is where the contents of Lisp strings are stored. */ |
| 1279 | 1279 | ||
| 1280 | struct sdata | 1280 | #ifdef GC_CHECK_STRING_BYTES |
| 1281 | |||
| 1282 | typedef struct | ||
| 1281 | { | 1283 | { |
| 1282 | /* Back-pointer to the string this sdata belongs to. If null, this | 1284 | /* Back-pointer to the string this sdata belongs to. If null, this |
| 1283 | structure is free, and the NBYTES member of the union below | 1285 | structure is free, and the NBYTES member of the union below |
| @@ -1287,34 +1289,42 @@ struct sdata | |||
| 1287 | contents. */ | 1289 | contents. */ |
| 1288 | struct Lisp_String *string; | 1290 | struct Lisp_String *string; |
| 1289 | 1291 | ||
| 1290 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1291 | |||
| 1292 | ptrdiff_t nbytes; | 1292 | ptrdiff_t nbytes; |
| 1293 | unsigned char data[1]; | 1293 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1294 | } sdata; | ||
| 1294 | 1295 | ||
| 1295 | #define SDATA_NBYTES(S) (S)->nbytes | 1296 | #define SDATA_NBYTES(S) (S)->nbytes |
| 1296 | #define SDATA_DATA(S) (S)->data | 1297 | #define SDATA_DATA(S) (S)->data |
| 1297 | #define SDATA_SELECTOR(member) member | 1298 | #define SDATA_SELECTOR(member) member |
| 1298 | 1299 | ||
| 1299 | #else /* not GC_CHECK_STRING_BYTES */ | 1300 | #else |
| 1300 | 1301 | ||
| 1301 | union | 1302 | typedef union |
| 1303 | { | ||
| 1304 | struct Lisp_String *string; | ||
| 1305 | |||
| 1306 | /* When STRING is non-null. */ | ||
| 1307 | struct | ||
| 1302 | { | 1308 | { |
| 1303 | /* When STRING is non-null. */ | 1309 | struct Lisp_String *string; |
| 1304 | unsigned char data[1]; | 1310 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1311 | } u; | ||
| 1305 | 1312 | ||
| 1306 | /* When STRING is null. */ | 1313 | /* When STRING is null. */ |
| 1314 | struct | ||
| 1315 | { | ||
| 1316 | struct Lisp_String *string; | ||
| 1307 | ptrdiff_t nbytes; | 1317 | ptrdiff_t nbytes; |
| 1308 | } u; | 1318 | } n; |
| 1319 | } sdata; | ||
| 1309 | 1320 | ||
| 1310 | #define SDATA_NBYTES(S) (S)->u.nbytes | 1321 | #define SDATA_NBYTES(S) (S)->n.nbytes |
| 1311 | #define SDATA_DATA(S) (S)->u.data | 1322 | #define SDATA_DATA(S) (S)->u.data |
| 1312 | #define SDATA_SELECTOR(member) u.member | 1323 | #define SDATA_SELECTOR(member) u.member |
| 1313 | 1324 | ||
| 1314 | #endif /* not GC_CHECK_STRING_BYTES */ | 1325 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1315 | 1326 | ||
| 1316 | #define SDATA_DATA_OFFSET offsetof (struct sdata, SDATA_SELECTOR (data)) | 1327 | #define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data)) |
| 1317 | }; | ||
| 1318 | 1328 | ||
| 1319 | 1329 | ||
| 1320 | /* Structure describing a block of memory which is sub-allocated to | 1330 | /* Structure describing a block of memory which is sub-allocated to |
| @@ -1329,10 +1339,10 @@ struct sblock | |||
| 1329 | 1339 | ||
| 1330 | /* Pointer to the next free sdata block. This points past the end | 1340 | /* Pointer to the next free sdata block. This points past the end |
| 1331 | of the sblock if there isn't any space left in this block. */ | 1341 | of the sblock if there isn't any space left in this block. */ |
| 1332 | struct sdata *next_free; | 1342 | sdata *next_free; |
| 1333 | 1343 | ||
| 1334 | /* Start of data. */ | 1344 | /* Start of data. */ |
| 1335 | struct sdata first_data; | 1345 | sdata first_data; |
| 1336 | }; | 1346 | }; |
| 1337 | 1347 | ||
| 1338 | /* Number of Lisp strings in a string_block structure. The 1020 is | 1348 | /* Number of Lisp strings in a string_block structure. The 1020 is |
| @@ -1388,7 +1398,7 @@ static EMACS_INT total_string_bytes; | |||
| 1388 | a pointer to the `u.data' member of its sdata structure; the | 1398 | a pointer to the `u.data' member of its sdata structure; the |
| 1389 | structure starts at a constant offset in front of that. */ | 1399 | structure starts at a constant offset in front of that. */ |
| 1390 | 1400 | ||
| 1391 | #define SDATA_OF_STRING(S) ((struct sdata *) ((S)->data - SDATA_DATA_OFFSET)) | 1401 | #define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET)) |
| 1392 | 1402 | ||
| 1393 | 1403 | ||
| 1394 | #ifdef GC_CHECK_STRING_OVERRUN | 1404 | #ifdef GC_CHECK_STRING_OVERRUN |
| @@ -1487,7 +1497,7 @@ string_bytes (struct Lisp_String *s) | |||
| 1487 | static void | 1497 | static void |
| 1488 | check_sblock (struct sblock *b) | 1498 | check_sblock (struct sblock *b) |
| 1489 | { | 1499 | { |
| 1490 | struct sdata *from, *end, *from_end; | 1500 | sdata *from, *end, *from_end; |
| 1491 | 1501 | ||
| 1492 | end = b->next_free; | 1502 | end = b->next_free; |
| 1493 | 1503 | ||
| @@ -1501,7 +1511,7 @@ check_sblock (struct sblock *b) | |||
| 1501 | same as the one recorded in the sdata structure. */ | 1511 | same as the one recorded in the sdata structure. */ |
| 1502 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) | 1512 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) |
| 1503 | : SDATA_NBYTES (from)); | 1513 | : SDATA_NBYTES (from)); |
| 1504 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1514 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1505 | } | 1515 | } |
| 1506 | } | 1516 | } |
| 1507 | 1517 | ||
| @@ -1631,7 +1641,7 @@ void | |||
| 1631 | allocate_string_data (struct Lisp_String *s, | 1641 | allocate_string_data (struct Lisp_String *s, |
| 1632 | EMACS_INT nchars, EMACS_INT nbytes) | 1642 | EMACS_INT nchars, EMACS_INT nbytes) |
| 1633 | { | 1643 | { |
| 1634 | struct sdata *data, *old_data; | 1644 | sdata *data, *old_data; |
| 1635 | struct sblock *b; | 1645 | struct sblock *b; |
| 1636 | ptrdiff_t needed, old_nbytes; | 1646 | ptrdiff_t needed, old_nbytes; |
| 1637 | 1647 | ||
| @@ -1701,7 +1711,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1701 | b = current_sblock; | 1711 | b = current_sblock; |
| 1702 | 1712 | ||
| 1703 | data = b->next_free; | 1713 | data = b->next_free; |
| 1704 | b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); | 1714 | b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); |
| 1705 | 1715 | ||
| 1706 | MALLOC_UNBLOCK_INPUT; | 1716 | MALLOC_UNBLOCK_INPUT; |
| 1707 | 1717 | ||
| @@ -1772,7 +1782,7 @@ sweep_strings (void) | |||
| 1772 | else | 1782 | else |
| 1773 | { | 1783 | { |
| 1774 | /* String is dead. Put it on the free-list. */ | 1784 | /* String is dead. Put it on the free-list. */ |
| 1775 | struct sdata *data = SDATA_OF_STRING (s); | 1785 | sdata *data = SDATA_OF_STRING (s); |
| 1776 | 1786 | ||
| 1777 | /* Save the size of S in its sdata so that we know | 1787 | /* Save the size of S in its sdata so that we know |
| 1778 | how large that is. Reset the sdata's string | 1788 | how large that is. Reset the sdata's string |
| @@ -1781,7 +1791,7 @@ sweep_strings (void) | |||
| 1781 | if (string_bytes (s) != SDATA_NBYTES (data)) | 1791 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 1782 | emacs_abort (); | 1792 | emacs_abort (); |
| 1783 | #else | 1793 | #else |
| 1784 | data->u.nbytes = STRING_BYTES (s); | 1794 | data->n.nbytes = STRING_BYTES (s); |
| 1785 | #endif | 1795 | #endif |
| 1786 | data->string = NULL; | 1796 | data->string = NULL; |
| 1787 | 1797 | ||
| @@ -1862,13 +1872,13 @@ static void | |||
| 1862 | compact_small_strings (void) | 1872 | compact_small_strings (void) |
| 1863 | { | 1873 | { |
| 1864 | struct sblock *b, *tb, *next; | 1874 | struct sblock *b, *tb, *next; |
| 1865 | struct sdata *from, *to, *end, *tb_end; | 1875 | sdata *from, *to, *end, *tb_end; |
| 1866 | struct sdata *to_end, *from_end; | 1876 | sdata *to_end, *from_end; |
| 1867 | 1877 | ||
| 1868 | /* TB is the sblock we copy to, TO is the sdata within TB we copy | 1878 | /* TB is the sblock we copy to, TO is the sdata within TB we copy |
| 1869 | to, and TB_END is the end of TB. */ | 1879 | to, and TB_END is the end of TB. */ |
| 1870 | tb = oldest_sblock; | 1880 | tb = oldest_sblock; |
| 1871 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1881 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1872 | to = &tb->first_data; | 1882 | to = &tb->first_data; |
| 1873 | 1883 | ||
| 1874 | /* Step through the blocks from the oldest to the youngest. We | 1884 | /* Step through the blocks from the oldest to the youngest. We |
| @@ -1897,7 +1907,7 @@ compact_small_strings (void) | |||
| 1897 | eassert (nbytes <= LARGE_STRING_BYTES); | 1907 | eassert (nbytes <= LARGE_STRING_BYTES); |
| 1898 | 1908 | ||
| 1899 | nbytes = SDATA_SIZE (nbytes); | 1909 | nbytes = SDATA_SIZE (nbytes); |
| 1900 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1910 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1901 | 1911 | ||
| 1902 | #ifdef GC_CHECK_STRING_OVERRUN | 1912 | #ifdef GC_CHECK_STRING_OVERRUN |
| 1903 | if (memcmp (string_overrun_cookie, | 1913 | if (memcmp (string_overrun_cookie, |
| @@ -1910,14 +1920,14 @@ compact_small_strings (void) | |||
| 1910 | if (s) | 1920 | if (s) |
| 1911 | { | 1921 | { |
| 1912 | /* If TB is full, proceed with the next sblock. */ | 1922 | /* If TB is full, proceed with the next sblock. */ |
| 1913 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1923 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1914 | if (to_end > tb_end) | 1924 | if (to_end > tb_end) |
| 1915 | { | 1925 | { |
| 1916 | tb->next_free = to; | 1926 | tb->next_free = to; |
| 1917 | tb = tb->next; | 1927 | tb = tb->next; |
| 1918 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1928 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1919 | to = &tb->first_data; | 1929 | to = &tb->first_data; |
| 1920 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1930 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1921 | } | 1931 | } |
| 1922 | 1932 | ||
| 1923 | /* Copy, and update the string's `data' pointer. */ | 1933 | /* Copy, and update the string's `data' pointer. */ |
| @@ -2581,7 +2591,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2581 | 2591 | ||
| 2582 | /* Size of the minimal vector allocated from block. */ | 2592 | /* Size of the minimal vector allocated from block. */ |
| 2583 | 2593 | ||
| 2584 | #define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector)) | 2594 | #define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object)) |
| 2585 | 2595 | ||
| 2586 | /* Size of the largest vector allocated from block. */ | 2596 | /* Size of the largest vector allocated from block. */ |
| 2587 | 2597 | ||
| @@ -2938,7 +2948,8 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2938 | else | 2948 | else |
| 2939 | { | 2949 | { |
| 2940 | struct large_vector *lv | 2950 | struct large_vector *lv |
| 2941 | = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, | 2951 | = lisp_malloc ((offsetof (struct large_vector, v.contents) |
| 2952 | + len * word_size), | ||
| 2942 | MEM_TYPE_VECTORLIKE); | 2953 | MEM_TYPE_VECTORLIKE); |
| 2943 | lv->next.vector = large_vectors; | 2954 | lv->next.vector = large_vectors; |
| 2944 | large_vectors = lv; | 2955 | large_vectors = lv; |
| @@ -5416,7 +5427,8 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5416 | total[4] = list3 (Qstring_bytes, make_number (1), | 5427 | total[4] = list3 (Qstring_bytes, make_number (1), |
| 5417 | bounded_number (total_string_bytes)); | 5428 | bounded_number (total_string_bytes)); |
| 5418 | 5429 | ||
| 5419 | total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)), | 5430 | total[5] = list3 (Qvectors, |
| 5431 | make_number (header_size + sizeof (Lisp_Object)), | ||
| 5420 | bounded_number (total_vectors)); | 5432 | bounded_number (total_vectors)); |
| 5421 | 5433 | ||
| 5422 | total[6] = list4 (Qvector_slots, make_number (word_size), | 5434 | total[6] = list4 (Qvector_slots, make_number (word_size), |
diff --git a/src/chartab.c b/src/chartab.c index 1c76e5a21e9..b7b9590a538 100644 --- a/src/chartab.c +++ b/src/chartab.c | |||
| @@ -128,7 +128,7 @@ the char-table has no extra slot. */) | |||
| 128 | n_extras = XINT (n); | 128 | n_extras = XINT (n); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras; | 131 | size = CHAR_TABLE_STANDARD_SLOTS + n_extras; |
| 132 | vector = Fmake_vector (make_number (size), init); | 132 | vector = Fmake_vector (make_number (size), init); |
| 133 | XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); | 133 | XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); |
| 134 | set_char_table_parent (vector, Qnil); | 134 | set_char_table_parent (vector, Qnil); |
| @@ -141,7 +141,7 @@ static Lisp_Object | |||
| 141 | make_sub_char_table (int depth, int min_char, Lisp_Object defalt) | 141 | make_sub_char_table (int depth, int min_char, Lisp_Object defalt) |
| 142 | { | 142 | { |
| 143 | Lisp_Object table; | 143 | Lisp_Object table; |
| 144 | int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth]; | 144 | int size = CHAR_TABLE_STANDARD_SLOTS + chartab_size[depth]; |
| 145 | 145 | ||
| 146 | table = Fmake_vector (make_number (size), defalt); | 146 | table = Fmake_vector (make_number (size), defalt); |
| 147 | XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); | 147 | XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); |
| @@ -207,7 +207,7 @@ copy_char_table (Lisp_Object table) | |||
| 207 | ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i]) | 207 | ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i]) |
| 208 | : XCHAR_TABLE (table)->contents[i])); | 208 | : XCHAR_TABLE (table)->contents[i])); |
| 209 | set_char_table_ascii (copy, char_table_ascii (copy)); | 209 | set_char_table_ascii (copy, char_table_ascii (copy)); |
| 210 | size -= VECSIZE (struct Lisp_Char_Table) - 1; | 210 | size -= CHAR_TABLE_STANDARD_SLOTS; |
| 211 | for (i = 0; i < size; i++) | 211 | for (i = 0; i < size; i++) |
| 212 | set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]); | 212 | set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]); |
| 213 | 213 | ||
diff --git a/src/conf_post.h b/src/conf_post.h index 46aea32ef30..32c4341b7a3 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -243,6 +243,17 @@ extern void _DebPrint (const char *fmt, ...); | |||
| 243 | #define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN | 243 | #define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN |
| 244 | #define INLINE_HEADER_END _GL_INLINE_HEADER_END | 244 | #define INLINE_HEADER_END _GL_INLINE_HEADER_END |
| 245 | 245 | ||
| 246 | /* To use the struct hack with N elements, declare the struct like this: | ||
| 247 | struct s { ...; t name[FLEXIBLE_ARRAY_MEMBER]; }; | ||
| 248 | and allocate (offsetof (struct s, name) + N * sizeof (t)) bytes. */ | ||
| 249 | #if 199901 <= __STDC_VERSION__ | ||
| 250 | # define FLEXIBLE_ARRAY_MEMBER | ||
| 251 | #elif __GNUC__ && !defined __STRICT_ANSI__ | ||
| 252 | # define FLEXIBLE_ARRAY_MEMBER 0 | ||
| 253 | #else | ||
| 254 | # define FLEXIBLE_ARRAY_MEMBER 1 | ||
| 255 | #endif | ||
| 256 | |||
| 246 | /* Use this to suppress gcc's `...may be used before initialized' warnings. */ | 257 | /* Use this to suppress gcc's `...may be used before initialized' warnings. */ |
| 247 | #ifdef lint | 258 | #ifdef lint |
| 248 | /* Use CODE only if lint checking is in effect. */ | 259 | /* Use CODE only if lint checking is in effect. */ |
diff --git a/src/image.c b/src/image.c index f9f6ce70040..ffb3cd15e93 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -3057,7 +3057,7 @@ struct xpm_cached_color | |||
| 3057 | XColor color; | 3057 | XColor color; |
| 3058 | 3058 | ||
| 3059 | /* Color name. */ | 3059 | /* Color name. */ |
| 3060 | char name[1]; | 3060 | char name[FLEXIBLE_ARRAY_MEMBER]; |
| 3061 | }; | 3061 | }; |
| 3062 | 3062 | ||
| 3063 | /* The hash table used for the color cache, and its bucket vector | 3063 | /* The hash table used for the color cache, and its bucket vector |
diff --git a/src/lisp.h b/src/lisp.h index e2d091e98f1..f4356cd140d 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1073,16 +1073,20 @@ SCHARS (Lisp_Object string) | |||
| 1073 | { | 1073 | { |
| 1074 | return XSTRING (string)->size; | 1074 | return XSTRING (string)->size; |
| 1075 | } | 1075 | } |
| 1076 | |||
| 1077 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1078 | extern ptrdiff_t string_bytes (struct Lisp_String *); | ||
| 1079 | #endif | ||
| 1076 | LISP_INLINE ptrdiff_t | 1080 | LISP_INLINE ptrdiff_t |
| 1077 | STRING_BYTES (struct Lisp_String *s) | 1081 | STRING_BYTES (struct Lisp_String *s) |
| 1078 | { | 1082 | { |
| 1079 | #ifdef GC_CHECK_STRING_BYTES | 1083 | #ifdef GC_CHECK_STRING_BYTES |
| 1080 | extern ptrdiff_t string_bytes (struct Lisp_String *); | ||
| 1081 | return string_bytes (s); | 1084 | return string_bytes (s); |
| 1082 | #else | 1085 | #else |
| 1083 | return s->size_byte < 0 ? s->size : s->size_byte; | 1086 | return s->size_byte < 0 ? s->size : s->size_byte; |
| 1084 | #endif | 1087 | #endif |
| 1085 | } | 1088 | } |
| 1089 | |||
| 1086 | LISP_INLINE ptrdiff_t | 1090 | LISP_INLINE ptrdiff_t |
| 1087 | SBYTES (Lisp_Object string) | 1091 | SBYTES (Lisp_Object string) |
| 1088 | { | 1092 | { |
| @@ -1136,7 +1140,7 @@ struct vectorlike_header | |||
| 1136 | struct Lisp_Vector | 1140 | struct Lisp_Vector |
| 1137 | { | 1141 | { |
| 1138 | struct vectorlike_header header; | 1142 | struct vectorlike_header header; |
| 1139 | Lisp_Object contents[1]; | 1143 | Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; |
| 1140 | }; | 1144 | }; |
| 1141 | 1145 | ||
| 1142 | /* A boolvector is a kind of vectorlike, with contents are like a string. */ | 1146 | /* A boolvector is a kind of vectorlike, with contents are like a string. */ |
| @@ -1149,7 +1153,7 @@ struct Lisp_Bool_Vector | |||
| 1149 | /* This is the size in bits. */ | 1153 | /* This is the size in bits. */ |
| 1150 | EMACS_INT size; | 1154 | EMACS_INT size; |
| 1151 | /* This contains the actual bits, packed into bytes. */ | 1155 | /* This contains the actual bits, packed into bytes. */ |
| 1152 | unsigned char data[1]; | 1156 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1153 | }; | 1157 | }; |
| 1154 | 1158 | ||
| 1155 | /* Some handy constants for calculating sizes | 1159 | /* Some handy constants for calculating sizes |
| @@ -1272,7 +1276,7 @@ struct Lisp_Char_Table | |||
| 1272 | Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)]; | 1276 | Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)]; |
| 1273 | 1277 | ||
| 1274 | /* These hold additional data. It is a vector. */ | 1278 | /* These hold additional data. It is a vector. */ |
| 1275 | Lisp_Object extras[1]; | 1279 | Lisp_Object extras[FLEXIBLE_ARRAY_MEMBER]; |
| 1276 | }; | 1280 | }; |
| 1277 | 1281 | ||
| 1278 | struct Lisp_Sub_Char_Table | 1282 | struct Lisp_Sub_Char_Table |
| @@ -1293,7 +1297,7 @@ struct Lisp_Sub_Char_Table | |||
| 1293 | Lisp_Object min_char; | 1297 | Lisp_Object min_char; |
| 1294 | 1298 | ||
| 1295 | /* Use set_sub_char_table_contents to set this. */ | 1299 | /* Use set_sub_char_table_contents to set this. */ |
| 1296 | Lisp_Object contents[1]; | 1300 | Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER]; |
| 1297 | }; | 1301 | }; |
| 1298 | 1302 | ||
| 1299 | LISP_INLINE Lisp_Object | 1303 | LISP_INLINE Lisp_Object |
| @@ -1366,7 +1370,7 @@ struct Lisp_Subr | |||
| 1366 | slots. */ | 1370 | slots. */ |
| 1367 | enum CHAR_TABLE_STANDARD_SLOTS | 1371 | enum CHAR_TABLE_STANDARD_SLOTS |
| 1368 | { | 1372 | { |
| 1369 | CHAR_TABLE_STANDARD_SLOTS = VECSIZE (struct Lisp_Char_Table) - 1 | 1373 | CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras) |
| 1370 | }; | 1374 | }; |
| 1371 | 1375 | ||
| 1372 | /* Return the number of "extra" slots in the char table CT. */ | 1376 | /* Return the number of "extra" slots in the char table CT. */ |
| @@ -3785,12 +3785,6 @@ get_rid (PSID sid) | |||
| 3785 | 3785 | ||
| 3786 | /* Caching SID and account values for faster lokup. */ | 3786 | /* Caching SID and account values for faster lokup. */ |
| 3787 | 3787 | ||
| 3788 | #ifdef __GNUC__ | ||
| 3789 | # define FLEXIBLE_ARRAY_MEMBER | ||
| 3790 | #else | ||
| 3791 | # define FLEXIBLE_ARRAY_MEMBER 1 | ||
| 3792 | #endif | ||
| 3793 | |||
| 3794 | struct w32_id { | 3788 | struct w32_id { |
| 3795 | unsigned rid; | 3789 | unsigned rid; |
| 3796 | struct w32_id *next; | 3790 | struct w32_id *next; |