comparison src/lisp.h @ 5038:9410323e4b0d

major dynarr fixes -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-20 Ben Wing <ben@xemacs.org> * device-x.c (Fx_get_resource): * dynarr.c: * dynarr.c (Dynarr_realloc): * dynarr.c (Dynarr_newf): * dynarr.c (Dynarr_lisp_realloc): * dynarr.c (Dynarr_lisp_newf): * dynarr.c (Dynarr_resize): * dynarr.c (Dynarr_insert_many): * dynarr.c (Dynarr_delete_many): * dynarr.c (Dynarr_memory_usage): * dynarr.c (stack_like_free): * file-coding.c (coding_reader): * file-coding.c (gzip_convert): * gutter.c (output_gutter): * lisp.h: * lisp.h (Dynarr_declare): * lisp.h (DYNARR_SET_LISP_IMP): * lisp.h (CHECK_NATNUM): * profile.c (create_timing_profile_table): * redisplay-output.c (sync_rune_structs): * redisplay-output.c (sync_display_line_structs): * redisplay-output.c (redisplay_output_window): * redisplay.c: * redisplay.c (get_display_block_from_line): * redisplay.c (add_ichar_rune_1): * redisplay.c (ensure_modeline_generated): * redisplay.c (generate_displayable_area): * redisplay.c (regenerate_window): * redisplay.c (update_line_start_cache): * signal.c: * signal.c (check_quit): Lots of rewriting of dynarr code. (1) Lots of documentation added. Also fix places that referenced a now-bogus internals node concerning redisplay critical sections. (2) Rename: Dynarr_add_lisp_string -> Dynarr_add_ext_lisp_string Dynarr_set_length -> Dynarr_set_lengthr ("restricted") Dynarr_increment -> Dynarr_incrementr Dynarr_resize_if -> Dynarr_resize_to_add (3) New functions: Dynarr_elsize = dy->elsize_ Dynarr_set_length(): Set length, resizing as necessary Dynarr_set_length_and_zero(): Set length, resizing as necessary, zeroing out new elements Dynarr_increase_length(), Dynarr_increase_length_and_zero(): Optimization of Dynarr_set_length(), Dynarr_set_length_and_zero() when size is known to increase Dynarr_resize_to_fit(): Resize as necessary to fit a given length. Dynarr_set(): Set element at a given position, increasing length as necessary and setting any newly created positions to 0 (4) Use Elemcount, Bytecount. (5) Rewrite many macros as inline functions.
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 03:46:22 -0600
parents 838630c0734f
children 92dc90c0bb40
comparison
equal deleted inserted replaced
5037:e70a73f9243d 5038:9410323e4b0d
315 these become needed, they can always be defined. */ 315 these become needed, they can always be defined. */
316 316
317 #ifdef ERROR_CHECK_STRUCTURES 317 #ifdef ERROR_CHECK_STRUCTURES
318 /* Check for problems with the catch list and specbind stack */ 318 /* Check for problems with the catch list and specbind stack */
319 #define ERROR_CHECK_CATCH 319 #define ERROR_CHECK_CATCH
320 /* Check for incoherent Dynarr structures, attempts to access Dynarr 320 /* Check for incoherent dynarr structures, attempts to access Dynarr
321 positions out of range, reentrant use of Dynarrs through Dynarr locking, 321 positions out of range, reentrant use of dynarrs through dynarr locking,
322 etc. */ 322 etc. */
323 #define ERROR_CHECK_DYNARR 323 #define ERROR_CHECK_DYNARR
324 /* Check for insufficient use of call_trapping_problems(), particularly 324 /* Check for insufficient use of call_trapping_problems(), particularly
325 due to glyph-related changes causing eval or QUIT within redisplay */ 325 due to glyph-related changes causing eval or QUIT within redisplay */
326 #define ERROR_CHECK_TRAPPING_PROBLEMS 326 #define ERROR_CHECK_TRAPPING_PROBLEMS
1453 1453
1454 /* Note that the simplest typedefs are near the top of this file. */ 1454 /* Note that the simplest typedefs are near the top of this file. */
1455 1455
1456 /* We put typedefs here so that prototype declarations don't choke. 1456 /* We put typedefs here so that prototype declarations don't choke.
1457 Note that we don't actually declare the structures here (except 1457 Note that we don't actually declare the structures here (except
1458 maybe for simple structures like Dynarrs); that keeps them private 1458 maybe for simple structures like dynarrs); that keeps them private
1459 to the routines that actually use them. */ 1459 to the routines that actually use them. */
1460 1460
1461 /* ------------------------------- */ 1461 /* ------------------------------- */
1462 /* Error_Behavior typedefs */ 1462 /* Error_Behavior typedefs */
1463 /* ------------------------------- */ 1463 /* ------------------------------- */
1719 EMACS_UINT p = XUINT (obj); 1719 EMACS_UINT p = XUINT (obj);
1720 return (void *) (p << 1); 1720 return (void *) (p << 1);
1721 } 1721 }
1722 1722
1723 /************************************************************************/ 1723 /************************************************************************/
1724 /** Definitions of dynamic arrays (Dynarrs) and other allocators **/ 1724 /** Definitions of dynamic arrays (dynarrs) and other allocators **/
1725 /************************************************************************/ 1725 /************************************************************************/
1726 1726
1727 BEGIN_C_DECLS 1727 BEGIN_C_DECLS
1728 1728
1729 /************* Dynarr declaration *************/ 1729 /************* Dynarr declaration *************/
1745 #define Dynarr_declare(type) \ 1745 #define Dynarr_declare(type) \
1746 struct lrecord_header header; \ 1746 struct lrecord_header header; \
1747 type *base; \ 1747 type *base; \
1748 DECLARE_DYNARR_LISP_IMP () \ 1748 DECLARE_DYNARR_LISP_IMP () \
1749 DECLARE_DYNARR_LOCKED () \ 1749 DECLARE_DYNARR_LOCKED () \
1750 int elsize; \ 1750 int elsize_; \
1751 int len_; \ 1751 int len_; \
1752 int largest_; \ 1752 int largest_; \
1753 int max_ 1753 int max_
1754 1754
1755 typedef struct dynarr 1755 typedef struct dynarr
1773 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) } 1773 { XD_INT_RESET, offsetof (base_type, max_), XD_INDIRECT(1, 0) }
1774 #endif /* NEW_GC */ 1774 #endif /* NEW_GC */
1775 1775
1776 /************* Dynarr verification *************/ 1776 /************* Dynarr verification *************/
1777 1777
1778 /* Dynarr locking and verification.
1779
1780 [I] VERIFICATION
1781
1782 Verification routines simply return their basic argument, possibly
1783 casted, but in the process perform some verification on it, aborting if
1784 the verification fails. The verification routines take FILE and LINE
1785 parameters, and use them to output the file and line of the caller
1786 when an abort occurs, rather than the file and line of the inline
1787 function, which is less than useful.
1788
1789 There are three basic types of verification routines:
1790
1791 (1) Verify the dynarr itself. This verifies the basic invariant
1792 involving the length/size values:
1793
1794 0 <= Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d)
1795
1796 (2) Verify the dynarr itself prior to modifying it. This performs
1797 the same verification as previously, but also checks that the
1798 dynarr is not locked (see below).
1799
1800 (3) Verify a dynarr position. Unfortunately we have to have
1801 different verification routines depending on which kind of operation
1802 is being performed:
1803
1804 (a) For Dynarr_at(), we check that the POS is bounded by Dynarr_largest(),
1805 i.e. 0 <= POS < Dynarr_largest().
1806 (b) For Dynarr_atp_allow_end(), we also have to allow
1807 POS == Dynarr_largest().
1808 (c) For Dynarr_atp(), we behave largely like Dynarr_at() but make a
1809 special exception when POS == 0 and Dynarr_largest() == 0 -- see
1810 comment below.
1811 (d) Some other routines contain the POS verification within their code,
1812 and make the check 0 <= POS < Dynarr_length() or
1813 0 <= POS <= Dynarr_length().
1814
1815 #### It is not well worked-out whether and in what circumstances it's
1816 allowed to use a position that is between Dynarr_length() and
1817 Dynarr_largest(). The ideal solution is to never allow this, and require
1818 instead that code first change the length before accessing higher
1819 positions. That would require looking through all the code that accesses
1820 dynarrs and fixing it appropriately (especially redisplay code, and
1821 especially redisplay code in the vicinity of a reference to
1822 Dynarr_largest(), since such code usually checks explicitly to see whether
1823 there is extra stuff between Dynarr_length() and Dynarr_largest().)
1824
1825 [II] LOCKING
1826
1827 The idea behind dynarr locking is simple: Locking a dynarr prevents
1828 any modification from occurring, or rather, leads to an abort upon
1829 any attempt to modify a dynarr.
1830
1831 Dynarr locking was originally added to catch some sporadic and hard-to-
1832 debug crashes in the redisplay code where dynarrs appeared to be getting
1833 corrupted in an unexpected fashion. The solution was to lock the
1834 dynarrs that were getting corrupted (in this case, the display-line
1835 dynarrs) around calls to routines that weren't supposed to be changing
1836 these dynarrs but might somehow be calling code that modified them.
1837 This eventually revealed that there was a reentrancy problem with
1838 redisplay that involved the QUIT mechanism and the processing done in
1839 order to determine whether C-g had been pressed -- this processing
1840 involves retrieving, processing and queueing pending events to see
1841 whether any of them result in a C-g keypress. However, at least under
1842 MS Windows this can result in redisplay being called reentrantly.
1843 For more info:--
1844
1845 (Info-goto-node "(internals)Critical Redisplay Sections")
1846
1847 */
1848
1778 #ifdef ERROR_CHECK_DYNARR 1849 #ifdef ERROR_CHECK_DYNARR
1779 DECLARE_INLINE_HEADER ( 1850 DECLARE_INLINE_HEADER (
1780 int 1851 int
1781 Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line) 1852 Dynarr_verify_pos_at (void *d, Elemcount pos, const Ascbyte *file, int line)
1782 ) 1853 )
1783 { 1854 {
1784 Dynarr *dy = (Dynarr *) d; 1855 Dynarr *dy = (Dynarr *) d;
1785 /* We use `largest', not `len', because the redisplay code often 1856 /* We use `largest', not `len', because the redisplay code often
1786 accesses stuff between len and largest. */ 1857 accesses stuff between len and largest. */
1788 return pos; 1859 return pos;
1789 } 1860 }
1790 1861
1791 DECLARE_INLINE_HEADER ( 1862 DECLARE_INLINE_HEADER (
1792 int 1863 int
1793 Dynarr_verify_pos_atp (void *d, int pos, const Ascbyte *file, int line) 1864 Dynarr_verify_pos_atp (void *d, Elemcount pos, const Ascbyte *file, int line)
1794 ) 1865 )
1795 { 1866 {
1796 Dynarr *dy = (Dynarr *) d; 1867 Dynarr *dy = (Dynarr *) d;
1797 /* We use `largest', not `len', because the redisplay code often 1868 /* We use `largest', not `len', because the redisplay code often
1798 accesses stuff between len and largest. */ 1869 accesses stuff between len and largest. */
1828 return pos; 1899 return pos;
1829 } 1900 }
1830 1901
1831 DECLARE_INLINE_HEADER ( 1902 DECLARE_INLINE_HEADER (
1832 int 1903 int
1833 Dynarr_verify_pos_atp_allow_end (void *d, int pos, const Ascbyte *file, 1904 Dynarr_verify_pos_atp_allow_end (void *d, Elemcount pos, const Ascbyte *file,
1834 int line) 1905 int line)
1835 ) 1906 )
1836 { 1907 {
1837 Dynarr *dy = (Dynarr *) d; 1908 Dynarr *dy = (Dynarr *) d;
1838 /* We use `largest', not `len', because the redisplay code often 1909 /* We use `largest', not `len', because the redisplay code often
1871 return Dynarr_verify_1 (d, file, line); 1942 return Dynarr_verify_1 (d, file, line);
1872 } 1943 }
1873 1944
1874 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__) 1945 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__)
1875 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__) 1946 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__)
1876 #define Dynarr_lock(d) \ 1947
1877 do { \ 1948 DECLARE_INLINE_HEADER (
1878 Dynarr *dy = Dynarr_verify_mod (d); \ 1949 void
1879 dy->locked = 1; \ 1950 Dynarr_lock (void *d)
1880 } while (0) 1951 )
1881 #define Dynarr_unlock(d) \ 1952 {
1882 do { \ 1953 Dynarr *dy = Dynarr_verify_mod (d);
1883 Dynarr *dy = Dynarr_verify (d); \ 1954 dy->locked = 1;
1884 dy->locked = 0; \ 1955 }
1885 } while (0) 1956
1886 #else 1957 DECLARE_INLINE_HEADER (
1958 void
1959 Dynarr_unlock (void *d)
1960 )
1961 {
1962 Dynarr *dy = Dynarr_verify (d);
1963 assert (dy->locked);
1964 dy->locked = 0;
1965 }
1966
1967 #else /* not ERROR_CHECK_DYNARR */
1968
1887 #define Dynarr_verify(d) ((Dynarr *) d) 1969 #define Dynarr_verify(d) ((Dynarr *) d)
1888 #define Dynarr_verify_mod(d) ((Dynarr *) d) 1970 #define Dynarr_verify_mod(d) ((Dynarr *) d)
1889 #define Dynarr_lock(d) DO_NOTHING 1971 #define Dynarr_lock(d) DO_NOTHING
1890 #define Dynarr_unlock(d) DO_NOTHING 1972 #define Dynarr_unlock(d) DO_NOTHING
1973
1891 #endif /* ERROR_CHECK_DYNARR */ 1974 #endif /* ERROR_CHECK_DYNARR */
1892 1975
1893 /************* Dynarr creation *************/ 1976 /************* Dynarr creation *************/
1894 1977
1895 MODULE_API void *Dynarr_newf (int elsize); 1978 MODULE_API void *Dynarr_newf (Bytecount elsize);
1896 MODULE_API void Dynarr_free (void *d); 1979 MODULE_API void Dynarr_free (void *d);
1897 1980
1898 #ifdef NEW_GC 1981 #ifdef NEW_GC
1899 MODULE_API void *Dynarr_lisp_newf (int elsize, 1982 MODULE_API void *Dynarr_lisp_newf (Bytecount elsize,
1900 const struct lrecord_implementation 1983 const struct lrecord_implementation
1901 *dynarr_imp, 1984 *dynarr_imp,
1902 const struct lrecord_implementation *imp); 1985 const struct lrecord_implementation *imp);
1903 1986
1904 #define Dynarr_lisp_new(type, dynarr_imp, imp) \ 1987 #define Dynarr_lisp_new(type, dynarr_imp, imp) \
1931 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d)) 2014 #define Dynarr_past_lastp(d) Dynarr_atp_allow_end (d, Dynarr_length (d))
1932 2015
1933 2016
1934 /************* Dynarr length/size retrieval and setting *************/ 2017 /************* Dynarr length/size retrieval and setting *************/
1935 2018
1936 /* Retrieve the length of a Dynarr. The `+ 0' is to ensure that this cannot 2019 /* Retrieve the length of a dynarr. The `+ 0' is to ensure that this cannot
1937 be used as an lvalue. */ 2020 be used as an lvalue. */
1938 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0) 2021 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0)
1939 /* Retrieve the largest ever length seen of a Dynarr. The `+ 0' is to 2022 /* Retrieve the largest ever length seen of a dynarr. The `+ 0' is to
1940 ensure that this cannot be used as an lvalue. */ 2023 ensure that this cannot be used as an lvalue. */
1941 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0) 2024 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0)
1942 /* Retrieve the number of elements that fit in the currently allocated 2025 /* Retrieve the number of elements that fit in the currently allocated
1943 space. The `+ 0' is to ensure that this cannot be used as an lvalue. */ 2026 space. The `+ 0' is to ensure that this cannot be used as an lvalue. */
1944 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0) 2027 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0)
1945 /* Retrieve the advertised memory usage of a Dynarr, i.e. the number of 2028 /* Return the size in bytes of an element in a dynarr. */
1946 bytes occupied by the elements in the Dynarr, not counting any overhead. */ 2029 #define Dynarr_elsize(d) (Dynarr_verify (d)->elsize_ + 0)
1947 #define Dynarr_sizeof(d) (Dynarr_length (d) * (d)->elsize) 2030 /* Retrieve the advertised memory usage of a dynarr, i.e. the number of
1948 /* Actually set the length of a Dynarr. This is a low-level routine that 2031 bytes occupied by the elements in the dynarr, not counting any overhead. */
1949 should not be directly used; use Dynarr_set_length() instead if you need 2032 #define Dynarr_sizeof(d) (Dynarr_length (d) * Dynarr_elsize (d))
1950 to, but be very careful when doing so! */ 2033
1951 #define Dynarr_set_length_1(d, n) \ 2034 /* Actually set the length of a dynarr. This is a low-level routine that
1952 do { \ 2035 should not be directly used; use Dynarr_set_length() or
1953 Elemcount _dsl1_n = (n); \ 2036 Dynarr_set_lengthr() instead. */
1954 dynarr_checking_assert (_dsl1_n >= 0 && _dsl1_n <= Dynarr_max (d)); \ 2037 DECLARE_INLINE_HEADER (
1955 (void) Dynarr_verify_mod (d); \ 2038 void
1956 (d)->len_ = _dsl1_n; \ 2039 Dynarr_set_length_1 (void *d, Elemcount len)
1957 /* Use the raw field references here otherwise we get a crash because \ 2040 )
1958 we've set the length but not yet fixed up the largest value. */ \ 2041 {
1959 if ((d)->len_ > (d)->largest_) \ 2042 Dynarr *dy = Dynarr_verify_mod (d);
1960 (d)->largest_ = (d)->len_; \ 2043 dynarr_checking_assert (len >= 0 && len <= Dynarr_max (dy));
1961 (void) Dynarr_verify_mod (d); \ 2044 /* Use the raw field references here otherwise we get a crash because
1962 } while (0) 2045 we've set the length but not yet fixed up the largest value. */
1963 2046 dy->len_ = len;
1964 /* The following two defines will get you into real trouble if you aren't 2047 if (dy->len_ > dy->largest_)
1965 careful. But they can save a lot of execution time when used wisely. */ 2048 dy->largest_ = dy->len_;
1966 #define Dynarr_set_length(d, n) \ 2049 (void) Dynarr_verify_mod (d);
1967 do { \ 2050 }
1968 Elemcount _dsl_n = (n); \ 2051
1969 dynarr_checking_assert (_dsl_n >= 0 && _dsl_n <= Dynarr_largest (d)); \ 2052 /* "Restricted set-length": Set the length of dynarr D to LEN,
1970 Dynarr_set_length_1 (d, _dsl_n); \ 2053 which must be in the range [0, Dynarr_largest(d)]. */
1971 } while (0) 2054
1972 #define Dynarr_increment(d) \ 2055 DECLARE_INLINE_HEADER (
1973 Dynarr_set_length (d, Dynarr_length (d) + 1) 2056 void
1974 2057 Dynarr_set_lengthr (void *d, Elemcount len)
1975 /* Reset the Dynarr's length to 0. */ 2058 )
1976 #define Dynarr_reset(d) Dynarr_set_length (d, 0) 2059 {
1977 2060 Dynarr *dy = Dynarr_verify_mod (d);
1978 MODULE_API void Dynarr_resize (void *dy, Elemcount size); 2061 dynarr_checking_assert (len >= 0 && len <= Dynarr_largest (dy));
1979 2062 Dynarr_set_length_1 (dy, len);
1980 #define Dynarr_resize_if(d, numels) \ 2063 }
1981 do { \ 2064
1982 Elemcount _dri_numels = (numels); \ 2065 /* "Restricted increment": Increment the length of dynarr D by 1; the resulting
1983 if (Dynarr_length (d) + _dri_numels > Dynarr_max (d)) \ 2066 length must be in the range [0, Dynarr_largest(d)]. */
1984 Dynarr_resize (d, Dynarr_length (d) + _dri_numels); \ 2067
1985 } while (0) 2068 #define Dynarr_incrementr(d) Dynarr_set_lengthr (d, Dynarr_length (d) + 1)
2069
2070
2071 MODULE_API void Dynarr_resize (void *d, Elemcount size);
2072
2073 DECLARE_INLINE_HEADER (
2074 void
2075 Dynarr_resize_to_fit (void *d, Elemcount size)
2076 )
2077 {
2078 Dynarr *dy = Dynarr_verify_mod (d);
2079 if (size > Dynarr_max (dy))
2080 Dynarr_resize (dy, size);
2081 }
2082
2083 #define Dynarr_resize_to_add(d, numels) \
2084 Dynarr_resize_to_fit (d, Dynarr_length (d) + numels)
2085
2086 /* This is an optimization. This is like Dynarr_set_length() but the length
2087 is guaranteed to be at least as big as the existing length. */
2088
2089 DECLARE_INLINE_HEADER (
2090 void
2091 Dynarr_increase_length (void *d, Elemcount len)
2092 )
2093 {
2094 Dynarr *dy = Dynarr_verify_mod (d);
2095 dynarr_checking_assert (len >= Dynarr_length (dy));
2096 Dynarr_resize_to_fit (dy, len);
2097 Dynarr_set_length_1 (dy, len);
2098 }
2099
2100 /* Set the length of dynarr D to LEN. If the length increases, resize as
2101 necessary to fit. (NOTE: This will leave uninitialized memory. If you
2102 aren't planning on immediately overwriting the memory, use
2103 Dynarr_set_length_and_zero() to zero out all the memory that would
2104 otherwise be uninitialized.) */
2105
2106 DECLARE_INLINE_HEADER (
2107 void
2108 Dynarr_set_length (void *d, Elemcount len)
2109 )
2110 {
2111 Dynarr *dy = Dynarr_verify_mod (d);
2112 Elemcount old_len = Dynarr_length (dy);
2113 if (old_len >= len)
2114 Dynarr_set_lengthr (dy, len);
2115 else
2116 Dynarr_increase_length (d, len);
2117 }
2118
2119 #define Dynarr_increment(d) Dynarr_increase_length (d, Dynarr_length (d) + 1)
2120
2121 /* Zero LEN contiguous elements starting at POS. */
2122
2123 DECLARE_INLINE_HEADER (
2124 void
2125 Dynarr_zero_many (void *d, Elemcount pos, Elemcount len)
2126 )
2127 {
2128 Dynarr *dy = Dynarr_verify_mod (d);
2129 memset ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), 0,
2130 len*Dynarr_elsize (dy));
2131 }
2132
2133 /* This is an optimization. This is like Dynarr_set_length_and_zero() but
2134 the length is guaranteed to be at least as big as the existing
2135 length. */
2136
2137 DECLARE_INLINE_HEADER (
2138 void
2139 Dynarr_increase_length_and_zero (void *d, Elemcount len)
2140 )
2141 {
2142 Dynarr *dy = Dynarr_verify_mod (d);
2143 Elemcount old_len = Dynarr_length (dy);
2144 Dynarr_increase_length (dy, len);
2145 Dynarr_zero_many (dy, old_len, len - old_len);
2146 }
2147
2148 /* Set the length of dynarr D to LEN. If the length increases, resize as
2149 necessary to fit and zero out all the elements between the old and new
2150 lengths. */
2151
2152 DECLARE_INLINE_HEADER (
2153 void
2154 Dynarr_set_length_and_zero (void *d, Elemcount len)
2155 )
2156 {
2157 Dynarr *dy = Dynarr_verify_mod (d);
2158 Elemcount old_len = Dynarr_length (dy);
2159 if (old_len >= len)
2160 Dynarr_set_lengthr (dy, len);
2161 else
2162 Dynarr_increase_length_and_zero (d, len);
2163 }
2164
2165 /* Reset the dynarr's length to 0. */
2166 #define Dynarr_reset(d) Dynarr_set_lengthr (d, 0)
1986 2167
1987 #ifdef MEMORY_USAGE_STATS 2168 #ifdef MEMORY_USAGE_STATS
1988 struct overhead_stats; 2169 struct overhead_stats;
1989 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats); 2170 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats);
1990 #endif 2171 #endif
1991 2172
1992 /************* Adding/deleting elements to/from a Dynarr *************/ 2173 /************* Adding/deleting elements to/from a dynarr *************/
2174
2175 /* Set the Lisp implementation of the element at POS in dynarr D. Only
2176 does this if the dynarr holds Lisp objects of a particular type (the
2177 objects themselves, not pointers to them), and only under NEW_GC. */
1993 2178
1994 #ifdef NEW_GC 2179 #ifdef NEW_GC
1995 #define Dynarr_add(d, el) \ 2180 #define DYNARR_SET_LISP_IMP(d, pos) \
1996 do { \ 2181 do { \
1997 const struct lrecord_implementation *imp = (d)->lisp_imp; \ 2182 if ((d)->lisp_imp) \
1998 (void) Dynarr_verify_mod (d); \
1999 Dynarr_resize_if (d, 1); \
2000 ((d)->base)[Dynarr_length (d)] = (el); \
2001 if (imp) \
2002 set_lheader_implementation \ 2183 set_lheader_implementation \
2003 ((struct lrecord_header *)&(((d)->base)[Dynarr_length (d)]), imp); \ 2184 ((struct lrecord_header *)&(((d)->base)[pos]), (d)->lisp_imp); \
2004 Dynarr_set_length_1 (d, Dynarr_length (d) + 1); \ 2185 } while (0)
2005 (void) Dynarr_verify_mod (d); \ 2186 #else
2187 #define DYNARR_SET_LISP_IMP(d, pos) DO_NOTHING
2188 #endif /* (not) NEW_GC */
2189
2190 /* Add Element EL to the end of dynarr D. */
2191
2192 #define Dynarr_add(d, el) \
2193 do { \
2194 Elemcount _da_pos = Dynarr_length (d); \
2195 (void) Dynarr_verify_mod (d); \
2196 Dynarr_increment (d); \
2197 ((d)->base)[_da_pos] = (el); \
2198 DYNARR_SET_LISP_IMP (d, _da_pos); \
2006 } while (0) 2199 } while (0)
2007 #else /* not NEW_GC */ 2200
2008 #define Dynarr_add(d, el) \ 2201 /* Set EL as the element at position POS in dynarr D.
2202 Expand the dynarr as necessary so that its length is enough to include
2203 position POS within it, and zero out any new elements created as a
2204 result of expansion, other than the one at POS. */
2205
2206 #define Dynarr_set(d, pos, el) \
2009 do { \ 2207 do { \
2208 Elemcount _ds_pos = (pos); \
2010 (void) Dynarr_verify_mod (d); \ 2209 (void) Dynarr_verify_mod (d); \
2011 Dynarr_resize_if (d, 1); \ 2210 if (Dynarr_length (d) < _ds_pos + 1) \
2012 ((d)->base)[Dynarr_length (d)] = (el); \ 2211 Dynarr_increase_length_and_zero (d, _ds_pos + 1); \
2013 Dynarr_set_length_1 (d, Dynarr_length (d) + 1); \ 2212 ((d)->base)[_ds_pos] = (el); \
2014 (void) Dynarr_verify_mod (d); \ 2213 DYNARR_SET_LISP_IMP (d, _ds_pos); \
2015 } while (0) 2214 } while (0)
2016 #endif /* not NEW_GC */ 2215
2017 2216 /* Add LEN contiguous elements, stored at BASE, to dynarr D. If BASE is
2018 2217 NULL, reserve space but don't store anything. */
2019 MODULE_API void Dynarr_insert_many (void *d, const void *el, int len, 2218
2020 int start); 2219 DECLARE_INLINE_HEADER (
2021 MODULE_API void Dynarr_delete_many (void *d, int start, int len); 2220 void
2022 2221 Dynarr_add_many (void *d, const void *base, Elemcount len)
2023 #define Dynarr_insert_many_at_start(d, el, len) \ 2222 )
2024 Dynarr_insert_many (d, el, len, 0) 2223 {
2224 /* This duplicates Dynarr_insert_many to some extent; but since it is
2225 called so often, it seemed useful to remove the unnecessary stuff
2226 from that function and to make it inline */
2227 Dynarr *dy = Dynarr_verify_mod (d);
2228 Elemcount pos = Dynarr_length (dy);
2229 Dynarr_increase_length (dy, Dynarr_length (dy) + len);
2230 if (base)
2231 memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
2232 len*Dynarr_elsize (dy));
2233 }
2234
2235 /* Insert LEN elements, currently pointed to by BASE, into dynarr D
2236 starting at position POS. */
2237
2238 MODULE_API void Dynarr_insert_many (void *d, const void *base, Elemcount len,
2239 Elemcount pos);
2240
2241 /* Prepend LEN elements, currently pointed to by BASE, to the beginning. */
2242
2243 #define Dynarr_prepend_many(d, base, len) Dynarr_insert_many (d, base, len, 0)
2244
2245 /* Add literal string S to dynarr D, which should hold chars or unsigned
2246 chars. The final zero byte is not stored. */
2247
2025 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1) 2248 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1)
2026 #define Dynarr_add_lisp_string(d, s, codesys) \ 2249
2250 /* Convert Lisp string S to an external encoding according to CODESYS and
2251 add to dynarr D, which should hold chars or unsigned chars. No final
2252 zero byte is appended. */
2253
2254 /* #### This should be an inline function but LISP_STRING_TO_SIZED_EXTERNAL
2255 isn't declared yet. */
2256
2257 #define Dynarr_add_ext_lisp_string(d, s, codesys) \
2027 do { \ 2258 do { \
2028 Lisp_Object dyna_ls_s = (s); \ 2259 Lisp_Object dyna_ls_s = (s); \
2029 Lisp_Object dyna_ls_cs = (codesys); \ 2260 Lisp_Object dyna_ls_cs = (codesys); \
2030 Extbyte *dyna_ls_eb; \ 2261 Extbyte *dyna_ls_eb; \
2031 Bytecount dyna_ls_bc; \ 2262 Bytecount dyna_ls_bc; \
2033 LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \ 2264 LISP_STRING_TO_SIZED_EXTERNAL (dyna_ls_s, dyna_ls_eb, \
2034 dyna_ls_bc, dyna_ls_cs); \ 2265 dyna_ls_bc, dyna_ls_cs); \
2035 Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \ 2266 Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc); \
2036 } while (0) 2267 } while (0)
2037 2268
2038 /* Add LEN contiguous elements to a Dynarr */ 2269 /* Delete LEN elements starting at position POS. */
2039 2270
2040 DECLARE_INLINE_HEADER ( 2271 MODULE_API void Dynarr_delete_many (void *d, Elemcount pos, Elemcount len);
2041 void 2272
2042 Dynarr_add_many (void *d, const void *el, int len) 2273 /* Pop off (i.e. delete) the last element from the dynarr and return it */
2043 )
2044 {
2045 /* This duplicates Dynarr_insert_many to some extent; but since it is
2046 called so often, it seemed useful to remove the unnecessary stuff
2047 from that function and to make it inline */
2048 Dynarr *dy = Dynarr_verify_mod (d);
2049 Dynarr_resize_if (dy, len);
2050 /* Some functions call us with a value of 0 to mean "reserve space but
2051 don't write into it" */
2052 if (el)
2053 memcpy ((char *) dy->base + Dynarr_sizeof (dy), el, len*dy->elsize);
2054 Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
2055 (void) Dynarr_verify_mod (dy);
2056 }
2057 2274
2058 #define Dynarr_pop(d) \ 2275 #define Dynarr_pop(d) \
2059 (dynarr_checking_assert (Dynarr_length (d) > 0), \ 2276 (dynarr_checking_assert (Dynarr_length (d) > 0), \
2060 Dynarr_verify_mod (d)->len_--, \ 2277 Dynarr_verify_mod (d)->len_--, \
2061 Dynarr_at (d, Dynarr_length (d))) 2278 Dynarr_at (d, Dynarr_length (d)))
2062 #define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1) 2279
2280 /* Delete the item at POS */
2281
2282 #define Dynarr_delete(d, pos) Dynarr_delete_many (d, pos, 1)
2283
2284 /* Delete the item located at memory address P, which must be a `type *'
2285 pointer, where `type' is the type of the elements of the dynarr. */
2063 #define Dynarr_delete_by_pointer(d, p) \ 2286 #define Dynarr_delete_by_pointer(d, p) \
2064 Dynarr_delete_many (d, (p) - ((d)->base), 1) 2287 Dynarr_delete_many (d, (p) - ((d)->base), 1)
2288
2289 /* Delete all elements that are numerically equal to EL. */
2065 2290
2066 #define Dynarr_delete_object(d, el) \ 2291 #define Dynarr_delete_object(d, el) \
2067 do \ 2292 do \
2068 { \ 2293 { \
2069 REGISTER int i; \ 2294 REGISTER int i; \
3198 { 3423 {
3199 assert_at_line (INTP (obj), file, line); 3424 assert_at_line (INTP (obj), file, line);
3200 return XREALINT (obj); 3425 return XREALINT (obj);
3201 } 3426 }
3202 3427
3203 #else /* no error checking */ 3428 #else /* not ERROR_CHECK_TYPES */
3204 3429
3205 #define XINT(obj) XREALINT (obj) 3430 #define XINT(obj) XREALINT (obj)
3206 3431
3207 #endif /* no error checking */ 3432 #endif /* (not) ERROR_CHECK_TYPES */
3208 3433
3209 #define CHECK_INT(x) do { \ 3434 #define CHECK_INT(x) do { \
3210 if (!INTP (x)) \ 3435 if (!INTP (x)) \
3211 dead_wrong_type_argument (Qintegerp, x); \ 3436 dead_wrong_type_argument (Qintegerp, x); \
3212 } while (0) 3437 } while (0)
3213 3438
3214 #define CONCHECK_INT(x) do { \ 3439 #define CONCHECK_INT(x) do { \
3215 if (!INTP (x)) \ 3440 if (!INTP (x)) \
3216 x = wrong_type_argument (Qintegerp, x); \ 3441 x = wrong_type_argument (Qintegerp, x); \
3217 } while (0) 3442 } while (0)
3443
3444 /* NOTE NOTE NOTE! This definition of "natural number" is mathematically
3445 wrong. Mathematically, a natural number is a positive integer; 0
3446 isn't included. This would be better called NONNEGINT(). */
3218 3447
3219 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0) 3448 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0)
3220 3449
3221 #define CHECK_NATNUM(x) do { \ 3450 #define CHECK_NATNUM(x) do { \
3222 if (!NATNUMP (x)) \ 3451 if (!NATNUMP (x)) \