Mercurial > hg > xemacs-beta
annotate src/syntax.c @ 5125:b5df3737028a ben-lisp-object
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 24 Feb 2010 01:58:04 -0600 |
parents | d1247f3cc363 ae48681c47fa |
children | 2a462149bd6a |
rev | line source |
---|---|
428 | 1 /* XEmacs routines to deal with syntax tables; also word and list parsing. |
2 Copyright (C) 1985-1994 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
1296 | 4 Copyright (C) 2001, 2002, 2003 Ben Wing. |
428 | 5 |
6 This file is part of XEmacs. | |
7 | |
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 | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: FSF 19.28. */ | |
24 | |
25 /* This file has been Mule-ized. */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
30 #include "buffer.h" | |
31 #include "syntax.h" | |
460 | 32 #include "extents.h" |
428 | 33 |
4710
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
34 #ifdef NEW_GC |
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
35 # define UNUSED_IF_NEW_GC(decl) UNUSED (decl) |
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
36 #else |
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
37 # define UNUSED_IF_NEW_GC(decl) decl |
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
38 #endif |
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
39 |
460 | 40 #define ST_COMMENT_STYLE 0x101 |
41 #define ST_STRING_STYLE 0x102 | |
42 | |
43 Lisp_Object Qsyntax_table; | |
44 int lookup_syntax_properties; | |
45 | |
428 | 46 Lisp_Object Qsyntax_table_p; |
47 | |
48 int words_include_escapes; | |
49 | |
50 int parse_sexp_ignore_comments; | |
51 | |
52 /* The following two variables are provided to tell additional information | |
53 to the regex routines. We do it this way rather than change the | |
54 arguments to re_search_2() in an attempt to maintain some call | |
55 compatibility with other versions of the regex code. */ | |
56 | |
57 /* Tell the regex routines not to QUIT. Normally there is a QUIT | |
58 each iteration in re_search_2(). */ | |
59 int no_quit_in_re_search; | |
60 | |
826 | 61 /* The standard syntax table is stored where it will automatically |
62 be used in all new buffers. */ | |
428 | 63 Lisp_Object Vstandard_syntax_table; |
64 | |
65 Lisp_Object Vsyntax_designator_chars_string; | |
66 | |
826 | 67 Lisp_Object Vtemp_table_for_use_updating_syntax_tables; |
68 | |
1296 | 69 /* A value that is guaranteed not be in a syntax table. */ |
70 Lisp_Object Vbogus_syntax_table_value; | |
71 | |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
72 Lisp_Object Qscan_error; |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
73 |
826 | 74 static void syntax_cache_table_was_changed (struct buffer *buf); |
75 | |
428 | 76 /* This is the internal form of the parse state used in parse-partial-sexp. */ |
77 | |
78 struct lisp_parse_state | |
79 { | |
80 int depth; /* Depth at end of parsing */ | |
867 | 81 Ichar instring; /* -1 if not within string, else desired terminator */ |
428 | 82 int incomment; /* Nonzero if within a comment at end of parsing */ |
460 | 83 int comstyle; /* comment style a=0, or b=1, or ST_COMMENT_STYLE */ |
428 | 84 int quoted; /* Nonzero if just after an escape char at end of |
85 parsing */ | |
665 | 86 Charbpos thislevelstart;/* Char number of most recent start-of-expression |
428 | 87 at current level */ |
665 | 88 Charbpos prevlevelstart;/* Char number of start of containing expression */ |
89 Charbpos location; /* Char number at which parsing stopped */ | |
428 | 90 int mindepth; /* Minimum depth seen while scanning */ |
826 | 91 Charbpos comstr_start;/* Position just after last comment/string starter */ |
92 Lisp_Object levelstarts;/* Char numbers of starts-of-expression | |
93 of levels (starting from outermost). */ | |
428 | 94 }; |
95 | |
96 /* These variables are a cache for finding the start of a defun. | |
97 find_start_pos is the place for which the defun start was found. | |
98 find_start_value is the defun start position found for it. | |
99 find_start_buffer is the buffer it was found in. | |
100 find_start_begv is the BEGV value when it was found. | |
101 find_start_modiff is the value of MODIFF when it was found. */ | |
102 | |
665 | 103 static Charbpos find_start_pos; |
104 static Charbpos find_start_value; | |
428 | 105 static struct buffer *find_start_buffer; |
665 | 106 static Charbpos find_start_begv; |
428 | 107 static int find_start_modiff; |
108 | |
109 /* Find a defun-start that is the last one before POS (or nearly the last). | |
110 We record what we find, so that another call in the same area | |
111 can return the same value right away. */ | |
112 | |
665 | 113 static Charbpos |
114 find_defun_start (struct buffer *buf, Charbpos pos) | |
428 | 115 { |
665 | 116 Charbpos tem; |
826 | 117 struct syntax_cache *scache; |
118 | |
428 | 119 /* Use previous finding, if it's valid and applies to this inquiry. */ |
120 if (buf == find_start_buffer | |
121 /* Reuse the defun-start even if POS is a little farther on. | |
122 POS might be in the next defun, but that's ok. | |
123 Our value may not be the best possible, but will still be usable. */ | |
124 && pos <= find_start_pos + 1000 | |
125 && pos >= find_start_value | |
126 && BUF_BEGV (buf) == find_start_begv | |
127 && BUF_MODIFF (buf) == find_start_modiff) | |
128 return find_start_value; | |
129 | |
130 /* Back up to start of line. */ | |
131 tem = find_next_newline (buf, pos, -1); | |
132 | |
826 | 133 scache = setup_buffer_syntax_cache (buf, tem, 1); |
428 | 134 while (tem > BUF_BEGV (buf)) |
135 { | |
826 | 136 UPDATE_SYNTAX_CACHE_BACKWARD (scache, tem); |
460 | 137 |
428 | 138 /* Open-paren at start of line means we found our defun-start. */ |
826 | 139 if (SYNTAX_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, tem)) == Sopen) |
428 | 140 break; |
141 /* Move to beg of previous line. */ | |
142 tem = find_next_newline (buf, tem, -2); | |
143 } | |
144 | |
145 /* Record what we found, for the next try. */ | |
146 find_start_value = tem; | |
147 find_start_buffer = buf; | |
148 find_start_modiff = BUF_MODIFF (buf); | |
149 find_start_begv = BUF_BEGV (buf); | |
150 find_start_pos = pos; | |
151 | |
152 return find_start_value; | |
153 } | |
154 | |
155 DEFUN ("syntax-table-p", Fsyntax_table_p, 1, 1, 0, /* | |
444 | 156 Return t if OBJECT is a syntax table. |
428 | 157 */ |
444 | 158 (object)) |
428 | 159 { |
444 | 160 return (CHAR_TABLEP (object) |
161 && XCHAR_TABLE_TYPE (object) == CHAR_TABLE_TYPE_SYNTAX) | |
428 | 162 ? Qt : Qnil; |
163 } | |
164 | |
165 static Lisp_Object | |
166 check_syntax_table (Lisp_Object obj, Lisp_Object default_) | |
167 { | |
168 if (NILP (obj)) | |
169 obj = default_; | |
170 while (NILP (Fsyntax_table_p (obj))) | |
171 obj = wrong_type_argument (Qsyntax_table_p, obj); | |
172 return obj; | |
173 } | |
174 | |
175 DEFUN ("syntax-table", Fsyntax_table, 0, 1, 0, /* | |
176 Return the current syntax table. | |
177 This is the one specified by the current buffer, or by BUFFER if it | |
178 is non-nil. | |
179 */ | |
180 (buffer)) | |
181 { | |
182 return decode_buffer (buffer, 0)->syntax_table; | |
183 } | |
184 | |
826 | 185 #ifdef DEBUG_XEMACS |
186 | |
187 DEFUN ("mirror-syntax-table", Fmirror_syntax_table, 0, 1, 0, /* | |
188 Return the current mirror syntax table, for debugging purposes. | |
189 This is the one specified by the current buffer, or by BUFFER if it | |
190 is non-nil. | |
191 */ | |
192 (buffer)) | |
193 { | |
194 return decode_buffer (buffer, 0)->mirror_syntax_table; | |
195 } | |
196 | |
197 DEFUN ("syntax-cache-info", Fsyntax_cache_info, 0, 1, 0, /* | |
198 Return info about the syntax cache in BUFFER. | |
199 BUFFER defaults to the current buffer if nil. | |
200 */ | |
201 (buffer)) | |
202 { | |
203 struct buffer *buf = decode_buffer (buffer, 0); | |
204 struct syntax_cache *cache = buf->syntax_cache; | |
205 return list4 (cache->start, cache->end, make_int (cache->prev_change), | |
206 make_int (cache->next_change)); | |
207 } | |
208 | |
209 #endif /* DEBUG_XEMACS */ | |
210 | |
428 | 211 DEFUN ("standard-syntax-table", Fstandard_syntax_table, 0, 0, 0, /* |
212 Return the standard syntax table. | |
213 This is the one used for new buffers. | |
214 */ | |
215 ()) | |
216 { | |
217 return Vstandard_syntax_table; | |
218 } | |
219 | |
220 DEFUN ("copy-syntax-table", Fcopy_syntax_table, 0, 1, 0, /* | |
444 | 221 Return a new syntax table which is a copy of SYNTAX-TABLE. |
222 SYNTAX-TABLE defaults to the standard syntax table. | |
428 | 223 */ |
444 | 224 (syntax_table)) |
428 | 225 { |
226 if (NILP (Vstandard_syntax_table)) | |
227 return Fmake_char_table (Qsyntax); | |
228 | |
444 | 229 syntax_table = check_syntax_table (syntax_table, Vstandard_syntax_table); |
230 return Fcopy_char_table (syntax_table); | |
428 | 231 } |
232 | |
233 DEFUN ("set-syntax-table", Fset_syntax_table, 1, 2, 0, /* | |
444 | 234 Select SYNTAX-TABLE as the new syntax table for BUFFER. |
428 | 235 BUFFER defaults to the current buffer if omitted. |
236 */ | |
444 | 237 (syntax_table, buffer)) |
428 | 238 { |
239 struct buffer *buf = decode_buffer (buffer, 0); | |
444 | 240 syntax_table = check_syntax_table (syntax_table, Qnil); |
241 buf->syntax_table = syntax_table; | |
242 buf->mirror_syntax_table = XCHAR_TABLE (syntax_table)->mirror_table; | |
826 | 243 syntax_cache_table_was_changed (buf); |
428 | 244 /* Indicate that this buffer now has a specified syntax table. */ |
245 buf->local_var_flags |= XINT (buffer_local_flags.syntax_table); | |
444 | 246 return syntax_table; |
428 | 247 } |
3252 | 248 |
249 | |
428 | 250 |
3252 | 251 /* |
252 * Syntax caching | |
253 */ | |
254 | |
255 /* syntax_cache object implementation */ | |
256 | |
257 static const struct memory_description syntax_cache_description_1 [] = { | |
258 { XD_LISP_OBJECT, offsetof (struct syntax_cache, object) }, | |
259 { XD_LISP_OBJECT, offsetof (struct syntax_cache, buffer) }, | |
260 { XD_LISP_OBJECT, offsetof (struct syntax_cache, syntax_table) }, | |
261 { XD_LISP_OBJECT, offsetof (struct syntax_cache, mirror_table) }, | |
262 { XD_LISP_OBJECT, offsetof (struct syntax_cache, start) }, | |
263 { XD_LISP_OBJECT, offsetof (struct syntax_cache, end) }, | |
264 { XD_END } | |
265 }; | |
266 | |
267 #ifdef NEW_GC | |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
268 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("syntax-cache", syntax_cache, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
269 0, syntax_cache_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
270 Lisp_Syntax_Cache); |
3252 | 271 #else /* not NEW_GC */ |
272 | |
273 const struct sized_memory_description syntax_cache_description = { | |
274 sizeof (struct syntax_cache), | |
275 syntax_cache_description_1 | |
276 }; | |
277 #endif /* not NEW_GC */ | |
278 | |
279 /* static syntax cache utilities */ | |
280 | |
281 static void | |
282 syntax_cache_table_was_changed (struct buffer *buf) | |
283 { | |
284 struct syntax_cache *cache = buf->syntax_cache; | |
285 if (cache->no_syntax_table_prop) | |
286 { | |
287 cache->syntax_table = | |
288 BUFFER_SYNTAX_TABLE (buf); | |
289 cache->mirror_table = | |
290 BUFFER_MIRROR_SYNTAX_TABLE (buf); | |
291 } | |
292 } | |
293 | |
294 static void | |
295 reset_buffer_syntax_cache_range (struct syntax_cache *cache, | |
296 Lisp_Object buffer, int infinite) | |
297 { | |
298 Fset_marker (cache->start, make_int (1), buffer); | |
299 Fset_marker (cache->end, make_int (1), buffer); | |
300 Fset_marker_insertion_type (cache->start, Qt); | |
301 Fset_marker_insertion_type (cache->end, Qnil); | |
302 /* #### Should we "cache->no_syntax_table_prop = 1;" here? */ | |
303 /* #### Cf comment on INFINITE in init_syntax_cache. -- sjt */ | |
304 if (infinite) | |
305 { | |
306 cache->prev_change = EMACS_INT_MIN; | |
307 cache->next_change = EMACS_INT_MAX; | |
308 } | |
309 else | |
310 { | |
311 cache->prev_change = -1; | |
312 cache->next_change = -1; | |
313 } | |
314 } | |
826 | 315 |
316 static void | |
317 init_syntax_cache (struct syntax_cache *cache, Lisp_Object object, | |
318 struct buffer *buffer, int infinite) | |
319 { | |
320 xzero (*cache); | |
321 cache->object = object; | |
322 cache->buffer = buffer; | |
323 cache->no_syntax_table_prop = 1; | |
1296 | 324 cache->syntax_table = |
325 BUFFER_SYNTAX_TABLE (cache->buffer); | |
326 cache->mirror_table = | |
826 | 327 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); |
328 cache->start = Qnil; | |
329 cache->end = Qnil; | |
3250 | 330 /* #### I'm not sure what INFINITE is for, but it's apparently needed by |
331 setup_syntax_cache(). It looks like it's supposed to guarantee that | |
332 the test for POS outside of cache-valid range will never succeed, so | |
333 that update_syntax_cache won't get called, but it's hard to be sure. | |
334 Cf reset_buffer_syntax_cache_range. -- sjt */ | |
826 | 335 if (infinite) |
336 { | |
337 cache->prev_change = EMACS_INT_MIN; | |
338 cache->next_change = EMACS_INT_MAX; | |
339 } | |
340 else | |
341 { | |
342 cache->prev_change = -1; | |
343 cache->next_change = -1; | |
344 } | |
345 } | |
346 | |
3252 | 347 /* external syntax cache API */ |
348 | |
3250 | 349 /* #### This function and associated logic still needs work, and especially |
350 documentation. */ | |
351 struct syntax_cache * /* return CACHE or the cache of OBJECT */ | |
352 setup_syntax_cache (struct syntax_cache *cache, /* syntax cache, may be NULL | |
353 if OBJECT is a buffer */ | |
354 Lisp_Object object, /* the object (if any) cache | |
355 is associated with */ | |
356 struct buffer *buffer, /* the buffer to use as source | |
357 of the syntax table */ | |
358 Charxpos from, /* initial position of cache */ | |
359 int count) /* direction? see code */ | |
826 | 360 { |
3250 | 361 /* If OBJECT is a buffer, use its cache. Initialize cache. Make it valid |
362 for the whole buffer if the syntax-table property is not being respected. | |
363 Else if OBJECT is not a buffer, initialize the cache passed in CACHE. | |
364 If the syntax-table property is being respected, update the cache. */ | |
826 | 365 if (BUFFERP (object)) |
3250 | 366 { |
367 cache = XBUFFER (object)->syntax_cache; | |
368 if (!lookup_syntax_properties) | |
369 reset_buffer_syntax_cache_range (cache, object, 1); | |
370 } | |
371 else | |
826 | 372 init_syntax_cache (cache, object, buffer, 0); |
373 if (lookup_syntax_properties) | |
374 { | |
375 if (count <= 0) | |
376 { | |
377 from--; | |
2167 | 378 from = buffer_or_string_clip_to_accessible_char (cache->object, |
826 | 379 from); |
380 } | |
381 if (!(from >= cache->prev_change && from < cache->next_change)) | |
382 update_syntax_cache (cache, from, count); | |
383 } | |
1296 | 384 #ifdef NOT_WORTH_THE_EFFORT |
385 update_mirror_syntax_if_dirty (cache->mirror_table); | |
386 #endif /* NOT_WORTH_THE_EFFORT */ | |
826 | 387 return cache; |
388 } | |
389 | |
390 struct syntax_cache * | |
391 setup_buffer_syntax_cache (struct buffer *buffer, Charxpos from, int count) | |
392 { | |
393 return setup_syntax_cache (NULL, wrap_buffer (buffer), buffer, from, count); | |
394 } | |
395 | |
460 | 396 /* |
397 Update syntax_cache to an appropriate setting for position POS | |
398 | |
399 The sign of COUNT gives the relative position of POS wrt the | |
400 previously valid interval. (not currently used) | |
401 | |
402 `syntax_cache.*_change' are the next and previous positions at | |
403 which syntax_code and c_s_t will need to be recalculated. | |
404 | |
3025 | 405 #### Currently this code uses `get-char-property', which will |
460 | 406 return the "last smallest" extent at a given position. In cases |
407 where overlapping extents are defined, this code will simply use | |
408 whatever is returned by get-char-property. | |
409 | |
410 It might be worth it at some point to merge provided syntax tables | |
826 | 411 outward to the current buffer (#### rewrite in English please?!). */ |
460 | 412 |
413 void | |
2286 | 414 update_syntax_cache (struct syntax_cache *cache, Charxpos cpos, |
415 int UNUSED (count)) | |
460 | 416 { |
417 Lisp_Object tmp_table; | |
826 | 418 Bytexpos pos; |
419 Bytexpos lim; | |
420 Bytexpos next, prev; | |
421 int at_begin = 0, at_end = 0; | |
460 | 422 |
826 | 423 if (NILP (cache->object)) |
424 return; | |
425 | |
426 pos = buffer_or_string_charxpos_to_bytexpos (cache->object, cpos); | |
427 | |
428 tmp_table = get_char_property (pos, Qsyntax_table, cache->object, | |
429 EXTENT_AT_AFTER, 0); | |
2506 | 430 lim = next_previous_single_property_change (pos, Qsyntax_table, |
431 cache->object, -1, 1, 0); | |
826 | 432 if (lim < 0) |
460 | 433 { |
826 | 434 next = buffer_or_string_absolute_end_byte (cache->object); |
435 at_begin = 1; | |
460 | 436 } |
826 | 437 else |
438 next = lim; | |
460 | 439 |
826 | 440 if (pos < buffer_or_string_absolute_end_byte (cache->object)) |
441 pos = next_bytexpos (cache->object, pos); | |
2506 | 442 lim = next_previous_single_property_change (pos, Qsyntax_table, |
443 cache->object, -1, 0, 0); | |
826 | 444 if (lim < 0) |
460 | 445 { |
826 | 446 prev = buffer_or_string_absolute_begin_byte (cache->object); |
447 at_end = 1; | |
460 | 448 } |
449 else | |
826 | 450 prev = lim; |
460 | 451 |
826 | 452 cache->prev_change = |
453 buffer_or_string_bytexpos_to_charxpos (cache->object, prev); | |
454 cache->next_change = | |
455 buffer_or_string_bytexpos_to_charxpos (cache->object, next); | |
460 | 456 |
826 | 457 if (BUFFERP (cache->object)) |
458 { | |
459 /* If we are at the beginning or end of buffer, check to see if there's | |
460 a zero-length `syntax-table' extent there (highly unlikely); if not, | |
461 then we can safely make the end closed, so it will take in newly | |
462 inserted text. (If such an extent is inserted, we will be informed | |
3250 | 463 through signal_syntax_cache_extent_changed().) */ |
826 | 464 Fset_marker (cache->start, make_int (cache->prev_change), cache->object); |
465 Fset_marker_insertion_type | |
466 (cache->start, | |
467 at_begin && NILP (extent_at (prev, cache->object, Qsyntax_table, | |
468 NULL, EXTENT_AT_AT, 0)) | |
469 ? Qnil : Qt); | |
470 Fset_marker (cache->end, make_int (cache->next_change), cache->object); | |
471 Fset_marker_insertion_type | |
472 (cache->end, | |
473 at_end && NILP (extent_at (next, cache->object, Qsyntax_table, | |
474 NULL, EXTENT_AT_AT, 0)) | |
475 ? Qt : Qnil); | |
476 } | |
477 | |
478 if (!NILP (Fsyntax_table_p (tmp_table))) | |
479 { | |
480 cache->use_code = 0; | |
1296 | 481 cache->syntax_table = tmp_table; |
482 cache->mirror_table = XCHAR_TABLE (tmp_table)->mirror_table; | |
826 | 483 cache->no_syntax_table_prop = 0; |
1296 | 484 #ifdef NOT_WORTH_THE_EFFORT |
485 update_mirror_syntax_if_dirty (cache->mirror_table); | |
486 #endif /* NOT_WORTH_THE_EFFORT */ | |
826 | 487 } |
488 else if (CONSP (tmp_table) && INTP (XCAR (tmp_table))) | |
489 { | |
490 cache->use_code = 1; | |
491 cache->syntax_code = XINT (XCAR (tmp_table)); | |
492 cache->no_syntax_table_prop = 0; | |
493 } | |
494 else | |
495 { | |
496 cache->use_code = 0; | |
497 cache->no_syntax_table_prop = 1; | |
1296 | 498 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer); |
499 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); | |
500 #ifdef NOT_WORTH_THE_EFFORT | |
501 update_mirror_syntax_if_dirty (cache->mirror_table); | |
502 #endif /* NOT_WORTH_THE_EFFORT */ | |
460 | 503 } |
504 } | |
3252 | 505 |
506 /* buffer-specific APIs used in buffer.c | |
507 #### This is really unclean; | |
508 the syntax cache should just be a LISP object */ | |
509 | |
510 void | |
511 mark_buffer_syntax_cache (struct buffer *buf) | |
512 { | |
513 struct syntax_cache *cache = buf->syntax_cache; | |
514 if (!cache) /* Vbuffer_defaults and such don't have caches */ | |
515 return; | |
516 mark_object (cache->object); | |
517 if (cache->buffer) | |
518 mark_object (wrap_buffer (cache->buffer)); | |
519 mark_object (cache->syntax_table); | |
520 mark_object (cache->mirror_table); | |
521 mark_object (cache->start); | |
522 mark_object (cache->end); | |
523 } | |
524 | |
525 void | |
526 init_buffer_syntax_cache (struct buffer *buf) | |
527 { | |
528 struct syntax_cache *cache; | |
529 #ifdef NEW_GC | |
5120
d1247f3cc363
latest work on lisp-object workspace;
Ben Wing <ben@xemacs.org>
parents:
5118
diff
changeset
|
530 buf->syntax_cache = XSYNTAX_CACHE (ALLOC_LISP_OBJECT (syntax_cache)); |
3252 | 531 #else /* not NEW_GC */ |
532 buf->syntax_cache = xnew_and_zero (struct syntax_cache); | |
533 #endif /* not NEW_GC */ | |
534 cache = buf->syntax_cache; | |
535 cache->object = wrap_buffer (buf); | |
536 cache->buffer = buf; | |
537 cache->no_syntax_table_prop = 1; | |
538 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer); | |
539 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); | |
540 cache->start = Fmake_marker (); | |
541 cache->end = Fmake_marker (); | |
542 reset_buffer_syntax_cache_range (cache, cache->object, 0); | |
543 } | |
544 | |
545 /* finalize the syntax cache for BUF */ | |
546 | |
547 void | |
4710
3a87551bfeb5
Fixes for a number of minor warnings issued by gcc. See xemacs-patches message
Jerry James <james@xemacs.org>
parents:
4653
diff
changeset
|
548 uninit_buffer_syntax_cache (struct buffer *UNUSED_IF_NEW_GC (buf)) |
3252 | 549 { |
4141 | 550 #ifndef NEW_GC |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4912
diff
changeset
|
551 xfree (buf->syntax_cache); |
3252 | 552 buf->syntax_cache = 0; |
4141 | 553 #endif /* not NEW_GC */ |
3252 | 554 } |
555 | |
556 /* extent-specific APIs used in extents.c and insdel.c */ | |
557 | |
558 /* The syntax-table property on the range covered by EXTENT may be changing, | |
559 either because EXTENT has a syntax-table property and is being attached | |
560 or detached (this includes having its endpoints changed), or because | |
561 the value of EXTENT's syntax-table property is changing. */ | |
562 | |
563 void | |
564 signal_syntax_cache_extent_changed (EXTENT extent) | |
565 { | |
566 Lisp_Object buffer = Fextent_object (wrap_extent (extent)); | |
567 if (BUFFERP (buffer)) | |
568 { | |
569 /* This was getting called with the buffer's start and end null, eg in | |
570 cperl mode, which triggers an assert in byte_marker_position. Cf | |
571 thread rooted at <yxz7j7xzk97.fsf@gimli.holgi.priv> on xemacs-beta. | |
572 <yxzfymklb6p.fsf@gimli.holgi.priv> has a recipe, but you also need | |
573 to delete or type SPC to get the crash. | |
574 #### Delete this comment when setup_syntax_cache is made sane. */ | |
575 struct syntax_cache *cache = XBUFFER (buffer)->syntax_cache; | |
576 /* #### would this be slower or less accurate in character terms? */ | |
577 Bytexpos start = extent_endpoint_byte (extent, 0); | |
578 Bytexpos end = extent_endpoint_byte (extent, 1); | |
579 Bytexpos start2 = byte_marker_position (cache->start); | |
580 Bytexpos end2 = byte_marker_position (cache->end); | |
581 /* If the extent is entirely before or entirely after the cache | |
582 range, it doesn't overlap. Otherwise, invalidate the range. */ | |
583 if (!(end < start2 || start > end2)) | |
584 reset_buffer_syntax_cache_range (cache, buffer, 0); | |
585 } | |
586 } | |
587 | |
588 /* Extents have been adjusted for insertion or deletion, so we need to | |
589 refetch the start and end position of the extent */ | |
590 void | |
591 signal_syntax_cache_extent_adjust (struct buffer *buf) | |
592 { | |
593 struct syntax_cache *cache = buf->syntax_cache; | |
594 /* If the cache was invalid before, leave it that way. We only want | |
595 to update the limits of validity when they were actually valid. */ | |
596 if (cache->prev_change < 0) | |
597 return; | |
598 cache->prev_change = marker_position (cache->start); | |
599 cache->next_change = marker_position (cache->end); | |
600 } | |
601 | |
602 | |
460 | 603 |
428 | 604 /* Convert a letter which signifies a syntax code |
605 into the code it signifies. | |
606 This is used by modify-syntax-entry, and other things. */ | |
607 | |
442 | 608 const unsigned char syntax_spec_code[0400] = |
428 | 609 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
610 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
611 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
612 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
613 (char) Swhitespace, 0377, (char) Sstring, 0377, | |
614 (char) Smath, 0377, 0377, (char) Squote, | |
615 (char) Sopen, (char) Sclose, 0377, 0377, | |
616 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote, | |
617 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
618 0377, 0377, 0377, 0377, | |
619 (char) Scomment, 0377, (char) Sendcomment, 0377, | |
620 (char) Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A ... */ | |
621 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
622 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, | |
623 0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol, | |
624 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */ | |
625 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | |
626 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, | |
460 | 627 0377, 0377, 0377, 0377, (char) Sstring_fence, 0377, 0377, 0377 |
428 | 628 }; |
629 | |
460 | 630 const unsigned char syntax_code_spec[] = " .w_()'\"$\\/<>@!|"; |
428 | 631 |
632 DEFUN ("syntax-designator-chars", Fsyntax_designator_chars, 0, 0, 0, /* | |
633 Return a string of the recognized syntax designator chars. | |
634 The chars are ordered by their internal syntax codes, which are | |
635 numbered starting at 0. | |
636 */ | |
637 ()) | |
638 { | |
639 return Vsyntax_designator_chars_string; | |
640 } | |
641 | |
642 DEFUN ("char-syntax", Fchar_syntax, 1, 2, 0, /* | |
444 | 643 Return the syntax code of CHARACTER, described by a character. |
644 For example, if CHARACTER is a word constituent, | |
645 the character `?w' is returned. | |
428 | 646 The characters that correspond to various syntax codes |
647 are listed in the documentation of `modify-syntax-entry'. | |
444 | 648 Optional second argument SYNTAX-TABLE defaults to the current buffer's |
428 | 649 syntax table. |
650 */ | |
444 | 651 (character, syntax_table)) |
428 | 652 { |
826 | 653 Lisp_Object mirrortab; |
428 | 654 |
444 | 655 if (NILP (character)) |
428 | 656 { |
444 | 657 character = make_char ('\000'); |
428 | 658 } |
444 | 659 CHECK_CHAR_COERCE_INT (character); |
826 | 660 syntax_table = check_syntax_table (syntax_table, |
661 current_buffer->syntax_table); | |
662 mirrortab = XCHAR_TABLE (syntax_table)->mirror_table; | |
663 return make_char (syntax_code_spec[(int) SYNTAX (mirrortab, | |
664 XCHAR (character))]); | |
428 | 665 } |
666 | |
667 #ifdef MULE | |
668 | |
669 enum syntaxcode | |
2286 | 670 charset_syntax (struct buffer *UNUSED (buf), Lisp_Object UNUSED (charset), |
671 int *multi_p_out) | |
428 | 672 { |
673 *multi_p_out = 1; | |
826 | 674 /* !!#### get this right */ |
3152 | 675 return Sword; |
428 | 676 } |
677 | |
678 #endif | |
679 | |
680 Lisp_Object | |
867 | 681 syntax_match (Lisp_Object syntax_table, Ichar ch) |
428 | 682 { |
826 | 683 Lisp_Object code = get_char_table (ch, syntax_table); |
428 | 684 Lisp_Object code2 = code; |
685 | |
686 if (CONSP (code)) | |
687 code2 = XCAR (code); | |
688 if (SYNTAX_FROM_CODE (XINT (code2)) == Sinherit) | |
826 | 689 code = get_char_table (ch, Vstandard_syntax_table); |
428 | 690 |
691 return CONSP (code) ? XCDR (code) : Qnil; | |
692 } | |
693 | |
694 DEFUN ("matching-paren", Fmatching_paren, 1, 2, 0, /* | |
444 | 695 Return the matching parenthesis of CHARACTER, or nil if none. |
696 Optional second argument SYNTAX-TABLE defaults to the current buffer's | |
428 | 697 syntax table. |
698 */ | |
444 | 699 (character, syntax_table)) |
428 | 700 { |
826 | 701 Lisp_Object mirrortab; |
1315 | 702 enum syntaxcode code; |
428 | 703 |
444 | 704 CHECK_CHAR_COERCE_INT (character); |
826 | 705 syntax_table = check_syntax_table (syntax_table, |
706 current_buffer->syntax_table); | |
707 mirrortab = XCHAR_TABLE (syntax_table)->mirror_table; | |
444 | 708 code = SYNTAX (mirrortab, XCHAR (character)); |
428 | 709 if (code == Sopen || code == Sclose || code == Sstring) |
444 | 710 return syntax_match (syntax_table, XCHAR (character)); |
428 | 711 return Qnil; |
712 } | |
713 | |
714 | |
715 | |
716 #ifdef MULE | |
717 /* Return 1 if there is a word boundary between two word-constituent | |
718 characters C1 and C2 if they appear in this order, else return 0. | |
719 There is no word boundary between two word-constituent ASCII | |
720 characters. */ | |
721 #define WORD_BOUNDARY_P(c1, c2) \ | |
867 | 722 (!(ichar_ascii_p (c1) && ichar_ascii_p (c2)) \ |
428 | 723 && word_boundary_p (c1, c2)) |
724 #endif | |
725 | |
726 /* Return the position across COUNT words from FROM. | |
727 If that many words cannot be found before the end of the buffer, return 0. | |
728 COUNT negative means scan backward and stop at word beginning. */ | |
729 | |
665 | 730 Charbpos |
731 scan_words (struct buffer *buf, Charbpos from, int count) | |
428 | 732 { |
665 | 733 Charbpos limit = count > 0 ? BUF_ZV (buf) : BUF_BEGV (buf); |
867 | 734 Ichar ch0, ch1; |
428 | 735 enum syntaxcode code; |
826 | 736 struct syntax_cache *scache = setup_buffer_syntax_cache (buf, from, count); |
460 | 737 |
428 | 738 /* #### is it really worth it to hand expand both cases? JV */ |
739 while (count > 0) | |
740 { | |
741 QUIT; | |
742 | |
743 while (1) | |
744 { | |
745 if (from == limit) | |
746 return 0; | |
747 | |
826 | 748 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 749 ch0 = BUF_FETCH_CHAR (buf, from); |
826 | 750 code = SYNTAX_FROM_CACHE (scache, ch0); |
428 | 751 |
442 | 752 from++; |
428 | 753 if (words_include_escapes |
754 && (code == Sescape || code == Scharquote)) | |
755 break; | |
756 if (code == Sword) | |
757 break; | |
758 } | |
759 | |
760 QUIT; | |
761 | |
762 while (from != limit) | |
763 { | |
826 | 764 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 765 ch1 = BUF_FETCH_CHAR (buf, from); |
826 | 766 code = SYNTAX_FROM_CACHE (scache, ch1); |
428 | 767 if (!(words_include_escapes |
768 && (code == Sescape || code == Scharquote))) | |
769 if (code != Sword | |
770 #ifdef MULE | |
771 || WORD_BOUNDARY_P (ch0, ch1) | |
434 | 772 #endif |
428 | 773 ) |
774 break; | |
775 #ifdef MULE | |
776 ch0 = ch1; | |
434 | 777 #endif |
428 | 778 from++; |
779 } | |
780 count--; | |
781 } | |
782 | |
783 while (count < 0) | |
784 { | |
785 QUIT; | |
786 | |
787 while (1) | |
788 { | |
789 if (from == limit) | |
790 return 0; | |
791 | |
826 | 792 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
428 | 793 ch1 = BUF_FETCH_CHAR (buf, from - 1); |
826 | 794 code = SYNTAX_FROM_CACHE (scache, ch1); |
460 | 795 from--; |
442 | 796 |
428 | 797 if (words_include_escapes |
798 && (code == Sescape || code == Scharquote)) | |
799 break; | |
800 if (code == Sword) | |
801 break; | |
802 } | |
803 | |
804 QUIT; | |
805 | |
806 while (from != limit) | |
807 { | |
826 | 808 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
428 | 809 ch0 = BUF_FETCH_CHAR (buf, from - 1); |
826 | 810 code = SYNTAX_FROM_CACHE (scache, ch0); |
460 | 811 |
428 | 812 if (!(words_include_escapes |
813 && (code == Sescape || code == Scharquote))) | |
814 if (code != Sword | |
815 #ifdef MULE | |
816 || WORD_BOUNDARY_P (ch0, ch1) | |
817 #endif | |
818 ) | |
819 break; | |
820 #ifdef MULE | |
821 ch1 = ch0; | |
822 #endif | |
823 from--; | |
824 } | |
825 count++; | |
826 } | |
827 | |
828 return from; | |
829 } | |
830 | |
446 | 831 DEFUN ("forward-word", Fforward_word, 0, 2, "_p", /* |
428 | 832 Move point forward COUNT words (backward if COUNT is negative). |
446 | 833 Normally t is returned, but if an edge of the buffer is reached, |
834 point is left there and nil is returned. | |
428 | 835 |
462 | 836 The characters that are moved over may be added to the current selection |
837 \(i.e. active region) if the Shift key is held down, a motion key is used | |
838 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
839 the documentation for this variable for more details. | |
840 | |
446 | 841 COUNT defaults to 1, and BUFFER defaults to the current buffer. |
428 | 842 */ |
843 (count, buffer)) | |
844 { | |
665 | 845 Charbpos val; |
428 | 846 struct buffer *buf = decode_buffer (buffer, 0); |
446 | 847 EMACS_INT n; |
848 | |
849 if (NILP (count)) | |
850 n = 1; | |
851 else | |
852 { | |
853 CHECK_INT (count); | |
854 n = XINT (count); | |
855 } | |
428 | 856 |
446 | 857 val = scan_words (buf, BUF_PT (buf), n); |
858 if (val) | |
428 | 859 { |
446 | 860 BUF_SET_PT (buf, val); |
861 return Qt; | |
862 } | |
863 else | |
864 { | |
865 BUF_SET_PT (buf, n > 0 ? BUF_ZV (buf) : BUF_BEGV (buf)); | |
428 | 866 return Qnil; |
867 } | |
868 } | |
869 | |
870 static void scan_sexps_forward (struct buffer *buf, | |
871 struct lisp_parse_state *, | |
665 | 872 Charbpos from, Charbpos end, |
428 | 873 int targetdepth, int stopbefore, |
874 Lisp_Object oldstate, | |
875 int commentstop); | |
876 | |
877 static int | |
665 | 878 find_start_of_comment (struct buffer *buf, Charbpos from, Charbpos stop, |
460 | 879 int comstyle) |
428 | 880 { |
867 | 881 Ichar c; |
428 | 882 enum syntaxcode code; |
883 | |
884 /* Look back, counting the parity of string-quotes, | |
885 and recording the comment-starters seen. | |
886 When we reach a safe place, assume that's not in a string; | |
887 then step the main scan to the earliest comment-starter seen | |
888 an even number of string quotes away from the safe place. | |
889 | |
890 OFROM[I] is position of the earliest comment-starter seen | |
891 which is I+2X quotes from the comment-end. | |
892 PARITY is current parity of quotes from the comment end. */ | |
893 int parity = 0; | |
867 | 894 Ichar my_stringend = 0; |
428 | 895 int string_lossage = 0; |
665 | 896 Charbpos comment_end = from; |
897 Charbpos comstart_pos = 0; | |
428 | 898 int comstart_parity = 0; |
899 int styles_match_p = 0; | |
460 | 900 /* mask to match comment styles against; for ST_COMMENT_STYLE, this |
901 will get set to SYNTAX_COMMENT_STYLE_B, but never get checked */ | |
902 int mask = comstyle ? SYNTAX_COMMENT_STYLE_B : SYNTAX_COMMENT_STYLE_A; | |
826 | 903 struct syntax_cache *scache = buf->syntax_cache; |
428 | 904 |
905 /* At beginning of range to scan, we're outside of strings; | |
906 that determines quote parity to the comment-end. */ | |
907 while (from != stop) | |
908 { | |
460 | 909 int syncode; |
910 | |
428 | 911 /* Move back and examine a character. */ |
912 from--; | |
826 | 913 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
428 | 914 |
915 c = BUF_FETCH_CHAR (buf, from); | |
826 | 916 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
917 code = SYNTAX_FROM_CODE (syncode); | |
428 | 918 |
919 /* is this a 1-char comment end sequence? if so, try | |
920 to see if style matches previously extracted mask */ | |
921 if (code == Sendcomment) | |
922 { | |
923 styles_match_p = | |
460 | 924 SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) & mask; |
428 | 925 } |
926 | |
927 /* or are we looking at a 1-char comment start sequence | |
928 of the style matching mask? */ | |
460 | 929 else if (code == Scomment) |
428 | 930 { |
460 | 931 styles_match_p = |
932 SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) & mask; | |
428 | 933 } |
934 | |
460 | 935 /* otherwise, is this a 2-char comment end or start sequence? */ |
936 else if (from > stop) | |
937 do | |
938 { | |
939 /* 2-char comment end sequence? */ | |
940 if (SYNTAX_CODE_END_SECOND_P (syncode)) | |
941 { | |
942 int prev_syncode; | |
826 | 943 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
460 | 944 prev_syncode = |
1315 | 945 SYNTAX_CODE_FROM_CACHE (scache, |
946 BUF_FETCH_CHAR (buf, from - 1)); | |
460 | 947 |
948 if (SYNTAX_CODES_END_P (prev_syncode, syncode)) | |
949 { | |
950 code = Sendcomment; | |
951 styles_match_p = | |
826 | 952 SYNTAX_CODES_COMMENT_MASK_END (prev_syncode, |
953 syncode) & mask; | |
460 | 954 from--; |
826 | 955 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
460 | 956 c = BUF_FETCH_CHAR (buf, from); |
957 | |
958 /* Found a comment-end sequence, so skip past the | |
959 check for a comment-start */ | |
960 break; | |
961 } | |
962 } | |
963 | |
964 /* 2-char comment start sequence? */ | |
965 if (SYNTAX_CODE_START_SECOND_P (syncode)) | |
966 { | |
967 int prev_syncode; | |
826 | 968 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
460 | 969 prev_syncode = |
1315 | 970 SYNTAX_CODE_FROM_CACHE (scache, |
971 BUF_FETCH_CHAR (buf, from - 1)); | |
460 | 972 |
973 if (SYNTAX_CODES_START_P (prev_syncode, syncode)) | |
974 { | |
975 code = Scomment; | |
976 styles_match_p = | |
826 | 977 SYNTAX_CODES_COMMENT_MASK_START (prev_syncode, |
978 syncode) & mask; | |
460 | 979 from--; |
826 | 980 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
460 | 981 c = BUF_FETCH_CHAR (buf, from); |
982 } | |
983 } | |
984 } while (0); | |
428 | 985 |
986 /* Ignore escaped characters. */ | |
987 if (char_quoted (buf, from)) | |
988 continue; | |
989 | |
990 /* Track parity of quotes. */ | |
991 if (code == Sstring) | |
992 { | |
993 parity ^= 1; | |
994 if (my_stringend == 0) | |
995 my_stringend = c; | |
996 /* If we have two kinds of string delimiters. | |
997 There's no way to grok this scanning backwards. */ | |
998 else if (my_stringend != c) | |
999 string_lossage = 1; | |
1000 } | |
1001 | |
460 | 1002 if (code == Sstring_fence || code == Scomment_fence) |
1003 { | |
1004 parity ^= 1; | |
1005 if (my_stringend == 0) | |
1006 my_stringend = | |
1007 code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE; | |
1008 /* If we have two kinds of string delimiters. | |
1009 There's no way to grok this scanning backwards. */ | |
1010 else if (my_stringend != (code == Sstring_fence | |
1011 ? ST_STRING_STYLE : ST_COMMENT_STYLE)) | |
1012 string_lossage = 1; | |
1013 } | |
1014 | |
428 | 1015 /* Record comment-starters according to that |
1016 quote-parity to the comment-end. */ | |
1017 if (code == Scomment && styles_match_p) | |
1018 { | |
1019 comstart_parity = parity; | |
1020 comstart_pos = from; | |
1021 } | |
1022 | |
1023 /* If we find another earlier comment-ender, | |
1024 any comment-starts earlier than that don't count | |
1025 (because they go with the earlier comment-ender). */ | |
1026 if (code == Sendcomment && styles_match_p) | |
1027 break; | |
1028 | |
1029 /* Assume a defun-start point is outside of strings. */ | |
1030 if (code == Sopen | |
1031 && (from == stop || BUF_FETCH_CHAR (buf, from - 1) == '\n')) | |
1032 break; | |
1033 } | |
1034 | |
1035 if (comstart_pos == 0) | |
1036 from = comment_end; | |
1037 /* If the earliest comment starter | |
1038 is followed by uniform paired string quotes or none, | |
1039 we know it can't be inside a string | |
1040 since if it were then the comment ender would be inside one. | |
1041 So it does start a comment. Skip back to it. */ | |
1042 else if (comstart_parity == 0 && !string_lossage) | |
1043 from = comstart_pos; | |
1044 else | |
1045 { | |
1046 /* We had two kinds of string delimiters mixed up | |
1047 together. Decode this going forwards. | |
1048 Scan fwd from the previous comment ender | |
1049 to the one in question; this records where we | |
1050 last passed a comment starter. */ | |
1051 | |
1052 struct lisp_parse_state state; | |
1053 scan_sexps_forward (buf, &state, find_defun_start (buf, comment_end), | |
1054 comment_end - 1, -10000, 0, Qnil, 0); | |
1055 if (state.incomment) | |
460 | 1056 from = state.comstr_start; |
428 | 1057 else |
1058 /* We can't grok this as a comment; scan it normally. */ | |
1059 from = comment_end; | |
826 | 1060 UPDATE_SYNTAX_CACHE_FORWARD (scache, from - 1); |
428 | 1061 } |
1062 return from; | |
1063 } | |
1064 | |
665 | 1065 static Charbpos |
826 | 1066 find_end_of_comment (struct buffer *buf, Charbpos from, Charbpos stop, |
1067 int comstyle) | |
428 | 1068 { |
1069 int c; | |
460 | 1070 int prev_code; |
1071 /* mask to match comment styles against; for ST_COMMENT_STYLE, this | |
1072 will get set to SYNTAX_COMMENT_STYLE_B, but never get checked */ | |
1073 int mask = comstyle ? SYNTAX_COMMENT_STYLE_B : SYNTAX_COMMENT_STYLE_A; | |
826 | 1074 struct syntax_cache *scache = buf->syntax_cache; |
428 | 1075 |
460 | 1076 /* This is only called by functions which have already set up the |
1077 syntax_cache and are keeping it up-to-date */ | |
428 | 1078 while (1) |
1079 { | |
1080 if (from == stop) | |
1081 { | |
1082 return -1; | |
1083 } | |
460 | 1084 |
826 | 1085 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1086 c = BUF_FETCH_CHAR (buf, from); |
460 | 1087 |
1088 /* Test for generic comments */ | |
1089 if (comstyle == ST_COMMENT_STYLE) | |
1090 { | |
826 | 1091 if (SYNTAX_FROM_CACHE (scache, c) == Scomment_fence) |
460 | 1092 { |
1093 from++; | |
826 | 1094 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1095 break; |
1096 } | |
1097 from++; | |
1098 continue; /* No need to test other comment styles in a | |
1099 generic comment */ | |
1100 } | |
1101 else | |
1102 | |
826 | 1103 if (SYNTAX_FROM_CACHE (scache, c) == Sendcomment |
460 | 1104 && SYNTAX_CODE_MATCHES_1CHAR_P |
826 | 1105 (SYNTAX_CODE_FROM_CACHE (scache, c), mask)) |
428 | 1106 /* we have encountered a comment end of the same style |
1107 as the comment sequence which began this comment | |
1108 section */ | |
460 | 1109 { |
1110 from++; | |
826 | 1111 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1112 break; |
1113 } | |
428 | 1114 |
826 | 1115 prev_code = SYNTAX_CODE_FROM_CACHE (scache, c); |
428 | 1116 from++; |
826 | 1117 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1118 if (from < stop |
460 | 1119 && SYNTAX_CODES_MATCH_END_P |
1120 (prev_code, | |
826 | 1121 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from)), |
460 | 1122 mask) |
1123 | |
1124 ) | |
428 | 1125 /* we have encountered a comment end of the same style |
1126 as the comment sequence which began this comment | |
1127 section */ | |
460 | 1128 { |
1129 from++; | |
826 | 1130 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1131 break; |
1132 } | |
428 | 1133 } |
1134 return from; | |
1135 } | |
1136 | |
1137 | |
1138 /* #### between FSF 19.23 and 19.28 there are some changes to the logic | |
1139 in this function (and minor changes to find_start_of_comment(), | |
1140 above, which is part of Fforward_comment() in FSF). Attempts to port | |
1141 that logic made this function break, so I'm leaving it out. If anyone | |
1142 ever complains about this function not working properly, take a look | |
1143 at those changes. --ben */ | |
1144 | |
446 | 1145 DEFUN ("forward-comment", Fforward_comment, 0, 2, 0, /* |
444 | 1146 Move forward across up to COUNT comments, or backwards if COUNT is negative. |
428 | 1147 Stop scanning if we find something other than a comment or whitespace. |
1148 Set point to where scanning stops. | |
444 | 1149 If COUNT comments are found as expected, with nothing except whitespace |
428 | 1150 between them, return t; otherwise return nil. |
1151 Point is set in either case. | |
446 | 1152 COUNT defaults to 1, and BUFFER defaults to the current buffer. |
428 | 1153 */ |
444 | 1154 (count, buffer)) |
428 | 1155 { |
665 | 1156 Charbpos from; |
1157 Charbpos stop; | |
867 | 1158 Ichar c; |
428 | 1159 enum syntaxcode code; |
460 | 1160 int syncode; |
444 | 1161 EMACS_INT n; |
428 | 1162 struct buffer *buf = decode_buffer (buffer, 0); |
826 | 1163 struct syntax_cache *scache; |
1164 | |
446 | 1165 if (NILP (count)) |
1166 n = 1; | |
1167 else | |
1168 { | |
1169 CHECK_INT (count); | |
1170 n = XINT (count); | |
1171 } | |
428 | 1172 |
1173 from = BUF_PT (buf); | |
1174 | |
826 | 1175 scache = setup_buffer_syntax_cache (buf, from, n); |
444 | 1176 while (n > 0) |
428 | 1177 { |
1178 QUIT; | |
1179 | |
1180 stop = BUF_ZV (buf); | |
1181 while (from < stop) | |
1182 { | |
460 | 1183 int comstyle = 0; /* mask for finding matching comment style */ |
428 | 1184 |
1185 if (char_quoted (buf, from)) | |
1186 { | |
1187 from++; | |
1188 continue; | |
1189 } | |
1190 | |
826 | 1191 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1192 c = BUF_FETCH_CHAR (buf, from); |
826 | 1193 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
1194 code = SYNTAX_FROM_CODE (syncode); | |
428 | 1195 |
1196 if (code == Scomment) | |
1197 { | |
1198 /* we have encountered a single character comment start | |
1199 sequence, and we are ignoring all text inside comments. | |
1200 we must record the comment style this character begins | |
1201 so that later, only a comment end of the same style actually | |
1202 ends the comment section */ | |
460 | 1203 comstyle = SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) |
1204 == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
428 | 1205 } |
1206 | |
460 | 1207 else if (code == Scomment_fence) |
1208 { | |
1209 from++; | |
1210 code = Scomment; | |
1211 comstyle = ST_COMMENT_STYLE; | |
1212 } | |
1213 | |
428 | 1214 else if (from < stop |
460 | 1215 && SYNTAX_CODE_START_FIRST_P (syncode)) |
428 | 1216 { |
460 | 1217 int next_syncode; |
826 | 1218 UPDATE_SYNTAX_CACHE_FORWARD (scache, from + 1); |
460 | 1219 next_syncode = |
826 | 1220 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from + 1)); |
460 | 1221 |
1222 if (SYNTAX_CODES_START_P (syncode, next_syncode)) | |
1223 { | |
1224 /* we have encountered a 2char comment start sequence and we | |
1225 are ignoring all text inside comments. we must record | |
1226 the comment style this sequence begins so that later, | |
1227 only a comment end of the same style actually ends | |
1228 the comment section */ | |
1229 code = Scomment; | |
1230 comstyle = | |
1231 SYNTAX_CODES_COMMENT_MASK_START (syncode, next_syncode) | |
1232 == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
1233 from++; | |
1234 } | |
428 | 1235 } |
1236 | |
1237 if (code == Scomment) | |
1238 { | |
826 | 1239 Charbpos newfrom = find_end_of_comment (buf, from, stop, |
1240 comstyle); | |
428 | 1241 if (newfrom < 0) |
1242 { | |
1243 /* we stopped because from==stop */ | |
1244 BUF_SET_PT (buf, stop); | |
1245 return Qnil; | |
1246 } | |
1247 from = newfrom; | |
1248 | |
1249 /* We have skipped one comment. */ | |
1250 break; | |
1251 } | |
1252 else if (code != Swhitespace | |
1253 && code != Sendcomment | |
1254 && code != Scomment ) | |
1255 { | |
1256 BUF_SET_PT (buf, from); | |
1257 return Qnil; | |
1258 } | |
1259 from++; | |
1260 } | |
1261 | |
1262 /* End of comment reached */ | |
444 | 1263 n--; |
428 | 1264 } |
1265 | |
444 | 1266 while (n < 0) |
428 | 1267 { |
1268 QUIT; | |
1269 | |
1270 stop = BUF_BEGV (buf); | |
1271 while (from > stop) | |
1272 { | |
460 | 1273 int comstyle = 0; /* mask for finding matching comment style */ |
428 | 1274 |
1275 from--; | |
1276 if (char_quoted (buf, from)) | |
1277 { | |
1278 from--; | |
1279 continue; | |
1280 } | |
1281 | |
1282 c = BUF_FETCH_CHAR (buf, from); | |
826 | 1283 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
1284 code = SYNTAX_FROM_CODE (syncode); | |
428 | 1285 |
1286 if (code == Sendcomment) | |
1287 { | |
1288 /* we have found a single char end comment. we must record | |
1289 the comment style encountered so that later, we can match | |
1290 only the proper comment begin sequence of the same style */ | |
460 | 1291 comstyle = SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) |
1292 == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
1293 } | |
1294 | |
1295 else if (code == Scomment_fence) | |
1296 { | |
1297 code = Sendcomment; | |
1298 comstyle = ST_COMMENT_STYLE; | |
428 | 1299 } |
1300 | |
1301 else if (from > stop | |
460 | 1302 && SYNTAX_CODE_END_SECOND_P (syncode)) |
428 | 1303 { |
460 | 1304 int prev_syncode; |
826 | 1305 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
460 | 1306 prev_syncode = |
826 | 1307 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from - 1)); |
460 | 1308 if (SYNTAX_CODES_END_P (prev_syncode, syncode)) |
1309 { | |
1310 /* We must record the comment style encountered so that | |
1311 later, we can match only the proper comment begin | |
1312 sequence of the same style. */ | |
1313 code = Sendcomment; | |
1314 comstyle = SYNTAX_CODES_COMMENT_MASK_END | |
1315 (prev_syncode, syncode) == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
1316 from--; | |
1317 } | |
428 | 1318 } |
1319 | |
1320 if (code == Sendcomment) | |
1321 { | |
460 | 1322 from = find_start_of_comment (buf, from, stop, comstyle); |
428 | 1323 break; |
1324 } | |
1325 | |
1326 else if (code != Swhitespace | |
460 | 1327 && code != Scomment |
1328 && code != Sendcomment) | |
428 | 1329 { |
1330 BUF_SET_PT (buf, from + 1); | |
1331 return Qnil; | |
1332 } | |
1333 } | |
1334 | |
444 | 1335 n++; |
428 | 1336 } |
1337 | |
1338 BUF_SET_PT (buf, from); | |
1339 return Qt; | |
1340 } | |
1341 | |
1342 | |
1343 Lisp_Object | |
665 | 1344 scan_lists (struct buffer *buf, Charbpos from, int count, int depth, |
444 | 1345 int sexpflag, int noerror) |
428 | 1346 { |
665 | 1347 Charbpos stop; |
867 | 1348 Ichar c; |
428 | 1349 int quoted; |
1350 int mathexit = 0; | |
1351 enum syntaxcode code; | |
460 | 1352 int syncode; |
428 | 1353 int min_depth = depth; /* Err out if depth gets less than this. */ |
826 | 1354 struct syntax_cache *scache; |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1355 Charbpos last_good = from; |
826 | 1356 |
428 | 1357 if (depth > 0) min_depth = 0; |
1358 | |
826 | 1359 scache = setup_buffer_syntax_cache (buf, from, count); |
428 | 1360 while (count > 0) |
1361 { | |
1362 QUIT; | |
1363 | |
1364 stop = BUF_ZV (buf); | |
1365 while (from < stop) | |
1366 { | |
460 | 1367 int comstyle = 0; /* mask for finding matching comment style */ |
428 | 1368 |
826 | 1369 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1370 c = BUF_FETCH_CHAR (buf, from); |
826 | 1371 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
1372 code = SYNTAX_FROM_CODE (syncode); | |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1373 if (depth == min_depth) |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1374 last_good = from; |
428 | 1375 from++; |
1376 | |
1377 /* a 1-char comment start sequence */ | |
1378 if (code == Scomment && parse_sexp_ignore_comments) | |
1379 { | |
460 | 1380 comstyle = SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) == |
1381 SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
428 | 1382 } |
1383 | |
1384 /* else, a 2-char comment start sequence? */ | |
1385 else if (from < stop | |
460 | 1386 && SYNTAX_CODE_START_FIRST_P (syncode) |
428 | 1387 && parse_sexp_ignore_comments) |
1388 { | |
460 | 1389 int next_syncode; |
826 | 1390 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1391 next_syncode = |
826 | 1392 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from)); |
460 | 1393 |
1394 if (SYNTAX_CODES_START_P (syncode, next_syncode)) | |
1395 { | |
826 | 1396 /* we have encountered a comment start sequence and we |
1397 are ignoring all text inside comments. we must record | |
1398 the comment style this sequence begins so that later, | |
1399 only a comment end of the same style actually ends | |
1400 the comment section */ | |
1401 code = Scomment; | |
460 | 1402 comstyle = SYNTAX_CODES_COMMENT_MASK_START |
1403 (syncode, next_syncode) == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
826 | 1404 from++; |
1405 } | |
428 | 1406 } |
826 | 1407 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1408 |
460 | 1409 if (SYNTAX_CODE_PREFIX (syncode)) |
428 | 1410 continue; |
1411 | |
1412 switch (code) | |
1413 { | |
1414 case Sescape: | |
1415 case Scharquote: | |
1416 if (from == stop) goto lose; | |
1417 from++; | |
1418 /* treat following character as a word constituent */ | |
1419 case Sword: | |
1420 case Ssymbol: | |
1421 if (depth || !sexpflag) break; | |
1422 /* This word counts as a sexp; return at end of it. */ | |
1423 while (from < stop) | |
1424 { | |
826 | 1425 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
1426 switch (SYNTAX_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from))) | |
428 | 1427 { |
1428 case Scharquote: | |
1429 case Sescape: | |
1430 from++; | |
1431 if (from == stop) goto lose; | |
1432 break; | |
1433 case Sword: | |
1434 case Ssymbol: | |
1435 case Squote: | |
1436 break; | |
1437 default: | |
1438 goto done; | |
1439 } | |
1440 from++; | |
1441 } | |
1442 goto done; | |
1443 | |
460 | 1444 case Scomment_fence: |
1445 comstyle = ST_COMMENT_STYLE; | |
428 | 1446 case Scomment: |
1447 if (!parse_sexp_ignore_comments) | |
1448 break; | |
826 | 1449 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 1450 { |
665 | 1451 Charbpos newfrom = |
460 | 1452 find_end_of_comment (buf, from, stop, comstyle); |
428 | 1453 if (newfrom < 0) |
1454 { | |
1455 /* we stopped because from == stop in search forward */ | |
1456 from = stop; | |
1457 if (depth == 0) | |
1458 goto done; | |
1459 goto lose; | |
1460 } | |
1461 from = newfrom; | |
1462 } | |
1463 break; | |
1464 | |
1465 case Smath: | |
1466 if (!sexpflag) | |
1467 break; | |
1468 if (from != stop && c == BUF_FETCH_CHAR (buf, from)) | |
1469 from++; | |
1470 if (mathexit) | |
1471 { | |
1472 mathexit = 0; | |
1473 goto close1; | |
1474 } | |
1475 mathexit = 1; | |
1476 | |
1477 case Sopen: | |
1478 if (!++depth) goto done; | |
1479 break; | |
1480 | |
1481 case Sclose: | |
1482 close1: | |
1483 if (!--depth) goto done; | |
1484 if (depth < min_depth) | |
1485 { | |
444 | 1486 if (noerror) |
428 | 1487 return Qnil; |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1488 signal_error_2 (Qscan_error, |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1489 "Containing expression ends prematurely", |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1490 make_int (last_good), make_int (from)); |
428 | 1491 } |
1492 break; | |
1493 | |
460 | 1494 case Sstring_fence: |
428 | 1495 case Sstring: |
1496 { | |
867 | 1497 Ichar stringterm; |
460 | 1498 |
1499 if (code != Sstring_fence) | |
1500 { | |
826 | 1501 /* XEmacs change: call syntax_match on character */ |
867 | 1502 Ichar ch = BUF_FETCH_CHAR (buf, from - 1); |
460 | 1503 Lisp_Object stermobj = |
1296 | 1504 syntax_match (scache->syntax_table, ch); |
428 | 1505 |
1506 if (CHARP (stermobj)) | |
1507 stringterm = XCHAR (stermobj); | |
1508 else | |
1509 stringterm = ch; | |
460 | 1510 } |
1511 else | |
1512 stringterm = '\0'; /* avoid compiler warnings */ | |
428 | 1513 |
1514 while (1) | |
1515 { | |
1516 if (from >= stop) | |
1517 goto lose; | |
826 | 1518 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1519 c = BUF_FETCH_CHAR (buf, from); |
1520 if (code == Sstring | |
1521 ? c == stringterm | |
826 | 1522 : SYNTAX_FROM_CACHE (scache, c) == Sstring_fence) |
428 | 1523 break; |
460 | 1524 |
826 | 1525 switch (SYNTAX_FROM_CACHE (scache, c)) |
428 | 1526 { |
1527 case Scharquote: | |
1528 case Sescape: | |
1529 from++; | |
1530 break; | |
1531 default: | |
1532 break; | |
1533 } | |
1534 from++; | |
1535 } | |
1536 from++; | |
1537 if (!depth && sexpflag) goto done; | |
1538 break; | |
1539 } | |
1540 | |
1541 default: | |
1542 break; | |
1543 } | |
1544 } | |
1545 | |
1546 /* Reached end of buffer. Error if within object, | |
1547 return nil if between */ | |
1548 if (depth) goto lose; | |
1549 | |
1550 return Qnil; | |
1551 | |
1552 /* End of object reached */ | |
1553 done: | |
1554 count--; | |
1555 } | |
1556 | |
1557 while (count < 0) | |
1558 { | |
1559 QUIT; | |
1560 | |
1561 stop = BUF_BEGV (buf); | |
1562 while (from > stop) | |
1563 { | |
460 | 1564 int comstyle = 0; /* mask for finding matching comment style */ |
428 | 1565 |
1566 from--; | |
826 | 1567 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
428 | 1568 quoted = char_quoted (buf, from); |
1569 if (quoted) | |
460 | 1570 { |
428 | 1571 from--; |
826 | 1572 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
460 | 1573 } |
428 | 1574 |
1575 c = BUF_FETCH_CHAR (buf, from); | |
826 | 1576 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
1577 code = SYNTAX_FROM_CODE (syncode); | |
428 | 1578 |
1579 if (code == Sendcomment && parse_sexp_ignore_comments) | |
1580 { | |
1581 /* we have found a single char end comment. we must record | |
1582 the comment style encountered so that later, we can match | |
1583 only the proper comment begin sequence of the same style */ | |
460 | 1584 comstyle = SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) |
1585 == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
428 | 1586 } |
1587 | |
1588 else if (from > stop | |
460 | 1589 && SYNTAX_CODE_END_SECOND_P (syncode) |
428 | 1590 && !char_quoted (buf, from - 1) |
1591 && parse_sexp_ignore_comments) | |
1592 { | |
460 | 1593 int prev_syncode; |
826 | 1594 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
1595 prev_syncode = | |
1596 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from - 1)); | |
460 | 1597 |
1598 if (SYNTAX_CODES_END_P (prev_syncode, syncode)) | |
1599 { | |
428 | 1600 /* we must record the comment style encountered so that |
1601 later, we can match only the proper comment begin | |
1602 sequence of the same style */ | |
1603 code = Sendcomment; | |
460 | 1604 comstyle = SYNTAX_CODES_COMMENT_MASK_END |
1605 (prev_syncode, syncode) == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
428 | 1606 from--; |
1607 } | |
460 | 1608 } |
428 | 1609 |
460 | 1610 if (SYNTAX_CODE_PREFIX (syncode)) |
428 | 1611 continue; |
1612 | |
434 | 1613 switch (quoted ? Sword : code) |
428 | 1614 { |
1615 case Sword: | |
1616 case Ssymbol: | |
1617 if (depth || !sexpflag) break; | |
1618 /* This word counts as a sexp; count object finished after | |
1619 passing it. */ | |
1620 while (from > stop) | |
1621 { | |
826 | 1622 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from); |
428 | 1623 quoted = char_quoted (buf, from - 1); |
1624 | |
1625 if (quoted) | |
1626 from--; | |
1627 if (! (quoted | |
1628 || (syncode = | |
826 | 1629 SYNTAX_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, |
1630 from - 1))) | |
428 | 1631 == Sword |
1632 || syncode == Ssymbol | |
1633 || syncode == Squote)) | |
1634 goto done2; | |
1635 from--; | |
1636 } | |
1637 goto done2; | |
1638 | |
1639 case Smath: | |
1640 if (!sexpflag) | |
1641 break; | |
1642 if (from != stop && c == BUF_FETCH_CHAR (buf, from - 1)) | |
1643 from--; | |
1644 if (mathexit) | |
1645 { | |
1646 mathexit = 0; | |
1647 goto open2; | |
1648 } | |
1649 mathexit = 1; | |
1650 | |
1651 case Sclose: | |
1652 if (!++depth) goto done2; | |
1653 break; | |
1654 | |
1655 case Sopen: | |
1656 open2: | |
1657 if (!--depth) goto done2; | |
1658 if (depth < min_depth) | |
1659 { | |
444 | 1660 if (noerror) |
428 | 1661 return Qnil; |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1662 signal_error_2 (Qscan_error, |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1663 "Containing expression ends prematurely", |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1664 make_int (last_good), make_int (from)); |
428 | 1665 } |
1666 break; | |
1667 | |
460 | 1668 case Scomment_fence: |
1669 comstyle = ST_COMMENT_STYLE; | |
428 | 1670 case Sendcomment: |
1671 if (parse_sexp_ignore_comments) | |
460 | 1672 from = find_start_of_comment (buf, from, stop, comstyle); |
428 | 1673 break; |
1674 | |
460 | 1675 case Sstring_fence: |
428 | 1676 case Sstring: |
1677 { | |
867 | 1678 Ichar stringterm; |
460 | 1679 |
1680 if (code != Sstring_fence) | |
1681 { | |
428 | 1682 /* XEmacs change: call syntax_match() on character */ |
867 | 1683 Ichar ch = BUF_FETCH_CHAR (buf, from); |
460 | 1684 Lisp_Object stermobj = |
1296 | 1685 syntax_match (scache->syntax_table, ch); |
428 | 1686 |
1687 if (CHARP (stermobj)) | |
1688 stringterm = XCHAR (stermobj); | |
1689 else | |
1690 stringterm = ch; | |
460 | 1691 } |
1692 else | |
1693 stringterm = '\0'; /* avoid compiler warnings */ | |
428 | 1694 |
1695 while (1) | |
1696 { | |
1697 if (from == stop) goto lose; | |
460 | 1698 |
826 | 1699 UPDATE_SYNTAX_CACHE_BACKWARD (scache, from - 1); |
460 | 1700 c = BUF_FETCH_CHAR (buf, from - 1); |
1701 | |
1702 if ((code == Sstring | |
1703 ? c == stringterm | |
826 | 1704 : SYNTAX_FROM_CACHE (scache, c) == Sstring_fence) |
460 | 1705 && !char_quoted (buf, from - 1)) |
1706 { | |
428 | 1707 break; |
460 | 1708 } |
1709 | |
428 | 1710 from--; |
1711 } | |
1712 from--; | |
1713 if (!depth && sexpflag) goto done2; | |
1714 break; | |
1715 } | |
1716 } | |
1717 } | |
1718 | |
1719 /* Reached start of buffer. Error if within object, | |
1720 return nil if between */ | |
1721 if (depth) goto lose; | |
1722 | |
1723 return Qnil; | |
1724 | |
1725 done2: | |
1726 count++; | |
1727 } | |
1728 | |
1729 | |
1730 return (make_int (from)); | |
1731 | |
1732 lose: | |
444 | 1733 if (!noerror) |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1734 signal_error_2 (Qscan_error, "Unbalanced parentheses", |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
1735 make_int (last_good), make_int (from)); |
428 | 1736 return Qnil; |
1737 } | |
1738 | |
1739 int | |
665 | 1740 char_quoted (struct buffer *buf, Charbpos pos) |
428 | 1741 { |
1742 enum syntaxcode code; | |
665 | 1743 Charbpos beg = BUF_BEGV (buf); |
428 | 1744 int quoted = 0; |
665 | 1745 Charbpos startpos = pos; |
826 | 1746 struct syntax_cache *scache = buf->syntax_cache; |
460 | 1747 |
1748 while (pos > beg) | |
1749 { | |
826 | 1750 UPDATE_SYNTAX_CACHE_BACKWARD (scache, pos - 1); |
1751 code = SYNTAX_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, pos - 1)); | |
428 | 1752 |
460 | 1753 if (code != Scharquote && code != Sescape) |
1754 break; | |
1755 pos--; | |
1756 quoted = !quoted; | |
1757 } | |
1758 | |
826 | 1759 UPDATE_SYNTAX_CACHE (scache, startpos); |
428 | 1760 return quoted; |
1761 } | |
1762 | |
1763 DEFUN ("scan-lists", Fscan_lists, 3, 5, 0, /* | |
1764 Scan from character number FROM by COUNT lists. | |
1765 Returns the character number of the position thus found. | |
1766 | |
1767 If DEPTH is nonzero, paren depth begins counting from that value, | |
1768 only places where the depth in parentheses becomes zero | |
1769 are candidates for stopping; COUNT such places are counted. | |
1770 Thus, a positive value for DEPTH means go out levels. | |
1771 | |
1772 Comments are ignored if `parse-sexp-ignore-comments' is non-nil. | |
1773 | |
1774 If the beginning or end of (the accessible part of) the buffer is reached | |
1775 and the depth is wrong, an error is signaled. | |
1776 If the depth is right but the count is not used up, nil is returned. | |
1777 | |
1778 If optional arg BUFFER is non-nil, scanning occurs in that buffer instead | |
1779 of in the current buffer. | |
1780 | |
1781 If optional arg NOERROR is non-nil, scan-lists will return nil instead of | |
1782 signalling an error. | |
1783 */ | |
444 | 1784 (from, count, depth, buffer, noerror)) |
428 | 1785 { |
1786 struct buffer *buf; | |
1787 | |
1788 CHECK_INT (from); | |
1789 CHECK_INT (count); | |
1790 CHECK_INT (depth); | |
1791 buf = decode_buffer (buffer, 0); | |
1792 | |
1793 return scan_lists (buf, XINT (from), XINT (count), XINT (depth), 0, | |
444 | 1794 !NILP (noerror)); |
428 | 1795 } |
1796 | |
1797 DEFUN ("scan-sexps", Fscan_sexps, 2, 4, 0, /* | |
1798 Scan from character number FROM by COUNT balanced expressions. | |
1799 If COUNT is negative, scan backwards. | |
1800 Returns the character number of the position thus found. | |
1801 | |
1802 Comments are ignored if `parse-sexp-ignore-comments' is non-nil. | |
1803 | |
1804 If the beginning or end of (the accessible part of) the buffer is reached | |
1805 in the middle of a parenthetical grouping, an error is signaled. | |
1806 If the beginning or end is reached between groupings | |
1807 but before count is used up, nil is returned. | |
1808 | |
1809 If optional arg BUFFER is non-nil, scanning occurs in that buffer instead | |
1810 of in the current buffer. | |
1811 | |
1812 If optional arg NOERROR is non-nil, scan-sexps will return nil instead of | |
1813 signalling an error. | |
1814 */ | |
444 | 1815 (from, count, buffer, noerror)) |
428 | 1816 { |
1817 struct buffer *buf = decode_buffer (buffer, 0); | |
1818 CHECK_INT (from); | |
1819 CHECK_INT (count); | |
1820 | |
444 | 1821 return scan_lists (buf, XINT (from), XINT (count), 0, 1, !NILP (noerror)); |
428 | 1822 } |
1823 | |
1824 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, 0, 1, 0, /* | |
1825 Move point backward over any number of chars with prefix syntax. | |
1826 This includes chars with "quote" or "prefix" syntax (' or p). | |
1827 | |
1828 Optional arg BUFFER defaults to the current buffer. | |
1829 */ | |
1830 (buffer)) | |
1831 { | |
1832 struct buffer *buf = decode_buffer (buffer, 0); | |
665 | 1833 Charbpos beg = BUF_BEGV (buf); |
1834 Charbpos pos = BUF_PT (buf); | |
867 | 1835 Ichar c = '\0'; /* initialize to avoid compiler warnings */ |
826 | 1836 struct syntax_cache *scache; |
1837 | |
1838 scache = setup_buffer_syntax_cache (buf, pos, -1); | |
428 | 1839 |
1840 while (pos > beg && !char_quoted (buf, pos - 1) | |
460 | 1841 /* Previous statement updates syntax table. */ |
826 | 1842 && (SYNTAX_FROM_CACHE (scache, c = BUF_FETCH_CHAR (buf, pos - 1)) == Squote |
1843 || SYNTAX_CODE_PREFIX (SYNTAX_CODE_FROM_CACHE (scache, c)))) | |
428 | 1844 pos--; |
1845 | |
1846 BUF_SET_PT (buf, pos); | |
1847 | |
1848 return Qnil; | |
1849 } | |
1850 | |
1851 /* Parse forward from FROM to END, | |
1852 assuming that FROM has state OLDSTATE (nil means FROM is start of function), | |
1853 and return a description of the state of the parse at END. | |
1854 If STOPBEFORE is nonzero, stop at the start of an atom. | |
1855 If COMMENTSTOP is nonzero, stop at the start of a comment. */ | |
1856 | |
1857 static void | |
1858 scan_sexps_forward (struct buffer *buf, struct lisp_parse_state *stateptr, | |
665 | 1859 Charbpos from, Charbpos end, |
428 | 1860 int targetdepth, int stopbefore, |
1861 Lisp_Object oldstate, | |
1862 int commentstop) | |
1863 { | |
1864 struct lisp_parse_state state; | |
1865 | |
1866 enum syntaxcode code; | |
1867 struct level { int last, prev; }; | |
1868 struct level levelstart[100]; | |
1869 struct level *curlevel = levelstart; | |
1870 struct level *endlevel = levelstart + 100; | |
1871 int depth; /* Paren depth of current scanning location. | |
1872 level - levelstart equals this except | |
1873 when the depth becomes negative. */ | |
1874 int mindepth; /* Lowest DEPTH value seen. */ | |
1875 int start_quoted = 0; /* Nonzero means starting after a char quote */ | |
460 | 1876 int boundary_stop = commentstop == -1; |
428 | 1877 Lisp_Object tem; |
826 | 1878 struct syntax_cache *scache; |
1879 | |
1880 scache = setup_buffer_syntax_cache (buf, from, 1); | |
428 | 1881 if (NILP (oldstate)) |
1882 { | |
1883 depth = 0; | |
1884 state.instring = -1; | |
1885 state.incomment = 0; | |
1886 state.comstyle = 0; /* comment style a by default */ | |
460 | 1887 state.comstr_start = -1; /* no comment/string seen. */ |
428 | 1888 } |
1889 else | |
1890 { | |
1891 tem = Fcar (oldstate); /* elt 0, depth */ | |
1892 if (!NILP (tem)) | |
1893 depth = XINT (tem); | |
1894 else | |
1895 depth = 0; | |
1896 | |
1897 oldstate = Fcdr (oldstate); | |
1898 oldstate = Fcdr (oldstate); | |
1899 oldstate = Fcdr (oldstate); | |
1900 tem = Fcar (oldstate); /* elt 3, instring */ | |
460 | 1901 state.instring = ( !NILP (tem) |
1902 ? ( INTP (tem) ? XINT (tem) : ST_STRING_STYLE) | |
1903 : -1); | |
428 | 1904 |
460 | 1905 oldstate = Fcdr (oldstate); |
1906 tem = Fcar (oldstate); /* elt 4, incomment */ | |
428 | 1907 state.incomment = !NILP (tem); |
1908 | |
1909 oldstate = Fcdr (oldstate); | |
1910 tem = Fcar (oldstate); /* elt 5, follows-quote */ | |
1911 start_quoted = !NILP (tem); | |
1912 | |
1913 /* if the eighth element of the list is nil, we are in comment style | |
3025 | 1914 a; if it is t, we are in comment style b; if it is `syntax-table', |
460 | 1915 we are in a generic comment */ |
428 | 1916 oldstate = Fcdr (oldstate); |
1917 oldstate = Fcdr (oldstate); | |
460 | 1918 tem = Fcar (oldstate); /* elt 7, comment style a/b/fence */ |
1919 state.comstyle = NILP (tem) ? 0 : ( EQ (tem, Qsyntax_table) | |
1920 ? ST_COMMENT_STYLE : 1 ); | |
1921 | |
1922 oldstate = Fcdr (oldstate); /* elt 8, start of last comment/string */ | |
1923 tem = Fcar (oldstate); | |
1924 state.comstr_start = NILP (tem) ? -1 : XINT (tem); | |
1925 | |
1926 /* elt 9, char numbers of starts-of-expression of levels | |
1927 (starting from outermost). */ | |
1928 oldstate = Fcdr (oldstate); | |
1929 tem = Fcar (oldstate); /* elt 9, intermediate data for | |
1930 continuation of parsing (subject | |
1931 to change). */ | |
1932 while (!NILP (tem)) /* >= second enclosing sexps. */ | |
1933 { | |
1934 curlevel->last = XINT (Fcar (tem)); | |
1935 if (++curlevel == endlevel) | |
826 | 1936 stack_overflow ("Nesting too deep for parser", |
1937 make_int (curlevel - levelstart)); | |
460 | 1938 curlevel->prev = -1; |
1939 curlevel->last = -1; | |
1940 tem = Fcdr (tem); | |
1941 } | |
428 | 1942 } |
1943 state.quoted = 0; | |
1944 mindepth = depth; | |
1945 | |
1946 curlevel->prev = -1; | |
1947 curlevel->last = -1; | |
1948 | |
1949 /* Enter the loop at a place appropriate for initial state. */ | |
1950 | |
1951 if (state.incomment) goto startincomment; | |
1952 if (state.instring >= 0) | |
1953 { | |
1954 if (start_quoted) goto startquotedinstring; | |
1955 goto startinstring; | |
1956 } | |
1957 if (start_quoted) goto startquoted; | |
1958 | |
1959 while (from < end) | |
1960 { | |
867 | 1961 Ichar c; |
460 | 1962 int syncode; |
1963 | |
428 | 1964 QUIT; |
1965 | |
826 | 1966 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1967 c = BUF_FETCH_CHAR (buf, from); |
826 | 1968 syncode = SYNTAX_CODE_FROM_CACHE (scache, c); |
1969 code = SYNTAX_FROM_CODE (syncode); | |
428 | 1970 from++; |
1971 | |
1972 /* record the comment style we have entered so that only the | |
1973 comment-ender sequence (or single char) of the same style | |
1974 actually terminates the comment section. */ | |
460 | 1975 if (code == Scomment) |
1976 { | |
1977 state.comstyle = | |
1978 SYNTAX_CODE_COMMENT_1CHAR_MASK (syncode) | |
1979 == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
1980 state.comstr_start = from - 1; | |
1981 } | |
1982 | |
1983 /* a generic comment delimiter? */ | |
1984 else if (code == Scomment_fence) | |
1985 { | |
1986 state.comstyle = ST_COMMENT_STYLE; | |
1987 state.comstr_start = from - 1; | |
1988 code = Scomment; | |
428 | 1989 } |
1990 | |
1991 else if (from < end && | |
460 | 1992 SYNTAX_CODE_START_FIRST_P (syncode)) |
428 | 1993 { |
460 | 1994 int next_syncode; |
826 | 1995 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 1996 next_syncode = |
826 | 1997 SYNTAX_CODE_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from)); |
460 | 1998 |
1999 if (SYNTAX_CODES_START_P (syncode, next_syncode)) | |
2000 { | |
428 | 2001 code = Scomment; |
460 | 2002 state.comstyle = SYNTAX_CODES_COMMENT_MASK_START |
2003 (syncode, next_syncode) == SYNTAX_COMMENT_STYLE_A ? 0 : 1; | |
2004 state.comstr_start = from - 1; | |
428 | 2005 from++; |
826 | 2006 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 2007 } |
428 | 2008 } |
2009 | |
460 | 2010 if (SYNTAX_CODE_PREFIX (syncode)) |
428 | 2011 continue; |
2012 switch (code) | |
2013 { | |
2014 case Sescape: | |
2015 case Scharquote: | |
2016 if (stopbefore) goto stop; /* this arg means stop at sexp start */ | |
2017 curlevel->last = from - 1; | |
2018 startquoted: | |
2019 if (from == end) goto endquoted; | |
2020 from++; | |
2021 goto symstarted; | |
2022 /* treat following character as a word constituent */ | |
2023 case Sword: | |
2024 case Ssymbol: | |
2025 if (stopbefore) goto stop; /* this arg means stop at sexp start */ | |
2026 curlevel->last = from - 1; | |
2027 symstarted: | |
2028 while (from < end) | |
2029 { | |
826 | 2030 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
2031 switch (SYNTAX_FROM_CACHE (scache, BUF_FETCH_CHAR (buf, from))) | |
428 | 2032 { |
2033 case Scharquote: | |
2034 case Sescape: | |
2035 from++; | |
2036 if (from == end) goto endquoted; | |
2037 break; | |
2038 case Sword: | |
2039 case Ssymbol: | |
2040 case Squote: | |
2041 break; | |
2042 default: | |
2043 goto symdone; | |
2044 } | |
2045 from++; | |
2046 } | |
2047 symdone: | |
2048 curlevel->prev = curlevel->last; | |
2049 break; | |
2050 | |
2051 case Scomment: | |
2052 state.incomment = 1; | |
460 | 2053 if (commentstop || boundary_stop) goto done; |
428 | 2054 startincomment: |
460 | 2055 if (commentstop == 1) |
428 | 2056 goto done; |
826 | 2057 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
428 | 2058 { |
826 | 2059 Charbpos newfrom = find_end_of_comment (buf, from, end, |
2060 state.comstyle); | |
428 | 2061 if (newfrom < 0) |
2062 { | |
2063 /* we terminated search because from == end */ | |
2064 from = end; | |
2065 goto done; | |
2066 } | |
2067 from = newfrom; | |
2068 } | |
2069 state.incomment = 0; | |
2070 state.comstyle = 0; /* reset the comment style */ | |
460 | 2071 if (boundary_stop) goto done; |
428 | 2072 break; |
2073 | |
2074 case Sopen: | |
2075 if (stopbefore) goto stop; /* this arg means stop at sexp start */ | |
2076 depth++; | |
2077 curlevel->last = from - 1; | |
2078 if (++curlevel == endlevel) | |
826 | 2079 stack_overflow ("Nesting too deep for parser", |
2080 make_int (curlevel - levelstart)); | |
428 | 2081 curlevel->prev = -1; |
2082 curlevel->last = -1; | |
2083 if (targetdepth == depth) goto done; | |
2084 break; | |
2085 | |
2086 case Sclose: | |
2087 depth--; | |
2088 if (depth < mindepth) | |
2089 mindepth = depth; | |
2090 if (curlevel != levelstart) | |
2091 curlevel--; | |
2092 curlevel->prev = curlevel->last; | |
2093 if (targetdepth == depth) goto done; | |
2094 break; | |
2095 | |
2096 case Sstring: | |
460 | 2097 case Sstring_fence: |
2098 state.comstr_start = from - 1; | |
428 | 2099 if (stopbefore) goto stop; /* this arg means stop at sexp start */ |
2100 curlevel->last = from - 1; | |
460 | 2101 if (code == Sstring_fence) |
428 | 2102 { |
460 | 2103 state.instring = ST_STRING_STYLE; |
2104 } | |
2105 else | |
2106 { | |
2107 /* XEmacs change: call syntax_match() on character */ | |
867 | 2108 Ichar ch = BUF_FETCH_CHAR (buf, from - 1); |
460 | 2109 Lisp_Object stermobj = |
1296 | 2110 syntax_match (scache->syntax_table, ch); |
428 | 2111 |
2112 if (CHARP (stermobj)) | |
2113 state.instring = XCHAR (stermobj); | |
2114 else | |
2115 state.instring = ch; | |
2116 } | |
460 | 2117 if (boundary_stop) goto done; |
428 | 2118 startinstring: |
2119 while (1) | |
2120 { | |
460 | 2121 enum syntaxcode temp_code; |
2122 | |
428 | 2123 if (from >= end) goto done; |
460 | 2124 |
826 | 2125 UPDATE_SYNTAX_CACHE_FORWARD (scache, from); |
460 | 2126 c = BUF_FETCH_CHAR (buf, from); |
826 | 2127 temp_code = SYNTAX_FROM_CACHE (scache, c); |
460 | 2128 |
2129 if ( | |
2130 state.instring != ST_STRING_STYLE && | |
2131 temp_code == Sstring && | |
2132 c == state.instring) break; | |
2133 | |
2134 switch (temp_code) | |
428 | 2135 { |
460 | 2136 case Sstring_fence: |
2137 if (state.instring == ST_STRING_STYLE) | |
2138 goto string_end; | |
2139 break; | |
428 | 2140 case Scharquote: |
2141 case Sescape: | |
2142 { | |
2143 from++; | |
2144 startquotedinstring: | |
2145 if (from >= end) goto endquoted; | |
2146 break; | |
2147 } | |
2148 default: | |
2149 break; | |
2150 } | |
2151 from++; | |
2152 } | |
460 | 2153 string_end: |
428 | 2154 state.instring = -1; |
2155 curlevel->prev = curlevel->last; | |
2156 from++; | |
460 | 2157 if (boundary_stop) goto done; |
428 | 2158 break; |
2159 | |
2160 case Smath: | |
2161 break; | |
2162 | |
2163 case Swhitespace: | |
2164 case Spunct: | |
2165 case Squote: | |
2166 case Sendcomment: | |
460 | 2167 case Scomment_fence: |
428 | 2168 case Sinherit: |
2169 case Smax: | |
2170 break; | |
2171 } | |
2172 } | |
2173 goto done; | |
2174 | |
2175 stop: /* Here if stopping before start of sexp. */ | |
2176 from--; /* We have just fetched the char that starts it; */ | |
2177 goto done; /* but return the position before it. */ | |
2178 | |
2179 endquoted: | |
2180 state.quoted = 1; | |
2181 done: | |
2182 state.depth = depth; | |
2183 state.mindepth = mindepth; | |
2184 state.thislevelstart = curlevel->prev; | |
2185 state.prevlevelstart | |
2186 = (curlevel == levelstart) ? -1 : (curlevel - 1)->last; | |
2187 state.location = from; | |
460 | 2188 state.levelstarts = Qnil; |
2189 while (--curlevel >= levelstart) | |
2190 state.levelstarts = Fcons (make_int (curlevel->last), | |
2191 state.levelstarts); | |
428 | 2192 |
2193 *stateptr = state; | |
2194 } | |
2195 | |
2196 DEFUN ("parse-partial-sexp", Fparse_partial_sexp, 2, 7, 0, /* | |
2197 Parse Lisp syntax starting at FROM until TO; return status of parse at TO. | |
2198 Parsing stops at TO or when certain criteria are met; | |
2199 point is set to where parsing stops. | |
444 | 2200 If fifth arg OLDSTATE is omitted or nil, |
428 | 2201 parsing assumes that FROM is the beginning of a function. |
460 | 2202 Value is a list of nine elements describing final state of parsing: |
428 | 2203 0. depth in parens. |
2204 1. character address of start of innermost containing list; nil if none. | |
2205 2. character address of start of last complete sexp terminated. | |
2206 3. non-nil if inside a string. | |
460 | 2207 (It is the character that will terminate the string, |
2208 or t if the string should be terminated by an explicit | |
2209 `syntax-table' property.) | |
428 | 2210 4. t if inside a comment. |
2211 5. t if following a quote character. | |
2212 6. the minimum paren-depth encountered during this scan. | |
460 | 2213 7. nil if in comment style a, or not in a comment; t if in comment style b; |
2214 `syntax-table' if given by an explicit `syntax-table' property. | |
2215 8. character address of start of last comment or string; nil if none. | |
2216 9. Intermediate data for continuation of parsing (subject to change). | |
428 | 2217 If third arg TARGETDEPTH is non-nil, parsing stops if the depth |
2218 in parentheses becomes equal to TARGETDEPTH. | |
2219 Fourth arg STOPBEFORE non-nil means stop when come to | |
2220 any character that starts a sexp. | |
460 | 2221 Fifth arg OLDSTATE is a nine-element list like what this function returns. |
428 | 2222 It is used to initialize the state of the parse. Its second and third |
2223 elements are ignored. | |
460 | 2224 Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. If it |
2225 is `syntax-table', stop after the start of a comment or a string, or after | |
2226 the end of a comment or string. | |
826 | 2227 Seventh arg BUFFER specifies the buffer to do the parsing in, and defaults |
2228 to the current buffer. | |
428 | 2229 */ |
2230 (from, to, targetdepth, stopbefore, oldstate, commentstop, buffer)) | |
2231 { | |
2232 struct lisp_parse_state state; | |
2233 int target; | |
665 | 2234 Charbpos start, end; |
428 | 2235 struct buffer *buf = decode_buffer (buffer, 0); |
2236 Lisp_Object val; | |
2237 | |
2238 if (!NILP (targetdepth)) | |
2239 { | |
2240 CHECK_INT (targetdepth); | |
2241 target = XINT (targetdepth); | |
2242 } | |
2243 else | |
2244 target = -100000; /* We won't reach this depth */ | |
2245 | |
2246 get_buffer_range_char (buf, from, to, &start, &end, 0); | |
2247 scan_sexps_forward (buf, &state, start, end, | |
2248 target, !NILP (stopbefore), oldstate, | |
460 | 2249 (NILP (commentstop) |
2250 ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1))); | |
428 | 2251 BUF_SET_PT (buf, state.location); |
2252 | |
2253 /* reverse order */ | |
2254 val = Qnil; | |
460 | 2255 val = Fcons (state.levelstarts, val); |
2256 val = Fcons ((state.incomment || (state.instring >= 0)) | |
2257 ? make_int (state.comstr_start) : Qnil, val); | |
2258 val = Fcons (state.comstyle ? (state.comstyle == ST_COMMENT_STYLE | |
2259 ? Qsyntax_table : Qt) : Qnil, val); | |
428 | 2260 val = Fcons (make_int (state.mindepth), val); |
2261 val = Fcons (state.quoted ? Qt : Qnil, val); | |
2262 val = Fcons (state.incomment ? Qt : Qnil, val); | |
460 | 2263 val = Fcons (state.instring < 0 |
2264 ? Qnil | |
2265 : (state.instring == ST_STRING_STYLE | |
2266 ? Qt : make_int (state.instring)), val); | |
826 | 2267 val = Fcons (state.thislevelstart < 0 ? Qnil : |
2268 make_int (state.thislevelstart), val); | |
2269 val = Fcons (state.prevlevelstart < 0 ? Qnil : | |
2270 make_int (state.prevlevelstart), val); | |
428 | 2271 val = Fcons (make_int (state.depth), val); |
2272 | |
2273 return val; | |
2274 } | |
2275 | |
2276 | |
2277 /* Updating of the mirror syntax table. | |
2278 | |
1296 | 2279 Each syntax table has a corresponding mirror table in it. Whenever we |
2280 make a change to a syntax table, we set a dirty flag. When accessing a | |
2281 value from the mirror table and the table is dirty, we call | |
2282 update_syntax_table() to clean it up. | |
428 | 2283 |
2284 #### We really only need to map over the changed range. | |
2285 | |
2286 If we change the standard syntax table, we need to map over | |
2287 all tables because any of them could be inheriting from the | |
2288 standard syntax table. | |
2289 | |
2290 When `set-syntax-table' is called, we set the buffer's mirror | |
2291 syntax table as well. | |
2292 */ | |
2293 | |
826 | 2294 static int |
2286 | 2295 copy_to_mirrortab (struct chartab_range *range, Lisp_Object UNUSED (table), |
826 | 2296 Lisp_Object val, void *arg) |
428 | 2297 { |
5013 | 2298 Lisp_Object mirrortab = GET_LISP_FROM_VOID (arg); |
428 | 2299 |
2300 if (CONSP (val)) | |
2301 val = XCAR (val); | |
826 | 2302 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit) |
2303 put_char_table (mirrortab, range, val); | |
2304 return 0; | |
2305 } | |
2306 | |
2307 static int | |
2286 | 2308 copy_if_not_already_present (struct chartab_range *range, |
2309 Lisp_Object UNUSED (table), | |
826 | 2310 Lisp_Object val, void *arg) |
2311 { | |
5013 | 2312 Lisp_Object mirrortab = GET_LISP_FROM_VOID (arg); |
826 | 2313 if (CONSP (val)) |
2314 val = XCAR (val); | |
2315 if (SYNTAX_FROM_CODE (XINT (val)) != Sinherit) | |
2316 { | |
2317 Lisp_Object existing = | |
1296 | 2318 updating_mirror_get_range_char_table (range, mirrortab, |
2319 Vbogus_syntax_table_value); | |
826 | 2320 if (NILP (existing)) |
2321 /* nothing at all */ | |
1296 | 2322 put_char_table (mirrortab, range, val); |
2323 else if (!EQ (existing, Vbogus_syntax_table_value)) | |
826 | 2324 /* full */ |
2325 ; | |
2326 else | |
2327 { | |
2328 Freset_char_table (Vtemp_table_for_use_updating_syntax_tables); | |
2329 copy_char_table_range | |
1296 | 2330 (mirrortab, Vtemp_table_for_use_updating_syntax_tables, range); |
2331 put_char_table (mirrortab, range, val); | |
826 | 2332 copy_char_table_range |
1296 | 2333 (Vtemp_table_for_use_updating_syntax_tables, mirrortab, range); |
826 | 2334 } |
428 | 2335 } |
826 | 2336 |
428 | 2337 return 0; |
2338 } | |
2339 | |
2340 static void | |
826 | 2341 update_just_this_syntax_table (Lisp_Object table) |
428 | 2342 { |
2343 struct chartab_range range; | |
826 | 2344 Lisp_Object mirrortab = XCHAR_TABLE (table)->mirror_table; |
2345 | |
1296 | 2346 assert (!XCHAR_TABLE (table)->mirror_table_p); |
826 | 2347 range.type = CHARTAB_RANGE_ALL; |
2348 Freset_char_table (mirrortab); | |
1296 | 2349 |
826 | 2350 /* First, copy the tables values other than inherit into the mirror |
2351 table. Then, for tables other than the standard syntax table, map | |
2352 over the standard table, copying values into the mirror table only if | |
2353 entries don't already exist in that table. (The copying step requires | |
2354 another mapping.) | |
2355 */ | |
428 | 2356 |
5013 | 2357 map_char_table (table, &range, copy_to_mirrortab, STORE_LISP_IN_VOID (mirrortab)); |
826 | 2358 /* second clause catches bootstrapping problems when initializing the |
2359 standard syntax table */ | |
2360 if (!EQ (table, Vstandard_syntax_table) && !NILP (Vstandard_syntax_table)) | |
1296 | 2361 map_char_table (Vstandard_syntax_table, &range, |
5013 | 2362 copy_if_not_already_present, STORE_LISP_IN_VOID (mirrortab)); |
3152 | 2363 /* The resetting made the default be Qnil. Put it back to Sword. */ |
2364 set_char_table_default (mirrortab, make_int (Sword)); | |
1296 | 2365 XCHAR_TABLE (mirrortab)->dirty = 0; |
428 | 2366 } |
2367 | |
2368 /* Called from chartab.c when a change is made to a syntax table. | |
2369 If this is the standard syntax table, we need to recompute | |
2370 *all* syntax tables (yuck). Otherwise we just recompute this | |
2371 one. */ | |
2372 | |
2373 void | |
826 | 2374 update_syntax_table (Lisp_Object table) |
428 | 2375 { |
1296 | 2376 Lisp_Object nonmirror = XCHAR_TABLE (table)->mirror_table; |
2377 assert (XCHAR_TABLE (table)->mirror_table_p); | |
2378 if (EQ (nonmirror, Vstandard_syntax_table)) | |
428 | 2379 { |
2380 Lisp_Object syntab; | |
2381 | |
2382 for (syntab = Vall_syntax_tables; !NILP (syntab); | |
2383 syntab = XCHAR_TABLE (syntab)->next_table) | |
826 | 2384 update_just_this_syntax_table (syntab); |
428 | 2385 } |
2386 else | |
1296 | 2387 update_just_this_syntax_table (nonmirror); |
428 | 2388 } |
2389 | |
2390 | |
2391 /************************************************************************/ | |
2392 /* initialization */ | |
2393 /************************************************************************/ | |
2394 | |
2395 void | |
2396 syms_of_syntax (void) | |
2397 { | |
3092 | 2398 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
2399 INIT_LISP_OBJECT (syntax_cache); |
3092 | 2400 #endif /* NEW_GC */ |
563 | 2401 DEFSYMBOL (Qsyntax_table_p); |
2402 DEFSYMBOL (Qsyntax_table); | |
428 | 2403 |
2404 DEFSUBR (Fsyntax_table_p); | |
2405 DEFSUBR (Fsyntax_table); | |
826 | 2406 #ifdef DEBUG_XEMACS |
2407 DEFSUBR (Fmirror_syntax_table); | |
2408 DEFSUBR (Fsyntax_cache_info); | |
2409 #endif /* DEBUG_XEMACS */ | |
428 | 2410 DEFSUBR (Fstandard_syntax_table); |
2411 DEFSUBR (Fcopy_syntax_table); | |
2412 DEFSUBR (Fset_syntax_table); | |
2413 DEFSUBR (Fsyntax_designator_chars); | |
2414 DEFSUBR (Fchar_syntax); | |
2415 DEFSUBR (Fmatching_paren); | |
2416 /* DEFSUBR (Fmodify_syntax_entry); now in Lisp. */ | |
2417 /* DEFSUBR (Fdescribe_syntax); now in Lisp. */ | |
2418 | |
2419 DEFSUBR (Fforward_word); | |
2420 | |
2421 DEFSUBR (Fforward_comment); | |
2422 DEFSUBR (Fscan_lists); | |
2423 DEFSUBR (Fscan_sexps); | |
2424 DEFSUBR (Fbackward_prefix_chars); | |
2425 DEFSUBR (Fparse_partial_sexp); | |
4912
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
2426 |
e99033b7e05c
use more specific `scan-error' in scan-lists to be GNU compatible
Ben Wing <ben@xemacs.org>
parents:
4759
diff
changeset
|
2427 DEFERROR_STANDARD (Qscan_error, Qsyntax_error); |
428 | 2428 } |
2429 | |
2430 void | |
2431 vars_of_syntax (void) | |
2432 { | |
2433 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments /* | |
2434 Non-nil means `forward-sexp', etc., should treat comments as whitespace. | |
2435 */ ); | |
434 | 2436 parse_sexp_ignore_comments = 0; |
428 | 2437 |
460 | 2438 DEFVAR_BOOL ("lookup-syntax-properties", &lookup_syntax_properties /* |
826 | 2439 Non-nil means `forward-sexp', etc., respect the `syntax-table' property. |
2440 This property can be placed on buffers or strings and can be used to explicitly | |
2441 specify the syntax table to be used for looking up the syntax of the chars | |
2442 having this property, or to directly specify the syntax of the chars. | |
2443 | |
460 | 2444 The value of this property should be either a syntax table, or a cons |
2445 of the form (SYNTAXCODE . MATCHCHAR), SYNTAXCODE being the numeric | |
2446 syntax code, MATCHCHAR being nil or the character to match (which is | |
826 | 2447 relevant only when the syntax code is open/close-type). |
460 | 2448 */ ); |
2449 lookup_syntax_properties = 1; | |
2450 | |
428 | 2451 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes /* |
2452 Non-nil means `forward-word', etc., should treat escape chars part of words. | |
2453 */ ); | |
434 | 2454 words_include_escapes = 0; |
428 | 2455 |
2456 no_quit_in_re_search = 0; | |
1296 | 2457 |
2458 Vbogus_syntax_table_value = make_float (0.0); | |
2459 staticpro (&Vbogus_syntax_table_value); | |
428 | 2460 } |
2461 | |
2462 static void | |
3540 | 2463 define_standard_syntax (const UExtbyte *p, enum syntaxcode syn) |
428 | 2464 { |
2465 for (; *p; p++) | |
2466 Fput_char_table (make_char (*p), make_int (syn), Vstandard_syntax_table); | |
2467 } | |
2468 | |
2469 void | |
2470 complex_vars_of_syntax (void) | |
2471 { | |
867 | 2472 Ichar i; |
3540 | 2473 const UExtbyte *p; /* Latin-1, not internal format. */ |
2474 | |
2475 #define SET_RANGE_SYNTAX(start, end, syntax) \ | |
2476 do { \ | |
2477 for (i = start; i <= end; i++) \ | |
2478 Fput_char_table(make_char(i), make_int(syntax), \ | |
2479 Vstandard_syntax_table); \ | |
2480 } while (0) | |
2481 | |
2482 /* Set this now, so first buffer creation can refer to it. | |
2483 | |
2484 Make it nil before calling copy-syntax-table so that copy-syntax-table | |
2485 will know not to try to copy from garbage */ | |
428 | 2486 Vstandard_syntax_table = Qnil; |
2487 Vstandard_syntax_table = Fcopy_syntax_table (Qnil); | |
2488 staticpro (&Vstandard_syntax_table); | |
2489 | |
826 | 2490 Vtemp_table_for_use_updating_syntax_tables = Fmake_char_table (Qgeneric); |
2491 staticpro (&Vtemp_table_for_use_updating_syntax_tables); | |
2492 | |
428 | 2493 Vsyntax_designator_chars_string = make_string_nocopy (syntax_code_spec, |
2494 Smax); | |
2495 staticpro (&Vsyntax_designator_chars_string); | |
2496 | |
3540 | 2497 /* Default character syntax is word. */ |
3152 | 2498 set_char_table_default (Vstandard_syntax_table, make_int (Sword)); |
428 | 2499 |
3540 | 2500 /* Control 0; treat as punctuation */ |
2501 SET_RANGE_SYNTAX(0, 32, Spunct); | |
428 | 2502 |
3544 | 2503 /* The whitespace--overwriting some of the above changes. |
2504 | |
2505 String literals are const char *s, not const unsigned char *s. */ | |
4653
25e5e5346d31
?\012 is whitespace, as it always should have been, thank you Karl Kleinpaste.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4141
diff
changeset
|
2506 define_standard_syntax((const UExtbyte *)" \t\015\014\012", Swhitespace); |
3540 | 2507 |
2508 /* DEL plus Control 1 */ | |
2509 SET_RANGE_SYNTAX(127, 159, Spunct); | |
2510 | |
3544 | 2511 define_standard_syntax ((const UExtbyte *)"\"", Sstring); |
2512 define_standard_syntax ((const UExtbyte *)"\\", Sescape); | |
2513 define_standard_syntax ((const UExtbyte *)"_-+*/&|<>=", Ssymbol); | |
2514 define_standard_syntax ((const UExtbyte *)".,;:?!#@~^'`", Spunct); | |
428 | 2515 |
3544 | 2516 for (p = (const UExtbyte *)"()[]{}"; *p; p+=2) |
428 | 2517 { |
2518 Fput_char_table (make_char (p[0]), | |
2519 Fcons (make_int (Sopen), make_char (p[1])), | |
2520 Vstandard_syntax_table); | |
2521 Fput_char_table (make_char (p[1]), | |
2522 Fcons (make_int (Sclose), make_char (p[0])), | |
2523 Vstandard_syntax_table); | |
2524 } | |
3540 | 2525 |
2526 /* Latin 1 "symbols." This contrasts with the FSF, where they're word | |
2527 constituents. */ | |
2528 SET_RANGE_SYNTAX(0240, 0277, Ssymbol); | |
2529 | |
2530 /* The guillemets. These are not parentheses, in contrast to what the old | |
2531 code did. */ | |
3569 | 2532 define_standard_syntax((const UExtbyte *)"\253\273", Spunct); |
3540 | 2533 |
2534 /* The inverted exclamation mark, and the multiplication and division | |
2535 signs. */ | |
3544 | 2536 define_standard_syntax((const UExtbyte *)"\241\327\367", Spunct); |
3540 | 2537 |
2538 #undef SET_RANGE_SYNTAX | |
428 | 2539 } |