comparison src/syntax.c @ 17464:36483a1ada24

(SYNTAX_ENTRY_VIA_PROPERTY): Set to take `syntax-table' text property into account when doing SYNTAX (c). (ST_COMMENT_STYLE, ST_STRING_STYLE): New codes to denote delimiters for new types of strings and comments. (Vparse_sexp_lookup_properties): New variable. (struct lisp_parse_state): Comment updated. (gl_state): New global variable. (update_syntax_table): New function. (char_quoted): Move earlier, update gl_state when needed. (find_defun_start): Update gl_state when needed. (back_comment): New function. (Scomment_fence, Sstring_fence): New delimeter char classes denoted by `!' and `|'. (Fchar_syntax, Fmatching_paren): Update gl_state to whole-bufferstate. (scan_words): update gl_state when needed. (Fskip_chars_forward): Move from search.c. (Fskip_chars_backward): Move from search.c. (Fskip_syntax_forward): Move from search.c. (Fskip_syntax_backward): Move from search.c. (skip_chars): Move from search.c. (Fforward_comment, scan_lists): Update gl_state when needed. Handle Scomment_fence, Sstring_fence. (Fbackward_prefix_chars) Update gl_state when needed. (scan_sexps_forward): Update gl_state when needed. Handle Scomment_fence, Sstring_fence. If comment_stop==-1, stop at start or end of comment or string. (Fparse-partial-sexp): Doc fix. (syms_of_syntax): Move initialization of skip* from search.c.
author Richard M. Stallman <rms@gnu.org>
date Tue, 15 Apr 1997 04:53:58 +0000
parents f8d7263cce09
children c6ba5208968b
comparison
equal deleted inserted replaced
17463:bb9ae80d22e2 17464:36483a1ada24
23 #include <ctype.h> 23 #include <ctype.h>
24 #include "lisp.h" 24 #include "lisp.h"
25 #include "commands.h" 25 #include "commands.h"
26 #include "buffer.h" 26 #include "buffer.h"
27 #include "charset.h" 27 #include "charset.h"
28
29 /* Make syntax table lookup grant data in gl_state. */
30 #define SYNTAX_ENTRY_VIA_PROPERTY
31
28 #include "syntax.h" 32 #include "syntax.h"
33 #include "intervals.h"
34
35 /* We use these constants in place for comment-style and
36 string-ender-char to distinguish comments/strings started by
37 comment_fence and string_fence codes. */
38
39 #define ST_COMMENT_STYLE (256 + 1)
40 #define ST_STRING_STYLE (256 + 2)
29 #include "category.h" 41 #include "category.h"
30 42
31 Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error; 43 Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error;
32 44
33 static void scan_sexps_forward (); 45 static void scan_sexps_forward ();
34 static int char_quoted (); 46 static int char_quoted ();
35 47
36 int words_include_escapes; 48 int words_include_escapes;
49 int parse_sexp_lookup_properties;
37 50
38 /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h, 51 /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
39 if not compiled with GCC. No need to mark it, since it is used 52 if not compiled with GCC. No need to mark it, since it is used
40 only very temporarily. */ 53 only very temporarily. */
41 Lisp_Object syntax_temp; 54 Lisp_Object syntax_temp;
42 55
43 /* This is the internal form of the parse state used in parse-partial-sexp. */ 56 /* This is the internal form of the parse state used in parse-partial-sexp. */
44 57
45 struct lisp_parse_state 58 struct lisp_parse_state
46 { 59 {
47 int depth; /* Depth at end of parsing */ 60 int depth; /* Depth at end of parsing. */
48 int instring; /* -1 if not within string, else desired terminator. */ 61 int instring; /* -1 if not within string, else desired terminator. */
49 int incomment; /* Nonzero if within a comment at end of parsing */ 62 int incomment; /* Nonzero if within a comment at end of parsing. */
50 int comstyle; /* comment style a=0, or b=1 */ 63 int comstyle; /* comment style a=0, or b=1, or ST_COMMENT_STYLE. */
51 int quoted; /* Nonzero if just after an escape char at end of parsing */ 64 int quoted; /* Nonzero if just after an escape char at end of parsing */
52 int thislevelstart; /* Char number of most recent start-of-expression at current level */ 65 int thislevelstart; /* Char number of most recent start-of-expression at current level */
53 int prevlevelstart; /* Char number of start of containing expression */ 66 int prevlevelstart; /* Char number of start of containing expression */
54 int location; /* Char number at which parsing stopped. */ 67 int location; /* Char number at which parsing stopped. */
55 int mindepth; /* Minimum depth seen while scanning. */ 68 int mindepth; /* Minimum depth seen while scanning. */
56 int comstart; /* Position just after last comment starter. */ 69 int comstr_start; /* Position just after last comment/string starter. */
57 }; 70 };
58 71
59 /* These variables are a cache for finding the start of a defun. 72 /* These variables are a cache for finding the start of a defun.
60 find_start_pos is the place for which the defun start was found. 73 find_start_pos is the place for which the defun start was found.
61 find_start_value is the defun start position found for it. 74 find_start_value is the defun start position found for it.
66 static int find_start_pos; 79 static int find_start_pos;
67 static int find_start_value; 80 static int find_start_value;
68 static struct buffer *find_start_buffer; 81 static struct buffer *find_start_buffer;
69 static int find_start_begv; 82 static int find_start_begv;
70 static int find_start_modiff; 83 static int find_start_modiff;
71 84
85
86 struct gl_state_s gl_state; /* Global state of syntax parser. */
87
88 INTERVAL interval_of ();
89 #define INTERVALS_AT_ONCE 10 /* 1 + max-number of intervals
90 to scan to property-change. */
91
92 /*
93 Update gl_state to an appropriate interval which contains POS. The
94 sign of COUNT give the relative position of POS wrt the previously
95 valid interval. If INIT, only [be]_property fields of gl_state are
96 valid at start, the rest is filled basing on OBJECT.
97
98 `gl_state.*_i' are the intervals, and pos is further in the search
99 direction than the intervals - or in an interval. We update the
100 current syntax-table basing on the property of this interval, and
101 update the interval to start further than POS - or be
102 NULL_INTERVAL. We also update lim_property to be the next value of
103 pos to call this subroutine again - or be before/after the
104 start/end of OBJECT. */
105
106 void
107 update_syntax_table (pos, count, init, object)
108 int pos, count, init;
109 Lisp_Object object;
110 {
111 Lisp_Object tmp_table;
112 int cnt = 0, doing_extra = 0, invalidate = 1;
113 INTERVAL i, oldi;
114
115 if (init)
116 {
117 gl_state.start = gl_state.b_property;
118 gl_state.stop = gl_state.e_property;
119 gl_state.forward_i = interval_of (pos, object);
120 i = gl_state.backward_i = gl_state.forward_i;
121 gl_state.left_ok = gl_state.right_ok = 1;
122 invalidate = 0;
123 if (NULL_INTERVAL_P (i))
124 return;
125 gl_state.b_property = i->position - 1;
126 gl_state.e_property = INTERVAL_LAST_POS (i);
127 goto update;
128 }
129 oldi = i = count > 0 ? gl_state.forward_i : gl_state.backward_i;
130
131 /* We are guarantied to be called with pos either in i, of further off. */
132 if (NULL_INTERVAL_P (i))
133 error ("Error in syntax_table logic for to-the-end intervals");
134 else if (pos < i->position) /* Move left. */
135 {
136 if (count > 0)
137 error ("Error in syntax_table logic for intervals <-.");
138 /* Update the interval. */
139 i = update_interval (i, pos);
140 if (oldi->position != INTERVAL_LAST_POS (i))
141 {
142 invalidate = 0;
143 gl_state.right_ok = 1; /* Invalidate the other end. */
144 gl_state.forward_i = i;
145 gl_state.e_property = INTERVAL_LAST_POS (i);
146 }
147 }
148 else if (pos >= INTERVAL_LAST_POS (i)) /* Move right. */
149 {
150 if (count < 0)
151 error ("Error in syntax_table logic for intervals ->.");
152 /* Update the interval. */
153 i = update_interval (i, pos);
154 if (i->position != INTERVAL_LAST_POS (oldi))
155 {
156 invalidate = 0;
157 gl_state.left_ok = 1; /* Invalidate the other end. */
158 gl_state.backward_i = i;
159 gl_state.b_property = i->position - 1;
160 }
161 }
162 else if (count > 0 ? gl_state.right_ok : gl_state.left_ok)
163 {
164 /* We do not need to recalculate tmp_table. */
165 tmp_table = gl_state.old_prop;
166 }
167
168 update:
169 tmp_table = textget (i->plist, Qsyntax_table);
170
171 if (invalidate)
172 invalidate = !EQ (tmp_table, gl_state.old_prop); /* Need to invalidate? */
173
174 if (invalidate) /* Did not get to adjacent interval. */
175 { /* with the same table => */
176 /* invalidate the old range. */
177 if (count > 0)
178 {
179 gl_state.backward_i = i;
180 gl_state.left_ok = 1; /* Invalidate the other end. */
181 gl_state.b_property = i->position - 1;
182 }
183 else
184 {
185 gl_state.forward_i = i;
186 gl_state.right_ok = 1; /* Invalidate the other end. */
187 gl_state.e_property = INTERVAL_LAST_POS (i);
188 }
189 }
190
191 gl_state.current_syntax_table = tmp_table;
192 gl_state.old_prop = tmp_table;
193 if (Fsyntax_table_p (tmp_table) == Qt)
194 {
195 gl_state.use_global = 0;
196 }
197 else if (CONSP (tmp_table))
198 {
199 gl_state.use_global = 1;
200 gl_state.global_code = tmp_table;
201 }
202 else
203 {
204 gl_state.use_global = 0;
205 gl_state.current_syntax_table = current_buffer->syntax_table;
206 }
207
208 while (!NULL_INTERVAL_P (i))
209 {
210 if (cnt && !EQ (tmp_table, textget (i->plist, Qsyntax_table)))
211 {
212 if (count > 0)
213 gl_state.right_ok = 0;
214 else
215 gl_state.left_ok = 0;
216 break;
217 }
218 else if (cnt == INTERVALS_AT_ONCE)
219 {
220 if (count > 0)
221 gl_state.right_ok = 1;
222 else
223 gl_state.left_ok = 1;
224 break;
225 }
226 cnt++;
227 i = count > 0 ? next_interval (i) : previous_interval (i);
228 }
229 if (NULL_INTERVAL_P (i))
230 { /* This property goes to the end. */
231 if (count > 0)
232 gl_state.e_property = gl_state.stop;
233 else
234 gl_state.b_property = gl_state.start;
235 }
236 else
237 {
238 if (count > 0)
239 {
240 gl_state.e_property = i->position;
241 gl_state.forward_i = i;
242 }
243 else
244 {
245 gl_state.b_property = i->position + LENGTH (i) - 1;
246 gl_state.backward_i = i;
247 }
248 }
249 }
250
251 /* Returns TRUE if char at POS is quoted.
252 Global syntax-table data should be set up already to be good at pos
253 or after. On return global syntax data is good for lookup at POS. */
254
255 static int
256 char_quoted (pos)
257 register int pos;
258 {
259 register enum syntaxcode code;
260 register int beg = BEGV;
261 register int quoted = 0;
262 int temp_pos = pos;
263
264 DEC_POS (temp_pos);
265 while (temp_pos >= beg
266 && ( UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos), 1)
267 && ((code = SYNTAX (FETCH_CHAR (temp_pos))) == Scharquote
268 || code == Sescape))
269 {
270 temp_pos--, quoted = !quoted;
271 }
272 UPDATE_SYNTAX_TABLE (pos);
273 return quoted;
274 }
275
72 /* Find a defun-start that is the last one before POS (or nearly the last). 276 /* Find a defun-start that is the last one before POS (or nearly the last).
73 We record what we find, so that another call in the same area 277 We record what we find, so that another call in the same area
74 can return the same value right away. */ 278 can return the same value right away.
279
280 There is no promise at which position the global syntax data is
281 valid on return from the subroutine, so the caller should explicitly
282 update the global data. */
75 283
76 static int 284 static int
77 find_defun_start (pos) 285 find_defun_start (pos)
78 int pos; 286 int pos;
79 { 287 {
92 return find_start_value; 300 return find_start_value;
93 301
94 /* Back up to start of line. */ 302 /* Back up to start of line. */
95 tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1); 303 tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1);
96 304
305 /* We optimize syntax-table lookup for rare updates. Thus we accept
306 only those `^\s(' which are good in global _and_ text-property
307 syntax-tables. */
308 gl_state.current_syntax_table = current_buffer->syntax_table;
309 gl_state.use_global = 0;
97 while (tem > BEGV) 310 while (tem > BEGV)
98 { 311 {
99 /* Open-paren at start of line means we found our defun-start. */ 312 /* Open-paren at start of line means we found our defun-start. */
100 if (SYNTAX (FETCH_CHAR (tem)) == Sopen) 313 if (SYNTAX (FETCH_CHAR (tem)) == Sopen)
101 break; 314 {
315 SETUP_SYNTAX_TABLE (tem + 1, -1); /* Try again... */
316 if (SYNTAX (FETCH_CHAR (tem)) == Sopen)
317 break;
318 /* Now fallback to the default value. */
319 gl_state.current_syntax_table = current_buffer->syntax_table;
320 gl_state.use_global = 0;
321 }
102 /* Move to beg of previous line. */ 322 /* Move to beg of previous line. */
103 tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1); 323 tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1);
104 } 324 }
105 325
106 /* Record what we found, for the next try. */ 326 /* Record what we found, for the next try. */
111 find_start_pos = pos; 331 find_start_pos = pos;
112 332
113 return find_start_value; 333 return find_start_value;
114 } 334 }
115 335
336 /* Checks whether FROM is the end of comment. Does not try to
337 fallback more than to STOP.
338 Returns -1 if cannot find comment ending at from, otherwise start
339 of comment. Global syntax data remains valid for
340 backward search starting at the returned value (or at FROM, if
341 the search was not successful). */
342
343 static int
344 back_comment (from, stop)
345 int from, stop;
346 {
347 /* Look back, counting the parity of string-quotes,
348 and recording the comment-starters seen.
349 When we reach a safe place, assume that's not in a string;
350 then step the main scan to the earliest comment-starter seen
351 an even number of string quotes away from the safe place.
352
353 OFROM[I] is position of the earliest comment-starter seen
354 which is I+2X quotes from the comment-end.
355 PARITY is current parity of quotes from the comment end. */
356 int parity = 0;
357 int my_stringend = 0;
358 int string_lossage = 0;
359 int comment_end = from;
360 int comstart_pos = 0;
361 int comstart_parity = 0;
362 int scanstart = from - 1;
363 register enum syntaxcode code;
364 int c, comstyle = 0;
365
366 /* At beginning of range to scan, we're outside of strings;
367 that determines quote parity to the comment-end. */
368 while (from != stop)
369 {
370 /* Move back and examine a character. */
371 DEC_POS (from);
372 UPDATE_SYNTAX_TABLE_BACKWARD (from);
373
374 c = FETCH_CHAR (from);
375 code = SYNTAX (c);
376
377 /* If this char is the second of a 2-char comment sequence,
378 back up and give the pair the appropriate syntax. */
379 if (from > stop && SYNTAX_COMEND_SECOND (c)
380 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)))
381 {
382 code = Sendcomment;
383 DEC_POS (from);
384 /* This is apparently the best we can do: */
385 UPDATE_SYNTAX_TABLE_BACKWARD (from);
386 c = FETCH_CHAR (from);
387 }
388
389 /* If this char starts a 2-char comment start sequence,
390 treat it like a 1-char comment starter. */
391 if (from < scanstart && SYNTAX_COMSTART_FIRST (c)
392 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1))
393 && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1)))
394 code = Scomment;
395
396 /* Ignore escaped characters. */
397 if (char_quoted (from))
398 continue;
399
400 /* Track parity of quotes. */
401 if (code == Sstring)
402 {
403 parity ^= 1;
404 if (my_stringend == 0)
405 my_stringend = c;
406 /* If we have two kinds of string delimiters.
407 There's no way to grok this scanning backwards. */
408 else if (my_stringend != c)
409 string_lossage = 1;
410 }
411
412 if (code == Sstring_fence || code == Scomment_fence)
413 {
414 parity ^= 1;
415 if (my_stringend == 0)
416 my_stringend =
417 code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE;
418 /* If we have two kinds of string delimiters.
419 There's no way to grok this scanning backwards. */
420 else if (my_stringend != (code == Sstring_fence
421 ? ST_STRING_STYLE : ST_COMMENT_STYLE))
422 string_lossage = 1;
423 }
424
425 /* Record comment-starters according to that
426 quote-parity to the comment-end. */
427 if (code == Scomment)
428 {
429 comstart_parity = parity;
430 comstart_pos = from;
431 }
432
433 /* If we find another earlier comment-ender,
434 any comment-starts earlier than that don't count
435 (because they go with the earlier comment-ender). */
436 if (code == Sendcomment
437 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle)
438 break;
439
440 /* Assume a defun-start point is outside of strings. */
441 if (code == Sopen
442 && (from == stop || FETCH_CHAR (from - 1) == '\n'))
443 break;
444 }
445
446 if (comstart_pos == 0)
447 {
448 from = comment_end;
449 UPDATE_SYNTAX_TABLE_FORWARD (comment_end - 1);
450 }
451 /* If the earliest comment starter
452 is followed by uniform paired string quotes or none,
453 we know it can't be inside a string
454 since if it were then the comment ender would be inside one.
455 So it does start a comment. Skip back to it. */
456 else if (comstart_parity == 0 && !string_lossage)
457 {
458 from = comstart_pos;
459 /* Globals are correct now. */
460 }
461 else
462 {
463 /* We had two kinds of string delimiters mixed up
464 together. Decode this going forwards.
465 Scan fwd from the previous comment ender
466 to the one in question; this records where we
467 last passed a comment starter. */
468 struct lisp_parse_state state;
469 scan_sexps_forward (&state, find_defun_start (comment_end),
470 comment_end - 1, -10000, 0, Qnil, 0);
471 if (state.incomment)
472 {
473 /* scan_sexps_forward changed the direction of search in
474 global variables, so we need to update it completely. */
475
476 from = state.comstr_start;
477 }
478 else
479 {
480 from = comment_end;
481 }
482 UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
483 }
484
485 return from;
486 }
487
116 DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0, 488 DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
117 "Return t if OBJECT is a syntax table.\n\ 489 "Return t if OBJECT is a syntax table.\n\
118 Currently, any char-table counts as a syntax table.") 490 Currently, any char-table counts as a syntax table.")
119 (object) 491 (object)
120 Lisp_Object object; 492 Lisp_Object object;
192 return table; 564 return table;
193 } 565 }
194 566
195 /* Convert a letter which signifies a syntax code 567 /* Convert a letter which signifies a syntax code
196 into the code it signifies. 568 into the code it signifies.
197 This is used by modify-syntax-entry, and other things. */ 569 This is used by modify-syntax-entry, and other things. */
198 570
199 unsigned char syntax_spec_code[0400] = 571 unsigned char syntax_spec_code[0400] =
200 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 572 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
201 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 573 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
202 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 574 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
203 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 575 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
204 (char) Swhitespace, 0377, (char) Sstring, 0377, 576 (char) Swhitespace, (char) Scomment_fence, (char) Sstring, 0377,
205 (char) Smath, 0377, 0377, (char) Squote, 577 (char) Smath, 0377, 0377, (char) Squote,
206 (char) Sopen, (char) Sclose, 0377, 0377, 578 (char) Sopen, (char) Sclose, 0377, 0377,
207 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote, 579 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote,
208 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 580 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
209 0377, 0377, 0377, 0377, 581 0377, 0377, 0377, 0377,
213 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, 585 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
214 0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol, 586 0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol,
215 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */ 587 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
216 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 588 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
217 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, 589 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
218 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377 590 0377, 0377, 0377, 0377, (char) Sstring_fence, 0377, 0377, 0377
219 }; 591 };
220 592
221 /* Indexed by syntax code, give the letter that describes it. */ 593 /* Indexed by syntax code, give the letter that describes it. */
222 594
223 char syntax_code_spec[14] = 595 char syntax_code_spec[16] =
224 { 596 {
225 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@' 597 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@',
598 '!', '|'
226 }; 599 };
227 600
228 /* Indexed by syntax code, give the object (cons of syntax code and 601 /* Indexed by syntax code, give the object (cons of syntax code and
229 nil) to be stored in syntax table. Since these objects can be 602 nil) to be stored in syntax table. Since these objects can be
230 shared among syntax tables, we generate them in advance. By 603 shared among syntax tables, we generate them in advance. By
264 are listed in the documentation of `modify-syntax-entry'.") 637 are listed in the documentation of `modify-syntax-entry'.")
265 (character) 638 (character)
266 Lisp_Object character; 639 Lisp_Object character;
267 { 640 {
268 int char_int; 641 int char_int;
642 gl_state.current_syntax_table = current_buffer->syntax_table;
643
644 gl_state.use_global = 0;
269 CHECK_NUMBER (character, 0); 645 CHECK_NUMBER (character, 0);
270 char_int = XINT (character); 646 char_int = XINT (character);
271 return make_number (syntax_code_spec[(int) SYNTAX (char_int)]); 647 return make_number (syntax_code_spec[(int) SYNTAX (char_int)]);
272 } 648 }
273 649
275 "Return the matching parenthesis of CHARACTER, or nil if none.") 651 "Return the matching parenthesis of CHARACTER, or nil if none.")
276 (character) 652 (character)
277 Lisp_Object character; 653 Lisp_Object character;
278 { 654 {
279 int char_int, code; 655 int char_int, code;
656 gl_state.current_syntax_table = current_buffer->syntax_table;
657 gl_state.use_global = 0;
280 CHECK_NUMBER (character, 0); 658 CHECK_NUMBER (character, 0);
281 char_int = XINT (character); 659 char_int = XINT (character);
282 code = SYNTAX (char_int); 660 code = SYNTAX (char_int);
283 if (code == Sopen || code == Sclose) 661 if (code == Sopen || code == Sclose)
284 return make_number (SYNTAX_MATCH (char_int)); 662 return make_number (SYNTAX_MATCH (char_int));
311 1 means CHAR is the start of a two-char comment start sequence.\n\ 689 1 means CHAR is the start of a two-char comment start sequence.\n\
312 2 means CHAR is the second character of such a sequence.\n\ 690 2 means CHAR is the second character of such a sequence.\n\
313 3 means CHAR is the start of a two-char comment end sequence.\n\ 691 3 means CHAR is the start of a two-char comment end sequence.\n\
314 4 means CHAR is the second character of such a sequence.\n\ 692 4 means CHAR is the second character of such a sequence.\n\
315 \n\ 693 \n\
316 There can be up to two orthogonal comment sequences. This is to support\n\ 694 There can be up to two orthogonal comment sequences. This is to support\n\
317 language modes such as C++. By default, all comment sequences are of style\n\ 695 language modes such as C++. By default, all comment sequences are of style\n\
318 a, but you can set the comment sequence style to b (on the second character\n\ 696 a, but you can set the comment sequence style to b (on the second character\n\
319 of a comment-start, or the first character of a comment-end sequence) using\n\ 697 of a comment-start, or the first character of a comment-end sequence) using\n\
320 this flag:\n\ 698 this flag:\n\
321 b means CHAR is part of comment sequence b.\n\ 699 b means CHAR is part of comment sequence b.\n\
577 ("*Help*", describe_syntax_1, current_buffer->syntax_table); 955 ("*Help*", describe_syntax_1, current_buffer->syntax_table);
578 956
579 return Qnil; 957 return Qnil;
580 } 958 }
581 959
960 int parse_sexp_ignore_comments;
961
582 /* Return the position across COUNT words from FROM. 962 /* Return the position across COUNT words from FROM.
583 If that many words cannot be found before the end of the buffer, return 0. 963 If that many words cannot be found before the end of the buffer, return 0.
584 COUNT negative means scan backward and stop at word beginning. */ 964 COUNT negative means scan backward and stop at word beginning. */
585 965
586 scan_words (from, count) 966 scan_words (from, count)
593 int temp_pos; 973 int temp_pos;
594 974
595 immediate_quit = 1; 975 immediate_quit = 1;
596 QUIT; 976 QUIT;
597 977
978 SETUP_SYNTAX_TABLE (from, count);
979
598 while (count > 0) 980 while (count > 0)
599 { 981 {
600 while (1) 982 while (1)
601 { 983 {
602 if (from == end) 984 if (from == end)
603 { 985 {
604 immediate_quit = 0; 986 immediate_quit = 0;
605 return 0; 987 return 0;
606 } 988 }
989 UPDATE_SYNTAX_TABLE_FORWARD (from);
607 ch0 = FETCH_CHAR (from); 990 ch0 = FETCH_CHAR (from);
608 code = SYNTAX (ch0); 991 code = SYNTAX (ch0);
609 INC_POS (from); 992 INC_POS (from);
610 if (words_include_escapes 993 if (words_include_escapes
611 && (code == Sescape || code == Scharquote)) 994 && (code == Sescape || code == Scharquote))
616 /* Now CH0 is a character which begins a word and FROM is the 999 /* Now CH0 is a character which begins a word and FROM is the
617 position of the next character. */ 1000 position of the next character. */
618 while (1) 1001 while (1)
619 { 1002 {
620 if (from == end) break; 1003 if (from == end) break;
1004 UPDATE_SYNTAX_TABLE_FORWARD (from);
621 ch1 = FETCH_CHAR (from); 1005 ch1 = FETCH_CHAR (from);
622 code = SYNTAX (ch1); 1006 code = SYNTAX (ch1);
623 if (!(words_include_escapes 1007 if (!(words_include_escapes
624 && (code == Sescape || code == Scharquote))) 1008 && (code == Sescape || code == Scharquote)))
625 if (code != Sword || WORD_BOUNDARY_P (ch0, ch1)) 1009 if (code != Sword || WORD_BOUNDARY_P (ch0, ch1))
637 { 1021 {
638 immediate_quit = 0; 1022 immediate_quit = 0;
639 return 0; 1023 return 0;
640 } 1024 }
641 DEC_POS (from); 1025 DEC_POS (from);
1026 UPDATE_SYNTAX_TABLE_BACKWARD (from);
642 ch1 = FETCH_CHAR (from); 1027 ch1 = FETCH_CHAR (from);
643 code = SYNTAX (ch1); 1028 code = SYNTAX (ch1);
644 if (words_include_escapes 1029 if (words_include_escapes
645 && (code == Sescape || code == Scharquote)) 1030 && (code == Sescape || code == Scharquote))
646 break; 1031 break;
652 while (1) 1037 while (1)
653 { 1038 {
654 if (from == beg) break; 1039 if (from == beg) break;
655 temp_pos = from; 1040 temp_pos = from;
656 DEC_POS (temp_pos); 1041 DEC_POS (temp_pos);
1042 UPDATE_SYNTAX_TABLE_BACKWARD (from);
657 ch0 = FETCH_CHAR (temp_pos); 1043 ch0 = FETCH_CHAR (temp_pos);
658 code = SYNTAX (ch0); 1044 code = SYNTAX (ch0);
659 if (!(words_include_escapes 1045 if (!(words_include_escapes
660 && (code == Sescape || code == Scharquote))) 1046 && (code == Sescape || code == Scharquote)))
661 if (code != Sword || WORD_BOUNDARY_P (ch0, ch1)) 1047 if (code != Sword || WORD_BOUNDARY_P (ch0, ch1))
689 } 1075 }
690 SET_PT (val); 1076 SET_PT (val);
691 return Qt; 1077 return Qt;
692 } 1078 }
693 1079
1080 Lisp_Object skip_chars ();
1081
1082 DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
1083 "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\
1084 STRING is like the inside of a `[...]' in a regular expression\n\
1085 except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
1086 Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
1087 With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\
1088 Returns the distance traveled, either zero or positive.")
1089 (string, lim)
1090 Lisp_Object string, lim;
1091 {
1092 return skip_chars (1, 0, string, lim);
1093 }
1094
1095 DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
1096 "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\
1097 See `skip-chars-forward' for details.\n\
1098 Returns the distance traveled, either zero or negative.")
1099 (string, lim)
1100 Lisp_Object string, lim;
1101 {
1102 return skip_chars (0, 0, string, lim);
1103 }
1104
1105 DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
1106 "Move point forward across chars in specified syntax classes.\n\
1107 SYNTAX is a string of syntax code characters.\n\
1108 Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
1109 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1110 This function returns the distance traveled, either zero or positive.")
1111 (syntax, lim)
1112 Lisp_Object syntax, lim;
1113 {
1114 return skip_chars (1, 1, syntax, lim);
1115 }
1116
1117 DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
1118 "Move point backward across chars in specified syntax classes.\n\
1119 SYNTAX is a string of syntax code characters.\n\
1120 Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
1121 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1122 This function returns the distance traveled, either zero or negative.")
1123 (syntax, lim)
1124 Lisp_Object syntax, lim;
1125 {
1126 return skip_chars (0, 1, syntax, lim);
1127 }
1128
1129 Lisp_Object
1130 skip_chars (forwardp, syntaxp, string, lim)
1131 int forwardp, syntaxp;
1132 Lisp_Object string, lim;
1133 {
1134 register unsigned char *p, *pend;
1135 register unsigned int c;
1136 unsigned char fastmap[0400];
1137 int negate = 0;
1138 register int i;
1139
1140 CHECK_STRING (string, 0);
1141
1142 if (NILP (lim))
1143 XSETINT (lim, forwardp ? ZV : BEGV);
1144 else
1145 CHECK_NUMBER_COERCE_MARKER (lim, 1);
1146
1147 /* In any case, don't allow scan outside bounds of buffer. */
1148 /* jla turned this off, for no known reason.
1149 bfox turned the ZV part on, and rms turned the
1150 BEGV part back on. */
1151 if (XINT (lim) > ZV)
1152 XSETFASTINT (lim, ZV);
1153 if (XINT (lim) < BEGV)
1154 XSETFASTINT (lim, BEGV);
1155
1156 p = XSTRING (string)->data;
1157 pend = p + XSTRING (string)->size;
1158 bzero (fastmap, sizeof fastmap);
1159
1160 if (p != pend && *p == '^')
1161 {
1162 negate = 1; p++;
1163 }
1164
1165 /* Find the characters specified and set their elements of fastmap.
1166 If syntaxp, each character counts as itself.
1167 Otherwise, handle backslashes and ranges specially. */
1168
1169 while (p != pend)
1170 {
1171 c = *p++;
1172 if (syntaxp)
1173 fastmap[syntax_spec_code[c]] = 1;
1174 else
1175 {
1176 if (c == '\\')
1177 {
1178 if (p == pend) break;
1179 c = *p++;
1180 }
1181 if (p != pend && *p == '-')
1182 {
1183 p++;
1184 if (p == pend) break;
1185 while (c <= *p)
1186 {
1187 fastmap[c] = 1;
1188 c++;
1189 }
1190 p++;
1191 }
1192 else
1193 fastmap[c] = 1;
1194 }
1195 }
1196
1197 /* If ^ was the first character, complement the fastmap. */
1198
1199 if (negate)
1200 for (i = 0; i < sizeof fastmap; i++)
1201 fastmap[i] ^= 1;
1202
1203 {
1204 int start_point = PT;
1205 int pos = PT;
1206
1207 immediate_quit = 1;
1208 if (syntaxp)
1209 {
1210 SETUP_SYNTAX_TABLE (pos, forwardp ? 1 : -1);
1211 if (forwardp)
1212 {
1213 while (pos < XINT (lim)
1214 && fastmap[(int) SYNTAX (FETCH_CHAR (pos))])
1215 {
1216 pos++;
1217 UPDATE_SYNTAX_TABLE_FORWARD (pos);
1218 }
1219 }
1220 else
1221 {
1222 while (pos > XINT (lim)
1223 && fastmap[(int) SYNTAX (FETCH_CHAR (pos - 1))])
1224 {
1225 pos--;
1226 UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
1227 }
1228 }
1229 }
1230 else
1231 {
1232 if (forwardp)
1233 {
1234 while (pos < XINT (lim) && fastmap[FETCH_CHAR (pos)])
1235 pos++;
1236 }
1237 else
1238 {
1239 while (pos > XINT (lim) && fastmap[FETCH_CHAR (pos - 1)])
1240 pos--;
1241 }
1242 }
1243 SET_PT (pos);
1244 immediate_quit = 0;
1245
1246 return make_number (PT - start_point);
1247 }
1248 }
1249
694 DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, 1250 DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0,
695 "Move forward across up to N comments. If N is negative, move backward.\n\ 1251 "Move forward across up to N comments. If N is negative, move backward.\n\
696 Stop scanning if we find something other than a comment or whitespace.\n\ 1252 Stop scanning if we find something other than a comment or whitespace.\n\
697 Set point to where scanning stops.\n\ 1253 Set point to where scanning stops.\n\
698 If N comments are found as expected, with nothing except whitespace\n\ 1254 If N comments are found as expected, with nothing except whitespace\n\
709 int count1; 1265 int count1;
710 int temp_pos; 1266 int temp_pos;
711 1267
712 CHECK_NUMBER (count, 0); 1268 CHECK_NUMBER (count, 0);
713 count1 = XINT (count); 1269 count1 = XINT (count);
1270 stop = count1 > 0 ? ZV : BEGV;
714 1271
715 immediate_quit = 1; 1272 immediate_quit = 1;
716 QUIT; 1273 QUIT;
717 1274
718 from = PT; 1275 from = PT;
719 1276
1277 SETUP_SYNTAX_TABLE (from, count1);
720 while (count1 > 0) 1278 while (count1 > 0)
721 { 1279 {
722 stop = ZV;
723 do 1280 do
724 { 1281 {
725 if (from == stop) 1282 if (from == stop)
726 { 1283 {
727 SET_PT (from); 1284 SET_PT (from);
728 immediate_quit = 0; 1285 immediate_quit = 0;
729 return Qnil; 1286 return Qnil;
730 } 1287 }
1288 UPDATE_SYNTAX_TABLE_FORWARD (from);
731 c = FETCH_CHAR (from); 1289 c = FETCH_CHAR (from);
732 code = SYNTAX (c); 1290 code = SYNTAX (c);
733 INC_POS (from); 1291 INC_POS (from);
734 comstyle = 0; 1292 comstyle = 0;
735 if (from < stop && SYNTAX_COMSTART_FIRST (c) 1293 if (from < stop && SYNTAX_COMSTART_FIRST (c)
745 comstyle = SYNTAX_COMMENT_STYLE (c1); 1303 comstyle = SYNTAX_COMMENT_STYLE (c1);
746 INC_POS (from); 1304 INC_POS (from);
747 } 1305 }
748 } 1306 }
749 while (code == Swhitespace || code == Sendcomment); 1307 while (code == Swhitespace || code == Sendcomment);
750 if (code != Scomment) 1308 if (code != Scomment && code != Scomment_fence)
751 { 1309 {
752 immediate_quit = 0; 1310 immediate_quit = 0;
753 DEC_POS (from); 1311 DEC_POS (from);
754 SET_PT (from); 1312 SET_PT (from);
755 return Qnil; 1313 return Qnil;
761 { 1319 {
762 immediate_quit = 0; 1320 immediate_quit = 0;
763 SET_PT (from); 1321 SET_PT (from);
764 return Qnil; 1322 return Qnil;
765 } 1323 }
1324 UPDATE_SYNTAX_TABLE_FORWARD (from);
766 c = FETCH_CHAR (from); 1325 c = FETCH_CHAR (from);
767 INC_POS (from); 1326 INC_POS (from);
768 if (SYNTAX (c) == Sendcomment 1327 if (SYNTAX (c) == Sendcomment
769 && SYNTAX_COMMENT_STYLE (c) == comstyle) 1328 && SYNTAX_COMMENT_STYLE (c) == comstyle)
770 /* we have encountered a comment end of the same style 1329 /* we have encountered a comment end of the same style
771 as the comment sequence which began this comment 1330 as the comment sequence which began this comment
772 section */ 1331 section */
1332 break;
1333 if (SYNTAX (c) == Scomment_fence
1334 && comstyle == ST_COMMENT_STYLE)
1335 /* we have encountered a comment end of the same style
1336 as the comment sequence which began this comment
1337 section. */
773 break; 1338 break;
774 if (from < stop && SYNTAX_COMEND_FIRST (c) 1339 if (from < stop && SYNTAX_COMEND_FIRST (c)
775 && (c1 = FETCH_CHAR (from), 1340 && (c1 = FETCH_CHAR (from),
776 SYNTAX_COMEND_SECOND (c1)) 1341 SYNTAX_COMEND_SECOND (c1))
777 && SYNTAX_COMMENT_STYLE (c) == comstyle) 1342 && SYNTAX_COMMENT_STYLE (c) == comstyle)
784 count1--; 1349 count1--;
785 } 1350 }
786 1351
787 while (count1 < 0) 1352 while (count1 < 0)
788 { 1353 {
789 stop = BEGV;
790 while (from > stop) 1354 while (from > stop)
791 { 1355 {
792 int quoted; 1356 int quoted;
793 1357
794 DEC_POS (from); 1358 DEC_POS (from);
795 quoted = char_quoted (from); 1359 quoted = char_quoted (from);
796 if (quoted) 1360 if (quoted)
797 DEC_POS (from); 1361 {
1362 DEC_POS (from);
1363 goto leave; /* ????? XXXXX */
1364 }
1365 UPDATE_SYNTAX_TABLE_BACKWARD (from);
798 c = FETCH_CHAR (from); 1366 c = FETCH_CHAR (from);
799 code = SYNTAX (c); 1367 code = SYNTAX (c);
800 comstyle = 0; 1368 comstyle = 0;
801 if (code == Sendcomment) 1369 if (code == Sendcomment)
802 comstyle = SYNTAX_COMMENT_STYLE (c); 1370 comstyle = SYNTAX_COMMENT_STYLE (c);
813 code = Sendcomment; 1381 code = Sendcomment;
814 comstyle = SYNTAX_COMMENT_STYLE (c1); 1382 comstyle = SYNTAX_COMMENT_STYLE (c1);
815 from = temp_pos; 1383 from = temp_pos;
816 } 1384 }
817 1385
818 if (code == Sendcomment && !quoted) 1386 if (code == Scomment_fence)
1387 {
1388 /* Skip until first preceding unquoted comment_fence. */
1389 int found = 0, ini = from;
1390
1391 while (--from != stop)
1392 {
1393 UPDATE_SYNTAX_TABLE_BACKWARD (from);
1394 c = FETCH_CHAR (from);
1395 if (SYNTAX (c) == Scomment_fence && !char_quoted (from))
1396 {
1397 found = 1;
1398 break;
1399 }
1400 }
1401 if (found == 0)
1402 {
1403 from = ini; /* Set point to ini + 1. */
1404 goto leave;
1405 }
1406 }
1407 else if (code == Sendcomment)
819 { 1408 {
820 #if 0 1409 #if 0
821 if (code != SYNTAX (c)) 1410 if (code != SYNTAX (c))
822 /* For a two-char comment ender, we can assume 1411 /* For a two-char comment ender, we can assume
823 it does end a comment. So scan back in a simple way. */ 1412 it does end a comment. So scan back in a simple way. */
844 break; 1433 break;
845 } 1434 }
846 break; 1435 break;
847 } 1436 }
848 #endif /* 0 */ 1437 #endif /* 0 */
849 1438 found = back_comment (from, stop);
1439 if (found != -1) from = found;
1440 #if 0
850 /* Look back, counting the parity of string-quotes, 1441 /* Look back, counting the parity of string-quotes,
851 and recording the comment-starters seen. 1442 and recording the comment-starters seen.
852 When we reach a safe place, assume that's not in a string; 1443 When we reach a safe place, assume that's not in a string;
853 then step the main scan to the earliest comment-starter seen 1444 then step the main scan to the earliest comment-starter seen
854 an even number of string quotes away from the safe place. 1445 an even number of string quotes away from the safe place.
871 while (from != stop) 1462 while (from != stop)
872 { 1463 {
873 /* Move back and examine a character. */ 1464 /* Move back and examine a character. */
874 DEC_POS (from); 1465 DEC_POS (from);
875 1466
1467 UPDATE_SYNTAX_TABLE_BACKWARD (from);
876 c = FETCH_CHAR (from); 1468 c = FETCH_CHAR (from);
877 code = SYNTAX (c); 1469 code = SYNTAX (c);
878 1470
879 /* If this char is the second of a 2-char comment sequence, 1471 /* If this char is the second of a 2-char comment sequence,
880 back up and give the pair the appropriate syntax. */ 1472 back up and give the pair the appropriate syntax. */
954 last passed a comment starter. */ 1546 last passed a comment starter. */
955 struct lisp_parse_state state; 1547 struct lisp_parse_state state;
956 scan_sexps_forward (&state, find_defun_start (comment_end), 1548 scan_sexps_forward (&state, find_defun_start (comment_end),
957 comment_end - 1, -10000, 0, Qnil, 0); 1549 comment_end - 1, -10000, 0, Qnil, 0);
958 if (state.incomment) 1550 if (state.incomment)
959 from = state.comstart; 1551 from = state.comstr_start;
960 else 1552 else
961 /* We can't grok this as a comment; scan it normally. */ 1553 /* We can't grok this as a comment; scan it normally. */
962 from = comment_end; 1554 from = comment_end;
963 } 1555 }
964 } 1556 }
1557 #endif /* 0 */
965 /* We have skipped one comment. */ 1558 /* We have skipped one comment. */
966 break; 1559 break;
967 } 1560 }
968 else if ((code != Swhitespace && code != Scomment) || quoted) 1561 else if (code != Swhitespace && code != Scomment)
969 { 1562 {
1563 leave:
970 immediate_quit = 0; 1564 immediate_quit = 0;
971 INC_POS (from); 1565 INC_POS (from);
972 SET_PT (from); 1566 SET_PT (from);
973 return Qnil; 1567 return Qnil;
974 } 1568 }
980 SET_PT (from); 1574 SET_PT (from);
981 immediate_quit = 0; 1575 immediate_quit = 0;
982 return Qt; 1576 return Qt;
983 } 1577 }
984 1578
985 int parse_sexp_ignore_comments;
986
987 Lisp_Object 1579 Lisp_Object
988 scan_lists (from, count, depth, sexpflag) 1580 scan_lists (from, count, depth, sexpflag)
989 register int from; 1581 register int from;
990 int count, depth, sexpflag; 1582 int count, depth, sexpflag;
991 { 1583 {
992 Lisp_Object val; 1584 Lisp_Object val;
993 register int stop; 1585 register int stop = count > 0 ? ZV : BEGV;
994 register int c, c1; 1586 register int c, c1;
995 int stringterm; 1587 int stringterm;
996 int quoted; 1588 int quoted;
997 int mathexit = 0; 1589 int mathexit = 0;
998 register enum syntaxcode code, temp_code; 1590 register enum syntaxcode code, temp_code;
999 int min_depth = depth; /* Err out if depth gets less than this. */ 1591 int min_depth = depth; /* Err out if depth gets less than this. */
1000 int comstyle = 0; /* style of comment encountered */ 1592 int comstyle = 0; /* style of comment encountered */
1001 int temp_pos; 1593 int temp_pos;
1002 int last_good = from; 1594 int last_good = from;
1595 int found;
1003 1596
1004 if (depth > 0) min_depth = 0; 1597 if (depth > 0) min_depth = 0;
1005 1598
1006 immediate_quit = 1; 1599 immediate_quit = 1;
1007 QUIT; 1600 QUIT;
1008 1601
1602 SETUP_SYNTAX_TABLE (from, count);
1009 while (count > 0) 1603 while (count > 0)
1010 { 1604 {
1011 stop = ZV;
1012 while (from < stop) 1605 while (from < stop)
1013 { 1606 {
1607 UPDATE_SYNTAX_TABLE_FORWARD (from);
1014 c = FETCH_CHAR (from); 1608 c = FETCH_CHAR (from);
1015 code = SYNTAX (c); 1609 code = SYNTAX (c);
1016 if (depth == min_depth) 1610 if (depth == min_depth)
1017 last_good = from; 1611 last_good = from;
1018 INC_POS (from); 1612 INC_POS (from);
1613 UPDATE_SYNTAX_TABLE_FORWARD (from);
1019 if (from < stop && SYNTAX_COMSTART_FIRST (c) 1614 if (from < stop && SYNTAX_COMSTART_FIRST (c)
1020 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)) 1615 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))
1021 && parse_sexp_ignore_comments) 1616 && parse_sexp_ignore_comments)
1022 { 1617 {
1023 /* we have encountered a comment start sequence and we 1618 /* we have encountered a comment start sequence and we
1024 are ignoring all text inside comments. we must record 1619 are ignoring all text inside comments. We must record
1025 the comment style this sequence begins so that later, 1620 the comment style this sequence begins so that later,
1026 only a comment end of the same style actually ends 1621 only a comment end of the same style actually ends
1027 the comment section */ 1622 the comment section */
1028 code = Scomment; 1623 code = Scomment;
1029 comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)); 1624 comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
1030 INC_POS (from); 1625 INC_POS (from);
1031 } 1626 }
1032 1627
1628 UPDATE_SYNTAX_TABLE_FORWARD (from);
1033 if (SYNTAX_PREFIX (c)) 1629 if (SYNTAX_PREFIX (c))
1034 continue; 1630 continue;
1035 1631
1036 switch (SWITCH_ENUM_CAST (code)) 1632 switch (SWITCH_ENUM_CAST (code))
1037 { 1633 {
1041 INC_POS (from); 1637 INC_POS (from);
1042 /* treat following character as a word constituent */ 1638 /* treat following character as a word constituent */
1043 case Sword: 1639 case Sword:
1044 case Ssymbol: 1640 case Ssymbol:
1045 if (depth || !sexpflag) break; 1641 if (depth || !sexpflag) break;
1046 /* This word counts as a sexp; return at end of it. */ 1642 /* This word counts as a sexp; return at end of it. */
1047 while (from < stop) 1643 while (from < stop)
1048 { 1644 {
1645 UPDATE_SYNTAX_TABLE_FORWARD (from);
1049 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) 1646 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
1050 { 1647 {
1051 case Scharquote: 1648 case Scharquote:
1052 case Sescape: 1649 case Sescape:
1053 INC_POS (from); 1650 INC_POS (from);
1063 INC_POS (from); 1660 INC_POS (from);
1064 } 1661 }
1065 goto done; 1662 goto done;
1066 1663
1067 case Scomment: 1664 case Scomment:
1665 case Scomment_fence:
1068 if (!parse_sexp_ignore_comments) break; 1666 if (!parse_sexp_ignore_comments) break;
1069 while (1) 1667 while (1)
1070 { 1668 {
1071 if (from == stop) 1669 if (from == stop)
1072 { 1670 {
1073 if (depth == 0) 1671 if (depth == 0)
1074 goto done; 1672 goto done;
1075 goto lose; 1673 goto lose;
1076 } 1674 }
1675 UPDATE_SYNTAX_TABLE_FORWARD (from);
1077 c = FETCH_CHAR (from); 1676 c = FETCH_CHAR (from);
1078 if (SYNTAX (c) == Sendcomment 1677 if (code == Scomment
1079 && SYNTAX_COMMENT_STYLE (c) == comstyle) 1678 ? (SYNTAX (c) == Sendcomment
1679 && SYNTAX_COMMENT_STYLE (c) == comstyle)
1680 : (SYNTAX (c) == Scomment_fence))
1080 /* we have encountered a comment end of the same style 1681 /* we have encountered a comment end of the same style
1081 as the comment sequence which began this comment 1682 as the comment sequence which began this comment
1082 section */ 1683 section */
1083 break; 1684 break;
1084 INC_POS (from); 1685 INC_POS (from);
1085 if (from < stop && SYNTAX_COMEND_FIRST (c) 1686 if (from < stop && SYNTAX_COMEND_FIRST (c)
1086 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) 1687 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from))
1087 && SYNTAX_COMMENT_STYLE (c) == comstyle) 1688 && SYNTAX_COMMENT_STYLE (c) == comstyle
1689 && code == Scomment)
1088 /* we have encountered a comment end of the same style 1690 /* we have encountered a comment end of the same style
1089 as the comment sequence which began this comment 1691 as the comment sequence which began this comment
1090 section */ 1692 section */
1091 { INC_POS (from); break; } 1693 { INC_POS (from); break; }
1092 } 1694 }
1117 Fcons (make_number (last_good), 1719 Fcons (make_number (last_good),
1118 Fcons (make_number (from), Qnil)))); 1720 Fcons (make_number (from), Qnil))));
1119 break; 1721 break;
1120 1722
1121 case Sstring: 1723 case Sstring:
1724 case Sstring_fence:
1122 temp_pos = from; 1725 temp_pos = from;
1123 DEC_POS (temp_pos); 1726 DEC_POS (temp_pos);
1124 stringterm = FETCH_CHAR (temp_pos); 1727 stringterm = FETCH_CHAR (temp_pos);
1125 while (1) 1728 while (1)
1126 { 1729 {
1127 if (from >= stop) goto lose; 1730 if (from >= stop) goto lose;
1128 if (FETCH_CHAR (from) == stringterm) break; 1731 UPDATE_SYNTAX_TABLE_FORWARD (from);
1732 if (code == Sstring
1733 ? (FETCH_CHAR (from) == stringterm)
1734 : SYNTAX (FETCH_CHAR (from)) == Sstring_fence)
1735 break;
1129 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) 1736 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
1130 { 1737 {
1131 case Scharquote: 1738 case Scharquote:
1132 case Sescape: 1739 case Sescape:
1133 INC_POS (from); 1740 INC_POS (from);
1151 count--; 1758 count--;
1152 } 1759 }
1153 1760
1154 while (count < 0) 1761 while (count < 0)
1155 { 1762 {
1156 stop = BEGV;
1157 while (from > stop) 1763 while (from > stop)
1158 { 1764 {
1159 DEC_POS (from); 1765 DEC_POS (from);
1766 UPDATE_SYNTAX_TABLE_BACKWARD (from);
1160 if (quoted = char_quoted (from)) 1767 if (quoted = char_quoted (from))
1161 DEC_POS (from); 1768 {
1769 DEC_POS (from);
1770 UPDATE_SYNTAX_TABLE_BACKWARD (from);
1771 }
1162 c = FETCH_CHAR (from); 1772 c = FETCH_CHAR (from);
1163 code = SYNTAX (c); 1773 code = SYNTAX (c);
1164 if (depth == min_depth) 1774 if (depth == min_depth)
1165 last_good = from; 1775 last_good = from;
1166 comstyle = 0; 1776 comstyle = 0;
1187 switch (SWITCH_ENUM_CAST (quoted ? Sword : code)) 1797 switch (SWITCH_ENUM_CAST (quoted ? Sword : code))
1188 { 1798 {
1189 case Sword: 1799 case Sword:
1190 case Ssymbol: 1800 case Ssymbol:
1191 if (depth || !sexpflag) break; 1801 if (depth || !sexpflag) break;
1192 /* This word counts as a sexp; count object finished after passing it. */ 1802 /* This word counts as a sexp; count object finished
1803 after passing it. */
1193 while (from > stop) 1804 while (from > stop)
1194 { 1805 {
1195 temp_pos = from; 1806 temp_pos = from;
1196 DEC_POS (temp_pos); 1807 DEC_POS (temp_pos);
1808 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos);
1197 quoted = char_quoted (temp_pos); 1809 quoted = char_quoted (temp_pos);
1198 if (quoted) 1810 if (quoted)
1199 { 1811 {
1200 from = temp_pos; 1812 from = temp_pos;
1201 DEC_POS (temp_pos); 1813 DEC_POS (temp_pos);
1814 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos);
1202 } 1815 }
1203 c1 = FETCH_CHAR (temp_pos); 1816 c1 = FETCH_CHAR (temp_pos);
1204 temp_code = SYNTAX (c1); 1817 temp_code = SYNTAX (c1);
1205 if (! (quoted || temp_code == Sword 1818 if (! (quoted || temp_code == Sword
1206 || temp_code == Ssymbol 1819 || temp_code == Ssymbol
1213 case Smath: 1826 case Smath:
1214 if (!sexpflag) 1827 if (!sexpflag)
1215 break; 1828 break;
1216 temp_pos = from; 1829 temp_pos = from;
1217 DEC_POS (temp_pos); 1830 DEC_POS (temp_pos);
1831 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos);
1218 if (from != stop && c == FETCH_CHAR (temp_pos)) 1832 if (from != stop && c == FETCH_CHAR (temp_pos))
1219 from = temp_pos; 1833 from = temp_pos;
1220 if (mathexit) 1834 if (mathexit)
1221 { 1835 {
1222 mathexit = 0; 1836 mathexit = 0;
1266 break; 1880 break;
1267 } 1881 }
1268 break; 1882 break;
1269 } 1883 }
1270 #endif /* 0 */ 1884 #endif /* 0 */
1271 1885 found = back_comment (from, stop);
1886 if (found != -1) from = found;
1887 #if 0
1272 /* Look back, counting the parity of string-quotes, 1888 /* Look back, counting the parity of string-quotes,
1273 and recording the comment-starters seen. 1889 and recording the comment-starters seen.
1274 When we reach a safe place, assume that's not in a string; 1890 When we reach a safe place, assume that's not in a string;
1275 then step the main scan to the earliest comment-starter seen 1891 then step the main scan to the earliest comment-starter seen
1276 an even number of string quotes away from the safe place. 1892 an even number of string quotes away from the safe place.
1377 last passed a comment starter. */ 1993 last passed a comment starter. */
1378 struct lisp_parse_state state; 1994 struct lisp_parse_state state;
1379 scan_sexps_forward (&state, find_defun_start (comment_end), 1995 scan_sexps_forward (&state, find_defun_start (comment_end),
1380 comment_end - 1, -10000, 0, Qnil, 0); 1996 comment_end - 1, -10000, 0, Qnil, 0);
1381 if (state.incomment) 1997 if (state.incomment)
1382 from = state.comstart; 1998 from = state.comstr_start;
1383 else 1999 else
1384 /* We can't grok this as a comment; scan it normally. */ 2000 /* We can't grok this as a comment; scan it normally. */
1385 from = comment_end; 2001 from = comment_end;
1386 } 2002 }
1387 } 2003 }
2004 #endif /* 0 */
1388 break; 2005 break;
1389 2006
2007 case Scomment_fence:
2008 case Sstring_fence:
2009 while (1)
2010 {
2011 DEC_POS (from);
2012 if (from == stop) goto lose;
2013 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2014 if (!char_quoted (from)
2015 && SYNTAX (FETCH_CHAR (from)) == code)
2016 break;
2017 }
2018 if (code == Sstring_fence && !depth && sexpflag) goto done2;
2019 break;
2020
1390 case Sstring: 2021 case Sstring:
1391 stringterm = FETCH_CHAR (from); 2022 stringterm = FETCH_CHAR (from);
1392 while (1) 2023 while (1)
1393 { 2024 {
1394 if (from == stop) goto lose; 2025 if (from == stop) goto lose;
1395 temp_pos = from; 2026 temp_pos = from;
1396 DEC_POS (temp_pos); 2027 DEC_POS (temp_pos);
2028 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos);
1397 if (!char_quoted (temp_pos) 2029 if (!char_quoted (temp_pos)
1398 && stringterm == FETCH_CHAR (temp_pos)) 2030 && stringterm == FETCH_CHAR (temp_pos))
1399 break; 2031 break;
1400 from = temp_pos; 2032 from = temp_pos;
1401 } 2033 }
1425 Fcons (build_string ("Unbalanced parentheses"), 2057 Fcons (build_string ("Unbalanced parentheses"),
1426 Fcons (make_number (last_good), 2058 Fcons (make_number (last_good),
1427 Fcons (make_number (from), Qnil)))); 2059 Fcons (make_number (from), Qnil))));
1428 2060
1429 /* NOTREACHED */ 2061 /* NOTREACHED */
1430 }
1431
1432 static int
1433 char_quoted (pos)
1434 register int pos;
1435 {
1436 register enum syntaxcode code;
1437 register int beg = BEGV;
1438 register int quoted = 0;
1439 int temp_pos = pos;
1440
1441 DEC_POS (temp_pos);
1442 while (pos > beg
1443 && ((code = SYNTAX (FETCH_CHAR (temp_pos))) == Scharquote
1444 || code == Sescape))
1445 {
1446 pos = temp_pos;
1447 quoted = !quoted;
1448 DEC_POS (temp_pos);
1449 }
1450 return quoted;
1451 } 2062 }
1452 2063
1453 DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0, 2064 DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
1454 "Scan from character number FROM by COUNT lists.\n\ 2065 "Scan from character number FROM by COUNT lists.\n\
1455 Returns the character number of the position thus found.\n\ 2066 Returns the character number of the position thus found.\n\
1503 int beg = BEGV; 2114 int beg = BEGV;
1504 int pos = PT; 2115 int pos = PT;
1505 int c; 2116 int c;
1506 int temp_pos = pos; 2117 int temp_pos = pos;
1507 2118
2119 if (pos > beg)
2120 {
2121 SETUP_SYNTAX_TABLE (pos, -1);
2122 }
1508 DEC_POS (temp_pos); 2123 DEC_POS (temp_pos);
1509 2124
1510 while (pos > beg && !char_quoted (temp_pos) 2125 while (pos > beg && !char_quoted (temp_pos)
2126 /* Previous statement updates syntax table. */
1511 && ((c = FETCH_CHAR (temp_pos), SYNTAX (c) == Squote) 2127 && ((c = FETCH_CHAR (temp_pos), SYNTAX (c) == Squote)
1512 || SYNTAX_PREFIX (c))) 2128 || SYNTAX_PREFIX (c)))
1513 { 2129 {
1514 pos = temp_pos; 2130 pos = temp_pos;
1515 DEC_POS (temp_pos); 2131 DEC_POS (temp_pos);
1548 when the depth becomes negative. */ 2164 when the depth becomes negative. */
1549 int mindepth; /* Lowest DEPTH value seen. */ 2165 int mindepth; /* Lowest DEPTH value seen. */
1550 int start_quoted = 0; /* Nonzero means starting after a char quote */ 2166 int start_quoted = 0; /* Nonzero means starting after a char quote */
1551 Lisp_Object tem; 2167 Lisp_Object tem;
1552 int prev_from; /* Keep one character before FROM. */ 2168 int prev_from; /* Keep one character before FROM. */
2169 int boundary_stop = commentstop == -1;
2170 int nofence;
1553 2171
1554 prev_from = from; 2172 prev_from = from;
1555 DEC_POS (prev_from); 2173 DEC_POS (prev_from);
1556 2174
1557 /* Use this macro instead of `from++'. */ 2175 /* Use this macro instead of `from++'. */
1558 #define INC_FROM do { prev_from = from; INC_POS (from); } while (0) 2176 #define INC_FROM do { prev_from = from; INC_POS (from); } while (0)
1559 2177
1560 immediate_quit = 1; 2178 immediate_quit = 1;
1561 QUIT; 2179 QUIT;
2180
2181 SETUP_SYNTAX_TABLE (from, 1);
1562 2182
1563 if (NILP (oldstate)) 2183 if (NILP (oldstate))
1564 { 2184 {
1565 depth = 0; 2185 depth = 0;
1566 state.instring = -1; 2186 state.instring = -1;
1567 state.incomment = 0; 2187 state.incomment = 0;
1568 state.comstyle = 0; /* comment style a by default */ 2188 state.comstyle = 0; /* comment style a by default. */
2189 state.comstr_start = -1; /* no comment/string seen. */
1569 } 2190 }
1570 else 2191 else
1571 { 2192 {
1572 tem = Fcar (oldstate); 2193 tem = Fcar (oldstate);
1573 if (!NILP (tem)) 2194 if (!NILP (tem))
1577 2198
1578 oldstate = Fcdr (oldstate); 2199 oldstate = Fcdr (oldstate);
1579 oldstate = Fcdr (oldstate); 2200 oldstate = Fcdr (oldstate);
1580 oldstate = Fcdr (oldstate); 2201 oldstate = Fcdr (oldstate);
1581 tem = Fcar (oldstate); 2202 tem = Fcar (oldstate);
1582 state.instring = !NILP (tem) ? XINT (tem) : -1; 2203 /* Check whether we are inside string_fence-style string: */
2204 state.instring = ( !NILP (tem)
2205 ? ( INTEGERP (tem) ? XINT (tem) : ST_STRING_STYLE)
2206 : -1);
1583 2207
1584 oldstate = Fcdr (oldstate); 2208 oldstate = Fcdr (oldstate);
1585 tem = Fcar (oldstate); 2209 tem = Fcar (oldstate);
1586 state.incomment = !NILP (tem); 2210 state.incomment = !NILP (tem);
1587 2211
1588 oldstate = Fcdr (oldstate); 2212 oldstate = Fcdr (oldstate);
1589 tem = Fcar (oldstate); 2213 tem = Fcar (oldstate);
1590 start_quoted = !NILP (tem); 2214 start_quoted = !NILP (tem);
1591 2215
1592 /* if the eight element of the list is nil, we are in comment 2216 /* if the eight element of the list is nil, we are in comment
1593 style a. if it is non-nil, we are in comment style b */ 2217 style a. If it is non-nil, we are in comment style b */
1594 oldstate = Fcdr (oldstate); 2218 oldstate = Fcdr (oldstate);
1595 oldstate = Fcdr (oldstate); 2219 oldstate = Fcdr (oldstate);
1596 tem = Fcar (oldstate); 2220 tem = Fcar (oldstate);
1597 state.comstyle = !NILP (tem); 2221 state.comstyle = NILP (tem) ? 0 : ( EQ (tem, Qsyntax_table)
2222 ? ST_COMMENT_STYLE : 1 );
2223
2224 oldstate = Fcdr (oldstate);
2225 tem = Fcar (oldstate);
2226 state.comstr_start = NILP (tem) ? -1 : XINT (tem) ;
1598 } 2227 }
1599 state.quoted = 0; 2228 state.quoted = 0;
1600 mindepth = depth; 2229 mindepth = depth;
1601 2230
1602 curlevel->prev = -1; 2231 curlevel->prev = -1;
1603 curlevel->last = -1; 2232 curlevel->last = -1;
1604 2233
1605 /* Enter the loop at a place appropriate for initial state. */ 2234 /* Enter the loop at a place appropriate for initial state. */
1606 2235
1607 if (state.incomment) goto startincomment; 2236 if (state.incomment) goto startincomment;
1608 if (state.instring >= 0) 2237 if (state.instring >= 0)
1609 { 2238 {
2239 nofence = state.instring != ST_STRING_STYLE;
1610 if (start_quoted) goto startquotedinstring; 2240 if (start_quoted) goto startquotedinstring;
1611 goto startinstring; 2241 goto startinstring;
1612 } 2242 }
1613 if (start_quoted) goto startquoted; 2243 if (start_quoted) goto startquoted;
1614 2244
1615 while (from < end) 2245 while (from < end)
1616 { 2246 {
2247 UPDATE_SYNTAX_TABLE_FORWARD (from);
1617 code = SYNTAX (FETCH_CHAR (from)); 2248 code = SYNTAX (FETCH_CHAR (from));
1618 INC_FROM; 2249 INC_FROM;
1619 if (code == Scomment) 2250 if (code == Scomment)
1620 state.comstart = prev_from; 2251 state.comstr_start = prev_from;
1621 2252
1622 else if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (prev_from)) 2253 else if (code == Scomment_fence
1623 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) 2254 || (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (prev_from))
2255 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))))
1624 { 2256 {
1625 /* Record the comment style we have entered so that only 2257 /* Record the comment style we have entered so that only
1626 the comment-end sequence of the same style actually 2258 the comment-end sequence of the same style actually
1627 terminates the comment section. */ 2259 terminates the comment section. */
2260 state.comstyle = ( code == Scomment_fence
2261 ? ST_COMMENT_STYLE
2262 : SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)));
2263 state.comstr_start = prev_from;
2264 if (code != Scomment_fence) INC_FROM;
1628 code = Scomment; 2265 code = Scomment;
1629 state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
1630 state.comstart = prev_from;
1631 INC_FROM;
1632 } 2266 }
1633 2267
1634 if (SYNTAX_PREFIX (FETCH_CHAR (prev_from))) 2268 if (SYNTAX_PREFIX (FETCH_CHAR (prev_from)))
1635 continue; 2269 continue;
1636 switch (SWITCH_ENUM_CAST (code)) 2270 switch (SWITCH_ENUM_CAST (code))
1649 if (stopbefore) goto stop; /* this arg means stop at sexp start */ 2283 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1650 curlevel->last = prev_from; 2284 curlevel->last = prev_from;
1651 symstarted: 2285 symstarted:
1652 while (from < end) 2286 while (from < end)
1653 { 2287 {
2288 UPDATE_SYNTAX_TABLE_FORWARD (from);
1654 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) 2289 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from))))
1655 { 2290 {
1656 case Scharquote: 2291 case Scharquote:
1657 case Sescape: 2292 case Sescape:
1658 INC_FROM; 2293 INC_FROM;
1670 symdone: 2305 symdone:
1671 curlevel->prev = curlevel->last; 2306 curlevel->prev = curlevel->last;
1672 break; 2307 break;
1673 2308
1674 startincomment: 2309 startincomment:
1675 if (commentstop) 2310 if (commentstop == 1)
1676 goto done; 2311 goto done;
1677 if (from != BEGV) 2312 if (from != BEGV)
1678 { 2313 {
1679 /* Enter the loop in the middle so that we find 2314 /* Enter the loop in the middle so that we find
1680 a 2-char comment ender if we start in the middle of it. */ 2315 a 2-char comment ender if we start in the middle of it. */
1681 prev = FETCH_CHAR (prev_from); 2316 prev = FETCH_CHAR (prev_from);
1682 goto startincomment_1; 2317 goto startincomment_1;
1683 } 2318 }
1684 /* At beginning of buffer, enter the loop the ordinary way. */ 2319 /* At beginning of buffer, enter the loop the ordinary way. */
2320 state.incomment = 1;
2321 goto commentloop;
1685 2322
1686 case Scomment: 2323 case Scomment:
1687 state.incomment = 1; 2324 state.incomment = 1;
1688 if (commentstop) 2325 if (commentstop || boundary_stop) goto done;
1689 goto done; 2326 commentloop:
1690 while (1) 2327 while (1)
1691 { 2328 {
1692 if (from == end) goto done; 2329 if (from == end) goto done;
2330 UPDATE_SYNTAX_TABLE_FORWARD (from);
1693 prev = FETCH_CHAR (from); 2331 prev = FETCH_CHAR (from);
1694 if (SYNTAX (prev) == Sendcomment 2332 if (SYNTAX (prev) == Sendcomment
1695 && SYNTAX_COMMENT_STYLE (prev) == state.comstyle) 2333 && SYNTAX_COMMENT_STYLE (prev) == state.comstyle)
1696 /* Only terminate the comment section if the endcomment 2334 /* Only terminate the comment section if the endcomment
1697 of the same style as the start sequence has been 2335 of the same style as the start sequence has been
1698 encountered. */ 2336 encountered. */
2337 break;
2338 if (state.comstyle == ST_COMMENT_STYLE
2339 && SYNTAX (prev) == Scomment_fence)
1699 break; 2340 break;
1700 INC_FROM; 2341 INC_FROM;
1701 startincomment_1: 2342 startincomment_1:
1702 if (from < end && SYNTAX_COMEND_FIRST (prev) 2343 if (from < end && SYNTAX_COMEND_FIRST (prev)
1703 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) 2344 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from))
1704 && SYNTAX_COMMENT_STYLE (prev) == state.comstyle) 2345 && SYNTAX_COMMENT_STYLE (prev) == state.comstyle)
1705 /* Only terminate the comment section if the end-comment 2346 /* Only terminate the comment section if the end-comment
1706 sequence of the same style as the start sequence has 2347 sequence of the same style as the start sequence has
1707 been encountered. */ 2348 been encountered. */
1708 { INC_FROM; break; } 2349 { break; }
1709 } 2350 }
2351 INC_FROM;
1710 state.incomment = 0; 2352 state.incomment = 0;
1711 state.comstyle = 0; /* reset the comment style */ 2353 state.comstyle = 0; /* reset the comment style */
2354 if (boundary_stop) goto done;
1712 break; 2355 break;
1713 2356
1714 case Sopen: 2357 case Sopen:
1715 if (stopbefore) goto stop; /* this arg means stop at sexp start */ 2358 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1716 depth++; 2359 depth++;
1732 curlevel->prev = curlevel->last; 2375 curlevel->prev = curlevel->last;
1733 if (targetdepth == depth) goto done; 2376 if (targetdepth == depth) goto done;
1734 break; 2377 break;
1735 2378
1736 case Sstring: 2379 case Sstring:
2380 case Sstring_fence:
2381 state.comstr_start = from - 1;
1737 if (stopbefore) goto stop; /* this arg means stop at sexp start */ 2382 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1738 curlevel->last = prev_from; 2383 curlevel->last = prev_from;
1739 state.instring = FETCH_CHAR (prev_from); 2384 state.instring = (code == Sstring
2385 ? (FETCH_CHAR (prev_from))
2386 : ST_STRING_STYLE);
2387 if (boundary_stop) goto done;
1740 startinstring: 2388 startinstring:
1741 while (1) 2389 {
1742 { 2390 nofence = state.instring != ST_STRING_STYLE;
1743 int c; 2391
1744 2392 while (1)
1745 if (from >= end) goto done; 2393 {
1746 c = FETCH_CHAR (from); 2394 int c;
1747 if (c == state.instring) break; 2395
1748 switch (SWITCH_ENUM_CAST (SYNTAX (c))) 2396 if (from >= end) goto done;
1749 { 2397 c = FETCH_CHAR (from);
1750 case Scharquote: 2398 if (nofence && c == state.instring) break;
1751 case Sescape: 2399 UPDATE_SYNTAX_TABLE_FORWARD (from);
1752 INC_FROM; 2400 switch (SWITCH_ENUM_CAST (SYNTAX (c)))
1753 startquotedinstring: 2401 {
1754 if (from >= end) goto endquoted; 2402 case Sstring_fence:
1755 } 2403 if (!nofence) goto string_end;
1756 INC_FROM; 2404 break;
1757 } 2405 case Scharquote:
2406 case Sescape:
2407 INC_FROM;
2408 startquotedinstring:
2409 if (from >= end) goto endquoted;
2410 }
2411 INC_FROM;
2412 }
2413 }
2414 string_end:
1758 state.instring = -1; 2415 state.instring = -1;
1759 curlevel->prev = curlevel->last; 2416 curlevel->prev = curlevel->last;
1760 INC_FROM; 2417 INC_FROM;
2418 if (boundary_stop) goto done;
1761 break; 2419 break;
1762 2420
1763 case Smath: 2421 case Smath:
1764 break; 2422 break;
1765 } 2423 }
1792 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\ 2450 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
1793 Parsing stops at TO or when certain criteria are met;\n\ 2451 Parsing stops at TO or when certain criteria are met;\n\
1794 point is set to where parsing stops.\n\ 2452 point is set to where parsing stops.\n\
1795 If fifth arg STATE is omitted or nil,\n\ 2453 If fifth arg STATE is omitted or nil,\n\
1796 parsing assumes that FROM is the beginning of a function.\n\ 2454 parsing assumes that FROM is the beginning of a function.\n\
1797 Value is a list of eight elements describing final state of parsing:\n\ 2455 Value is a list of nine elements describing final state of parsing:\n\
1798 0. depth in parens.\n\ 2456 0. depth in parens.\n\
1799 1. character address of start of innermost containing list; nil if none.\n\ 2457 1. character address of start of innermost containing list; nil if none.\n\
1800 2. character address of start of last complete sexp terminated.\n\ 2458 2. character address of start of last complete sexp terminated.\n\
1801 3. non-nil if inside a string.\n\ 2459 3. non-nil if inside a string.\n\
1802 (it is the character that will terminate the string.)\n\ 2460 (it is the character that will terminate the string,\n\
2461 or t if the string should be terminated by an explicit\n\
2462 `syntax-table' property.)\n\
1803 4. t if inside a comment.\n\ 2463 4. t if inside a comment.\n\
1804 5. t if following a quote character.\n\ 2464 5. t if following a quote character.\n\
1805 6. the minimum paren-depth encountered during this scan.\n\ 2465 6. the minimum paren-depth encountered during this scan.\n\
1806 7. t if in a comment of style `b'.\n\ 2466 7. t if in a comment of style `b'; `syntax-table' if given by an explicit\n\
2467 `syntax-table' property.\n\
2468 8. character address of start of last comment or string; nil if none.\n\
1807 If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\ 2469 If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
1808 in parentheses becomes equal to TARGETDEPTH.\n\ 2470 in parentheses becomes equal to TARGETDEPTH.\n\
1809 Fourth arg STOPBEFORE non-nil means stop when come to\n\ 2471 Fourth arg STOPBEFORE non-nil means stop when come to\n\
1810 any character that starts a sexp.\n\ 2472 any character that starts a sexp.\n\
1811 Fifth arg STATE is an eight-list like what this function returns.\n\ 2473 Fifth arg STATE is an eight-list like what this function returns.\n\
1812 It is used to initialize the state of the parse. Its second and third 2474 It is used to initialize the state of the parse. Its second and third
1813 elements are ignored. 2475 elements are ignored.
1814 Sixth args COMMENTSTOP non-nil means stop at the start of a comment.") 2476 Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. If\n\
2477 it is `syntax-table', stop after the start of a comment or a string, or\n\
2478 after end of a comment or a string.")
1815 (from, to, targetdepth, stopbefore, state, commentstop) 2479 (from, to, targetdepth, stopbefore, state, commentstop)
1816 */ 2480 */
1817 2481
1818 DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0, 2482 DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0,
1819 0 /* See immediately above */) 2483 0 /* See immediately above */)
1832 target = -100000; /* We won't reach this depth */ 2496 target = -100000; /* We won't reach this depth */
1833 2497
1834 validate_region (&from, &to); 2498 validate_region (&from, &to);
1835 scan_sexps_forward (&state, XINT (from), XINT (to), 2499 scan_sexps_forward (&state, XINT (from), XINT (to),
1836 target, !NILP (stopbefore), oldstate, 2500 target, !NILP (stopbefore), oldstate,
1837 !NILP (commentstop)); 2501 (NILP (commentstop)
2502 ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1)));
1838 2503
1839 SET_PT (state.location); 2504 SET_PT (state.location);
1840 2505
1841 return Fcons (make_number (state.depth), 2506 return Fcons (make_number (state.depth),
1842 Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart), 2507 Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart),
1843 Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart), 2508 Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart),
1844 Fcons (state.instring >= 0 ? make_number (state.instring) : Qnil, 2509 Fcons (state.instring >= 0
2510 ? (state.instring == ST_STRING_STYLE
2511 ? Qt : make_number (state.instring)) : Qnil,
1845 Fcons (state.incomment ? Qt : Qnil, 2512 Fcons (state.incomment ? Qt : Qnil,
1846 Fcons (state.quoted ? Qt : Qnil, 2513 Fcons (state.quoted ? Qt : Qnil,
1847 Fcons (make_number (state.mindepth), 2514 Fcons (make_number (state.mindepth),
1848 Fcons (state.comstyle ? Qt : Qnil, 2515 Fcons (state.comstyle
1849 Qnil)))))))); 2516 ? (state.comstyle == ST_COMMENT_STYLE
2517 ? Qsyntax_table : Qt) : Qnil,
2518 Fcons (state.comstr_start != -1 ? make_number (state.comstr_start) : Qnil,
2519 Qnil)))))))));
1850 } 2520 }
1851 2521
1852 init_syntax_once () 2522 init_syntax_once ()
1853 { 2523 {
1854 register int i, c; 2524 register int i, c;
1935 build_string ("Scan error")); 2605 build_string ("Scan error"));
1936 2606
1937 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments, 2607 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments,
1938 "Non-nil means `forward-sexp', etc., should treat comments as whitespace."); 2608 "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
1939 2609
2610 DEFVAR_BOOL ("parse-sexp-lookup-properties", &parse_sexp_lookup_properties,
2611 "Non-nil means `forward-sexp', etc., grant `syntax-table' property.\n\
2612 The value of this property should be either a syntax table, or a cons\n\
2613 of the form (SYNTAXCODE . MATCHCHAR), SYNTAXCODE being the numeric\n\
2614 syntax code, MATCHCHAR being nil or the character to match (which is\n\
2615 relevant only for open/close type.");
2616
1940 words_include_escapes = 0; 2617 words_include_escapes = 0;
1941 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes, 2618 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes,
1942 "Non-nil means `forward-word', etc., should treat escape chars part of words."); 2619 "Non-nil means `forward-word', etc., should treat escape chars part of words.");
1943 2620
1944 defsubr (&Ssyntax_table_p); 2621 defsubr (&Ssyntax_table_p);
1951 defsubr (&Smodify_syntax_entry); 2628 defsubr (&Smodify_syntax_entry);
1952 defsubr (&Sdescribe_syntax); 2629 defsubr (&Sdescribe_syntax);
1953 2630
1954 defsubr (&Sforward_word); 2631 defsubr (&Sforward_word);
1955 2632
2633 defsubr (&Sskip_chars_forward);
2634 defsubr (&Sskip_chars_backward);
2635 defsubr (&Sskip_syntax_forward);
2636 defsubr (&Sskip_syntax_backward);
2637
1956 defsubr (&Sforward_comment); 2638 defsubr (&Sforward_comment);
1957 defsubr (&Sscan_lists); 2639 defsubr (&Sscan_lists);
1958 defsubr (&Sscan_sexps); 2640 defsubr (&Sscan_sexps);
1959 defsubr (&Sbackward_prefix_chars); 2641 defsubr (&Sbackward_prefix_chars);
1960 defsubr (&Sparse_partial_sexp); 2642 defsubr (&Sparse_partial_sexp);