aboutsummaryrefslogtreecommitdiffstats
path: root/src/syntax.c
diff options
context:
space:
mode:
authorRichard M. Stallman1997-04-15 04:53:58 +0000
committerRichard M. Stallman1997-04-15 04:53:58 +0000
commit195d13612d320503ec7efe4fbf8acbaa114114db (patch)
treebab72c741f8fcf365f781dbe30d4e7840b0fee98 /src/syntax.c
parent8bb43c28a30734966e16c7968baafb469a0a3f18 (diff)
downloademacs-195d13612d320503ec7efe4fbf8acbaa114114db.tar.gz
emacs-195d13612d320503ec7efe4fbf8acbaa114114db.zip
(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.
Diffstat (limited to 'src/syntax.c')
-rw-r--r--src/syntax.c884
1 files changed, 783 insertions, 101 deletions
diff --git a/src/syntax.c b/src/syntax.c
index ee935e77911..3cf575b71eb 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -25,7 +25,19 @@ Boston, MA 02111-1307, USA. */
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
31Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error; 43Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error;
@@ -34,6 +46,7 @@ static void scan_sexps_forward ();
34static int char_quoted (); 46static int char_quoted ();
35 47
36int words_include_escapes; 48int words_include_escapes;
49int 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
@@ -44,16 +57,16 @@ Lisp_Object syntax_temp;
44 57
45struct lisp_parse_state 58struct 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.
@@ -68,10 +81,205 @@ static int find_start_value;
68static struct buffer *find_start_buffer; 81static struct buffer *find_start_buffer;
69static int find_start_begv; 82static int find_start_begv;
70static int find_start_modiff; 83static int find_start_modiff;
84
85
86struct gl_state_s gl_state; /* Global state of syntax parser. */
87
88INTERVAL 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
106void
107update_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 }
71 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
255static int
256char_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
76static int 284static int
77find_defun_start (pos) 285find_defun_start (pos)
@@ -94,11 +302,23 @@ find_defun_start (pos)
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 }
@@ -113,6 +333,158 @@ find_defun_start (pos)
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
343static int
344back_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
116DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0, 488DEFUN ("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\
118Currently, any char-table counts as a syntax table.") 490Currently, any char-table counts as a syntax table.")
@@ -194,14 +566,14 @@ One argument, a syntax table.")
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
199unsigned char syntax_spec_code[0400] = 571unsigned 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,
@@ -215,14 +587,15 @@ unsigned char syntax_spec_code[0400] =
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
223char syntax_code_spec[14] = 595char 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
@@ -266,6 +639,9 @@ are listed in the documentation of `modify-syntax-entry'.")
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)]);
@@ -277,6 +653,8 @@ DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0,
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);
@@ -313,7 +691,7 @@ Defined flags are the characters 1, 2, 3, 4, b, and p.\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\
316There can be up to two orthogonal comment sequences. This is to support\n\ 694There can be up to two orthogonal comment sequences. This is to support\n\
317language modes such as C++. By default, all comment sequences are of style\n\ 695language modes such as C++. By default, all comment sequences are of style\n\
318a, but you can set the comment sequence style to b (on the second character\n\ 696a, but you can set the comment sequence style to b (on the second character\n\
319of a comment-start, or the first character of a comment-end sequence) using\n\ 697of a comment-start, or the first character of a comment-end sequence) using\n\
@@ -579,6 +957,8 @@ The descriptions are inserted in a buffer, which is then displayed.")
579 return Qnil; 957 return Qnil;
580} 958}
581 959
960int 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. */
@@ -595,6 +975,8 @@ scan_words (from, count)
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)
@@ -604,6 +986,7 @@ scan_words (from, count)
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);
@@ -618,6 +1001,7 @@ scan_words (from, count)
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
@@ -639,6 +1023,7 @@ scan_words (from, count)
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
@@ -654,6 +1039,7 @@ scan_words (from, count)
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
@@ -691,6 +1077,176 @@ and nil is returned.")
691 return Qt; 1077 return Qt;
692} 1078}
693 1079
1080Lisp_Object skip_chars ();
1081
1082DEFUN ("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\
1084STRING is like the inside of a `[...]' in a regular expression\n\
1085except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
1086Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
1087With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\
1088Returns 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
1095DEFUN ("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\
1097See `skip-chars-forward' for details.\n\
1098Returns 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
1105DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
1106 "Move point forward across chars in specified syntax classes.\n\
1107SYNTAX is a string of syntax code characters.\n\
1108Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
1109If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1110This 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
1117DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
1118 "Move point backward across chars in specified syntax classes.\n\
1119SYNTAX is a string of syntax code characters.\n\
1120Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
1121If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1122This 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
1129Lisp_Object
1130skip_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
694DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, 1250DEFUN ("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\
696Stop scanning if we find something other than a comment or whitespace.\n\ 1252Stop scanning if we find something other than a comment or whitespace.\n\
@@ -711,15 +1267,16 @@ between them, return t; otherwise return nil.")
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)
@@ -728,6 +1285,7 @@ between them, return t; otherwise return nil.")
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);
@@ -747,7 +1305,7 @@ between them, return t; otherwise return nil.")
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);
@@ -763,6 +1321,7 @@ between them, return t; otherwise return nil.")
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
@@ -771,6 +1330,12 @@ between them, return t; otherwise return nil.")
771 as the comment sequence which began this comment 1330 as the comment sequence which began this comment
772 section */ 1331 section */
773 break; 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. */
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))
@@ -786,7 +1351,6 @@ between them, return t; otherwise return nil.")
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;
@@ -794,7 +1358,11 @@ between them, return t; otherwise return nil.")
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;
@@ -815,7 +1383,28 @@ between them, return t; otherwise return nil.")
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))
@@ -846,7 +1435,9 @@ between them, return t; otherwise return nil.")
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;
@@ -873,6 +1464,7 @@ between them, return t; otherwise return nil.")
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
@@ -956,17 +1548,19 @@ between them, return t; otherwise return nil.")
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);
@@ -982,46 +1576,47 @@ between them, return t; otherwise return nil.")
982 return Qt; 1576 return Qt;
983} 1577}
984 1578
985int parse_sexp_ignore_comments;
986
987Lisp_Object 1579Lisp_Object
988scan_lists (from, count, depth, sexpflag) 1580scan_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 */
@@ -1030,6 +1625,7 @@ scan_lists (from, count, depth, sexpflag)
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
@@ -1043,9 +1639,10 @@ scan_lists (from, count, depth, sexpflag)
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:
@@ -1065,6 +1662,7 @@ scan_lists (from, count, depth, sexpflag)
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 {
@@ -1074,9 +1672,12 @@ scan_lists (from, count, depth, sexpflag)
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 */
@@ -1084,7 +1685,8 @@ scan_lists (from, count, depth, sexpflag)
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 */
@@ -1119,13 +1721,18 @@ scan_lists (from, count, depth, sexpflag)
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:
@@ -1153,12 +1760,15 @@ scan_lists (from, count, depth, sexpflag)
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)
@@ -1189,16 +1799,19 @@ scan_lists (from, count, depth, sexpflag)
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);
@@ -1215,6 +1828,7 @@ scan_lists (from, count, depth, 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)
@@ -1268,7 +1882,9 @@ scan_lists (from, count, depth, sexpflag)
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;
@@ -1379,14 +1995,29 @@ scan_lists (from, count, depth, sexpflag)
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)
@@ -1394,6 +2025,7 @@ scan_lists (from, count, depth, sexpflag)
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;
@@ -1429,27 +2061,6 @@ scan_lists (from, count, depth, sexpflag)
1429 /* NOTREACHED */ 2061 /* NOTREACHED */
1430} 2062}
1431 2063
1432static int
1433char_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}
1452
1453DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0, 2064DEFUN ("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\
1455Returns the character number of the position thus found.\n\ 2066Returns the character number of the position thus found.\n\
@@ -1505,9 +2116,14 @@ This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
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 {
@@ -1550,6 +2166,8 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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);
@@ -1560,12 +2178,15 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
1560 immediate_quit = 1; 2178 immediate_quit = 1;
1561 QUIT; 2179 QUIT;
1562 2180
2181 SETUP_SYNTAX_TABLE (from, 1);
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 {
@@ -1579,7 +2200,10 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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);
@@ -1590,11 +2214,16 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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 */
2218 oldstate = Fcdr (oldstate);
1594 oldstate = Fcdr (oldstate); 2219 oldstate = Fcdr (oldstate);
2220 tem = Fcar (oldstate);
2221 state.comstyle = NILP (tem) ? 0 : ( EQ (tem, Qsyntax_table)
2222 ? ST_COMMENT_STYLE : 1 );
2223
1595 oldstate = Fcdr (oldstate); 2224 oldstate = Fcdr (oldstate);
1596 tem = Fcar (oldstate); 2225 tem = Fcar (oldstate);
1597 state.comstyle = !NILP (tem); 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;
@@ -1602,11 +2231,12 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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 }
@@ -1614,21 +2244,25 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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)))
@@ -1651,6 +2285,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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:
@@ -1672,7 +2307,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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 {
@@ -1682,14 +2317,17 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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)
@@ -1697,6 +2335,9 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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. */
1699 break; 2337 break;
2338 if (state.comstyle == ST_COMMENT_STYLE
2339 && SYNTAX (prev) == Scomment_fence)
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)
@@ -1705,10 +2346,12 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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:
@@ -1734,30 +2377,45 @@ scan_sexps_forward (stateptr, from, end, targetdepth,
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:
@@ -1794,16 +2452,20 @@ 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\
1795If fifth arg STATE is omitted or nil,\n\ 2453If 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\
1797Value is a list of eight elements describing final state of parsing:\n\ 2455Value 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\
1807If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\ 2469If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
1808in parentheses becomes equal to TARGETDEPTH.\n\ 2470in parentheses becomes equal to TARGETDEPTH.\n\
1809Fourth arg STOPBEFORE non-nil means stop when come to\n\ 2471Fourth arg STOPBEFORE non-nil means stop when come to\n\
@@ -1811,7 +2473,9 @@ Fourth arg STOPBEFORE non-nil means stop when come to\n\
1811Fifth arg STATE is an eight-list like what this function returns.\n\ 2473Fifth arg STATE is an eight-list like what this function returns.\n\
1812It is used to initialize the state of the parse. Its second and third 2474It is used to initialize the state of the parse. Its second and third
1813elements are ignored. 2475elements are ignored.
1814Sixth args COMMENTSTOP non-nil means stop at the start of a comment.") 2476Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. If\n\
2477it is `syntax-table', stop after the start of a comment or a string, or\n\
2478after 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
@@ -1834,19 +2498,25 @@ DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0,
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
1852init_syntax_once () 2522init_syntax_once ()
@@ -1937,6 +2607,13 @@ syms_of_syntax ()
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\
2612The value of this property should be either a syntax table, or a cons\n\
2613of the form (SYNTAXCODE . MATCHCHAR), SYNTAXCODE being the numeric\n\
2614syntax code, MATCHCHAR being nil or the character to match (which is\n\
2615relevant 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.");
@@ -1953,6 +2630,11 @@ syms_of_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);