Mercurial > hg > xemacs-beta
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 /************************************************************************/ |