Mercurial > hg > xemacs-beta
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)) \ |