comparison src/lisp.h @ 4967:0d4c9d0f6a8d

rewrite dynarr code -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-03 Ben Wing <ben@xemacs.org> * device-x.c (x_get_resource_prefix): * device-x.c (Fx_get_resource): * device-x.c (Fx_get_resource_prefix): * device-x.c (Fx_put_resource): * dialog-msw.c: * dialog-msw.c (handle_question_dialog_box): * dired-msw.c (mswindows_sort_files): * dired-msw.c (mswindows_get_files): * extents.c (extent_fragment_sort_by_priority): * extents.c (Fset_extent_parent): * file-coding.c (coding_reader): * file-coding.c (coding_writer): * file-coding.c (gzip_convert): * frame.c (generate_title_string): * gutter.c (calculate_gutter_size_from_display_lines): * indent.c (vmotion_1): * lread.c (read_bit_vector): * mule-coding.c (iso2022_decode): * rangetab.c: * rangetab.c (Fcopy_range_table): * rangetab.c (Fget_range_table): * rangetab.c (unified_range_table_copy_data): * redisplay-msw.c (mswindows_output_string): * redisplay-output.c (output_display_line): * redisplay-output.c (redisplay_move_cursor): * redisplay-output.c (redisplay_clear_bottom_of_window): * redisplay-tty.c (tty_output_ichar_dynarr): * redisplay-tty.c (set_foreground_to): * redisplay-tty.c (set_background_to): * redisplay-xlike-inc.c (XLIKE_output_string): * redisplay.c (redisplay_window_text_width_string): * redisplay.c (redisplay_text_width_string): * redisplay.c (create_text_block): * redisplay.c (SET_CURRENT_MODE_CHARS_PIXSIZE): * redisplay.c (generate_fstring_runes): * redisplay.c (regenerate_modeline): * redisplay.c (ensure_modeline_generated): * redisplay.c (real_current_modeline_height): * redisplay.c (create_string_text_block): * redisplay.c (regenerate_window): * redisplay.c (REGEN_INC_FIND_START_END): * redisplay.c (point_visible): * redisplay.c (redisplay_window): * redisplay.c (mark_glyph_block_dynarr): * redisplay.c (line_start_cache_start): * redisplay.c (start_with_line_at_pixpos): * redisplay.c (update_line_start_cache): * redisplay.c (glyph_to_pixel_translation): * redisplay.c (pixel_to_glyph_translation): * sysdep.c (qxe_readdir): * text.c (dfc_convert_to_external_format): * text.c (dfc_convert_to_internal_format): * toolbar-common.c (common_output_toolbar_button): * window.c (window_modeline_height): * window.c (Fwindow_last_line_visible_height): * window.c (window_displayed_height): * window.c (window_scroll): * window.c (get_current_pixel_pos): Use Dynarr_begin() in place of Dynarr_atp (foo, 0). * dynarr.c (Dynarr_realloc): * dynarr.c (Dynarr_lisp_realloc): * dynarr.c (Dynarr_resize): * dynarr.c (Dynarr_insert_many): * dynarr.c (Dynarr_delete_many): * dynarr.c (Dynarr_memory_usage): * dynarr.c (stack_like_malloc): * dynarr.c (stack_like_free): * lisp.h: * lisp.h (DECLARE_DYNARR_LISP_IMP): * lisp.h (XD_DYNARR_DESC): * lisp.h (Dynarr_pop): * gutter.c (output_gutter): * redisplay-output.c (sync_rune_structs): * redisplay-output.c (redisplay_output_window): Redo the dynarr code, add greater checks. Rename the `len', `largest' and `max' members to `len_', `largest_' and `max_' to try and catch existing places that might directly modify these values. Make new accessors Dynarr_largest() and Dynarr_max() and make them and existing Dynarr_length() be non-lvalues by adding '+ 0' to them; fix a couple of places in the redisplay code that tried to modify the length directly by setting Dynarr_length(). Use the accessors whenever possible even in the dynarr code itself. The accessors also verify that 0 <= len <= largest <= max. Rename settor function Dynarr_set_size() to Dynarr_set_length() and use it more consistently; also create lower-level Dynarr_set_length_1(). This latter function should be the only function that directly modifies the `len_' member of a Dynarr, and in the process makes sure that the `largest' value is kept correct. Consistently use ERROR_CHECK_STRUCTURES instead of ERROR_CHECK_TYPES for error-checking code. Reintroduce the temporarily disabled verification code on the positions of Dynarr_at(), Dynarr_atp() and Dynarr_atp_past_end(). Also create Dynarr_resize_if() in place of a repeated code fragment. Clean up all the functions that modify Dynarrs to use the new macros and functions and verify the correctness of the Dynarr both before and after the change. Note that there are two kinds of verification -- one for accessing and one for modifying. The difference is that the modify verification additionally checks to make sure that the Dynarr isn't locked. (This is used in redisplay to check for problems with reentrancy.) * lrecord.h: Move XD_DYNARR_DESC to lisp.h, grouping with the dynarr code.
author Ben Wing <ben@xemacs.org>
date Wed, 03 Feb 2010 20:51:18 -0600
parents 48b63cd88a21
children cbe181529c34
comparison
equal deleted inserted replaced
4966:48b63cd88a21 4967:0d4c9d0f6a8d
1695 1695
1696 /* OK, you can open them again */ 1696 /* OK, you can open them again */
1697 1697
1698 END_C_DECLS 1698 END_C_DECLS
1699 1699
1700 #include "lrecord.h"
1701
1700 /************************************************************************/ 1702 /************************************************************************/
1701 /** Definitions of basic Lisp objects **/ 1703 /** Definitions of dynamic arrays (Dynarrs) and other allocators **/
1702 /************************************************************************/ 1704 /************************************************************************/
1703 1705
1704 #include "lrecord.h"
1705
1706 BEGIN_C_DECLS 1706 BEGIN_C_DECLS
1707 1707
1708 /* ------------------------ dynamic arrays ------------------- */ 1708 /************* Dynarr declaration *************/
1709 1709
1710 #ifdef NEW_GC 1710 #ifdef NEW_GC
1711 #define DECLARE_DYNARR_LISP_IMP() \
1712 const struct lrecord_implementation *lisp_imp;
1713 #else
1714 #define DECLARE_DYNARR_LISP_IMP()
1715 #endif
1716
1711 #ifdef ERROR_CHECK_STRUCTURES 1717 #ifdef ERROR_CHECK_STRUCTURES
1712 #define Dynarr_declare(type) \ 1718 #define DECLARE_DYNARR_LOCKED() \
1713 struct lrecord_header header; \ 1719 int locked;
1714 type *base; \
1715 const struct lrecord_implementation *lisp_imp; \
1716 int locked; \
1717 int elsize; \
1718 int len; \
1719 int largest; \
1720 int max
1721 #else 1720 #else
1722 #define Dynarr_declare(type) \ 1721 #define DECLARE_DYNARR_LOCKED()
1723 struct lrecord_header header; \ 1722 #endif
1724 type *base; \ 1723
1725 const struct lrecord_implementation *lisp_imp; \ 1724 #define Dynarr_declare(type) \
1726 int elsize; \ 1725 struct lrecord_header header; \
1727 int len; \ 1726 type *base; \
1728 int largest; \ 1727 DECLARE_DYNARR_LISP_IMP () \
1729 int max 1728 DECLARE_DYNARR_LOCKED () \
1730 #endif /* ERROR_CHECK_STRUCTURES */ 1729 int elsize; \
1731 #else /* not NEW_GC */ 1730 int len_; \
1732 #ifdef ERROR_CHECK_STRUCTURES 1731 int largest_; \
1733 #define Dynarr_declare(type) \ 1732 int max_
1734 struct lrecord_header header; \
1735 type *base; \
1736 int locked; \
1737 int elsize; \
1738 int len; \
1739 int largest; \
1740 int max
1741 #else
1742 #define Dynarr_declare(type) \
1743 struct lrecord_header header; \
1744 type *base; \
1745 int elsize; \
1746 int len; \
1747 int largest; \
1748 int max
1749 #endif /* ERROR_CHECK_STRUCTURES */
1750 #endif /* not NEW_GC */
1751 1733
1752 typedef struct dynarr 1734 typedef struct dynarr
1753 { 1735 {
1754 Dynarr_declare (void); 1736 Dynarr_declare (void);
1755 } Dynarr; 1737 } Dynarr;
1756 1738
1757 MODULE_API void *Dynarr_newf (int elsize); 1739 #define XD_DYNARR_DESC(base_type, sub_desc) \
1758 MODULE_API void Dynarr_resize (void *dy, Elemcount size); 1740 { XD_BLOCK_PTR, offsetof (base_type, base), \
1759 MODULE_API void Dynarr_insert_many (void *d, const void *el, int len, 1741 XD_INDIRECT(1, 0), {sub_desc} }, \
1760 int start); 1742 { XD_INT, offsetof (base_type, len_) }, \
1761 MODULE_API void Dynarr_delete_many (void *d, int start, int len); 1743 { XD_INT_RESET, offsetof (base_type, largest_), XD_INDIRECT(1, 0) }, \
1762 MODULE_API void Dynarr_free (void *d); 1744 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) }
1763 1745
1764 #ifdef ERROR_CHECK_TYPES 1746 #ifdef NEW_GC
1747 #define XD_LISP_DYNARR_DESC(base_type, sub_desc) \
1748 { XD_LISP_OBJECT_BLOCK_PTR, offsetof (base_type, base), \
1749 XD_INDIRECT(1, 0), {sub_desc} }, \
1750 { XD_INT, offsetof (base_type, len_) }, \
1751 { XD_INT_RESET, offsetof (base_type, largest_), XD_INDIRECT(1, 0) }, \
1752 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) }
1753 #endif /* NEW_GC */
1754
1755 /************* Dynarr verification *************/
1756
1757 #ifdef ERROR_CHECK_STRUCTURES
1765 DECLARE_INLINE_HEADER ( 1758 DECLARE_INLINE_HEADER (
1766 int 1759 int
1767 Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line) 1760 Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line)
1768 ) 1761 )
1769 { 1762 {
1770 Dynarr *dy = (Dynarr *) d; 1763 Dynarr *dy = (Dynarr *) d;
1771 /* We use `largest', not `len', because the redisplay code often 1764 /* We use `largest', not `len', because the redisplay code often
1772 accesses stuff between len and largest. */ 1765 accesses stuff between len and largest. */
1773 assert_at_line (pos >= 0 && pos < dy->largest, file, line); 1766 assert_at_line (pos >= 0 && pos < dy->largest_, file, line);
1774 return pos; 1767 return pos;
1775 } 1768 }
1776 1769
1777 DECLARE_INLINE_HEADER ( 1770 DECLARE_INLINE_HEADER (
1778 int 1771 int
1791 the result of Dynarr_atp() not only points past the end of the 1784 the result of Dynarr_atp() not only points past the end of the
1792 allocated array, but the array may not have ever been allocated and 1785 allocated array, but the array may not have ever been allocated and
1793 hence the return value is NULL. But the length of 0 causes the 1786 hence the return value is NULL. But the length of 0 causes the
1794 pointer to never get checked. These can occur throughout the code 1787 pointer to never get checked. These can occur throughout the code
1795 so we put in a special check. */ 1788 so we put in a special check. */
1796 if (pos == 0 && dy->len == 0) 1789 if (pos == 0 && dy->len_ == 0)
1797 return pos; 1790 return pos;
1798 /* #### It's vaguely possible that some code could legitimately want to 1791 /* #### It's vaguely possible that some code could legitimately want to
1799 retrieve a pointer to the position just past the end of dynarr memory. 1792 retrieve a pointer to the position just past the end of dynarr memory.
1800 This could happen with Dynarr_atp() but not Dynarr_at(). If so, it 1793 This could happen with Dynarr_atp() but not Dynarr_at(). If so, it
1801 will trigger this assert(). In such cases, it should be obvious that 1794 will trigger this assert(). In such cases, it should be obvious that
1804 Dynarr_atp() but which allows for pointing at invalid addresses -- we 1797 Dynarr_atp() but which allows for pointing at invalid addresses -- we
1805 really want to check for cases of accessing just past the end of 1798 really want to check for cases of accessing just past the end of
1806 memory, which is a likely off-by-one problem to occur and will usually 1799 memory, which is a likely off-by-one problem to occur and will usually
1807 not trigger a protection fault (instead, you'll just get random 1800 not trigger a protection fault (instead, you'll just get random
1808 behavior, possibly overwriting other memory, which is bad). */ 1801 behavior, possibly overwriting other memory, which is bad). */
1809 assert_at_line (pos >= 0 && pos < dy->largest, file, line); 1802 assert_at_line (pos >= 0 && pos < dy->largest_, file, line);
1810 return pos; 1803 return pos;
1811 } 1804 }
1812 1805
1813 DECLARE_INLINE_HEADER ( 1806 DECLARE_INLINE_HEADER (
1814 int 1807 int
1819 Dynarr *dy = (Dynarr *) d; 1812 Dynarr *dy = (Dynarr *) d;
1820 /* We use `largest', not `len', because the redisplay code often 1813 /* We use `largest', not `len', because the redisplay code often
1821 accesses stuff between len and largest. 1814 accesses stuff between len and largest.
1822 We also allow referencing the very end, past the end of allocated 1815 We also allow referencing the very end, past the end of allocated
1823 legitimately space. See comments in Dynarr_verify_pos_atp.()*/ 1816 legitimately space. See comments in Dynarr_verify_pos_atp.()*/
1824 assert_at_line (pos >= 0 && pos <= dy->largest, file, line); 1817 assert_at_line (pos >= 0 && pos <= dy->largest_, file, line);
1825 return pos; 1818 return pos;
1826 } 1819 }
1827 1820
1828 #else 1821 #else
1829 #define Dynarr_verify_pos_at(d, pos, file, line) (pos) 1822 #define Dynarr_verify_pos_at(d, pos, file, line) (pos)
1830 #define Dynarr_verify_pos_atp(d, pos, file, line) (pos) 1823 #define Dynarr_verify_pos_atp(d, pos, file, line) (pos)
1831 #define Dynarr_verify_pos_atp_allow_end(d, pos, file, line) (pos) 1824 #define Dynarr_verify_pos_atp_allow_end(d, pos, file, line) (pos)
1832 #endif /* ERROR_CHECK_TYPES */ 1825 #endif /* ERROR_CHECK_STRUCTURES */
1826
1827 #ifdef ERROR_CHECK_STRUCTURES
1828 DECLARE_INLINE_HEADER (
1829 Dynarr *
1830 Dynarr_verify_1 (void *d, const Ascbyte *file, int line)
1831 )
1832 {
1833 Dynarr *dy = (Dynarr *) d;
1834 assert_at_line (dy->len_ >= 0 && dy->len_ <= dy->largest_ &&
1835 dy->largest_ <= dy->max_, file, line);
1836 return dy;
1837 }
1838
1839 DECLARE_INLINE_HEADER (
1840 Dynarr *
1841 Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line)
1842 )
1843 {
1844 Dynarr *dy = (Dynarr *) d;
1845 assert_at_line (!dy->locked, file, line);
1846 return Dynarr_verify_1 (d, file, line);
1847 }
1848
1849 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__)
1850 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__)
1851 #define Dynarr_lock(d) \
1852 do { \
1853 Dynarr *dy = Dynarr_verify_mod (d); \
1854 dy->locked = 1; \
1855 } while (0)
1856 #define Dynarr_unlock(d) \
1857 do { \
1858 Dynarr *dy = Dynarr_verify (d); \
1859 dy->locked = 0; \
1860 } while (0)
1861 #else
1862 #define Dynarr_verify(d) (d)
1863 #define Dynarr_verify_mod(d) (d)
1864 #define Dynarr_lock(d) DO_NOTHING
1865 #define Dynarr_unlock(d) DO_NOTHING
1866 #endif /* ERROR_CHECK_STRUCTURES */
1867
1868 /************* Dynarr creation *************/
1869
1870 MODULE_API void *Dynarr_newf (int elsize);
1871 MODULE_API void Dynarr_free (void *d);
1833 1872
1834 #ifdef NEW_GC 1873 #ifdef NEW_GC
1835 MODULE_API void *Dynarr_lisp_newf (int elsize, 1874 MODULE_API void *Dynarr_lisp_newf (int elsize,
1836 const struct lrecord_implementation 1875 const struct lrecord_implementation
1837 *dynarr_imp, 1876 *dynarr_imp,
1844 #endif /* NEW_GC */ 1883 #endif /* NEW_GC */
1845 #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type))) 1884 #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type)))
1846 #define Dynarr_new2(dynarr_type, type) \ 1885 #define Dynarr_new2(dynarr_type, type) \
1847 ((dynarr_type *) Dynarr_newf (sizeof (type))) 1886 ((dynarr_type *) Dynarr_newf (sizeof (type)))
1848 1887
1849 #ifdef ERROR_CHECK_TYPES_GCC_NOT_BROKEN 1888 /************* Dynarr access *************/
1889
1890 #ifdef ERROR_CHECK_STRUCTURES
1850 /* Enabling this leads to crashes in Cygwin 1.7, gcc 3.4.4 */ 1891 /* Enabling this leads to crashes in Cygwin 1.7, gcc 3.4.4 */
1851 #define Dynarr_at(d, pos) \ 1892 #define Dynarr_at(d, pos) \
1852 ((d)->base[Dynarr_verify_pos_at (d, pos, __FILE__, __LINE__)]) 1893 ((d)->base[Dynarr_verify_pos_at (d, pos, __FILE__, __LINE__)])
1853 #define Dynarr_atp_allow_end(d, pos) \ 1894 #define Dynarr_atp_allow_end(d, pos) \
1854 (&((d)->base[Dynarr_verify_pos_atp_allow_end (d, pos, __FILE__, __LINE__)])) 1895 (&((d)->base[Dynarr_verify_pos_atp_allow_end (d, pos, __FILE__, __LINE__)]))
1862 1903
1863 /* Old #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) */ 1904 /* Old #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) */
1864 #define Dynarr_begin(d) Dynarr_atp (d, 0) 1905 #define Dynarr_begin(d) Dynarr_atp (d, 0)
1865 #define Dynarr_lastp(d) Dynarr_atp (d, Dynarr_length (d) - 1) 1906 #define Dynarr_lastp(d) Dynarr_atp (d, Dynarr_length (d) - 1)
1866 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d)) 1907 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d))
1867 #define Dynarr_sizeof(d) ((d)->len * (d)->elsize) 1908
1868 1909
1869 #ifdef ERROR_CHECK_STRUCTURES 1910 /************* Dynarr length/size retrieval and setting *************/
1870 DECLARE_INLINE_HEADER ( 1911
1871 Dynarr * 1912 /* Retrieve the length of a Dynarr. The `+ 0' is to ensure that this cannot
1872 Dynarr_verify_1 (void *d, const Ascbyte *file, int line) 1913 be used as an lvalue. */
1873 ) 1914 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0)
1874 { 1915 /* Retrieve the largest ever length seen of a Dynarr. The `+ 0' is to
1875 Dynarr *dy = (Dynarr *) d; 1916 ensure that this cannot be used as an lvalue. */
1876 assert_at_line (dy->len >= 0 && dy->len <= dy->largest && 1917 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0)
1877 dy->largest <= dy->max, file, line); 1918 /* Retrieve the number of elements that fit in the currently allocated
1878 return dy; 1919 space. The `+ 0' is to ensure that this cannot be used as an lvalue. */
1879 } 1920 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0)
1880 1921 /* Retrieve the advertised memory usage of a Dynarr, i.e. the number of
1881 DECLARE_INLINE_HEADER ( 1922 bytes occupied by the elements in the Dynarr, not counting any overhead. */
1882 Dynarr * 1923 #define Dynarr_sizeof(d) (Dynarr_length (d) * (d)->elsize)
1883 Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line) 1924 /* Actually set the length of a Dynarr. This is a low-level routine that
1884 ) 1925 should not be directly used; use Dynarr_set_length() instead if you need
1885 { 1926 to, but be very careful when doing so! */
1886 Dynarr *dy = (Dynarr *) d; 1927 #define Dynarr_set_length_1(d, n) \
1887 assert_at_line (!dy->locked, file, line); 1928 do { \
1888 assert_at_line (dy->len >= 0 && dy->len <= dy->largest && 1929 Elemcount _dsl1_n = (n); \
1889 dy->largest <= dy->max, file, line); 1930 structure_checking_assert (_dsl1_n >= 0 && _dsl1_n <= Dynarr_max (d)); \
1890 return dy; 1931 (void) Dynarr_verify_mod (d); \
1891 } 1932 (d)->len_ = _dsl1_n; \
1892 1933 /* Use the raw field references here otherwise we get a crash because \
1893 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__) 1934 we've set the length but not yet fixed up the largest value. */ \
1894 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__) 1935 if ((d)->len_ > (d)->largest_) \
1895 #define Dynarr_lock(d) (Dynarr_verify_mod (d)->locked = 1) 1936 (d)->largest_ = (d)->len_; \
1896 #define Dynarr_unlock(d) ((d)->locked = 0) 1937 (void) Dynarr_verify_mod (d); \
1897 #else 1938 } while (0)
1898 #define Dynarr_verify(d) (d) 1939
1899 #define Dynarr_verify_mod(d) (d) 1940 /* The following two defines will get you into real trouble if you aren't
1900 #define Dynarr_lock(d) 1941 careful. But they can save a lot of execution time when used wisely. */
1901 #define Dynarr_unlock(d) 1942 #define Dynarr_set_length(d, n) \
1902 #endif /* ERROR_CHECK_STRUCTURES */ 1943 do { \
1903 1944 Elemcount _dsl_n = (n); \
1904 #define Dynarr_length(d) (Dynarr_verify (d)->len) 1945 structure_checking_assert (_dsl_n >= 0 && _dsl_n <= Dynarr_largest (d)); \
1905 #define Dynarr_largest(d) (Dynarr_verify (d)->largest) 1946 Dynarr_set_length_1 (d, _dsl_n); \
1906 #define Dynarr_reset(d) (Dynarr_verify_mod (d)->len = 0) 1947 } while (0)
1948 #define Dynarr_increment(d) \
1949 Dynarr_set_length (d, Dynarr_length (d) + 1)
1950
1951 /* Reset the Dynarr's length to 0. */
1952 #define Dynarr_reset(d) Dynarr_set_length (d, 0)
1953
1954 MODULE_API void Dynarr_resize (void *dy, Elemcount size);
1955
1956 #define Dynarr_resize_if(d, numels) \
1957 do { \
1958 Elemcount _dri_numels = (numels); \
1959 if (Dynarr_length (d) + _dri_numels > Dynarr_max (d)) \
1960 Dynarr_resize (d, Dynarr_length (d) + _dri_numels); \
1961 } while (0)
1962
1963 #ifdef MEMORY_USAGE_STATS
1964 struct overhead_stats;
1965 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats);
1966 #endif
1967
1968 /************* Adding/deleting elements to/from a Dynarr *************/
1969
1970 #ifdef NEW_GC
1971 #define Dynarr_add(d, el) \
1972 do { \
1973 const struct lrecord_implementation *imp = (d)->lisp_imp; \
1974 (void) Dynarr_verify_mod (d); \
1975 Dynarr_resize_if (d, 1); \
1976 ((d)->base)[Dynarr_length (d)] = (el); \
1977 if (imp) \
1978 set_lheader_implementation \
1979 ((struct lrecord_header *)&(((d)->base)[Dynarr_length (d)]), imp); \
1980 Dynarr_set_length_1 (d, Dynarr_length (d) + 1); \
1981 (void) Dynarr_verify_mod (d); \
1982 } while (0)
1983 #else /* not NEW_GC */
1984 #define Dynarr_add(d, el) \
1985 do { \
1986 (void) Dynarr_verify_mod (d); \
1987 Dynarr_resize_if (d, 1); \
1988 ((d)->base)[Dynarr_length (d)] = (el); \
1989 Dynarr_set_length_1 (d, Dynarr_length (d) + 1); \
1990 (void) Dynarr_verify_mod (d); \
1991 } while (0)
1992 #endif /* not NEW_GC */
1993
1994
1995 MODULE_API void Dynarr_insert_many (void *d, const void *el, int len,
1996 int start);
1997 MODULE_API void Dynarr_delete_many (void *d, int start, int len);
1998
1907 #define Dynarr_insert_many_at_start(d, el, len) \ 1999 #define Dynarr_insert_many_at_start(d, el, len) \
1908 Dynarr_insert_many (d, el, len, 0) 2000 Dynarr_insert_many (d, el, len, 0)
1909 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1) 2001 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1)
1910 #define Dynarr_add_lisp_string(d, s, codesys) \ 2002 #define Dynarr_add_lisp_string(d, s, codesys) \
1911 do { \ 2003 do { \
1917 LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \ 2009 LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \
1918 dyna_ls_bc, dyna_ls_cs); \ 2010 dyna_ls_bc, dyna_ls_cs); \
1919 Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \ 2011 Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \
1920 } while (0) 2012 } while (0)
1921 2013
1922 #ifdef NEW_GC
1923 #define Dynarr_add(d, el) \
1924 do { \
1925 const struct lrecord_implementation *imp = (d)->lisp_imp; \
1926 if (Dynarr_verify_mod (d)->len >= (d)->max) \
1927 Dynarr_resize ((d), (d)->len+1); \
1928 ((d)->base)[(d)->len] = (el); \
1929 \
1930 if (imp) \
1931 set_lheader_implementation \
1932 ((struct lrecord_header *)&(((d)->base)[(d)->len]), imp); \
1933 \
1934 (d)->len++; \
1935 if ((d)->len > (d)->largest) \
1936 (d)->largest = (d)->len; \
1937 } while (0)
1938 #else /* not NEW_GC */
1939 #define Dynarr_add(d, el) ( \
1940 Dynarr_verify_mod (d)->len >= (d)->max ? Dynarr_resize ((d), (d)->len+1) : \
1941 (void) 0, \
1942 ((d)->base)[(d)->len++] = (el), \
1943 (d)->len > (d)->largest ? (d)->largest = (d)->len : (int) 0)
1944 #endif /* not NEW_GC */
1945
1946 /* Add LEN contiguous elements to a Dynarr */ 2014 /* Add LEN contiguous elements to a Dynarr */
1947 2015
1948 DECLARE_INLINE_HEADER ( 2016 DECLARE_INLINE_HEADER (
1949 void 2017 void
1950 Dynarr_add_many (void *d, const void *el, int len) 2018 Dynarr_add_many (void *d, const void *el, int len)
1951 ) 2019 )
1952 { 2020 {
1953 /* This duplicates Dynarr_insert_many to some extent; but since it is 2021 /* This duplicates Dynarr_insert_many to some extent; but since it is
1954 called so often, it seemed useful to remove the unnecessary stuff 2022 called so often, it seemed useful to remove the unnecessary stuff
1955 from that function and to make it inline */ 2023 from that function and to make it inline */
1956 Dynarr *dy = (Dynarr *) Dynarr_verify (d); 2024 Dynarr *dy = Dynarr_verify_mod (d);
1957 2025 Dynarr_resize_if (dy, len);
1958 if (dy->len + len > dy->max)
1959 Dynarr_resize (dy, dy->len + len);
1960 /* Some functions call us with a value of 0 to mean "reserve space but 2026 /* Some functions call us with a value of 0 to mean "reserve space but
1961 don't write into it" */ 2027 don't write into it" */
1962 if (el) 2028 if (el)
1963 memcpy ((char *) dy->base + dy->len*dy->elsize, el, len*dy->elsize); 2029 memcpy ((char *) dy->base + Dynarr_sizeof (dy), el, len*dy->elsize);
1964 dy->len += len; 2030 Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
1965 2031 (void) Dynarr_verify_mod (dy);
1966 if (dy->len > dy->largest)
1967 dy->largest = dy->len;
1968 } 2032 }
1969 2033
1970 /* The following defines will get you into real trouble if you aren't
1971 careful. But they can save a lot of execution time when used wisely. */
1972 #define Dynarr_increment(d) (Dynarr_verify_mod (d)->len++)
1973 #define Dynarr_set_size(d, n) \
1974 do { \
1975 Bytecount _dss_n = (n); \
1976 structure_checking_assert (_dss_n >= 0 && _dss_n <= (d)->largest); \
1977 Dynarr_verify_mod (d)->len = _dss_n; \
1978 } while (0)
1979
1980 #define Dynarr_pop(d) \ 2034 #define Dynarr_pop(d) \
1981 (assert ((d)->len > 0), Dynarr_verify_mod (d)->len--, \ 2035 (structure_checking_assert (Dynarr_length (d) > 0), \
1982 Dynarr_at (d, (d)->len)) 2036 Dynarr_verify_mod (d)->len_--, \
2037 Dynarr_at (d, Dynarr_length (d)))
1983 #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1) 2038 #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1)
1984 #define Dynarr_delete_by_pointer(d, p) \ 2039 #define Dynarr_delete_by_pointer(d, p) \
1985 Dynarr_delete_many (d, (p) - ((d)->base), 1) 2040 Dynarr_delete_many (d, (p) - ((d)->base), 1)
1986 2041
1987 #define Dynarr_delete_object(d, el) \ 2042 #define Dynarr_delete_object(d, el) \
1993 if (el == Dynarr_at (d, i)) \ 2048 if (el == Dynarr_at (d, i)) \
1994 Dynarr_delete_many (d, i, 1); \ 2049 Dynarr_delete_many (d, i, 1); \
1995 } \ 2050 } \
1996 } while (0) 2051 } while (0)
1997 2052
1998 #ifdef MEMORY_USAGE_STATS 2053 /************* Dynarr typedefs *************/
1999 struct overhead_stats;
2000 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats);
2001 #endif
2002
2003 void *stack_like_malloc (Bytecount size);
2004 void stack_like_free (void *val);
2005
2006 /* ------------------------------- */
2007 /* Dynarr typedefs */
2008 /* ------------------------------- */
2009 2054
2010 /* Dynarr typedefs -- basic types first */ 2055 /* Dynarr typedefs -- basic types first */
2011 2056
2012 typedef struct 2057 typedef struct
2013 { 2058 {
2127 2172
2128 typedef struct 2173 typedef struct
2129 { 2174 {
2130 Dynarr_declare (Lisp_Object *); 2175 Dynarr_declare (Lisp_Object *);
2131 } Lisp_Object_ptr_dynarr; 2176 } Lisp_Object_ptr_dynarr;
2177
2178
2179 /************* Stack-like malloc/free: Another allocator *************/
2180
2181 void *stack_like_malloc (Bytecount size);
2182 void stack_like_free (void *val);
2183
2184
2185 /************************************************************************/
2186 /** Definitions of other basic Lisp objects **/
2187 /************************************************************************/
2132 2188
2133 /*------------------------------ unbound -------------------------------*/ 2189 /*------------------------------ unbound -------------------------------*/
2134 2190
2135 /* Qunbound is a special Lisp_Object (actually of type 2191 /* Qunbound is a special Lisp_Object (actually of type
2136 symbol-value-forward), that can never be visible to 2192 symbol-value-forward), that can never be visible to