Mercurial > hg > xemacs-beta
comparison src/lisp.h @ 4844:91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
dynarr.c: Add comment explaining Dynarr_largest() use.
dynarr.c: In Dynarr_insert_many(), don't call Dynarr_resize() unless we
actually need to resize, and note that an assert() that we are
inserting at or below the current end could be wrong if code
wants to access stuff between `len' and `largest'.
dynarr.c: Don't just Dynarr_resize() to the right size; instead use
Dynarr_reset() then Dynarr_add_many(), so that the 'len' and
'largest' and such get set properly.
dynarr.c, faces.c, gutter.c, lisp.h, lread.c, lrecord.h, redisplay-output.c, redisplay.c: Rename Dynarr member 'cur' to 'len' since it's the length of
the dynarr, not really a pointer to a "current insertion point".
Use type_checking_assert() instead of just assert() in some places.
Add additional assertions (Dynarr_verify*()) to check that we're
being given positions within range. Use them in Dynarr_at,
Dynarr_atp, etc. New Dynarr_atp_allow_end() for retrieving a
pointer to a position that might be the element past the last one.
New Dynarr_past_lastp() to retrieve a pointer to the position
past the last one, using Dynarr_atp_allow_end(). Change code
appropriately to use it.
Rename Dynarr_end() to Dynarr_lastp() (pointer to the last
element) for clarity, and change code appropriately to use it.
Change code appropriately to use Dynarr_begin().
Rewrite Dynarr_add_many(). New version can accept a NULL pointer
to mean "reserve space but don't put anything in it". Used by
stack_like_malloc().
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 13 Jan 2010 04:07:42 -0600 |
parents | 715b15990d0a |
children | a98ca4640147 |
comparison
equal
deleted
inserted
replaced
4843:715b15990d0a | 4844:91b3d00e717f |
---|---|
1711 struct lrecord_header header; \ | 1711 struct lrecord_header header; \ |
1712 type *base; \ | 1712 type *base; \ |
1713 const struct lrecord_implementation *lisp_imp; \ | 1713 const struct lrecord_implementation *lisp_imp; \ |
1714 int locked; \ | 1714 int locked; \ |
1715 int elsize; \ | 1715 int elsize; \ |
1716 int cur; \ | 1716 int len; \ |
1717 int largest; \ | 1717 int largest; \ |
1718 int max | 1718 int max |
1719 #else | 1719 #else |
1720 #define Dynarr_declare(type) \ | 1720 #define Dynarr_declare(type) \ |
1721 struct lrecord_header header; \ | 1721 struct lrecord_header header; \ |
1722 type *base; \ | 1722 type *base; \ |
1723 const struct lrecord_implementation *lisp_imp; \ | 1723 const struct lrecord_implementation *lisp_imp; \ |
1724 int elsize; \ | 1724 int elsize; \ |
1725 int cur; \ | 1725 int len; \ |
1726 int largest; \ | 1726 int largest; \ |
1727 int max | 1727 int max |
1728 #endif /* ERROR_CHECK_STRUCTURES */ | 1728 #endif /* ERROR_CHECK_STRUCTURES */ |
1729 #else /* not NEW_GC */ | 1729 #else /* not NEW_GC */ |
1730 #ifdef ERROR_CHECK_STRUCTURES | 1730 #ifdef ERROR_CHECK_STRUCTURES |
1731 #define Dynarr_declare(type) \ | 1731 #define Dynarr_declare(type) \ |
1732 struct lrecord_header header; \ | 1732 struct lrecord_header header; \ |
1733 type *base; \ | 1733 type *base; \ |
1734 int locked; \ | 1734 int locked; \ |
1735 int elsize; \ | 1735 int elsize; \ |
1736 int cur; \ | 1736 int len; \ |
1737 int largest; \ | 1737 int largest; \ |
1738 int max | 1738 int max |
1739 #else | 1739 #else |
1740 #define Dynarr_declare(type) \ | 1740 #define Dynarr_declare(type) \ |
1741 struct lrecord_header header; \ | 1741 struct lrecord_header header; \ |
1742 type *base; \ | 1742 type *base; \ |
1743 int elsize; \ | 1743 int elsize; \ |
1744 int cur; \ | 1744 int len; \ |
1745 int largest; \ | 1745 int largest; \ |
1746 int max | 1746 int max |
1747 #endif /* ERROR_CHECK_STRUCTURES */ | 1747 #endif /* ERROR_CHECK_STRUCTURES */ |
1748 #endif /* not NEW_GC */ | 1748 #endif /* not NEW_GC */ |
1749 | 1749 |
1752 Dynarr_declare (void); | 1752 Dynarr_declare (void); |
1753 } Dynarr; | 1753 } Dynarr; |
1754 | 1754 |
1755 MODULE_API void *Dynarr_newf (int elsize); | 1755 MODULE_API void *Dynarr_newf (int elsize); |
1756 MODULE_API void Dynarr_resize (void *dy, Elemcount size); | 1756 MODULE_API void Dynarr_resize (void *dy, Elemcount size); |
1757 MODULE_API void Dynarr_insert_many (void *d, const void *el, int len, int start); | 1757 MODULE_API void Dynarr_insert_many (void *d, const void *el, int len, |
1758 int start); | |
1758 MODULE_API void Dynarr_delete_many (void *d, int start, int len); | 1759 MODULE_API void Dynarr_delete_many (void *d, int start, int len); |
1759 MODULE_API void Dynarr_free (void *d); | 1760 MODULE_API void Dynarr_free (void *d); |
1761 | |
1762 #ifdef ERROR_CHECK_TYPES | |
1763 DECLARE_INLINE_HEADER ( | |
1764 int | |
1765 Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line) | |
1766 ) | |
1767 { | |
1768 Dynarr *dy = (Dynarr *) d; | |
1769 /* We use `largest', not `len', because the redisplay code often | |
1770 accesses stuff between len and largest. */ | |
1771 assert_at_line (pos >= 0 && pos < dy->largest, file, line); | |
1772 return pos; | |
1773 } | |
1774 #else | |
1775 #define Dynarr_verify_pos(d, pos, file, line) (pos) | |
1776 #endif /* ERROR_CHECK_TYPES */ | |
1777 | |
1778 #ifdef ERROR_CHECK_TYPES | |
1779 DECLARE_INLINE_HEADER ( | |
1780 int | |
1781 Dynarr_verify_pos_atp (void *d, int pos, const Ascbyte *file, int line) | |
1782 ) | |
1783 { | |
1784 Dynarr *dy = (Dynarr *) d; | |
1785 /* We use `largest', not `len', because the redisplay code often | |
1786 accesses stuff between len and largest. */ | |
1787 /* Code will often do something like ... | |
1788 | |
1789 val = make_bit_vector_from_byte_vector (Dynarr_atp (dyn, 0), | |
1790 Dynarr_length (dyn)); | |
1791 | |
1792 which works fine when the Dynarr_length is non-zero, but when zero, | |
1793 the result of Dynarr_atp() not only points past the end of the | |
1794 allocated array, but the array may not have ever been allocated and | |
1795 hence the return value is NULL. But the length of 0 causes the | |
1796 pointer to never get checked. These can occur throughout the code | |
1797 so we put in a special check. */ | |
1798 if (pos == 0 && dy->len == 0) | |
1799 return pos; | |
1800 /* #### It's vaguely possible that some code could legitimately want to | |
1801 retrieve a pointer to the position just past the end of dynarr memory. | |
1802 This could happen with Dynarr_atp() but not Dynarr_at(). If so, it | |
1803 will trigger this assert(). In such cases, it should be obvious that | |
1804 the code wants to do this; rather than relaxing the assert, we should | |
1805 probably create a new macro Dynarr_atp_allow_end() which is like | |
1806 Dynarr_atp() but which allows for pointing at invalid addresses -- we | |
1807 really want to check for cases of accessing just past the end of | |
1808 memory, which is a likely off-by-one problem to occur and will usually | |
1809 not trigger a protection fault (instead, you'll just get random | |
1810 behavior, possibly overwriting other memory, which is bad). */ | |
1811 assert_at_line (pos >= 0 && pos < dy->largest, file, line); | |
1812 return pos; | |
1813 } | |
1814 | |
1815 DECLARE_INLINE_HEADER ( | |
1816 int | |
1817 Dynarr_verify_pos_atp_allow_end (void *d, int pos, const Ascbyte *file, | |
1818 int line) | |
1819 ) | |
1820 { | |
1821 Dynarr *dy = (Dynarr *) d; | |
1822 /* We use `largest', not `len', because the redisplay code often | |
1823 accesses stuff between len and largest. | |
1824 We also allow referencing the very end, past the end of allocated | |
1825 legitimately space. See comments in Dynarr_verify_pos_atp.()*/ | |
1826 assert_at_line (pos >= 0 && pos <= dy->largest, file, line); | |
1827 return pos; | |
1828 } | |
1829 | |
1830 #else | |
1831 #define Dynarr_verify_pos_at(d, pos, file, line) (pos) | |
1832 #define Dynarr_verify_pos_atp(d, pos, file, line) (pos) | |
1833 #define Dynarr_verify_pos_atp_allow_end(d, pos, file, line) (pos) | |
1834 #endif /* ERROR_CHECK_TYPES */ | |
1760 | 1835 |
1761 #ifdef NEW_GC | 1836 #ifdef NEW_GC |
1762 MODULE_API void *Dynarr_lisp_newf (int elsize, | 1837 MODULE_API void *Dynarr_lisp_newf (int elsize, |
1763 const struct lrecord_implementation | 1838 const struct lrecord_implementation |
1764 *dynarr_imp, | 1839 *dynarr_imp, |
1770 ((dynarr_type *) Dynarr_lisp_newf (sizeof (type)), dynarr_imp, imp) | 1845 ((dynarr_type *) Dynarr_lisp_newf (sizeof (type)), dynarr_imp, imp) |
1771 #endif /* NEW_GC */ | 1846 #endif /* NEW_GC */ |
1772 #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type))) | 1847 #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type))) |
1773 #define Dynarr_new2(dynarr_type, type) \ | 1848 #define Dynarr_new2(dynarr_type, type) \ |
1774 ((dynarr_type *) Dynarr_newf (sizeof (type))) | 1849 ((dynarr_type *) Dynarr_newf (sizeof (type))) |
1775 #define Dynarr_at(d, pos) ((d)->base[pos]) | 1850 |
1776 #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) | 1851 #define Dynarr_at(d, pos) \ |
1852 ((d)->base[Dynarr_verify_pos_at (d, pos, __FILE__, __LINE__)]) | |
1853 #define Dynarr_atp_allow_end(d, pos) \ | |
1854 (&((d)->base[Dynarr_verify_pos_atp_allow_end (d, pos, __FILE__, __LINE__)])) | |
1855 #define Dynarr_atp(d, pos) \ | |
1856 (&((d)->base[Dynarr_verify_pos_atp (d, pos, __FILE__, __LINE__)])) | |
1857 | |
1858 /* Old #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) */ | |
1777 #define Dynarr_begin(d) Dynarr_atp (d, 0) | 1859 #define Dynarr_begin(d) Dynarr_atp (d, 0) |
1778 #define Dynarr_end(d) Dynarr_atp (d, Dynarr_length (d) - 1) | 1860 #define Dynarr_lastp(d) Dynarr_atp (d, Dynarr_length (d) - 1) |
1779 #define Dynarr_sizeof(d) ((d)->cur * (d)->elsize) | 1861 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d)) |
1862 #define Dynarr_sizeof(d) ((d)->len * (d)->elsize) | |
1780 | 1863 |
1781 #ifdef ERROR_CHECK_STRUCTURES | 1864 #ifdef ERROR_CHECK_STRUCTURES |
1782 DECLARE_INLINE_HEADER ( | 1865 DECLARE_INLINE_HEADER ( |
1783 Dynarr * | 1866 Dynarr * |
1784 Dynarr_verify_1 (void *d, const Ascbyte *file, int line) | 1867 Dynarr_verify_1 (void *d, const Ascbyte *file, int line) |
1785 ) | 1868 ) |
1786 { | 1869 { |
1787 Dynarr *dy = (Dynarr *) d; | 1870 Dynarr *dy = (Dynarr *) d; |
1788 assert_at_line (dy->cur >= 0 && dy->cur <= dy->largest && | 1871 assert_at_line (dy->len >= 0 && dy->len <= dy->largest && |
1789 dy->largest <= dy->max, file, line); | 1872 dy->largest <= dy->max, file, line); |
1790 return dy; | 1873 return dy; |
1791 } | 1874 } |
1792 | 1875 |
1793 DECLARE_INLINE_HEADER ( | 1876 DECLARE_INLINE_HEADER ( |
1795 Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line) | 1878 Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line) |
1796 ) | 1879 ) |
1797 { | 1880 { |
1798 Dynarr *dy = (Dynarr *) d; | 1881 Dynarr *dy = (Dynarr *) d; |
1799 assert_at_line (!dy->locked, file, line); | 1882 assert_at_line (!dy->locked, file, line); |
1800 assert_at_line (dy->cur >= 0 && dy->cur <= dy->largest && | 1883 assert_at_line (dy->len >= 0 && dy->len <= dy->largest && |
1801 dy->largest <= dy->max, file, line); | 1884 dy->largest <= dy->max, file, line); |
1802 return dy; | 1885 return dy; |
1803 } | 1886 } |
1804 | 1887 |
1805 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__) | 1888 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__) |
1811 #define Dynarr_verify_mod(d) (d) | 1894 #define Dynarr_verify_mod(d) (d) |
1812 #define Dynarr_lock(d) | 1895 #define Dynarr_lock(d) |
1813 #define Dynarr_unlock(d) | 1896 #define Dynarr_unlock(d) |
1814 #endif /* ERROR_CHECK_STRUCTURES */ | 1897 #endif /* ERROR_CHECK_STRUCTURES */ |
1815 | 1898 |
1816 #define Dynarr_length(d) (Dynarr_verify (d)->cur) | 1899 #define Dynarr_length(d) (Dynarr_verify (d)->len) |
1817 #define Dynarr_largest(d) (Dynarr_verify (d)->largest) | 1900 #define Dynarr_largest(d) (Dynarr_verify (d)->largest) |
1818 #define Dynarr_reset(d) (Dynarr_verify_mod (d)->cur = 0) | 1901 #define Dynarr_reset(d) (Dynarr_verify_mod (d)->len = 0) |
1819 #define Dynarr_add_many(d, el, len) Dynarr_insert_many (d, el, len, (d)->cur) | |
1820 #define Dynarr_insert_many_at_start(d, el, len) \ | 1902 #define Dynarr_insert_many_at_start(d, el, len) \ |
1821 Dynarr_insert_many (d, el, len, 0) | 1903 Dynarr_insert_many (d, el, len, 0) |
1822 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1) | 1904 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1) |
1823 #define Dynarr_add_lisp_string(d, s, codesys) \ | 1905 #define Dynarr_add_lisp_string(d, s, codesys) \ |
1824 do { \ | 1906 do { \ |
1834 | 1916 |
1835 #ifdef NEW_GC | 1917 #ifdef NEW_GC |
1836 #define Dynarr_add(d, el) \ | 1918 #define Dynarr_add(d, el) \ |
1837 do { \ | 1919 do { \ |
1838 const struct lrecord_implementation *imp = (d)->lisp_imp; \ | 1920 const struct lrecord_implementation *imp = (d)->lisp_imp; \ |
1839 if (Dynarr_verify_mod (d)->cur >= (d)->max) \ | 1921 if (Dynarr_verify_mod (d)->len >= (d)->max) \ |
1840 Dynarr_resize ((d), (d)->cur+1); \ | 1922 Dynarr_resize ((d), (d)->len+1); \ |
1841 ((d)->base)[(d)->cur] = (el); \ | 1923 ((d)->base)[(d)->len] = (el); \ |
1842 \ | 1924 \ |
1843 if (imp) \ | 1925 if (imp) \ |
1844 set_lheader_implementation \ | 1926 set_lheader_implementation \ |
1845 ((struct lrecord_header *)&(((d)->base)[(d)->cur]), imp); \ | 1927 ((struct lrecord_header *)&(((d)->base)[(d)->len]), imp); \ |
1846 \ | 1928 \ |
1847 (d)->cur++; \ | 1929 (d)->len++; \ |
1848 if ((d)->cur > (d)->largest) \ | 1930 if ((d)->len > (d)->largest) \ |
1849 (d)->largest = (d)->cur; \ | 1931 (d)->largest = (d)->len; \ |
1850 } while (0) | 1932 } while (0) |
1851 #else /* not NEW_GC */ | 1933 #else /* not NEW_GC */ |
1852 #define Dynarr_add(d, el) ( \ | 1934 #define Dynarr_add(d, el) ( \ |
1853 Dynarr_verify_mod (d)->cur >= (d)->max ? Dynarr_resize ((d), (d)->cur+1) : \ | 1935 Dynarr_verify_mod (d)->len >= (d)->max ? Dynarr_resize ((d), (d)->len+1) : \ |
1854 (void) 0, \ | 1936 (void) 0, \ |
1855 ((d)->base)[(d)->cur++] = (el), \ | 1937 ((d)->base)[(d)->len++] = (el), \ |
1856 (d)->cur > (d)->largest ? (d)->largest = (d)->cur : (int) 0) | 1938 (d)->len > (d)->largest ? (d)->largest = (d)->len : (int) 0) |
1857 #endif /* not NEW_GC */ | 1939 #endif /* not NEW_GC */ |
1858 | 1940 |
1941 /* Add LEN contiguous elements to a Dynarr */ | |
1942 | |
1943 DECLARE_INLINE_HEADER ( | |
1944 void | |
1945 Dynarr_add_many (void *d, const void *el, int len) | |
1946 ) | |
1947 { | |
1948 /* This duplicates Dynarr_insert_many to some extent; but since it is | |
1949 called so often, it seemed useful to remove the unnecessary stuff | |
1950 from that function and to make it inline */ | |
1951 Dynarr *dy = (Dynarr *) Dynarr_verify (d); | |
1952 | |
1953 if (dy->len + len > dy->max) | |
1954 Dynarr_resize (dy, dy->len + len); | |
1955 /* Some functions call us with a value of 0 to mean "reserve space but | |
1956 don't write into it" */ | |
1957 if (el) | |
1958 memcpy ((char *) dy->base + dy->len*dy->elsize, el, len*dy->elsize); | |
1959 dy->len += len; | |
1960 | |
1961 if (dy->len > dy->largest) | |
1962 dy->largest = dy->len; | |
1963 } | |
1859 | 1964 |
1860 /* The following defines will get you into real trouble if you aren't | 1965 /* The following defines will get you into real trouble if you aren't |
1861 careful. But they can save a lot of execution time when used wisely. */ | 1966 careful. But they can save a lot of execution time when used wisely. */ |
1862 #define Dynarr_increment(d) (Dynarr_verify_mod (d)->cur++) | 1967 #define Dynarr_increment(d) (Dynarr_verify_mod (d)->len++) |
1863 #define Dynarr_set_size(d, n) (Dynarr_verify_mod (d)->cur = n) | 1968 #define Dynarr_set_size(d, n) \ |
1969 do { \ | |
1970 Bytecount _dss_n = (n); \ | |
1971 structure_checking_assert (_dss_n >= 0 && _dss_n <= (d)->largest); \ | |
1972 Dynarr_verify_mod (d)->len = _dss_n; \ | |
1973 } while (0) | |
1864 | 1974 |
1865 #define Dynarr_pop(d) \ | 1975 #define Dynarr_pop(d) \ |
1866 (assert ((d)->cur > 0), Dynarr_verify_mod (d)->cur--, \ | 1976 (assert ((d)->len > 0), Dynarr_verify_mod (d)->len--, \ |
1867 Dynarr_at (d, (d)->cur)) | 1977 Dynarr_at (d, (d)->len)) |
1868 #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1) | 1978 #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1) |
1869 #define Dynarr_delete_by_pointer(d, p) \ | 1979 #define Dynarr_delete_by_pointer(d, p) \ |
1870 Dynarr_delete_many (d, (p) - ((d)->base), 1) | 1980 Dynarr_delete_many (d, (p) - ((d)->base), 1) |
1871 | 1981 |
1872 #define Dynarr_delete_object(d, el) \ | 1982 #define Dynarr_delete_object(d, el) \ |