comparison src/syntax.c @ 1296:87084e8445a7

[xemacs-hg @ 2003-02-14 09:50:15 by ben] syntax-table fixes 1. the updating of mirror tables every time a syntax table was modified was taking up huge amounts of time so i added a dirty flag and made the updating "just-in-time". 2. no-longer-used char-table-entries were not getting "freed", generating tons of garbage. 3. syntax_match() was being incorrectly called on mirror tables in the cache, not the original syntax table. buffer.c, syntax.c: Move syntax table description from buffer.c to syntax.c. chartab.c, chartab.h: Free extra char table entries to avoid excessive garbage. Add flags for dirty and mirror_table_p to char tables. Add a back pointer from mirror tables to the original syntax table. When modifying a syntax table, don't update the mirror table right away, just mark as dirty. Add various asserts to make sure we are dealing with the right type of table (mirror or non-mirror). font-lock.c, syntax.c, syntax.h: Add entry to syntax caches for the non-mirror table. Set it appropriately when initializing the syntax table. Use it, not the mirror table, for calls to syntax_match(). Don't create a bogus float each time, just once at startup. Add some asserts, as in chartab.c. syntax.h: When retrieving the syntax code, check the dirty flag and update the mirror tables as appropriate. Add some asserts, as above.
author ben
date Fri, 14 Feb 2003 09:50:17 +0000
parents 79c6ff3eef26
children 70921960b980
comparison
equal deleted inserted replaced
1295:064ef1d07d63 1296:87084e8445a7
1 /* XEmacs routines to deal with syntax tables; also word and list parsing. 1 /* XEmacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985-1994 Free Software Foundation, Inc. 2 Copyright (C) 1985-1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 2001, 2002 Ben Wing. 4 Copyright (C) 2001, 2002, 2003 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
7 7
8 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
83 Lisp_Object Vstandard_syntax_table; 83 Lisp_Object Vstandard_syntax_table;
84 84
85 Lisp_Object Vsyntax_designator_chars_string; 85 Lisp_Object Vsyntax_designator_chars_string;
86 86
87 Lisp_Object Vtemp_table_for_use_updating_syntax_tables; 87 Lisp_Object Vtemp_table_for_use_updating_syntax_tables;
88
89 /* A value that is guaranteed not be in a syntax table. */
90 Lisp_Object Vbogus_syntax_table_value;
88 91
89 static void syntax_cache_table_was_changed (struct buffer *buf); 92 static void syntax_cache_table_was_changed (struct buffer *buf);
90 93
91 /* This is the internal form of the parse state used in parse-partial-sexp. */ 94 /* This is the internal form of the parse state used in parse-partial-sexp. */
92 95
269 { 272 {
270 xzero (*cache); 273 xzero (*cache);
271 cache->object = object; 274 cache->object = object;
272 cache->buffer = buffer; 275 cache->buffer = buffer;
273 cache->no_syntax_table_prop = 1; 276 cache->no_syntax_table_prop = 1;
274 cache->current_syntax_table = 277 cache->syntax_table =
278 BUFFER_SYNTAX_TABLE (cache->buffer);
279 cache->mirror_table =
275 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); 280 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
276 cache->start = Qnil; 281 cache->start = Qnil;
277 cache->end = Qnil; 282 cache->end = Qnil;
278 if (infinite) 283 if (infinite)
279 { 284 {
306 from); 311 from);
307 } 312 }
308 if (!(from >= cache->prev_change && from < cache->next_change)) 313 if (!(from >= cache->prev_change && from < cache->next_change))
309 update_syntax_cache (cache, from, count); 314 update_syntax_cache (cache, from, count);
310 } 315 }
316 #ifdef NOT_WORTH_THE_EFFORT
317 update_mirror_syntax_if_dirty (cache->mirror_table);
318 #endif /* NOT_WORTH_THE_EFFORT */
311 return cache; 319 return cache;
312 } 320 }
313 321
314 struct syntax_cache * 322 struct syntax_cache *
315 setup_buffer_syntax_cache (struct buffer *buffer, Charxpos from, int count) 323 setup_buffer_syntax_cache (struct buffer *buffer, Charxpos from, int count)
316 { 324 {
317 return setup_syntax_cache (NULL, wrap_buffer (buffer), buffer, from, count); 325 return setup_syntax_cache (NULL, wrap_buffer (buffer), buffer, from, count);
318 } 326 }
327
328 static const struct memory_description syntax_cache_description_1 [] = {
329 { XD_LISP_OBJECT, offsetof (struct syntax_cache, object) },
330 { XD_LISP_OBJECT, offsetof (struct syntax_cache, buffer) },
331 { XD_LISP_OBJECT, offsetof (struct syntax_cache, syntax_table) },
332 { XD_LISP_OBJECT, offsetof (struct syntax_cache, mirror_table) },
333 { XD_LISP_OBJECT, offsetof (struct syntax_cache, start) },
334 { XD_LISP_OBJECT, offsetof (struct syntax_cache, end) },
335 { XD_END }
336 };
337
338 const struct sized_memory_description syntax_cache_description = {
339 sizeof (struct syntax_cache),
340 syntax_cache_description_1
341 };
319 342
320 void 343 void
321 mark_buffer_syntax_cache (struct buffer *buf) 344 mark_buffer_syntax_cache (struct buffer *buf)
322 { 345 {
323 struct syntax_cache *cache = buf->syntax_cache; 346 struct syntax_cache *cache = buf->syntax_cache;
324 if (!cache) /* Vbuffer_defaults and such don't have caches */ 347 if (!cache) /* Vbuffer_defaults and such don't have caches */
325 return; 348 return;
326 mark_object (cache->object); 349 mark_object (cache->object);
327 if (cache->buffer) 350 if (cache->buffer)
328 mark_object (wrap_buffer (cache->buffer)); 351 mark_object (wrap_buffer (cache->buffer));
329 mark_object (cache->current_syntax_table); 352 mark_object (cache->syntax_table);
353 mark_object (cache->mirror_table);
330 mark_object (cache->start); 354 mark_object (cache->start);
331 mark_object (cache->end); 355 mark_object (cache->end);
332 } 356 }
333 357
334 static void 358 static void
349 buf->syntax_cache = xnew_and_zero (struct syntax_cache); 373 buf->syntax_cache = xnew_and_zero (struct syntax_cache);
350 cache = buf->syntax_cache; 374 cache = buf->syntax_cache;
351 cache->object = wrap_buffer (buf); 375 cache->object = wrap_buffer (buf);
352 cache->buffer = buf; 376 cache->buffer = buf;
353 cache->no_syntax_table_prop = 1; 377 cache->no_syntax_table_prop = 1;
354 cache->current_syntax_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); 378 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer);
379 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
355 cache->start = Fmake_marker (); 380 cache->start = Fmake_marker ();
356 cache->end = Fmake_marker (); 381 cache->end = Fmake_marker ();
357 reset_buffer_cache_range (cache, cache->object); 382 reset_buffer_cache_range (cache, cache->object);
358 } 383 }
359 384
368 static void 393 static void
369 syntax_cache_table_was_changed (struct buffer *buf) 394 syntax_cache_table_was_changed (struct buffer *buf)
370 { 395 {
371 struct syntax_cache *cache = buf->syntax_cache; 396 struct syntax_cache *cache = buf->syntax_cache;
372 if (cache->no_syntax_table_prop) 397 if (cache->no_syntax_table_prop)
373 cache->current_syntax_table = 398 {
374 BUFFER_MIRROR_SYNTAX_TABLE (buf); 399 cache->syntax_table =
400 BUFFER_SYNTAX_TABLE (buf);
401 cache->mirror_table =
402 BUFFER_MIRROR_SYNTAX_TABLE (buf);
403 }
375 } 404 }
376 405
377 /* The syntax-table property on the range covered by EXTENT may be changing, 406 /* The syntax-table property on the range covered by EXTENT may be changing,
378 either because EXTENT has a syntax-table property and is being attached 407 either because EXTENT has a syntax-table property and is being attached
379 or detached (this includes having its endpoints changed), or because 408 or detached (this includes having its endpoints changed), or because
493 } 522 }
494 523
495 if (!NILP (Fsyntax_table_p (tmp_table))) 524 if (!NILP (Fsyntax_table_p (tmp_table)))
496 { 525 {
497 cache->use_code = 0; 526 cache->use_code = 0;
498 cache->current_syntax_table = 527 cache->syntax_table = tmp_table;
499 XCHAR_TABLE (tmp_table)->mirror_table; 528 cache->mirror_table = XCHAR_TABLE (tmp_table)->mirror_table;
500 cache->no_syntax_table_prop = 0; 529 cache->no_syntax_table_prop = 0;
530 #ifdef NOT_WORTH_THE_EFFORT
531 update_mirror_syntax_if_dirty (cache->mirror_table);
532 #endif /* NOT_WORTH_THE_EFFORT */
501 } 533 }
502 else if (CONSP (tmp_table) && INTP (XCAR (tmp_table))) 534 else if (CONSP (tmp_table) && INTP (XCAR (tmp_table)))
503 { 535 {
504 cache->use_code = 1; 536 cache->use_code = 1;
505 cache->syntax_code = XINT (XCAR (tmp_table)); 537 cache->syntax_code = XINT (XCAR (tmp_table));
507 } 539 }
508 else 540 else
509 { 541 {
510 cache->use_code = 0; 542 cache->use_code = 0;
511 cache->no_syntax_table_prop = 1; 543 cache->no_syntax_table_prop = 1;
512 cache->current_syntax_table = 544 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer);
513 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); 545 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
546 #ifdef NOT_WORTH_THE_EFFORT
547 update_mirror_syntax_if_dirty (cache->mirror_table);
548 #endif /* NOT_WORTH_THE_EFFORT */
514 } 549 }
515 } 550 }
516 551
517 /* Convert a letter which signifies a syntax code 552 /* Convert a letter which signifies a syntax code
518 into the code it signifies. 553 into the code it signifies.
1405 if (code != Sstring_fence) 1440 if (code != Sstring_fence)
1406 { 1441 {
1407 /* XEmacs change: call syntax_match on character */ 1442 /* XEmacs change: call syntax_match on character */
1408 Ichar ch = BUF_FETCH_CHAR (buf, from - 1); 1443 Ichar ch = BUF_FETCH_CHAR (buf, from - 1);
1409 Lisp_Object stermobj = 1444 Lisp_Object stermobj =
1410 syntax_match (scache->current_syntax_table, ch); 1445 syntax_match (scache->syntax_table, ch);
1411 1446
1412 if (CHARP (stermobj)) 1447 if (CHARP (stermobj))
1413 stringterm = XCHAR (stermobj); 1448 stringterm = XCHAR (stermobj);
1414 else 1449 else
1415 stringterm = ch; 1450 stringterm = ch;
1585 if (code != Sstring_fence) 1620 if (code != Sstring_fence)
1586 { 1621 {
1587 /* XEmacs change: call syntax_match() on character */ 1622 /* XEmacs change: call syntax_match() on character */
1588 Ichar ch = BUF_FETCH_CHAR (buf, from); 1623 Ichar ch = BUF_FETCH_CHAR (buf, from);
1589 Lisp_Object stermobj = 1624 Lisp_Object stermobj =
1590 syntax_match (scache->current_syntax_table, ch); 1625 syntax_match (scache->syntax_table, ch);
1591 1626
1592 if (CHARP (stermobj)) 1627 if (CHARP (stermobj))
1593 stringterm = XCHAR (stermobj); 1628 stringterm = XCHAR (stermobj);
1594 else 1629 else
1595 stringterm = ch; 1630 stringterm = ch;
2010 else 2045 else
2011 { 2046 {
2012 /* XEmacs change: call syntax_match() on character */ 2047 /* XEmacs change: call syntax_match() on character */
2013 Ichar ch = BUF_FETCH_CHAR (buf, from - 1); 2048 Ichar ch = BUF_FETCH_CHAR (buf, from - 1);
2014 Lisp_Object stermobj = 2049 Lisp_Object stermobj =
2015 syntax_match (scache->current_syntax_table, ch); 2050 syntax_match (scache->syntax_table, ch);
2016 2051
2017 if (CHARP (stermobj)) 2052 if (CHARP (stermobj))
2018 state.instring = XCHAR (stermobj); 2053 state.instring = XCHAR (stermobj);
2019 else 2054 else
2020 state.instring = ch; 2055 state.instring = ch;
2179 } 2214 }
2180 2215
2181 2216
2182 /* Updating of the mirror syntax table. 2217 /* Updating of the mirror syntax table.
2183 2218
2184 Each syntax table has a corresponding mirror table in it. 2219 Each syntax table has a corresponding mirror table in it. Whenever we
2185 Whenever we make a change to a syntax table, we call 2220 make a change to a syntax table, we set a dirty flag. When accessing a
2186 update_syntax_table() on it. 2221 value from the mirror table and the table is dirty, we call
2222 update_syntax_table() to clean it up.
2187 2223
2188 #### We really only need to map over the changed range. 2224 #### We really only need to map over the changed range.
2189 2225
2190 If we change the standard syntax table, we need to map over 2226 If we change the standard syntax table, we need to map over
2191 all tables because any of them could be inheriting from the 2227 all tables because any of them could be inheriting from the
2206 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit) 2242 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit)
2207 put_char_table (mirrortab, range, val); 2243 put_char_table (mirrortab, range, val);
2208 return 0; 2244 return 0;
2209 } 2245 }
2210 2246
2211 struct cinap
2212 {
2213 Lisp_Object mirrortab;
2214 Lisp_Object bogus;
2215 };
2216
2217 static int 2247 static int
2218 copy_if_not_already_present (struct chartab_range *range, Lisp_Object table, 2248 copy_if_not_already_present (struct chartab_range *range, Lisp_Object table,
2219 Lisp_Object val, void *arg) 2249 Lisp_Object val, void *arg)
2220 { 2250 {
2221 struct cinap *a = (struct cinap *) arg; 2251 Lisp_Object mirrortab = VOID_TO_LISP (arg);
2222
2223 if (CONSP (val)) 2252 if (CONSP (val))
2224 val = XCAR (val); 2253 val = XCAR (val);
2225 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit) 2254 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit)
2226 { 2255 {
2227 Lisp_Object existing = 2256 Lisp_Object existing =
2228 get_range_char_table (range, a->mirrortab, a->bogus); 2257 updating_mirror_get_range_char_table (range, mirrortab,
2258 Vbogus_syntax_table_value);
2229 if (NILP (existing)) 2259 if (NILP (existing))
2230 /* nothing at all */ 2260 /* nothing at all */
2231 put_char_table (a->mirrortab, range, val); 2261 put_char_table (mirrortab, range, val);
2232 else if (!EQ (existing, a->bogus)) 2262 else if (!EQ (existing, Vbogus_syntax_table_value))
2233 /* full */ 2263 /* full */
2234 ; 2264 ;
2235 else 2265 else
2236 { 2266 {
2237 Freset_char_table (Vtemp_table_for_use_updating_syntax_tables); 2267 Freset_char_table (Vtemp_table_for_use_updating_syntax_tables);
2238 copy_char_table_range 2268 copy_char_table_range
2239 (a->mirrortab, 2269 (mirrortab, Vtemp_table_for_use_updating_syntax_tables, range);
2240 Vtemp_table_for_use_updating_syntax_tables, 2270 put_char_table (mirrortab, range, val);
2241 range);
2242 put_char_table (a->mirrortab, range, val);
2243 copy_char_table_range 2271 copy_char_table_range
2244 (Vtemp_table_for_use_updating_syntax_tables, 2272 (Vtemp_table_for_use_updating_syntax_tables, mirrortab, range);
2245 a->mirrortab, range);
2246 } 2273 }
2247 } 2274 }
2248 2275
2249 return 0; 2276 return 0;
2250 } 2277 }
2253 update_just_this_syntax_table (Lisp_Object table) 2280 update_just_this_syntax_table (Lisp_Object table)
2254 { 2281 {
2255 struct chartab_range range; 2282 struct chartab_range range;
2256 Lisp_Object mirrortab = XCHAR_TABLE (table)->mirror_table; 2283 Lisp_Object mirrortab = XCHAR_TABLE (table)->mirror_table;
2257 2284
2285 assert (!XCHAR_TABLE (table)->mirror_table_p);
2258 range.type = CHARTAB_RANGE_ALL; 2286 range.type = CHARTAB_RANGE_ALL;
2259 Freset_char_table (mirrortab); 2287 Freset_char_table (mirrortab);
2288
2260 /* First, copy the tables values other than inherit into the mirror 2289 /* First, copy the tables values other than inherit into the mirror
2261 table. Then, for tables other than the standard syntax table, map 2290 table. Then, for tables other than the standard syntax table, map
2262 over the standard table, copying values into the mirror table only if 2291 over the standard table, copying values into the mirror table only if
2263 entries don't already exist in that table. (The copying step requires 2292 entries don't already exist in that table. (The copying step requires
2264 another mapping.) 2293 another mapping.)
2266 2295
2267 map_char_table (table, &range, copy_to_mirrortab, LISP_TO_VOID (mirrortab)); 2296 map_char_table (table, &range, copy_to_mirrortab, LISP_TO_VOID (mirrortab));
2268 /* second clause catches bootstrapping problems when initializing the 2297 /* second clause catches bootstrapping problems when initializing the
2269 standard syntax table */ 2298 standard syntax table */
2270 if (!EQ (table, Vstandard_syntax_table) && !NILP (Vstandard_syntax_table)) 2299 if (!EQ (table, Vstandard_syntax_table) && !NILP (Vstandard_syntax_table))
2271 { 2300 map_char_table (Vstandard_syntax_table, &range,
2272 struct cinap cinap; 2301 copy_if_not_already_present, LISP_TO_VOID (mirrortab));
2273 struct gcpro gcpro1;
2274 cinap.mirrortab = mirrortab;
2275 /* Something that won't be in the table. */
2276 cinap.bogus = make_float (0.0);
2277 GCPRO1 (cinap.bogus);
2278 map_char_table (Vstandard_syntax_table, &range,
2279 copy_if_not_already_present, &cinap);
2280 UNGCPRO;
2281 }
2282 /* The resetting made the default be Qnil. Put it back to Spunct. */ 2302 /* The resetting made the default be Qnil. Put it back to Spunct. */
2283 set_char_table_default (mirrortab, make_int (Spunct)); 2303 set_char_table_default (mirrortab, make_int (Spunct));
2304 XCHAR_TABLE (mirrortab)->dirty = 0;
2284 } 2305 }
2285 2306
2286 /* Called from chartab.c when a change is made to a syntax table. 2307 /* Called from chartab.c when a change is made to a syntax table.
2287 If this is the standard syntax table, we need to recompute 2308 If this is the standard syntax table, we need to recompute
2288 *all* syntax tables (yuck). Otherwise we just recompute this 2309 *all* syntax tables (yuck). Otherwise we just recompute this
2289 one. */ 2310 one. */
2290 2311
2291 void 2312 void
2292 update_syntax_table (Lisp_Object table) 2313 update_syntax_table (Lisp_Object table)
2293 { 2314 {
2294 if (EQ (table, Vstandard_syntax_table)) 2315 Lisp_Object nonmirror = XCHAR_TABLE (table)->mirror_table;
2316 assert (XCHAR_TABLE (table)->mirror_table_p);
2317 if (EQ (nonmirror, Vstandard_syntax_table))
2295 { 2318 {
2296 Lisp_Object syntab; 2319 Lisp_Object syntab;
2297 2320
2298 for (syntab = Vall_syntax_tables; !NILP (syntab); 2321 for (syntab = Vall_syntax_tables; !NILP (syntab);
2299 syntab = XCHAR_TABLE (syntab)->next_table) 2322 syntab = XCHAR_TABLE (syntab)->next_table)
2300 update_just_this_syntax_table (syntab); 2323 update_just_this_syntax_table (syntab);
2301 } 2324 }
2302 else 2325 else
2303 update_just_this_syntax_table (table); 2326 update_just_this_syntax_table (nonmirror);
2304 } 2327 }
2305 2328
2306 2329
2307 /************************************************************************/ 2330 /************************************************************************/
2308 /* initialization */ 2331 /* initialization */
2363 Non-nil means `forward-word', etc., should treat escape chars part of words. 2386 Non-nil means `forward-word', etc., should treat escape chars part of words.
2364 */ ); 2387 */ );
2365 words_include_escapes = 0; 2388 words_include_escapes = 0;
2366 2389
2367 no_quit_in_re_search = 0; 2390 no_quit_in_re_search = 0;
2391
2392 Vbogus_syntax_table_value = make_float (0.0);
2393 staticpro (&Vbogus_syntax_table_value);
2368 } 2394 }
2369 2395
2370 static void 2396 static void
2371 define_standard_syntax (const char *p, enum syntaxcode syn) 2397 define_standard_syntax (const char *p, enum syntaxcode syn)
2372 { 2398 {