aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-12-08 11:32:48 -0800
committerPaul Eggert2016-12-08 13:00:32 -0800
commitf0a1e9ec3fba3d5bea5bd62f525dba3fb005d1b1 (patch)
treed4d752498b6da8154e6d3cf8dfed94643ae67614 /src
parent162ba405ac144c2a0cb6854f791ff7d3203b0e2f (diff)
downloademacs-f0a1e9ec3fba3d5bea5bd62f525dba3fb005d1b1.tar.gz
emacs-f0a1e9ec3fba3d5bea5bd62f525dba3fb005d1b1.zip
Make read1 more reentrant
This is needed if ‘read’ is called soon after startup, before the Unicode tables have been set up, and it reads a \N escape and needs to look up a value the Unicode tables, a lookup that in turn calls read1 recursively. Although this change doesn’t make ‘read’ fully reentrant, it’s good enough to handle this case. * src/lread.c (read_buffer_size, read_buffer): Remove static vars. (grow_read_buffer): Revamp to use locals, not statics, and to record memory allocation un the specpdl. All callers changed. (read1): Start with a stack-based buffer, and use the heap only if the stack buffer is too small. Use unbind_to to free any heap buffer allocated. Use bool for boolean. Redo symbol loop so that only one call to grow_read_buffer is needed. (init_obarray): Remove no-longer-needed initialization.
Diffstat (limited to 'src')
-rw-r--r--src/lread.c203
1 files changed, 106 insertions, 97 deletions
diff --git a/src/lread.c b/src/lread.c
index 1335ccfea78..157a392a158 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2144,16 +2144,28 @@ read0 (Lisp_Object readcharfun)
2144 Fmake_string (make_number (1), make_number (c))); 2144 Fmake_string (make_number (1), make_number (c)));
2145} 2145}
2146 2146
2147static ptrdiff_t read_buffer_size; 2147/* Grow a read buffer BUF that contains OFFSET useful bytes of data,
2148static char *read_buffer; 2148 by at least MAX_MULTIBYTE_LENGTH bytes. Update *BUF_ADDR and
2149 2149 *BUF_SIZE accordingly; 0 <= OFFSET <= *BUF_SIZE. If *BUF_ADDR is
2150/* Grow the read buffer by at least MAX_MULTIBYTE_LENGTH bytes. */ 2150 initially null, BUF is on the stack: copy its data to the new heap
2151 2151 buffer. Otherwise, BUF must equal *BUF_ADDR and can simply be
2152static void 2152 reallocated. Either way, remember the heap allocation (which is at
2153grow_read_buffer (void) 2153 pdl slot COUNT) so that it can be freed when unwinding the stack.*/
2154
2155static char *
2156grow_read_buffer (char *buf, ptrdiff_t offset,
2157 char **buf_addr, ptrdiff_t *buf_size, ptrdiff_t count)
2154{ 2158{
2155 read_buffer = xpalloc (read_buffer, &read_buffer_size, 2159 char *p = xpalloc (*buf_addr, buf_size, MAX_MULTIBYTE_LENGTH, -1, 1);
2156 MAX_MULTIBYTE_LENGTH, -1, 1); 2160 if (!*buf_addr)
2161 {
2162 memcpy (p, buf, offset);
2163 record_unwind_protect_ptr (xfree, p);
2164 }
2165 else
2166 set_unwind_protect_ptr (count, xfree, p);
2167 *buf_addr = p;
2168 return p;
2157} 2169}
2158 2170
2159/* Return the scalar value that has the Unicode character name NAME. 2171/* Return the scalar value that has the Unicode character name NAME.
@@ -2432,6 +2444,9 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2432 if (length == 0) 2444 if (length == 0)
2433 invalid_syntax ("Empty character name"); 2445 invalid_syntax ("Empty character name");
2434 name[length] = '\0'; 2446 name[length] = '\0';
2447
2448 /* character_name_to_code can invoke read1, recursively.
2449 This is why read1's buffer is not static. */
2435 return character_name_to_code (name, length); 2450 return character_name_to_code (name, length);
2436 } 2451 }
2437 2452
@@ -2541,8 +2556,9 @@ static Lisp_Object
2541read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) 2556read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2542{ 2557{
2543 int c; 2558 int c;
2544 bool uninterned_symbol = 0; 2559 bool uninterned_symbol = false;
2545 bool multibyte; 2560 bool multibyte;
2561 char stackbuf[MAX_ALLOCA];
2546 2562
2547 *pch = 0; 2563 *pch = 0;
2548 2564
@@ -2873,7 +2889,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2873 /* #:foo is the uninterned symbol named foo. */ 2889 /* #:foo is the uninterned symbol named foo. */
2874 if (c == ':') 2890 if (c == ':')
2875 { 2891 {
2876 uninterned_symbol = 1; 2892 uninterned_symbol = true;
2877 c = READCHAR; 2893 c = READCHAR;
2878 if (!(c > 040 2894 if (!(c > 040
2879 && c != NO_BREAK_SPACE 2895 && c != NO_BREAK_SPACE
@@ -3084,16 +3100,20 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3084 3100
3085 case '"': 3101 case '"':
3086 { 3102 {
3103 ptrdiff_t count = SPECPDL_INDEX ();
3104 char *read_buffer = stackbuf;
3105 ptrdiff_t read_buffer_size = sizeof stackbuf;
3106 char *heapbuf = NULL;
3087 char *p = read_buffer; 3107 char *p = read_buffer;
3088 char *end = read_buffer + read_buffer_size; 3108 char *end = read_buffer + read_buffer_size;
3089 int ch; 3109 int ch;
3090 /* True if we saw an escape sequence specifying 3110 /* True if we saw an escape sequence specifying
3091 a multibyte character. */ 3111 a multibyte character. */
3092 bool force_multibyte = 0; 3112 bool force_multibyte = false;
3093 /* True if we saw an escape sequence specifying 3113 /* True if we saw an escape sequence specifying
3094 a single-byte character. */ 3114 a single-byte character. */
3095 bool force_singlebyte = 0; 3115 bool force_singlebyte = false;
3096 bool cancel = 0; 3116 bool cancel = false;
3097 ptrdiff_t nchars = 0; 3117 ptrdiff_t nchars = 0;
3098 3118
3099 while ((ch = READCHAR) >= 0 3119 while ((ch = READCHAR) >= 0
@@ -3102,7 +3122,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3102 if (end - p < MAX_MULTIBYTE_LENGTH) 3122 if (end - p < MAX_MULTIBYTE_LENGTH)
3103 { 3123 {
3104 ptrdiff_t offset = p - read_buffer; 3124 ptrdiff_t offset = p - read_buffer;
3105 grow_read_buffer (); 3125 read_buffer = grow_read_buffer (read_buffer, offset,
3126 &heapbuf, &read_buffer_size,
3127 count);
3106 p = read_buffer + offset; 3128 p = read_buffer + offset;
3107 end = read_buffer + read_buffer_size; 3129 end = read_buffer + read_buffer_size;
3108 } 3130 }
@@ -3117,7 +3139,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3117 if (ch == -1) 3139 if (ch == -1)
3118 { 3140 {
3119 if (p == read_buffer) 3141 if (p == read_buffer)
3120 cancel = 1; 3142 cancel = true;
3121 continue; 3143 continue;
3122 } 3144 }
3123 3145
@@ -3125,9 +3147,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3125 ch = ch & ~CHAR_MODIFIER_MASK; 3147 ch = ch & ~CHAR_MODIFIER_MASK;
3126 3148
3127 if (CHAR_BYTE8_P (ch)) 3149 if (CHAR_BYTE8_P (ch))
3128 force_singlebyte = 1; 3150 force_singlebyte = true;
3129 else if (! ASCII_CHAR_P (ch)) 3151 else if (! ASCII_CHAR_P (ch))
3130 force_multibyte = 1; 3152 force_multibyte = true;
3131 else /* I.e. ASCII_CHAR_P (ch). */ 3153 else /* I.e. ASCII_CHAR_P (ch). */
3132 { 3154 {
3133 /* Allow `\C- ' and `\C-?'. */ 3155 /* Allow `\C- ' and `\C-?'. */
@@ -3153,7 +3175,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3153 string. */ 3175 string. */
3154 modifiers &= ~CHAR_META; 3176 modifiers &= ~CHAR_META;
3155 ch = BYTE8_TO_CHAR (ch | 0x80); 3177 ch = BYTE8_TO_CHAR (ch | 0x80);
3156 force_singlebyte = 1; 3178 force_singlebyte = true;
3157 } 3179 }
3158 } 3180 }
3159 3181
@@ -3166,9 +3188,9 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3166 { 3188 {
3167 p += CHAR_STRING (ch, (unsigned char *) p); 3189 p += CHAR_STRING (ch, (unsigned char *) p);
3168 if (CHAR_BYTE8_P (ch)) 3190 if (CHAR_BYTE8_P (ch))
3169 force_singlebyte = 1; 3191 force_singlebyte = true;
3170 else if (! ASCII_CHAR_P (ch)) 3192 else if (! ASCII_CHAR_P (ch))
3171 force_multibyte = 1; 3193 force_multibyte = true;
3172 } 3194 }
3173 nchars++; 3195 nchars++;
3174 } 3196 }
@@ -3180,7 +3202,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3180 return zero instead. This is for doc strings 3202 return zero instead. This is for doc strings
3181 that we are really going to find in etc/DOC.nn.nn. */ 3203 that we are really going to find in etc/DOC.nn.nn. */
3182 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel) 3204 if (!NILP (Vpurify_flag) && NILP (Vdoc_file_name) && cancel)
3183 return make_number (0); 3205 return unbind_to (count, make_number (0));
3184 3206
3185 if (! force_multibyte && force_singlebyte) 3207 if (! force_multibyte && force_singlebyte)
3186 { 3208 {
@@ -3191,9 +3213,11 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3191 p = read_buffer + nchars; 3213 p = read_buffer + nchars;
3192 } 3214 }
3193 3215
3194 return make_specified_string (read_buffer, nchars, p - read_buffer, 3216 Lisp_Object result
3195 (force_multibyte 3217 = make_specified_string (read_buffer, nchars, p - read_buffer,
3196 || (p - read_buffer != nchars))); 3218 (force_multibyte
3219 || (p - read_buffer != nchars)));
3220 return unbind_to (count, result);
3197 } 3221 }
3198 3222
3199 case '.': 3223 case '.':
@@ -3221,81 +3245,74 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3221 3245
3222 read_symbol: 3246 read_symbol:
3223 { 3247 {
3248 ptrdiff_t count = SPECPDL_INDEX ();
3249 char *read_buffer = stackbuf;
3250 ptrdiff_t read_buffer_size = sizeof stackbuf;
3251 char *heapbuf = NULL;
3224 char *p = read_buffer; 3252 char *p = read_buffer;
3225 bool quoted = 0; 3253 char *end = read_buffer + read_buffer_size;
3254 bool quoted = false;
3226 EMACS_INT start_position = readchar_count - 1; 3255 EMACS_INT start_position = readchar_count - 1;
3227 3256
3228 { 3257 do
3229 char *end = read_buffer + read_buffer_size; 3258 {
3230 3259 if (end - p < MAX_MULTIBYTE_LENGTH + 1)
3231 do 3260 {
3232 { 3261 ptrdiff_t offset = p - read_buffer;
3233 if (end - p < MAX_MULTIBYTE_LENGTH) 3262 read_buffer = grow_read_buffer (read_buffer, offset,
3234 { 3263 &heapbuf, &read_buffer_size,
3235 ptrdiff_t offset = p - read_buffer; 3264 count);
3236 grow_read_buffer (); 3265 p = read_buffer + offset;
3237 p = read_buffer + offset; 3266 end = read_buffer + read_buffer_size;
3238 end = read_buffer + read_buffer_size; 3267 }
3239 }
3240 3268
3241 if (c == '\\') 3269 if (c == '\\')
3242 { 3270 {
3243 c = READCHAR; 3271 c = READCHAR;
3244 if (c == -1) 3272 if (c == -1)
3245 end_of_file_error (); 3273 end_of_file_error ();
3246 quoted = 1; 3274 quoted = true;
3247 } 3275 }
3248 3276
3249 if (multibyte) 3277 if (multibyte)
3250 p += CHAR_STRING (c, (unsigned char *) p); 3278 p += CHAR_STRING (c, (unsigned char *) p);
3251 else 3279 else
3252 *p++ = c; 3280 *p++ = c;
3253 c = READCHAR; 3281 c = READCHAR;
3254 } 3282 }
3255 while (c > 040 3283 while (c > 040
3256 && c != NO_BREAK_SPACE 3284 && c != NO_BREAK_SPACE
3257 && (c >= 0200 3285 && (c >= 0200
3258 || strchr ("\"';()[]#`,", c) == NULL)); 3286 || strchr ("\"';()[]#`,", c) == NULL));
3259 3287
3260 if (p == end) 3288 *p = 0;
3261 { 3289 UNREAD (c);
3262 ptrdiff_t offset = p - read_buffer;
3263 grow_read_buffer ();
3264 p = read_buffer + offset;
3265 end = read_buffer + read_buffer_size;
3266 }
3267 *p = 0;
3268 UNREAD (c);
3269 }
3270 3290
3271 if (!quoted && !uninterned_symbol) 3291 if (!quoted && !uninterned_symbol)
3272 { 3292 {
3273 Lisp_Object result = string_to_number (read_buffer, 10, 0); 3293 Lisp_Object result = string_to_number (read_buffer, 10, 0);
3274 if (! NILP (result)) 3294 if (! NILP (result))
3275 return result; 3295 return unbind_to (count, result);
3276 } 3296 }
3277 { 3297
3278 Lisp_Object name, result; 3298 ptrdiff_t nbytes = p - read_buffer;
3279 ptrdiff_t nbytes = p - read_buffer; 3299 ptrdiff_t nchars
3280 ptrdiff_t nchars 3300 = (multibyte
3281 = (multibyte 3301 ? multibyte_chars_in_text ((unsigned char *) read_buffer,
3282 ? multibyte_chars_in_text ((unsigned char *) read_buffer, 3302 nbytes)
3283 nbytes) 3303 : nbytes);
3284 : nbytes); 3304 Lisp_Object name = ((uninterned_symbol && ! NILP (Vpurify_flag)
3285 3305 ? make_pure_string : make_specified_string)
3286 name = ((uninterned_symbol && ! NILP (Vpurify_flag) 3306 (read_buffer, nchars, nbytes, multibyte));
3287 ? make_pure_string : make_specified_string) 3307 Lisp_Object result = (uninterned_symbol ? Fmake_symbol (name)
3288 (read_buffer, nchars, nbytes, multibyte)); 3308 : Fintern (name, Qnil));
3289 result = (uninterned_symbol ? Fmake_symbol (name) 3309
3290 : Fintern (name, Qnil)); 3310 if (EQ (Vread_with_symbol_positions, Qt)
3291 3311 || EQ (Vread_with_symbol_positions, readcharfun))
3292 if (EQ (Vread_with_symbol_positions, Qt) 3312 Vread_symbol_positions_list
3293 || EQ (Vread_with_symbol_positions, readcharfun)) 3313 = Fcons (Fcons (result, make_number (start_position)),
3294 Vread_symbol_positions_list 3314 Vread_symbol_positions_list);
3295 = Fcons (Fcons (result, make_number (start_position)), 3315 return unbind_to (count, result);
3296 Vread_symbol_positions_list);
3297 return result;
3298 }
3299 } 3316 }
3300 } 3317 }
3301} 3318}
@@ -4104,12 +4121,7 @@ OBARRAY defaults to the value of `obarray'. */)
4104void 4121void
4105init_obarray (void) 4122init_obarray (void)
4106{ 4123{
4107 Lisp_Object oblength; 4124 Vobarray = Fmake_vector (make_number (OBARRAY_SIZE), make_number (0));
4108 ptrdiff_t size = 100 + MAX_MULTIBYTE_LENGTH;
4109
4110 XSETFASTINT (oblength, OBARRAY_SIZE);
4111
4112 Vobarray = Fmake_vector (oblength, make_number (0));
4113 initial_obarray = Vobarray; 4125 initial_obarray = Vobarray;
4114 staticpro (&initial_obarray); 4126 staticpro (&initial_obarray);
4115 4127
@@ -4132,9 +4144,6 @@ init_obarray (void)
4132 Vpurify_flag = Qt; 4144 Vpurify_flag = Qt;
4133 4145
4134 DEFSYM (Qvariable_documentation, "variable-documentation"); 4146 DEFSYM (Qvariable_documentation, "variable-documentation");
4135
4136 read_buffer = xmalloc (size);
4137 read_buffer_size = size;
4138} 4147}
4139 4148
4140void 4149void