comparison src/lisp.h @ 5168:cf900a2f1fa3

extract gap array from extents.c, use in range tables -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-03-22 Ben Wing <ben@xemacs.org> * Makefile.in.in (objs): * array.c: * array.c (gap_array_adjust_markers): * array.c (gap_array_move_gap): * array.c (gap_array_make_gap): * array.c (gap_array_insert_els): * array.c (gap_array_delete_els): * array.c (gap_array_make_marker): * array.c (gap_array_delete_marker): * array.c (gap_array_delete_all_markers): * array.c (gap_array_clone): * array.h: * depend: * emacs.c (main_1): * extents.c: * extents.c (EXTENT_GAP_ARRAY_AT): * extents.c (extent_list_num_els): * extents.c (extent_list_locate): * extents.c (extent_list_at): * extents.c (extent_list_delete_all): * extents.c (allocate_extent_list): * extents.c (syms_of_extents): * extents.h: * extents.h (XEXTENT_LIST_MARKER): * lisp.h: * rangetab.c: * rangetab.c (mark_range_table): * rangetab.c (print_range_table): * rangetab.c (range_table_equal): * rangetab.c (range_table_hash): * rangetab.c (verify_range_table): * rangetab.c (get_range_table_pos): * rangetab.c (Fmake_range_table): * rangetab.c (Fcopy_range_table): * rangetab.c (Fget_range_table): * rangetab.c (put_range_table): * rangetab.c (Fclear_range_table): * rangetab.c (Fmap_range_table): * rangetab.c (unified_range_table_bytes_needed): * rangetab.c (unified_range_table_copy_data): * rangetab.c (unified_range_table_lookup): * rangetab.h: * rangetab.h (struct range_table_entry): * rangetab.h (struct Lisp_Range_Table): * rangetab.h (rangetab_gap_array_at): * symsinit.h: Rename dynarr.c to array.c. Move gap array from extents.c to array.c. Extract dynarr, gap array and stack-like malloc into new file array.h. Rename GAP_ARRAY_NUM_ELS -> gap_array_length(). Add gap_array_at(), gap_array_atp(). Rewrite range table code to use gap arrays. Make put_range_table() smarter so that its operation is O(log n) for adding a localized range. * gc.c (lispdesc_block_size_1): Don't ABORT() when two elements are located at the same place. This will happen with a size-0 gap array -- both parts of the array (before and after gap) are in the same place.
author Ben Wing <ben@xemacs.org>
date Mon, 22 Mar 2010 19:12:15 -0500
parents ab9ee10a53e4
children 6c6d78781d59
comparison
equal deleted inserted replaced
5167:e374ea766cc1 5168:cf900a2f1fa3
1730 EMACS_UINT p = XUINT (obj); 1730 EMACS_UINT p = XUINT (obj);
1731 return (void *) (p << 1); 1731 return (void *) (p << 1);
1732 } 1732 }
1733 1733
1734 /************************************************************************/ 1734 /************************************************************************/
1735 /** Definitions of dynamic arrays (dynarrs) and other allocators **/ 1735 /** Definitions of dynarrs and other allocators **/
1736 /************************************************************************/ 1736 /************************************************************************/
1737 1737
1738 BEGIN_C_DECLS 1738 #include "array.h"
1739
1740 /************* Dynarr declaration *************/
1741
1742 #ifdef NEW_GC
1743 #define DECLARE_DYNARR_LISP_IMP() \
1744 const struct lrecord_implementation *lisp_imp;
1745 #else
1746 #define DECLARE_DYNARR_LISP_IMP()
1747 #endif
1748
1749 #ifdef ERROR_CHECK_DYNARR
1750 #define DECLARE_DYNARR_LOCKED() \
1751 int locked;
1752 #else
1753 #define DECLARE_DYNARR_LOCKED()
1754 #endif
1755
1756 #define Dynarr_declare(type) \
1757 struct lrecord_header header; \
1758 type *base; \
1759 DECLARE_DYNARR_LISP_IMP () \
1760 DECLARE_DYNARR_LOCKED () \
1761 int elsize_; \
1762 int len_; \
1763 int largest_; \
1764 int max_
1765
1766 typedef struct dynarr
1767 {
1768 Dynarr_declare (void);
1769 } Dynarr;
1770
1771 #define XD_DYNARR_DESC(base_type, sub_desc) \
1772 { XD_BLOCK_PTR, offsetof (base_type, base), \
1773 XD_INDIRECT(1, 0), {sub_desc} }, \
1774 { XD_INT, offsetof (base_type, len_) }, \
1775 { XD_INT_RESET, offsetof (base_type, largest_), XD_INDIRECT(1, 0) }, \
1776 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) }
1777
1778 #ifdef NEW_GC
1779 #define XD_LISP_DYNARR_DESC(base_type, sub_desc) \
1780 { XD_LISP_OBJECT_BLOCK_PTR, offsetof (base_type, base), \
1781 XD_INDIRECT(1, 0), {sub_desc} }, \
1782 { XD_INT, offsetof (base_type, len_) }, \
1783 { XD_INT_RESET, offsetof (base_type, largest_), XD_INDIRECT(1, 0) }, \
1784 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) }
1785 #endif /* NEW_GC */
1786
1787 /************* Dynarr verification *************/
1788
1789 /* Dynarr locking and verification.
1790
1791 [I] VERIFICATION
1792
1793 Verification routines simply return their basic argument, possibly
1794 casted, but in the process perform some verification on it, aborting if
1795 the verification fails. The verification routines take FILE and LINE
1796 parameters, and use them to output the file and line of the caller
1797 when an abort occurs, rather than the file and line of the inline
1798 function, which is less than useful.
1799
1800 There are three basic types of verification routines:
1801
1802 (1) Verify the dynarr itself. This verifies the basic invariant
1803 involving the length/size values:
1804
1805 0 <= Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d)
1806
1807 (2) Verify the dynarr itself prior to modifying it. This performs
1808 the same verification as previously, but also checks that the
1809 dynarr is not locked (see below).
1810
1811 (3) Verify a dynarr position. Unfortunately we have to have
1812 different verification routines depending on which kind of operation
1813 is being performed:
1814
1815 (a) For Dynarr_at(), we check that the POS is bounded by Dynarr_largest(),
1816 i.e. 0 <= POS < Dynarr_largest().
1817 (b) For Dynarr_atp_allow_end(), we also have to allow
1818 POS == Dynarr_largest().
1819 (c) For Dynarr_atp(), we behave largely like Dynarr_at() but make a
1820 special exception when POS == 0 and Dynarr_largest() == 0 -- see
1821 comment below.
1822 (d) Some other routines contain the POS verification within their code,
1823 and make the check 0 <= POS < Dynarr_length() or
1824 0 <= POS <= Dynarr_length().
1825
1826 #### It is not well worked-out whether and in what circumstances it's
1827 allowed to use a position that is between Dynarr_length() and
1828 Dynarr_largest(). The ideal solution is to never allow this, and require
1829 instead that code first change the length before accessing higher
1830 positions. That would require looking through all the code that accesses
1831 dynarrs and fixing it appropriately (especially redisplay code, and
1832 especially redisplay code in the vicinity of a reference to
1833 Dynarr_largest(), since such code usually checks explicitly to see whether
1834 there is extra stuff between Dynarr_length() and Dynarr_largest().)
1835
1836 [II] LOCKING
1837
1838 The idea behind dynarr locking is simple: Locking a dynarr prevents
1839 any modification from occurring, or rather, leads to an abort upon
1840 any attempt to modify a dynarr.
1841
1842 Dynarr locking was originally added to catch some sporadic and hard-to-
1843 debug crashes in the redisplay code where dynarrs appeared to be getting
1844 corrupted in an unexpected fashion. The solution was to lock the
1845 dynarrs that were getting corrupted (in this case, the display-line
1846 dynarrs) around calls to routines that weren't supposed to be changing
1847 these dynarrs but might somehow be calling code that modified them.
1848 This eventually revealed that there was a reentrancy problem with
1849 redisplay that involved the QUIT mechanism and the processing done in
1850 order to determine whether C-g had been pressed -- this processing
1851 involves retrieving, processing and queueing pending events to see
1852 whether any of them result in a C-g keypress. However, at least under
1853 MS Windows this can result in redisplay being called reentrantly.
1854 For more info:--
1855
1856 (Info-goto-node "(internals)Critical Redisplay Sections")
1857
1858 */
1859
1860 #ifdef ERROR_CHECK_DYNARR
1861 DECLARE_INLINE_HEADER (
1862 int
1863 Dynarr_verify_pos_at (void *d, Elemcount pos, const Ascbyte *file, int line)
1864 )
1865 {
1866 Dynarr *dy = (Dynarr *) d;
1867 /* We use `largest', not `len', because the redisplay code often
1868 accesses stuff between len and largest. */
1869 assert_at_line (pos >= 0 && pos < dy->largest_, file, line);
1870 return pos;
1871 }
1872
1873 DECLARE_INLINE_HEADER (
1874 int
1875 Dynarr_verify_pos_atp (void *d, Elemcount pos, const Ascbyte *file, int line)
1876 )
1877 {
1878 Dynarr *dy = (Dynarr *) d;
1879 /* We use `largest', not `len', because the redisplay code often
1880 accesses stuff between len and largest. */
1881 /* [[ Code will often do something like ...
1882
1883 val = make_bit_vector_from_byte_vector (Dynarr_atp (dyn, 0),
1884 Dynarr_length (dyn));
1885
1886 which works fine when the Dynarr_length is non-zero, but when zero,
1887 the result of Dynarr_atp() not only points past the end of the
1888 allocated array, but the array may not have ever been allocated and
1889 hence the return value is NULL. But the length of 0 causes the
1890 pointer to never get checked. These can occur throughout the code
1891 so we put in a special check. --ben ]]
1892
1893 Update: The common idiom `Dynarr_atp (dyn, 0)' has been changed to
1894 `Dynarr_begin (dyn)'. Possibly this special check at POS 0 can be
1895 done only for Dynarr_begin() not for general Dynarr_atp(). --ben */
1896 if (pos == 0 && dy->len_ == 0)
1897 return pos;
1898 /* #### It's vaguely possible that some code could legitimately want to
1899 retrieve a pointer to the position just past the end of dynarr memory.
1900 This could happen with Dynarr_atp() but not Dynarr_at(). If so, it
1901 will trigger this assert(). In such cases, it should be obvious that
1902 the code wants to do this; rather than relaxing the assert, we should
1903 probably create a new macro Dynarr_atp_allow_end() which is like
1904 Dynarr_atp() but which allows for pointing at invalid addresses -- we
1905 really want to check for cases of accessing just past the end of
1906 memory, which is a likely off-by-one problem to occur and will usually
1907 not trigger a protection fault (instead, you'll just get random
1908 behavior, possibly overwriting other memory, which is bad). --ben */
1909 assert_at_line (pos >= 0 && pos < dy->largest_, file, line);
1910 return pos;
1911 }
1912
1913 DECLARE_INLINE_HEADER (
1914 int
1915 Dynarr_verify_pos_atp_allow_end (void *d, Elemcount pos, const Ascbyte *file,
1916 int line)
1917 )
1918 {
1919 Dynarr *dy = (Dynarr *) d;
1920 /* We use `largest', not `len', because the redisplay code often
1921 accesses stuff between len and largest.
1922 We also allow referencing the very end, past the end of allocated
1923 legitimately space. See comments in Dynarr_verify_pos_atp.()*/
1924 assert_at_line (pos >= 0 && pos <= dy->largest_, file, line);
1925 return pos;
1926 }
1927
1928 #else
1929 #define Dynarr_verify_pos_at(d, pos, file, line) (pos)
1930 #define Dynarr_verify_pos_atp(d, pos, file, line) (pos)
1931 #define Dynarr_verify_pos_atp_allow_end(d, pos, file, line) (pos)
1932 #endif /* ERROR_CHECK_DYNARR */
1933
1934 #ifdef ERROR_CHECK_DYNARR
1935 DECLARE_INLINE_HEADER (
1936 Dynarr *
1937 Dynarr_verify_1 (void *d, const Ascbyte *file, int line)
1938 )
1939 {
1940 Dynarr *dy = (Dynarr *) d;
1941 assert_at_line (dy->len_ >= 0 && dy->len_ <= dy->largest_ &&
1942 dy->largest_ <= dy->max_, file, line);
1943 return dy;
1944 }
1945
1946 DECLARE_INLINE_HEADER (
1947 Dynarr *
1948 Dynarr_verify_mod_1 (void *d, const Ascbyte *file, int line)
1949 )
1950 {
1951 Dynarr *dy = (Dynarr *) d;
1952 assert_at_line (!dy->locked, file, line);
1953 return Dynarr_verify_1 (d, file, line);
1954 }
1955
1956 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__)
1957 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__)
1958
1959 DECLARE_INLINE_HEADER (
1960 void
1961 Dynarr_lock (void *d)
1962 )
1963 {
1964 Dynarr *dy = Dynarr_verify_mod (d);
1965 dy->locked = 1;
1966 }
1967
1968 DECLARE_INLINE_HEADER (
1969 void
1970 Dynarr_unlock (void *d)
1971 )
1972 {
1973 Dynarr *dy = Dynarr_verify (d);
1974 assert (dy->locked);
1975 dy->locked = 0;
1976 }
1977
1978 #else /* not ERROR_CHECK_DYNARR */
1979
1980 #define Dynarr_verify(d) ((Dynarr *) d)
1981 #define Dynarr_verify_mod(d) ((Dynarr *) d)
1982 #define Dynarr_lock(d) DO_NOTHING
1983 #define Dynarr_unlock(d) DO_NOTHING
1984
1985 #endif /* ERROR_CHECK_DYNARR */
1986
1987 /************* Dynarr creation *************/
1988
1989 MODULE_API void *Dynarr_newf (Bytecount elsize);
1990 MODULE_API void Dynarr_free (void *d);
1991
1992 #ifdef NEW_GC
1993 MODULE_API void *Dynarr_lisp_newf (Bytecount elsize,
1994 const struct lrecord_implementation
1995 *dynarr_imp,
1996 const struct lrecord_implementation *imp);
1997
1998 #define Dynarr_lisp_new(type, dynarr_imp, imp) \
1999 ((type##_dynarr *) Dynarr_lisp_newf (sizeof (type), dynarr_imp, imp))
2000 #define Dynarr_lisp_new2(dynarr_type, type, dynarr_imp, imp) \
2001 ((dynarr_type *) Dynarr_lisp_newf (sizeof (type)), dynarr_imp, imp)
2002 #endif /* NEW_GC */
2003 #define Dynarr_new(type) ((type##_dynarr *) Dynarr_newf (sizeof (type)))
2004 #define Dynarr_new2(dynarr_type, type) \
2005 ((dynarr_type *) Dynarr_newf (sizeof (type)))
2006
2007 /************* Dynarr access *************/
2008
2009 #ifdef ERROR_CHECK_DYNARR
2010 #define Dynarr_at(d, pos) \
2011 ((d)->base[Dynarr_verify_pos_at (d, pos, __FILE__, __LINE__)])
2012 #define Dynarr_atp_allow_end(d, pos) \
2013 (&((d)->base[Dynarr_verify_pos_atp_allow_end (d, pos, __FILE__, __LINE__)]))
2014 #define Dynarr_atp(d, pos) \
2015 (&((d)->base[Dynarr_verify_pos_atp (d, pos, __FILE__, __LINE__)]))
2016 #else
2017 #define Dynarr_at(d, pos) ((d)->base[pos])
2018 #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos))
2019 #define Dynarr_atp_allow_end(d, pos) Dynarr_atp (d, pos)
2020 #endif
2021
2022 /* Old #define Dynarr_atp(d, pos) (&Dynarr_at (d, pos)) */
2023 #define Dynarr_begin(d) Dynarr_atp (d, 0)
2024 #define Dynarr_lastp(d) Dynarr_atp (d, Dynarr_length (d) - 1)
2025 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d))
2026
2027
2028 /************* Dynarr length/size retrieval and setting *************/
2029
2030 /* Retrieve the length of a dynarr. The `+ 0' is to ensure that this cannot
2031 be used as an lvalue. */
2032 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0)
2033 /* Retrieve the largest ever length seen of a dynarr. The `+ 0' is to
2034 ensure that this cannot be used as an lvalue. */
2035 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0)
2036 /* Retrieve the number of elements that fit in the currently allocated
2037 space. The `+ 0' is to ensure that this cannot be used as an lvalue. */
2038 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0)
2039 /* Return the size in bytes of an element in a dynarr. */
2040 #define Dynarr_elsize(d) (Dynarr_verify (d)->elsize_ + 0)
2041 /* Retrieve the advertised memory usage of a dynarr, i.e. the number of
2042 bytes occupied by the elements in the dynarr, not counting any overhead. */
2043 #define Dynarr_sizeof(d) (Dynarr_length (d) * Dynarr_elsize (d))
2044
2045 /* Actually set the length of a dynarr. This is a low-level routine that
2046 should not be directly used; use Dynarr_set_length() or
2047 Dynarr_set_lengthr() instead. */
2048 DECLARE_INLINE_HEADER (
2049 void
2050 Dynarr_set_length_1 (void *d, Elemcount len)
2051 )
2052 {
2053 Dynarr *dy = Dynarr_verify_mod (d);
2054 dynarr_checking_assert (len >= 0 && len <= Dynarr_max (dy));
2055 /* Use the raw field references here otherwise we get a crash because
2056 we've set the length but not yet fixed up the largest value. */
2057 dy->len_ = len;
2058 if (dy->len_ > dy->largest_)
2059 dy->largest_ = dy->len_;
2060 (void) Dynarr_verify_mod (d);
2061 }
2062
2063 /* "Restricted set-length": Set the length of dynarr D to LEN,
2064 which must be in the range [0, Dynarr_largest(d)]. */
2065
2066 DECLARE_INLINE_HEADER (
2067 void
2068 Dynarr_set_lengthr (void *d, Elemcount len)
2069 )
2070 {
2071 Dynarr *dy = Dynarr_verify_mod (d);
2072 dynarr_checking_assert (len >= 0 && len <= Dynarr_largest (dy));
2073 Dynarr_set_length_1 (dy, len);
2074 }
2075
2076 /* "Restricted increment": Increment the length of dynarr D by 1; the resulting
2077 length must be in the range [0, Dynarr_largest(d)]. */
2078
2079 #define Dynarr_incrementr(d) Dynarr_set_lengthr (d, Dynarr_length (d) + 1)
2080
2081
2082 MODULE_API void Dynarr_resize (void *d, Elemcount size);
2083
2084 DECLARE_INLINE_HEADER (
2085 void
2086 Dynarr_resize_to_fit (void *d, Elemcount size)
2087 )
2088 {
2089 Dynarr *dy = Dynarr_verify_mod (d);
2090 if (size > Dynarr_max (dy))
2091 Dynarr_resize (dy, size);
2092 }
2093
2094 #define Dynarr_resize_to_add(d, numels) \
2095 Dynarr_resize_to_fit (d, Dynarr_length (d) + numels)
2096
2097 /* This is an optimization. This is like Dynarr_set_length() but the length
2098 is guaranteed to be at least as big as the existing length. */
2099
2100 DECLARE_INLINE_HEADER (
2101 void
2102 Dynarr_increase_length (void *d, Elemcount len)
2103 )
2104 {
2105 Dynarr *dy = Dynarr_verify_mod (d);
2106 dynarr_checking_assert (len >= Dynarr_length (dy));
2107 Dynarr_resize_to_fit (dy, len);
2108 Dynarr_set_length_1 (dy, len);
2109 }
2110
2111 /* Set the length of dynarr D to LEN. If the length increases, resize as
2112 necessary to fit. (NOTE: This will leave uninitialized memory. If you
2113 aren't planning on immediately overwriting the memory, use
2114 Dynarr_set_length_and_zero() to zero out all the memory that would
2115 otherwise be uninitialized.) */
2116
2117 DECLARE_INLINE_HEADER (
2118 void
2119 Dynarr_set_length (void *d, Elemcount len)
2120 )
2121 {
2122 Dynarr *dy = Dynarr_verify_mod (d);
2123 Elemcount old_len = Dynarr_length (dy);
2124 if (old_len >= len)
2125 Dynarr_set_lengthr (dy, len);
2126 else
2127 Dynarr_increase_length (d, len);
2128 }
2129
2130 #define Dynarr_increment(d) Dynarr_increase_length (d, Dynarr_length (d) + 1)
2131
2132 /* Zero LEN contiguous elements starting at POS. */
2133
2134 DECLARE_INLINE_HEADER (
2135 void
2136 Dynarr_zero_many (void *d, Elemcount pos, Elemcount len)
2137 )
2138 {
2139 Dynarr *dy = Dynarr_verify_mod (d);
2140 memset ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), 0,
2141 len*Dynarr_elsize (dy));
2142 }
2143
2144 /* This is an optimization. This is like Dynarr_set_length_and_zero() but
2145 the length is guaranteed to be at least as big as the existing
2146 length. */
2147
2148 DECLARE_INLINE_HEADER (
2149 void
2150 Dynarr_increase_length_and_zero (void *d, Elemcount len)
2151 )
2152 {
2153 Dynarr *dy = Dynarr_verify_mod (d);
2154 Elemcount old_len = Dynarr_length (dy);
2155 Dynarr_increase_length (dy, len);
2156 Dynarr_zero_many (dy, old_len, len - old_len);
2157 }
2158
2159 /* Set the length of dynarr D to LEN. If the length increases, resize as
2160 necessary to fit and zero out all the elements between the old and new
2161 lengths. */
2162
2163 DECLARE_INLINE_HEADER (
2164 void
2165 Dynarr_set_length_and_zero (void *d, Elemcount len)
2166 )
2167 {
2168 Dynarr *dy = Dynarr_verify_mod (d);
2169 Elemcount old_len = Dynarr_length (dy);
2170 if (old_len >= len)
2171 Dynarr_set_lengthr (dy, len);
2172 else
2173 Dynarr_increase_length_and_zero (d, len);
2174 }
2175
2176 /* Reset the dynarr's length to 0. */
2177 #define Dynarr_reset(d) Dynarr_set_lengthr (d, 0)
2178
2179 #ifdef MEMORY_USAGE_STATS
2180 struct usage_stats;
2181 Bytecount Dynarr_memory_usage (void *d, struct usage_stats *stats);
2182 #endif
2183
2184 /************* Adding/deleting elements to/from a dynarr *************/
2185
2186 /* Set the Lisp implementation of the element at POS in dynarr D. Only
2187 does this if the dynarr holds Lisp objects of a particular type (the
2188 objects themselves, not pointers to them), and only under NEW_GC. */
2189
2190 #ifdef NEW_GC
2191 #define DYNARR_SET_LISP_IMP(d, pos) \
2192 do { \
2193 if ((d)->lisp_imp) \
2194 set_lheader_implementation \
2195 ((struct lrecord_header *)&(((d)->base)[pos]), (d)->lisp_imp); \
2196 } while (0)
2197 #else
2198 #define DYNARR_SET_LISP_IMP(d, pos) DO_NOTHING
2199 #endif /* (not) NEW_GC */
2200
2201 /* Add Element EL to the end of dynarr D. */
2202
2203 #define Dynarr_add(d, el) \
2204 do { \
2205 Elemcount _da_pos = Dynarr_length (d); \
2206 (void) Dynarr_verify_mod (d); \
2207 Dynarr_increment (d); \
2208 ((d)->base)[_da_pos] = (el); \
2209 DYNARR_SET_LISP_IMP (d, _da_pos); \
2210 } while (0)
2211
2212 /* Set EL as the element at position POS in dynarr D.
2213 Expand the dynarr as necessary so that its length is enough to include
2214 position POS within it, and zero out any new elements created as a
2215 result of expansion, other than the one at POS. */
2216
2217 #define Dynarr_set(d, pos, el) \
2218 do { \
2219 Elemcount _ds_pos = (pos); \
2220 (void) Dynarr_verify_mod (d); \
2221 if (Dynarr_length (d) < _ds_pos + 1) \
2222 Dynarr_increase_length_and_zero (d, _ds_pos + 1); \
2223 ((d)->base)[_ds_pos] = (el); \
2224 DYNARR_SET_LISP_IMP (d, _ds_pos); \
2225 } while (0)
2226
2227 /* Add LEN contiguous elements, stored at BASE, to dynarr D. If BASE is
2228 NULL, reserve space but don't store anything. */
2229
2230 DECLARE_INLINE_HEADER (
2231 void
2232 Dynarr_add_many (void *d, const void *base, Elemcount len)
2233 )
2234 {
2235 /* This duplicates Dynarr_insert_many to some extent; but since it is
2236 called so often, it seemed useful to remove the unnecessary stuff
2237 from that function and to make it inline */
2238 Dynarr *dy = Dynarr_verify_mod (d);
2239 Elemcount pos = Dynarr_length (dy);
2240 Dynarr_increase_length (dy, Dynarr_length (dy) + len);
2241 if (base)
2242 memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
2243 len*Dynarr_elsize (dy));
2244 }
2245
2246 /* Insert LEN elements, currently pointed to by BASE, into dynarr D
2247 starting at position POS. */
2248
2249 MODULE_API void Dynarr_insert_many (void *d, const void *base, Elemcount len,
2250 Elemcount pos);
2251
2252 /* Prepend LEN elements, currently pointed to by BASE, to the beginning. */
2253
2254 #define Dynarr_prepend_many(d, base, len) Dynarr_insert_many (d, base, len, 0)
2255
2256 /* Add literal string S to dynarr D, which should hold chars or unsigned
2257 chars. The final zero byte is not stored. */
2258
2259 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1)
2260
2261 /* Convert Lisp string S to an external encoding according to CODESYS and
2262 add to dynarr D, which should hold chars or unsigned chars. No final
2263 zero byte is appended. */
2264
2265 /* #### This should be an inline function but LISP_STRING_TO_SIZED_EXTERNAL
2266 isn't declared yet. */
2267
2268 #define Dynarr_add_ext_lisp_string(d, s, codesys) \
2269 do { \
2270 Lisp_Object dyna_ls_s = (s); \
2271 Lisp_Object dyna_ls_cs = (codesys); \
2272 Extbyte *dyna_ls_eb; \
2273 Bytecount dyna_ls_bc; \
2274 \
2275 LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \
2276 dyna_ls_bc, dyna_ls_cs); \
2277 Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \
2278 } while (0)
2279
2280 /* Delete LEN elements starting at position POS. */
2281
2282 MODULE_API void Dynarr_delete_many (void *d, Elemcount pos, Elemcount len);
2283
2284 /* Pop off (i.e. delete) the last element from the dynarr and return it */
2285
2286 #define Dynarr_pop(d) \
2287 (dynarr_checking_assert (Dynarr_length (d) > 0), \
2288 Dynarr_verify_mod (d)->len_--, \
2289 Dynarr_at (d, Dynarr_length (d)))
2290
2291 /* Delete the item at POS */
2292
2293 #define Dynarr_delete(d, pos) Dynarr_delete_many (d, pos, 1)
2294
2295 /* Delete the item located at memory address P, which must be a `type *'
2296 pointer, where `type' is the type of the elements of the dynarr. */
2297 #define Dynarr_delete_by_pointer(d, p) \
2298 Dynarr_delete_many (d, (p) - ((d)->base), 1)
2299
2300 /* Delete all elements that are numerically equal to EL. */
2301
2302 #define Dynarr_delete_object(d, el) \
2303 do \
2304 { \
2305 REGISTER int i; \
2306 for (i = Dynarr_length (d) - 1; i >= 0; i--) \
2307 { \
2308 if (el == Dynarr_at (d, i)) \
2309 Dynarr_delete_many (d, i, 1); \
2310 } \
2311 } while (0)
2312 1739
2313 /************* Dynarr typedefs *************/ 1740 /************* Dynarr typedefs *************/
2314 1741
2315 /* Dynarr typedefs -- basic types first */ 1742 /* Dynarr typedefs -- basic types first */
2316 1743
2432 1859
2433 typedef struct 1860 typedef struct
2434 { 1861 {
2435 Dynarr_declare (Lisp_Object *); 1862 Dynarr_declare (Lisp_Object *);
2436 } Lisp_Object_ptr_dynarr; 1863 } Lisp_Object_ptr_dynarr;
2437
2438
2439 /************* Stack-like malloc/free: Another allocator *************/
2440
2441 void *stack_like_malloc (Bytecount size);
2442 void stack_like_free (void *val);
2443 1864
2444 1865
2445 /************************************************************************/ 1866 /************************************************************************/
2446 /** Definitions of other basic Lisp objects **/ 1867 /** Definitions of other basic Lisp objects **/
2447 /************************************************************************/ 1868 /************************************************************************/