diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 87 |
1 files changed, 58 insertions, 29 deletions
diff --git a/src/alloc.c b/src/alloc.c index 29ccb38e7b7..d6d456a8fc0 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1782,11 +1782,13 @@ allocate_string (void) | |||
| 1782 | plus a NUL byte at the end. Allocate an sdata structure DATA for | 1782 | plus a NUL byte at the end. Allocate an sdata structure DATA for |
| 1783 | S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the | 1783 | S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the |
| 1784 | end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte | 1784 | end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte |
| 1785 | to NBYTES. Free S->u.s.data if it was initially non-null. */ | 1785 | to NBYTES. Free S->u.s.data if it was initially non-null. |
| 1786 | |||
| 1787 | If CLEARIT, also clear the other bytes of S->u.s.data. */ | ||
| 1786 | 1788 | ||
| 1787 | void | 1789 | void |
| 1788 | allocate_string_data (struct Lisp_String *s, | 1790 | allocate_string_data (struct Lisp_String *s, |
| 1789 | EMACS_INT nchars, EMACS_INT nbytes) | 1791 | EMACS_INT nchars, EMACS_INT nbytes, bool clearit) |
| 1790 | { | 1792 | { |
| 1791 | sdata *data, *old_data; | 1793 | sdata *data, *old_data; |
| 1792 | struct sblock *b; | 1794 | struct sblock *b; |
| @@ -1817,7 +1819,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1817 | mallopt (M_MMAP_MAX, 0); | 1819 | mallopt (M_MMAP_MAX, 0); |
| 1818 | #endif | 1820 | #endif |
| 1819 | 1821 | ||
| 1820 | b = lisp_malloc (size + GC_STRING_EXTRA, false, MEM_TYPE_NON_LISP); | 1822 | b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP); |
| 1821 | 1823 | ||
| 1822 | #ifdef DOUG_LEA_MALLOC | 1824 | #ifdef DOUG_LEA_MALLOC |
| 1823 | if (!mmap_lisp_allowed_p ()) | 1825 | if (!mmap_lisp_allowed_p ()) |
| @@ -1850,6 +1852,8 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1850 | { | 1852 | { |
| 1851 | b = current_sblock; | 1853 | b = current_sblock; |
| 1852 | data = b->next_free; | 1854 | data = b->next_free; |
| 1855 | if (clearit) | ||
| 1856 | memset (SDATA_DATA (data), 0, nbytes); | ||
| 1853 | } | 1857 | } |
| 1854 | 1858 | ||
| 1855 | data->string = s; | 1859 | data->string = s; |
| @@ -2114,6 +2118,9 @@ string_overflow (void) | |||
| 2114 | error ("Maximum string size exceeded"); | 2118 | error ("Maximum string size exceeded"); |
| 2115 | } | 2119 | } |
| 2116 | 2120 | ||
| 2121 | static Lisp_Object make_clear_string (EMACS_INT, bool); | ||
| 2122 | static Lisp_Object make_clear_multibyte_string (EMACS_INT, EMACS_INT, bool); | ||
| 2123 | |||
| 2117 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0, | 2124 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0, |
| 2118 | doc: /* Return a newly created string of length LENGTH, with INIT in each element. | 2125 | doc: /* Return a newly created string of length LENGTH, with INIT in each element. |
| 2119 | LENGTH must be an integer. | 2126 | LENGTH must be an integer. |
| @@ -2122,19 +2129,20 @@ If optional argument MULTIBYTE is non-nil, the result will be | |||
| 2122 | a multibyte string even if INIT is an ASCII character. */) | 2129 | a multibyte string even if INIT is an ASCII character. */) |
| 2123 | (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte) | 2130 | (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte) |
| 2124 | { | 2131 | { |
| 2125 | register Lisp_Object val; | 2132 | Lisp_Object val; |
| 2126 | int c; | ||
| 2127 | EMACS_INT nbytes; | 2133 | EMACS_INT nbytes; |
| 2128 | 2134 | ||
| 2129 | CHECK_FIXNAT (length); | 2135 | CHECK_FIXNAT (length); |
| 2130 | CHECK_CHARACTER (init); | 2136 | CHECK_CHARACTER (init); |
| 2131 | 2137 | ||
| 2132 | c = XFIXNAT (init); | 2138 | int c = XFIXNAT (init); |
| 2139 | bool clearit = !c; | ||
| 2140 | |||
| 2133 | if (ASCII_CHAR_P (c) && NILP (multibyte)) | 2141 | if (ASCII_CHAR_P (c) && NILP (multibyte)) |
| 2134 | { | 2142 | { |
| 2135 | nbytes = XFIXNUM (length); | 2143 | nbytes = XFIXNUM (length); |
| 2136 | val = make_uninit_string (nbytes); | 2144 | val = make_clear_string (nbytes, clearit); |
| 2137 | if (nbytes) | 2145 | if (nbytes && !clearit) |
| 2138 | { | 2146 | { |
| 2139 | memset (SDATA (val), c, nbytes); | 2147 | memset (SDATA (val), c, nbytes); |
| 2140 | SDATA (val)[nbytes] = 0; | 2148 | SDATA (val)[nbytes] = 0; |
| @@ -2145,26 +2153,27 @@ a multibyte string even if INIT is an ASCII character. */) | |||
| 2145 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 2153 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 2146 | ptrdiff_t len = CHAR_STRING (c, str); | 2154 | ptrdiff_t len = CHAR_STRING (c, str); |
| 2147 | EMACS_INT string_len = XFIXNUM (length); | 2155 | EMACS_INT string_len = XFIXNUM (length); |
| 2148 | unsigned char *p, *beg, *end; | ||
| 2149 | 2156 | ||
| 2150 | if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes)) | 2157 | if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes)) |
| 2151 | string_overflow (); | 2158 | string_overflow (); |
| 2152 | val = make_uninit_multibyte_string (string_len, nbytes); | 2159 | val = make_clear_multibyte_string (string_len, nbytes, clearit); |
| 2153 | for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len) | 2160 | if (!clearit) |
| 2154 | { | 2161 | { |
| 2155 | /* First time we just copy `str' to the data of `val'. */ | 2162 | unsigned char *beg = SDATA (val), *end = beg + nbytes; |
| 2156 | if (p == beg) | 2163 | for (unsigned char *p = beg; p < end; p += len) |
| 2157 | memcpy (p, str, len); | ||
| 2158 | else | ||
| 2159 | { | 2164 | { |
| 2160 | /* Next time we copy largest possible chunk from | 2165 | /* First time we just copy STR to the data of VAL. */ |
| 2161 | initialized to uninitialized part of `val'. */ | 2166 | if (p == beg) |
| 2162 | len = min (p - beg, end - p); | 2167 | memcpy (p, str, len); |
| 2163 | memcpy (p, beg, len); | 2168 | else |
| 2169 | { | ||
| 2170 | /* Next time we copy largest possible chunk from | ||
| 2171 | initialized to uninitialized part of VAL. */ | ||
| 2172 | len = min (p - beg, end - p); | ||
| 2173 | memcpy (p, beg, len); | ||
| 2174 | } | ||
| 2164 | } | 2175 | } |
| 2165 | } | 2176 | } |
| 2166 | if (nbytes) | ||
| 2167 | *p = 0; | ||
| 2168 | } | 2177 | } |
| 2169 | 2178 | ||
| 2170 | return val; | 2179 | return val; |
| @@ -2334,26 +2343,37 @@ make_specified_string (const char *contents, | |||
| 2334 | 2343 | ||
| 2335 | 2344 | ||
| 2336 | /* Return a unibyte Lisp_String set up to hold LENGTH characters | 2345 | /* Return a unibyte Lisp_String set up to hold LENGTH characters |
| 2337 | occupying LENGTH bytes. */ | 2346 | occupying LENGTH bytes. If CLEARIT, clear its contents to null |
| 2347 | bytes; otherwise, the contents are uninitialized. */ | ||
| 2338 | 2348 | ||
| 2339 | Lisp_Object | 2349 | static Lisp_Object |
| 2340 | make_uninit_string (EMACS_INT length) | 2350 | make_clear_string (EMACS_INT length, bool clearit) |
| 2341 | { | 2351 | { |
| 2342 | Lisp_Object val; | 2352 | Lisp_Object val; |
| 2343 | 2353 | ||
| 2344 | if (!length) | 2354 | if (!length) |
| 2345 | return empty_unibyte_string; | 2355 | return empty_unibyte_string; |
| 2346 | val = make_uninit_multibyte_string (length, length); | 2356 | val = make_clear_multibyte_string (length, length, clearit); |
| 2347 | STRING_SET_UNIBYTE (val); | 2357 | STRING_SET_UNIBYTE (val); |
| 2348 | return val; | 2358 | return val; |
| 2349 | } | 2359 | } |
| 2350 | 2360 | ||
| 2361 | /* Return a unibyte Lisp_String set up to hold LENGTH characters | ||
| 2362 | occupying LENGTH bytes. */ | ||
| 2363 | |||
| 2364 | Lisp_Object | ||
| 2365 | make_uninit_string (EMACS_INT length) | ||
| 2366 | { | ||
| 2367 | return make_clear_string (length, false); | ||
| 2368 | } | ||
| 2369 | |||
| 2351 | 2370 | ||
| 2352 | /* Return a multibyte Lisp_String set up to hold NCHARS characters | 2371 | /* Return a multibyte Lisp_String set up to hold NCHARS characters |
| 2353 | which occupy NBYTES bytes. */ | 2372 | which occupy NBYTES bytes. If CLEARIT, clear its contents to null |
| 2373 | bytes; otherwise, the contents are uninitialized. */ | ||
| 2354 | 2374 | ||
| 2355 | Lisp_Object | 2375 | static Lisp_Object |
| 2356 | make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | 2376 | make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit) |
| 2357 | { | 2377 | { |
| 2358 | Lisp_Object string; | 2378 | Lisp_Object string; |
| 2359 | struct Lisp_String *s; | 2379 | struct Lisp_String *s; |
| @@ -2365,12 +2385,21 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2365 | 2385 | ||
| 2366 | s = allocate_string (); | 2386 | s = allocate_string (); |
| 2367 | s->u.s.intervals = NULL; | 2387 | s->u.s.intervals = NULL; |
| 2368 | allocate_string_data (s, nchars, nbytes); | 2388 | allocate_string_data (s, nchars, nbytes, clearit); |
| 2369 | XSETSTRING (string, s); | 2389 | XSETSTRING (string, s); |
| 2370 | string_chars_consed += nbytes; | 2390 | string_chars_consed += nbytes; |
| 2371 | return string; | 2391 | return string; |
| 2372 | } | 2392 | } |
| 2373 | 2393 | ||
| 2394 | /* Return a multibyte Lisp_String set up to hold NCHARS characters | ||
| 2395 | which occupy NBYTES bytes. */ | ||
| 2396 | |||
| 2397 | Lisp_Object | ||
| 2398 | make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | ||
| 2399 | { | ||
| 2400 | return make_clear_multibyte_string (nchars, nbytes, false); | ||
| 2401 | } | ||
| 2402 | |||
| 2374 | /* Print arguments to BUF according to a FORMAT, then return | 2403 | /* Print arguments to BUF according to a FORMAT, then return |
| 2375 | a Lisp_String initialized with the data from BUF. */ | 2404 | a Lisp_String initialized with the data from BUF. */ |
| 2376 | 2405 | ||