Merge from emacs-24; up to 2012-12-31T11:35:13Z!rudalics@gmx.at
[bpt/emacs.git] / src / syntax.c
1 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2013 Free
3 Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20
21 #include <config.h>
22
23 #define SYNTAX_INLINE EXTERN_INLINE
24
25 #include <sys/types.h>
26
27 #include "lisp.h"
28 #include "commands.h"
29 #include "character.h"
30 #include "buffer.h"
31 #include "keymap.h"
32 #include "regex.h"
33
34 /* Make syntax table lookup grant data in gl_state. */
35 #define SYNTAX_ENTRY_VIA_PROPERTY
36
37 #include "syntax.h"
38 #include "intervals.h"
39 #include "category.h"
40
41 /* Eight single-bit flags have the following meanings:
42 1. This character is the first of a two-character comment-start sequence.
43 2. This character is the second of a two-character comment-start sequence.
44 3. This character is the first of a two-character comment-end sequence.
45 4. This character is the second of a two-character comment-end sequence.
46 5. This character is a prefix, for backward-prefix-chars.
47 6. The char is part of a delimiter for comments of style "b".
48 7. This character is part of a nestable comment sequence.
49 8. The char is part of a delimiter for comments of style "c".
50 Note that any two-character sequence whose first character has flag 1
51 and whose second character has flag 2 will be interpreted as a comment start.
52
53 Bits 6 and 8 discriminate among different comment styles.
54 Languages such as C++ allow two orthogonal syntax start/end pairs
55 and bit 6 determines whether a comment-end or Scommentend
56 ends style a or b. Comment markers can start style a, b, c, or bc.
57 Style a is always the default.
58 For 2-char comment markers, the style b flag is looked up only on the second
59 char of the comment marker and on the first char of the comment ender.
60 For style c (like the nested flag), the flag can be placed on any of
61 the chars. */
62
63 /* These functions extract specific flags from an integer
64 that holds the syntax code and the flags. */
65
66 static bool
67 SYNTAX_FLAGS_COMSTART_FIRST (int flags)
68 {
69 return (flags >> 16) & 1;
70 }
71 static bool
72 SYNTAX_FLAGS_COMSTART_SECOND (int flags)
73 {
74 return (flags >> 17) & 1;
75 }
76 static bool
77 SYNTAX_FLAGS_COMEND_FIRST (int flags)
78 {
79 return (flags >> 18) & 1;
80 }
81 static bool
82 SYNTAX_FLAGS_COMEND_SECOND (int flags)
83 {
84 return (flags >> 19) & 1;
85 }
86 static bool
87 SYNTAX_FLAGS_PREFIX (int flags)
88 {
89 return (flags >> 20) & 1;
90 }
91 static bool
92 SYNTAX_FLAGS_COMMENT_STYLEB (int flags)
93 {
94 return (flags >> 21) & 1;
95 }
96 static bool
97 SYNTAX_FLAGS_COMMENT_STYLEC (int flags)
98 {
99 return (flags >> 23) & 1;
100 }
101 static int
102 SYNTAX_FLAGS_COMMENT_STYLEC2 (int flags)
103 {
104 return (flags >> 22) & 2; /* SYNTAX_FLAGS_COMMENT_STYLEC (flags) * 2 */
105 }
106 static bool
107 SYNTAX_FLAGS_COMMENT_NESTED (int flags)
108 {
109 return (flags >> 22) & 1;
110 }
111
112 /* FLAGS should be the flags of the main char of the comment marker, e.g.
113 the second for comstart and the first for comend. */
114 static int
115 SYNTAX_FLAGS_COMMENT_STYLE (int flags, int other_flags)
116 {
117 return (SYNTAX_FLAGS_COMMENT_STYLEB (flags)
118 | SYNTAX_FLAGS_COMMENT_STYLEC2 (flags)
119 | SYNTAX_FLAGS_COMMENT_STYLEC2 (other_flags));
120 }
121
122 /* Extract a particular flag for a given character. */
123
124 static bool
125 SYNTAX_COMEND_FIRST (int c)
126 {
127 return SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c));
128 }
129
130 /* We use these constants in place for comment-style and
131 string-ender-char to distinguish comments/strings started by
132 comment_fence and string_fence codes. */
133
134 enum
135 {
136 ST_COMMENT_STYLE = 256 + 1,
137 ST_STRING_STYLE = 256 + 2
138 };
139
140 static Lisp_Object Qsyntax_table_p;
141 static Lisp_Object Qsyntax_table, Qscan_error;
142
143 /* This is the internal form of the parse state used in parse-partial-sexp. */
144
145 struct lisp_parse_state
146 {
147 EMACS_INT depth; /* Depth at end of parsing. */
148 int instring; /* -1 if not within string, else desired terminator. */
149 EMACS_INT incomment; /* -1 if in unnestable comment else comment nesting */
150 int comstyle; /* comment style a=0, or b=1, or ST_COMMENT_STYLE. */
151 bool quoted; /* True if just after an escape char at end of parsing. */
152 EMACS_INT mindepth; /* Minimum depth seen while scanning. */
153 /* Char number of most recent start-of-expression at current level */
154 ptrdiff_t thislevelstart;
155 /* Char number of start of containing expression */
156 ptrdiff_t prevlevelstart;
157 ptrdiff_t location; /* Char number at which parsing stopped. */
158 ptrdiff_t location_byte; /* Corresponding byte position. */
159 ptrdiff_t comstr_start; /* Position of last comment/string starter. */
160 Lisp_Object levelstarts; /* Char numbers of starts-of-expression
161 of levels (starting from outermost). */
162 };
163 \f
164 /* These variables are a cache for finding the start of a defun.
165 find_start_pos is the place for which the defun start was found.
166 find_start_value is the defun start position found for it.
167 find_start_value_byte is the corresponding byte position.
168 find_start_buffer is the buffer it was found in.
169 find_start_begv is the BEGV value when it was found.
170 find_start_modiff is the value of MODIFF when it was found. */
171
172 static ptrdiff_t find_start_pos;
173 static ptrdiff_t find_start_value;
174 static ptrdiff_t find_start_value_byte;
175 static struct buffer *find_start_buffer;
176 static ptrdiff_t find_start_begv;
177 static EMACS_INT find_start_modiff;
178
179
180 static Lisp_Object skip_chars (bool, Lisp_Object, Lisp_Object, bool);
181 static Lisp_Object skip_syntaxes (bool, Lisp_Object, Lisp_Object);
182 static Lisp_Object scan_lists (EMACS_INT, EMACS_INT, EMACS_INT, bool);
183 static void scan_sexps_forward (struct lisp_parse_state *,
184 ptrdiff_t, ptrdiff_t, ptrdiff_t, EMACS_INT,
185 bool, Lisp_Object, int);
186 static bool in_classes (int, Lisp_Object);
187
188 /* This setter is used only in this file, so it can be private. */
189 static void
190 bset_syntax_table (struct buffer *b, Lisp_Object val)
191 {
192 b->INTERNAL_FIELD (syntax_table) = val;
193 }
194 \f
195 /* Whether the syntax of the character C has the prefix flag set. */
196 bool
197 syntax_prefix_flag_p (int c)
198 {
199 return SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c));
200 }
201
202 struct gl_state_s gl_state; /* Global state of syntax parser. */
203
204 enum { INTERVALS_AT_ONCE = 10 }; /* 1 + max-number of intervals
205 to scan to property-change. */
206
207 /* Set the syntax entry VAL for char C in table TABLE. */
208
209 static void
210 SET_RAW_SYNTAX_ENTRY (Lisp_Object table, int c, Lisp_Object val)
211 {
212 CHAR_TABLE_SET (table, c, val);
213 }
214
215 /* Set the syntax entry VAL for char-range RANGE in table TABLE.
216 RANGE is a cons (FROM . TO) specifying the range of characters. */
217
218 static void
219 SET_RAW_SYNTAX_ENTRY_RANGE (Lisp_Object table, Lisp_Object range,
220 Lisp_Object val)
221 {
222 Fset_char_table_range (table, range, val);
223 }
224
225 /* Extract the information from the entry for character C
226 in the current syntax table. */
227
228 static Lisp_Object
229 SYNTAX_MATCH (int c)
230 {
231 Lisp_Object ent = SYNTAX_ENTRY (c);
232 return CONSP (ent) ? XCDR (ent) : Qnil;
233 }
234
235 /* This should be called with FROM at the start of forward
236 search, or after the last position of the backward search. It
237 makes sure that the first char is picked up with correct table, so
238 one does not need to call UPDATE_SYNTAX_TABLE immediately after the
239 call.
240 Sign of COUNT gives the direction of the search.
241 */
242
243 static void
244 SETUP_SYNTAX_TABLE (ptrdiff_t from, ptrdiff_t count)
245 {
246 SETUP_BUFFER_SYNTAX_TABLE ();
247 gl_state.b_property = BEGV;
248 gl_state.e_property = ZV + 1;
249 gl_state.object = Qnil;
250 gl_state.offset = 0;
251 if (parse_sexp_lookup_properties)
252 if (count > 0 || from > BEGV)
253 update_syntax_table (count > 0 ? from : from - 1, count, 1, Qnil);
254 }
255
256 /* Same as above, but in OBJECT. If OBJECT is nil, use current buffer.
257 If it is t (which is only used in fast_c_string_match_ignore_case),
258 ignore properties altogether.
259
260 This is meant for regex.c to use. For buffers, regex.c passes arguments
261 to the UPDATE_SYNTAX_TABLE functions which are relative to BEGV.
262 So if it is a buffer, we set the offset field to BEGV. */
263
264 void
265 SETUP_SYNTAX_TABLE_FOR_OBJECT (Lisp_Object object,
266 ptrdiff_t from, ptrdiff_t count)
267 {
268 SETUP_BUFFER_SYNTAX_TABLE ();
269 gl_state.object = object;
270 if (BUFFERP (gl_state.object))
271 {
272 struct buffer *buf = XBUFFER (gl_state.object);
273 gl_state.b_property = 1;
274 gl_state.e_property = BUF_ZV (buf) - BUF_BEGV (buf) + 1;
275 gl_state.offset = BUF_BEGV (buf) - 1;
276 }
277 else if (NILP (gl_state.object))
278 {
279 gl_state.b_property = 1;
280 gl_state.e_property = ZV - BEGV + 1;
281 gl_state.offset = BEGV - 1;
282 }
283 else if (EQ (gl_state.object, Qt))
284 {
285 gl_state.b_property = 0;
286 gl_state.e_property = PTRDIFF_MAX;
287 gl_state.offset = 0;
288 }
289 else
290 {
291 gl_state.b_property = 0;
292 gl_state.e_property = 1 + SCHARS (gl_state.object);
293 gl_state.offset = 0;
294 }
295 if (parse_sexp_lookup_properties)
296 update_syntax_table (from + gl_state.offset - (count <= 0),
297 count, 1, gl_state.object);
298 }
299
300 /* Update gl_state to an appropriate interval which contains CHARPOS. The
301 sign of COUNT give the relative position of CHARPOS wrt the previously
302 valid interval. If INIT, only [be]_property fields of gl_state are
303 valid at start, the rest is filled basing on OBJECT.
304
305 `gl_state.*_i' are the intervals, and CHARPOS is further in the search
306 direction than the intervals - or in an interval. We update the
307 current syntax-table basing on the property of this interval, and
308 update the interval to start further than CHARPOS - or be
309 NULL. We also update lim_property to be the next value of
310 charpos to call this subroutine again - or be before/after the
311 start/end of OBJECT. */
312
313 void
314 update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init,
315 Lisp_Object object)
316 {
317 Lisp_Object tmp_table;
318 int cnt = 0;
319 bool invalidate = 1;
320 INTERVAL i;
321
322 if (init)
323 {
324 gl_state.old_prop = Qnil;
325 gl_state.start = gl_state.b_property;
326 gl_state.stop = gl_state.e_property;
327 i = interval_of (charpos, object);
328 gl_state.backward_i = gl_state.forward_i = i;
329 invalidate = 0;
330 if (!i)
331 return;
332 /* interval_of updates only ->position of the return value, so
333 update the parents manually to speed up update_interval. */
334 while (!NULL_PARENT (i))
335 {
336 if (AM_RIGHT_CHILD (i))
337 INTERVAL_PARENT (i)->position = i->position
338 - LEFT_TOTAL_LENGTH (i) + TOTAL_LENGTH (i) /* right end */
339 - TOTAL_LENGTH (INTERVAL_PARENT (i))
340 + LEFT_TOTAL_LENGTH (INTERVAL_PARENT (i));
341 else
342 INTERVAL_PARENT (i)->position = i->position - LEFT_TOTAL_LENGTH (i)
343 + TOTAL_LENGTH (i);
344 i = INTERVAL_PARENT (i);
345 }
346 i = gl_state.forward_i;
347 gl_state.b_property = i->position - gl_state.offset;
348 gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset;
349 goto update;
350 }
351 i = count > 0 ? gl_state.forward_i : gl_state.backward_i;
352
353 /* We are guaranteed to be called with CHARPOS either in i,
354 or further off. */
355 if (!i)
356 error ("Error in syntax_table logic for to-the-end intervals");
357 else if (charpos < i->position) /* Move left. */
358 {
359 if (count > 0)
360 error ("Error in syntax_table logic for intervals <-");
361 /* Update the interval. */
362 i = update_interval (i, charpos);
363 if (INTERVAL_LAST_POS (i) != gl_state.b_property)
364 {
365 invalidate = 0;
366 gl_state.forward_i = i;
367 gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset;
368 }
369 }
370 else if (charpos >= INTERVAL_LAST_POS (i)) /* Move right. */
371 {
372 if (count < 0)
373 error ("Error in syntax_table logic for intervals ->");
374 /* Update the interval. */
375 i = update_interval (i, charpos);
376 if (i->position != gl_state.e_property)
377 {
378 invalidate = 0;
379 gl_state.backward_i = i;
380 gl_state.b_property = i->position - gl_state.offset;
381 }
382 }
383
384 update:
385 tmp_table = textget (i->plist, Qsyntax_table);
386
387 if (invalidate)
388 invalidate = !EQ (tmp_table, gl_state.old_prop); /* Need to invalidate? */
389
390 if (invalidate) /* Did not get to adjacent interval. */
391 { /* with the same table => */
392 /* invalidate the old range. */
393 if (count > 0)
394 {
395 gl_state.backward_i = i;
396 gl_state.b_property = i->position - gl_state.offset;
397 }
398 else
399 {
400 gl_state.forward_i = i;
401 gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset;
402 }
403 }
404
405 if (!EQ (tmp_table, gl_state.old_prop))
406 {
407 gl_state.current_syntax_table = tmp_table;
408 gl_state.old_prop = tmp_table;
409 if (EQ (Fsyntax_table_p (tmp_table), Qt))
410 {
411 gl_state.use_global = 0;
412 }
413 else if (CONSP (tmp_table))
414 {
415 gl_state.use_global = 1;
416 gl_state.global_code = tmp_table;
417 }
418 else
419 {
420 gl_state.use_global = 0;
421 gl_state.current_syntax_table = BVAR (current_buffer, syntax_table);
422 }
423 }
424
425 while (i)
426 {
427 if (cnt && !EQ (tmp_table, textget (i->plist, Qsyntax_table)))
428 {
429 if (count > 0)
430 {
431 gl_state.e_property = i->position - gl_state.offset;
432 gl_state.forward_i = i;
433 }
434 else
435 {
436 gl_state.b_property
437 = i->position + LENGTH (i) - gl_state.offset;
438 gl_state.backward_i = i;
439 }
440 return;
441 }
442 else if (cnt == INTERVALS_AT_ONCE)
443 {
444 if (count > 0)
445 {
446 gl_state.e_property
447 = i->position + LENGTH (i) - gl_state.offset
448 /* e_property at EOB is not set to ZV but to ZV+1, so that
449 we can do INC(from);UPDATE_SYNTAX_TABLE_FORWARD without
450 having to check eob between the two. */
451 + (next_interval (i) ? 0 : 1);
452 gl_state.forward_i = i;
453 }
454 else
455 {
456 gl_state.b_property = i->position - gl_state.offset;
457 gl_state.backward_i = i;
458 }
459 return;
460 }
461 cnt++;
462 i = count > 0 ? next_interval (i) : previous_interval (i);
463 }
464 eassert (i == NULL); /* This property goes to the end. */
465 if (count > 0)
466 gl_state.e_property = gl_state.stop;
467 else
468 gl_state.b_property = gl_state.start;
469 }
470 \f
471 /* Returns true if char at CHARPOS is quoted.
472 Global syntax-table data should be set up already to be good at CHARPOS
473 or after. On return global syntax data is good for lookup at CHARPOS. */
474
475 static bool
476 char_quoted (ptrdiff_t charpos, ptrdiff_t bytepos)
477 {
478 enum syntaxcode code;
479 ptrdiff_t beg = BEGV;
480 bool quoted = 0;
481 ptrdiff_t orig = charpos;
482
483 while (charpos > beg)
484 {
485 int c;
486 DEC_BOTH (charpos, bytepos);
487
488 UPDATE_SYNTAX_TABLE_BACKWARD (charpos);
489 c = FETCH_CHAR_AS_MULTIBYTE (bytepos);
490 code = SYNTAX (c);
491 if (! (code == Scharquote || code == Sescape))
492 break;
493
494 quoted = !quoted;
495 }
496
497 UPDATE_SYNTAX_TABLE (orig);
498 return quoted;
499 }
500
501 /* Return the bytepos one character before BYTEPOS.
502 We assume that BYTEPOS is not at the start of the buffer. */
503
504 static ptrdiff_t
505 dec_bytepos (ptrdiff_t bytepos)
506 {
507 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
508 return bytepos - 1;
509
510 DEC_POS (bytepos);
511 return bytepos;
512 }
513 \f
514 /* Return a defun-start position before POS and not too far before.
515 It should be the last one before POS, or nearly the last.
516
517 When open_paren_in_column_0_is_defun_start is nonzero,
518 only the beginning of the buffer is treated as a defun-start.
519
520 We record the information about where the scan started
521 and what its result was, so that another call in the same area
522 can return the same value very quickly.
523
524 There is no promise at which position the global syntax data is
525 valid on return from the subroutine, so the caller should explicitly
526 update the global data. */
527
528 static ptrdiff_t
529 find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
530 {
531 ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
532
533 if (!open_paren_in_column_0_is_defun_start)
534 {
535 find_start_value = BEGV;
536 find_start_value_byte = BEGV_BYTE;
537 find_start_buffer = current_buffer;
538 find_start_modiff = MODIFF;
539 find_start_begv = BEGV;
540 find_start_pos = pos;
541 return BEGV;
542 }
543
544 /* Use previous finding, if it's valid and applies to this inquiry. */
545 if (current_buffer == find_start_buffer
546 /* Reuse the defun-start even if POS is a little farther on.
547 POS might be in the next defun, but that's ok.
548 Our value may not be the best possible, but will still be usable. */
549 && pos <= find_start_pos + 1000
550 && pos >= find_start_value
551 && BEGV == find_start_begv
552 && MODIFF == find_start_modiff)
553 return find_start_value;
554
555 /* Back up to start of line. */
556 scan_newline (pos, pos_byte, BEGV, BEGV_BYTE, -1, 1);
557
558 /* We optimize syntax-table lookup for rare updates. Thus we accept
559 only those `^\s(' which are good in global _and_ text-property
560 syntax-tables. */
561 SETUP_BUFFER_SYNTAX_TABLE ();
562 while (PT > BEGV)
563 {
564 int c;
565
566 /* Open-paren at start of line means we may have found our
567 defun-start. */
568 c = FETCH_CHAR_AS_MULTIBYTE (PT_BYTE);
569 if (SYNTAX (c) == Sopen)
570 {
571 SETUP_SYNTAX_TABLE (PT + 1, -1); /* Try again... */
572 c = FETCH_CHAR_AS_MULTIBYTE (PT_BYTE);
573 if (SYNTAX (c) == Sopen)
574 break;
575 /* Now fallback to the default value. */
576 SETUP_BUFFER_SYNTAX_TABLE ();
577 }
578 /* Move to beg of previous line. */
579 scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -2, 1);
580 }
581
582 /* Record what we found, for the next try. */
583 find_start_value = PT;
584 find_start_value_byte = PT_BYTE;
585 find_start_buffer = current_buffer;
586 find_start_modiff = MODIFF;
587 find_start_begv = BEGV;
588 find_start_pos = pos;
589
590 TEMP_SET_PT_BOTH (opoint, opoint_byte);
591
592 return find_start_value;
593 }
594 \f
595 /* Return the SYNTAX_COMEND_FIRST of the character before POS, POS_BYTE. */
596
597 static bool
598 prev_char_comend_first (ptrdiff_t pos, ptrdiff_t pos_byte)
599 {
600 int c;
601 bool val;
602
603 DEC_BOTH (pos, pos_byte);
604 UPDATE_SYNTAX_TABLE_BACKWARD (pos);
605 c = FETCH_CHAR (pos_byte);
606 val = SYNTAX_COMEND_FIRST (c);
607 UPDATE_SYNTAX_TABLE_FORWARD (pos + 1);
608 return val;
609 }
610
611 /* Check whether charpos FROM is at the end of a comment.
612 FROM_BYTE is the bytepos corresponding to FROM.
613 Do not move back before STOP.
614
615 Return true if we find a comment ending at FROM/FROM_BYTE.
616
617 If successful, store the charpos of the comment's beginning
618 into *CHARPOS_PTR, and the bytepos into *BYTEPOS_PTR.
619
620 Global syntax data remains valid for backward search starting at
621 the returned value (or at FROM, if the search was not successful). */
622
623 static bool
624 back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
625 bool comnested, int comstyle, ptrdiff_t *charpos_ptr,
626 ptrdiff_t *bytepos_ptr)
627 {
628 /* Look back, counting the parity of string-quotes,
629 and recording the comment-starters seen.
630 When we reach a safe place, assume that's not in a string;
631 then step the main scan to the earliest comment-starter seen
632 an even number of string quotes away from the safe place.
633
634 OFROM[I] is position of the earliest comment-starter seen
635 which is I+2X quotes from the comment-end.
636 PARITY is current parity of quotes from the comment end. */
637 int string_style = -1; /* Presumed outside of any string. */
638 bool string_lossage = 0;
639 /* Not a real lossage: indicates that we have passed a matching comment
640 starter plus a non-matching comment-ender, meaning that any matching
641 comment-starter we might see later could be a false positive (hidden
642 inside another comment).
643 Test case: { a (* b } c (* d *) */
644 bool comment_lossage = 0;
645 ptrdiff_t comment_end = from;
646 ptrdiff_t comment_end_byte = from_byte;
647 ptrdiff_t comstart_pos = 0;
648 ptrdiff_t comstart_byte IF_LINT (= 0);
649 /* Place where the containing defun starts,
650 or 0 if we didn't come across it yet. */
651 ptrdiff_t defun_start = 0;
652 ptrdiff_t defun_start_byte = 0;
653 enum syntaxcode code;
654 ptrdiff_t nesting = 1; /* current comment nesting */
655 int c;
656 int syntax = 0;
657
658 /* FIXME: A }} comment-ender style leads to incorrect behavior
659 in the case of {{ c }}} because we ignore the last two chars which are
660 assumed to be comment-enders although they aren't. */
661
662 /* At beginning of range to scan, we're outside of strings;
663 that determines quote parity to the comment-end. */
664 while (from != stop)
665 {
666 ptrdiff_t temp_byte;
667 int prev_syntax;
668 bool com2start, com2end, comstart;
669
670 /* Move back and examine a character. */
671 DEC_BOTH (from, from_byte);
672 UPDATE_SYNTAX_TABLE_BACKWARD (from);
673
674 prev_syntax = syntax;
675 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
676 syntax = SYNTAX_WITH_FLAGS (c);
677 code = SYNTAX (c);
678
679 /* Check for 2-char comment markers. */
680 com2start = (SYNTAX_FLAGS_COMSTART_FIRST (syntax)
681 && SYNTAX_FLAGS_COMSTART_SECOND (prev_syntax)
682 && (comstyle
683 == SYNTAX_FLAGS_COMMENT_STYLE (prev_syntax, syntax))
684 && (SYNTAX_FLAGS_COMMENT_NESTED (prev_syntax)
685 || SYNTAX_FLAGS_COMMENT_NESTED (syntax)) == comnested);
686 com2end = (SYNTAX_FLAGS_COMEND_FIRST (syntax)
687 && SYNTAX_FLAGS_COMEND_SECOND (prev_syntax));
688 comstart = (com2start || code == Scomment);
689
690 /* Nasty cases with overlapping 2-char comment markers:
691 - snmp-mode: -- c -- foo -- c --
692 --- c --
693 ------ c --
694 - c-mode: *||*
695 |* *|* *|
696 |*| |* |*|
697 /// */
698
699 /* If a 2-char comment sequence partly overlaps with another,
700 we don't try to be clever. E.g. |*| in C, or }% in modes that
701 have %..\n and %{..}%. */
702 if (from > stop && (com2end || comstart))
703 {
704 ptrdiff_t next = from, next_byte = from_byte;
705 int next_c, next_syntax;
706 DEC_BOTH (next, next_byte);
707 UPDATE_SYNTAX_TABLE_BACKWARD (next);
708 next_c = FETCH_CHAR_AS_MULTIBYTE (next_byte);
709 next_syntax = SYNTAX_WITH_FLAGS (next_c);
710 if (((comstart || comnested)
711 && SYNTAX_FLAGS_COMEND_SECOND (syntax)
712 && SYNTAX_FLAGS_COMEND_FIRST (next_syntax))
713 || ((com2end || comnested)
714 && SYNTAX_FLAGS_COMSTART_SECOND (syntax)
715 && (comstyle
716 == SYNTAX_FLAGS_COMMENT_STYLE (syntax, prev_syntax))
717 && SYNTAX_FLAGS_COMSTART_FIRST (next_syntax)))
718 goto lossage;
719 /* UPDATE_SYNTAX_TABLE_FORWARD (next + 1); */
720 }
721
722 if (com2start && comstart_pos == 0)
723 /* We're looking at a comment starter. But it might be a comment
724 ender as well (see snmp-mode). The first time we see one, we
725 need to consider it as a comment starter,
726 and the subsequent times as a comment ender. */
727 com2end = 0;
728
729 /* Turn a 2-char comment sequences into the appropriate syntax. */
730 if (com2end)
731 code = Sendcomment;
732 else if (com2start)
733 code = Scomment;
734 /* Ignore comment starters of a different style. */
735 else if (code == Scomment
736 && (comstyle != SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0)
737 || SYNTAX_FLAGS_COMMENT_NESTED (syntax) != comnested))
738 continue;
739
740 /* Ignore escaped characters, except comment-enders. */
741 if (code != Sendcomment && char_quoted (from, from_byte))
742 continue;
743
744 switch (code)
745 {
746 case Sstring_fence:
747 case Scomment_fence:
748 c = (code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE);
749 case Sstring:
750 /* Track parity of quotes. */
751 if (string_style == -1)
752 /* Entering a string. */
753 string_style = c;
754 else if (string_style == c)
755 /* Leaving the string. */
756 string_style = -1;
757 else
758 /* If we have two kinds of string delimiters.
759 There's no way to grok this scanning backwards. */
760 string_lossage = 1;
761 break;
762
763 case Scomment:
764 /* We've already checked that it is the relevant comstyle. */
765 if (string_style != -1 || comment_lossage || string_lossage)
766 /* There are odd string quotes involved, so let's be careful.
767 Test case in Pascal: " { " a { " } */
768 goto lossage;
769
770 if (!comnested)
771 {
772 /* Record best comment-starter so far. */
773 comstart_pos = from;
774 comstart_byte = from_byte;
775 }
776 else if (--nesting <= 0)
777 /* nested comments have to be balanced, so we don't need to
778 keep looking for earlier ones. We use here the same (slightly
779 incorrect) reasoning as below: since it is followed by uniform
780 paired string quotes, this comment-start has to be outside of
781 strings, else the comment-end itself would be inside a string. */
782 goto done;
783 break;
784
785 case Sendcomment:
786 if (SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == comstyle
787 && ((com2end && SYNTAX_FLAGS_COMMENT_NESTED (prev_syntax))
788 || SYNTAX_FLAGS_COMMENT_NESTED (syntax)) == comnested)
789 /* This is the same style of comment ender as ours. */
790 {
791 if (comnested)
792 nesting++;
793 else
794 /* Anything before that can't count because it would match
795 this comment-ender rather than ours. */
796 from = stop; /* Break out of the loop. */
797 }
798 else if (comstart_pos != 0 || c != '\n')
799 /* We're mixing comment styles here, so we'd better be careful.
800 The (comstart_pos != 0 || c != '\n') check is not quite correct
801 (we should just always set comment_lossage), but removing it
802 would imply that any multiline comment in C would go through
803 lossage, which seems overkill.
804 The failure should only happen in the rare cases such as
805 { (* } *) */
806 comment_lossage = 1;
807 break;
808
809 case Sopen:
810 /* Assume a defun-start point is outside of strings. */
811 if (open_paren_in_column_0_is_defun_start
812 && (from == stop
813 || (temp_byte = dec_bytepos (from_byte),
814 FETCH_CHAR (temp_byte) == '\n')))
815 {
816 defun_start = from;
817 defun_start_byte = from_byte;
818 from = stop; /* Break out of the loop. */
819 }
820 break;
821
822 default:
823 break;
824 }
825 }
826
827 if (comstart_pos == 0)
828 {
829 from = comment_end;
830 from_byte = comment_end_byte;
831 UPDATE_SYNTAX_TABLE_FORWARD (comment_end - 1);
832 }
833 /* If comstart_pos is set and we get here (ie. didn't jump to `lossage'
834 or `done'), then we've found the beginning of the non-nested comment. */
835 else if (1) /* !comnested */
836 {
837 from = comstart_pos;
838 from_byte = comstart_byte;
839 UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
840 }
841 else
842 {
843 struct lisp_parse_state state;
844 lossage:
845 /* We had two kinds of string delimiters mixed up
846 together. Decode this going forwards.
847 Scan fwd from a known safe place (beginning-of-defun)
848 to the one in question; this records where we
849 last passed a comment starter. */
850 /* If we did not already find the defun start, find it now. */
851 if (defun_start == 0)
852 {
853 defun_start = find_defun_start (comment_end, comment_end_byte);
854 defun_start_byte = find_start_value_byte;
855 }
856 do
857 {
858 scan_sexps_forward (&state,
859 defun_start, defun_start_byte,
860 comment_end, TYPE_MINIMUM (EMACS_INT),
861 0, Qnil, 0);
862 defun_start = comment_end;
863 if (state.incomment == (comnested ? 1 : -1)
864 && state.comstyle == comstyle)
865 from = state.comstr_start;
866 else
867 {
868 from = comment_end;
869 if (state.incomment)
870 /* If comment_end is inside some other comment, maybe ours
871 is nested, so we need to try again from within the
872 surrounding comment. Example: { a (* " *) */
873 {
874 /* FIXME: We should advance by one or two chars. */
875 defun_start = state.comstr_start + 2;
876 defun_start_byte = CHAR_TO_BYTE (defun_start);
877 }
878 }
879 } while (defun_start < comment_end);
880
881 from_byte = CHAR_TO_BYTE (from);
882 UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
883 }
884
885 done:
886 *charpos_ptr = from;
887 *bytepos_ptr = from_byte;
888
889 return from != comment_end;
890 }
891 \f
892 DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
893 doc: /* Return t if OBJECT is a syntax table.
894 Currently, any char-table counts as a syntax table. */)
895 (Lisp_Object object)
896 {
897 if (CHAR_TABLE_P (object)
898 && EQ (XCHAR_TABLE (object)->purpose, Qsyntax_table))
899 return Qt;
900 return Qnil;
901 }
902
903 static void
904 check_syntax_table (Lisp_Object obj)
905 {
906 CHECK_TYPE (CHAR_TABLE_P (obj) && EQ (XCHAR_TABLE (obj)->purpose, Qsyntax_table),
907 Qsyntax_table_p, obj);
908 }
909
910 DEFUN ("syntax-table", Fsyntax_table, Ssyntax_table, 0, 0, 0,
911 doc: /* Return the current syntax table.
912 This is the one specified by the current buffer. */)
913 (void)
914 {
915 return BVAR (current_buffer, syntax_table);
916 }
917
918 DEFUN ("standard-syntax-table", Fstandard_syntax_table,
919 Sstandard_syntax_table, 0, 0, 0,
920 doc: /* Return the standard syntax table.
921 This is the one used for new buffers. */)
922 (void)
923 {
924 return Vstandard_syntax_table;
925 }
926
927 DEFUN ("copy-syntax-table", Fcopy_syntax_table, Scopy_syntax_table, 0, 1, 0,
928 doc: /* Construct a new syntax table and return it.
929 It is a copy of the TABLE, which defaults to the standard syntax table. */)
930 (Lisp_Object table)
931 {
932 Lisp_Object copy;
933
934 if (!NILP (table))
935 check_syntax_table (table);
936 else
937 table = Vstandard_syntax_table;
938
939 copy = Fcopy_sequence (table);
940
941 /* Only the standard syntax table should have a default element.
942 Other syntax tables should inherit from parents instead. */
943 set_char_table_defalt (copy, Qnil);
944
945 /* Copied syntax tables should all have parents.
946 If we copied one with no parent, such as the standard syntax table,
947 use the standard syntax table as the copy's parent. */
948 if (NILP (XCHAR_TABLE (copy)->parent))
949 Fset_char_table_parent (copy, Vstandard_syntax_table);
950 return copy;
951 }
952
953 DEFUN ("set-syntax-table", Fset_syntax_table, Sset_syntax_table, 1, 1, 0,
954 doc: /* Select a new syntax table for the current buffer.
955 One argument, a syntax table. */)
956 (Lisp_Object table)
957 {
958 int idx;
959 check_syntax_table (table);
960 bset_syntax_table (current_buffer, table);
961 /* Indicate that this buffer now has a specified syntax table. */
962 idx = PER_BUFFER_VAR_IDX (syntax_table);
963 SET_PER_BUFFER_VALUE_P (current_buffer, idx, 1);
964 return table;
965 }
966 \f
967 /* Convert a letter which signifies a syntax code
968 into the code it signifies.
969 This is used by modify-syntax-entry, and other things. */
970
971 unsigned char const syntax_spec_code[0400] =
972 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
973 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
974 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
975 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
976 Swhitespace, Scomment_fence, Sstring, 0377, Smath, 0377, 0377, Squote,
977 Sopen, Sclose, 0377, 0377, 0377, Swhitespace, Spunct, Scharquote,
978 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
979 0377, 0377, 0377, 0377, Scomment, 0377, Sendcomment, 0377,
980 Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A ... */
981 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
982 0377, 0377, 0377, 0377, 0377, 0377, 0377, Sword,
983 0377, 0377, 0377, 0377, Sescape, 0377, 0377, Ssymbol,
984 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
985 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
986 0377, 0377, 0377, 0377, 0377, 0377, 0377, Sword,
987 0377, 0377, 0377, 0377, Sstring_fence, 0377, 0377, 0377
988 };
989
990 /* Indexed by syntax code, give the letter that describes it. */
991
992 char const syntax_code_spec[16] =
993 {
994 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@',
995 '!', '|'
996 };
997
998 /* Indexed by syntax code, give the object (cons of syntax code and
999 nil) to be stored in syntax table. Since these objects can be
1000 shared among syntax tables, we generate them in advance. By
1001 sharing objects, the function `describe-syntax' can give a more
1002 compact listing. */
1003 static Lisp_Object Vsyntax_code_object;
1004
1005 \f
1006 DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0,
1007 doc: /* Return the syntax code of CHARACTER, described by a character.
1008 For example, if CHARACTER is a word constituent, the
1009 character `w' (119) is returned.
1010 The characters that correspond to various syntax codes
1011 are listed in the documentation of `modify-syntax-entry'. */)
1012 (Lisp_Object character)
1013 {
1014 int char_int;
1015 CHECK_CHARACTER (character);
1016 char_int = XINT (character);
1017 SETUP_BUFFER_SYNTAX_TABLE ();
1018 return make_number (syntax_code_spec[SYNTAX (char_int)]);
1019 }
1020
1021 DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0,
1022 doc: /* Return the matching parenthesis of CHARACTER, or nil if none. */)
1023 (Lisp_Object character)
1024 {
1025 int char_int;
1026 enum syntaxcode code;
1027 CHECK_CHARACTER (character);
1028 char_int = XINT (character);
1029 SETUP_BUFFER_SYNTAX_TABLE ();
1030 code = SYNTAX (char_int);
1031 if (code == Sopen || code == Sclose)
1032 return SYNTAX_MATCH (char_int);
1033 return Qnil;
1034 }
1035
1036 DEFUN ("string-to-syntax", Fstring_to_syntax, Sstring_to_syntax, 1, 1, 0,
1037 doc: /* Convert a syntax descriptor STRING into a raw syntax descriptor.
1038 STRING should be a string of the form allowed as argument of
1039 `modify-syntax-entry'. The return value is a raw syntax descriptor: a
1040 cons cell \(CODE . MATCHING-CHAR) which can be used, for example, as
1041 the value of a `syntax-table' text property. */)
1042 (Lisp_Object string)
1043 {
1044 const unsigned char *p;
1045 int val;
1046 Lisp_Object match;
1047
1048 CHECK_STRING (string);
1049
1050 p = SDATA (string);
1051 val = syntax_spec_code[*p++];
1052 if (val == 0377)
1053 error ("Invalid syntax description letter: %c", p[-1]);
1054
1055 if (val == Sinherit)
1056 return Qnil;
1057
1058 if (*p)
1059 {
1060 int len;
1061 int character = STRING_CHAR_AND_LENGTH (p, len);
1062 XSETINT (match, character);
1063 if (XFASTINT (match) == ' ')
1064 match = Qnil;
1065 p += len;
1066 }
1067 else
1068 match = Qnil;
1069
1070 while (*p)
1071 switch (*p++)
1072 {
1073 case '1':
1074 val |= 1 << 16;
1075 break;
1076
1077 case '2':
1078 val |= 1 << 17;
1079 break;
1080
1081 case '3':
1082 val |= 1 << 18;
1083 break;
1084
1085 case '4':
1086 val |= 1 << 19;
1087 break;
1088
1089 case 'p':
1090 val |= 1 << 20;
1091 break;
1092
1093 case 'b':
1094 val |= 1 << 21;
1095 break;
1096
1097 case 'n':
1098 val |= 1 << 22;
1099 break;
1100
1101 case 'c':
1102 val |= 1 << 23;
1103 break;
1104 }
1105
1106 if (val < ASIZE (Vsyntax_code_object) && NILP (match))
1107 return AREF (Vsyntax_code_object, val);
1108 else
1109 /* Since we can't use a shared object, let's make a new one. */
1110 return Fcons (make_number (val), match);
1111 }
1112
1113 /* I really don't know why this is interactive
1114 help-form should at least be made useful whilst reading the second arg. */
1115 DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3,
1116 "cSet syntax for character: \nsSet syntax for %s to: ",
1117 doc: /* Set syntax for character CHAR according to string NEWENTRY.
1118 The syntax is changed only for table SYNTAX-TABLE, which defaults to
1119 the current buffer's syntax table.
1120 CHAR may be a cons (MIN . MAX), in which case, syntaxes of all characters
1121 in the range MIN to MAX are changed.
1122 The first character of NEWENTRY should be one of the following:
1123 Space or - whitespace syntax. w word constituent.
1124 _ symbol constituent. . punctuation.
1125 ( open-parenthesis. ) close-parenthesis.
1126 " string quote. \\ escape.
1127 $ paired delimiter. ' expression quote or prefix operator.
1128 < comment starter. > comment ender.
1129 / character-quote. @ inherit from parent table.
1130 | generic string fence. ! generic comment fence.
1131
1132 Only single-character comment start and end sequences are represented thus.
1133 Two-character sequences are represented as described below.
1134 The second character of NEWENTRY is the matching parenthesis,
1135 used only if the first character is `(' or `)'.
1136 Any additional characters are flags.
1137 Defined flags are the characters 1, 2, 3, 4, b, p, and n.
1138 1 means CHAR is the start of a two-char comment start sequence.
1139 2 means CHAR is the second character of such a sequence.
1140 3 means CHAR is the start of a two-char comment end sequence.
1141 4 means CHAR is the second character of such a sequence.
1142
1143 There can be several orthogonal comment sequences. This is to support
1144 language modes such as C++. By default, all comment sequences are of style
1145 a, but you can set the comment sequence style to b (on the second character
1146 of a comment-start, and the first character of a comment-end sequence) and/or
1147 c (on any of its chars) using this flag:
1148 b means CHAR is part of comment sequence b.
1149 c means CHAR is part of comment sequence c.
1150 n means CHAR is part of a nestable comment sequence.
1151
1152 p means CHAR is a prefix character for `backward-prefix-chars';
1153 such characters are treated as whitespace when they occur
1154 between expressions.
1155 usage: (modify-syntax-entry CHAR NEWENTRY &optional SYNTAX-TABLE) */)
1156 (Lisp_Object c, Lisp_Object newentry, Lisp_Object syntax_table)
1157 {
1158 if (CONSP (c))
1159 {
1160 CHECK_CHARACTER_CAR (c);
1161 CHECK_CHARACTER_CDR (c);
1162 }
1163 else
1164 CHECK_CHARACTER (c);
1165
1166 if (NILP (syntax_table))
1167 syntax_table = BVAR (current_buffer, syntax_table);
1168 else
1169 check_syntax_table (syntax_table);
1170
1171 newentry = Fstring_to_syntax (newentry);
1172 if (CONSP (c))
1173 SET_RAW_SYNTAX_ENTRY_RANGE (syntax_table, c, newentry);
1174 else
1175 SET_RAW_SYNTAX_ENTRY (syntax_table, XINT (c), newentry);
1176
1177 /* We clear the regexp cache, since character classes can now have
1178 different values from those in the compiled regexps.*/
1179 clear_regexp_cache ();
1180
1181 return Qnil;
1182 }
1183 \f
1184 /* Dump syntax table to buffer in human-readable format */
1185
1186 DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
1187 Sinternal_describe_syntax_value, 1, 1, 0,
1188 doc: /* Insert a description of the internal syntax description SYNTAX at point. */)
1189 (Lisp_Object syntax)
1190 {
1191 int code, syntax_code;
1192 bool start1, start2, end1, end2, prefix, comstyleb, comstylec, comnested;
1193 char str[2];
1194 Lisp_Object first, match_lisp, value = syntax;
1195
1196 if (NILP (value))
1197 {
1198 insert_string ("default");
1199 return syntax;
1200 }
1201
1202 if (CHAR_TABLE_P (value))
1203 {
1204 insert_string ("deeper char-table ...");
1205 return syntax;
1206 }
1207
1208 if (!CONSP (value))
1209 {
1210 insert_string ("invalid");
1211 return syntax;
1212 }
1213
1214 first = XCAR (value);
1215 match_lisp = XCDR (value);
1216
1217 if (!INTEGERP (first) || !(NILP (match_lisp) || CHARACTERP (match_lisp)))
1218 {
1219 insert_string ("invalid");
1220 return syntax;
1221 }
1222
1223 syntax_code = XINT (first) & INT_MAX;
1224 code = syntax_code & 0377;
1225 start1 = SYNTAX_FLAGS_COMSTART_FIRST (syntax_code);
1226 start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code);;
1227 end1 = SYNTAX_FLAGS_COMEND_FIRST (syntax_code);
1228 end2 = SYNTAX_FLAGS_COMEND_SECOND (syntax_code);
1229 prefix = SYNTAX_FLAGS_PREFIX (syntax_code);
1230 comstyleb = SYNTAX_FLAGS_COMMENT_STYLEB (syntax_code);
1231 comstylec = SYNTAX_FLAGS_COMMENT_STYLEC (syntax_code);
1232 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax_code);
1233
1234 if (Smax <= code)
1235 {
1236 insert_string ("invalid");
1237 return syntax;
1238 }
1239
1240 str[0] = syntax_code_spec[code], str[1] = 0;
1241 insert (str, 1);
1242
1243 if (NILP (match_lisp))
1244 insert (" ", 1);
1245 else
1246 insert_char (XINT (match_lisp));
1247
1248 if (start1)
1249 insert ("1", 1);
1250 if (start2)
1251 insert ("2", 1);
1252
1253 if (end1)
1254 insert ("3", 1);
1255 if (end2)
1256 insert ("4", 1);
1257
1258 if (prefix)
1259 insert ("p", 1);
1260 if (comstyleb)
1261 insert ("b", 1);
1262 if (comstylec)
1263 insert ("c", 1);
1264 if (comnested)
1265 insert ("n", 1);
1266
1267 insert_string ("\twhich means: ");
1268
1269 switch (code)
1270 {
1271 case Swhitespace:
1272 insert_string ("whitespace"); break;
1273 case Spunct:
1274 insert_string ("punctuation"); break;
1275 case Sword:
1276 insert_string ("word"); break;
1277 case Ssymbol:
1278 insert_string ("symbol"); break;
1279 case Sopen:
1280 insert_string ("open"); break;
1281 case Sclose:
1282 insert_string ("close"); break;
1283 case Squote:
1284 insert_string ("prefix"); break;
1285 case Sstring:
1286 insert_string ("string"); break;
1287 case Smath:
1288 insert_string ("math"); break;
1289 case Sescape:
1290 insert_string ("escape"); break;
1291 case Scharquote:
1292 insert_string ("charquote"); break;
1293 case Scomment:
1294 insert_string ("comment"); break;
1295 case Sendcomment:
1296 insert_string ("endcomment"); break;
1297 case Sinherit:
1298 insert_string ("inherit"); break;
1299 case Scomment_fence:
1300 insert_string ("comment fence"); break;
1301 case Sstring_fence:
1302 insert_string ("string fence"); break;
1303 default:
1304 insert_string ("invalid");
1305 return syntax;
1306 }
1307
1308 if (!NILP (match_lisp))
1309 {
1310 insert_string (", matches ");
1311 insert_char (XINT (match_lisp));
1312 }
1313
1314 if (start1)
1315 insert_string (",\n\t is the first character of a comment-start sequence");
1316 if (start2)
1317 insert_string (",\n\t is the second character of a comment-start sequence");
1318
1319 if (end1)
1320 insert_string (",\n\t is the first character of a comment-end sequence");
1321 if (end2)
1322 insert_string (",\n\t is the second character of a comment-end sequence");
1323 if (comstyleb)
1324 insert_string (" (comment style b)");
1325 if (comstylec)
1326 insert_string (" (comment style c)");
1327 if (comnested)
1328 insert_string (" (nestable)");
1329
1330 if (prefix)
1331 insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
1332
1333 return syntax;
1334 }
1335 \f
1336 /* Return the position across COUNT words from FROM.
1337 If that many words cannot be found before the end of the buffer, return 0.
1338 COUNT negative means scan backward and stop at word beginning. */
1339
1340 ptrdiff_t
1341 scan_words (register ptrdiff_t from, register EMACS_INT count)
1342 {
1343 register ptrdiff_t beg = BEGV;
1344 register ptrdiff_t end = ZV;
1345 register ptrdiff_t from_byte = CHAR_TO_BYTE (from);
1346 register enum syntaxcode code;
1347 int ch0, ch1;
1348 Lisp_Object func, pos;
1349
1350 immediate_quit = 1;
1351 QUIT;
1352
1353 SETUP_SYNTAX_TABLE (from, count);
1354
1355 while (count > 0)
1356 {
1357 while (1)
1358 {
1359 if (from == end)
1360 {
1361 immediate_quit = 0;
1362 return 0;
1363 }
1364 UPDATE_SYNTAX_TABLE_FORWARD (from);
1365 ch0 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
1366 code = SYNTAX (ch0);
1367 INC_BOTH (from, from_byte);
1368 if (words_include_escapes
1369 && (code == Sescape || code == Scharquote))
1370 break;
1371 if (code == Sword)
1372 break;
1373 }
1374 /* Now CH0 is a character which begins a word and FROM is the
1375 position of the next character. */
1376 func = CHAR_TABLE_REF (Vfind_word_boundary_function_table, ch0);
1377 if (! NILP (Ffboundp (func)))
1378 {
1379 pos = call2 (func, make_number (from - 1), make_number (end));
1380 if (INTEGERP (pos) && from < XINT (pos) && XINT (pos) <= ZV)
1381 {
1382 from = XINT (pos);
1383 from_byte = CHAR_TO_BYTE (from);
1384 }
1385 }
1386 else
1387 {
1388 while (1)
1389 {
1390 if (from == end) break;
1391 UPDATE_SYNTAX_TABLE_FORWARD (from);
1392 ch1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
1393 code = SYNTAX (ch1);
1394 if ((code != Sword
1395 && (! words_include_escapes
1396 || (code != Sescape && code != Scharquote)))
1397 || word_boundary_p (ch0, ch1))
1398 break;
1399 INC_BOTH (from, from_byte);
1400 ch0 = ch1;
1401 }
1402 }
1403 count--;
1404 }
1405 while (count < 0)
1406 {
1407 while (1)
1408 {
1409 if (from == beg)
1410 {
1411 immediate_quit = 0;
1412 return 0;
1413 }
1414 DEC_BOTH (from, from_byte);
1415 UPDATE_SYNTAX_TABLE_BACKWARD (from);
1416 ch1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
1417 code = SYNTAX (ch1);
1418 if (words_include_escapes
1419 && (code == Sescape || code == Scharquote))
1420 break;
1421 if (code == Sword)
1422 break;
1423 }
1424 /* Now CH1 is a character which ends a word and FROM is the
1425 position of it. */
1426 func = CHAR_TABLE_REF (Vfind_word_boundary_function_table, ch1);
1427 if (! NILP (Ffboundp (func)))
1428 {
1429 pos = call2 (func, make_number (from), make_number (beg));
1430 if (INTEGERP (pos) && BEGV <= XINT (pos) && XINT (pos) < from)
1431 {
1432 from = XINT (pos);
1433 from_byte = CHAR_TO_BYTE (from);
1434 }
1435 }
1436 else
1437 {
1438 while (1)
1439 {
1440 if (from == beg)
1441 break;
1442 DEC_BOTH (from, from_byte);
1443 UPDATE_SYNTAX_TABLE_BACKWARD (from);
1444 ch0 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
1445 code = SYNTAX (ch0);
1446 if ((code != Sword
1447 && (! words_include_escapes
1448 || (code != Sescape && code != Scharquote)))
1449 || word_boundary_p (ch0, ch1))
1450 {
1451 INC_BOTH (from, from_byte);
1452 break;
1453 }
1454 ch1 = ch0;
1455 }
1456 }
1457 count++;
1458 }
1459
1460 immediate_quit = 0;
1461
1462 return from;
1463 }
1464
1465 DEFUN ("forward-word", Fforward_word, Sforward_word, 0, 1, "^p",
1466 doc: /* Move point forward ARG words (backward if ARG is negative).
1467 Normally returns t.
1468 If an edge of the buffer or a field boundary is reached, point is left there
1469 and the function returns nil. Field boundaries are not noticed if
1470 `inhibit-field-text-motion' is non-nil. */)
1471 (Lisp_Object arg)
1472 {
1473 Lisp_Object tmp;
1474 ptrdiff_t orig_val, val;
1475
1476 if (NILP (arg))
1477 XSETFASTINT (arg, 1);
1478 else
1479 CHECK_NUMBER (arg);
1480
1481 val = orig_val = scan_words (PT, XINT (arg));
1482 if (! orig_val)
1483 val = XINT (arg) > 0 ? ZV : BEGV;
1484
1485 /* Avoid jumping out of an input field. */
1486 tmp = Fconstrain_to_field (make_number (val), make_number (PT),
1487 Qt, Qnil, Qnil);
1488 val = XFASTINT (tmp);
1489
1490 SET_PT (val);
1491 return val == orig_val ? Qt : Qnil;
1492 }
1493 \f
1494 DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,
1495 doc: /* Move point forward, stopping before a char not in STRING, or at pos LIM.
1496 STRING is like the inside of a `[...]' in a regular expression
1497 except that `]' is never special and `\\' quotes `^', `-' or `\\'
1498 (but not at the end of a range; quoting is never needed there).
1499 Thus, with arg "a-zA-Z", this skips letters stopping before first nonletter.
1500 With arg "^a-zA-Z", skips nonletters stopping before first letter.
1501 Char classes, e.g. `[:alpha:]', are supported.
1502
1503 Returns the distance traveled, either zero or positive. */)
1504 (Lisp_Object string, Lisp_Object lim)
1505 {
1506 return skip_chars (1, string, lim, 1);
1507 }
1508
1509 DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
1510 doc: /* Move point backward, stopping after a char not in STRING, or at pos LIM.
1511 See `skip-chars-forward' for details.
1512 Returns the distance traveled, either zero or negative. */)
1513 (Lisp_Object string, Lisp_Object lim)
1514 {
1515 return skip_chars (0, string, lim, 1);
1516 }
1517
1518 DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
1519 doc: /* Move point forward across chars in specified syntax classes.
1520 SYNTAX is a string of syntax code characters.
1521 Stop before a char whose syntax is not in SYNTAX, or at position LIM.
1522 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.
1523 This function returns the distance traveled, either zero or positive. */)
1524 (Lisp_Object syntax, Lisp_Object lim)
1525 {
1526 return skip_syntaxes (1, syntax, lim);
1527 }
1528
1529 DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
1530 doc: /* Move point backward across chars in specified syntax classes.
1531 SYNTAX is a string of syntax code characters.
1532 Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.
1533 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.
1534 This function returns the distance traveled, either zero or negative. */)
1535 (Lisp_Object syntax, Lisp_Object lim)
1536 {
1537 return skip_syntaxes (0, syntax, lim);
1538 }
1539
1540 static Lisp_Object
1541 skip_chars (bool forwardp, Lisp_Object string, Lisp_Object lim,
1542 bool handle_iso_classes)
1543 {
1544 int c;
1545 char fastmap[0400];
1546 /* Store the ranges of non-ASCII characters. */
1547 int *char_ranges IF_LINT (= NULL);
1548 int n_char_ranges = 0;
1549 bool negate = 0;
1550 ptrdiff_t i, i_byte;
1551 /* True if the current buffer is multibyte and the region contains
1552 non-ASCII chars. */
1553 bool multibyte;
1554 /* True if STRING is multibyte and it contains non-ASCII chars. */
1555 bool string_multibyte;
1556 ptrdiff_t size_byte;
1557 const unsigned char *str;
1558 int len;
1559 Lisp_Object iso_classes;
1560
1561 CHECK_STRING (string);
1562 iso_classes = Qnil;
1563
1564 if (NILP (lim))
1565 XSETINT (lim, forwardp ? ZV : BEGV);
1566 else
1567 CHECK_NUMBER_COERCE_MARKER (lim);
1568
1569 /* In any case, don't allow scan outside bounds of buffer. */
1570 if (XINT (lim) > ZV)
1571 XSETFASTINT (lim, ZV);
1572 if (XINT (lim) < BEGV)
1573 XSETFASTINT (lim, BEGV);
1574
1575 multibyte = (!NILP (BVAR (current_buffer, enable_multibyte_characters))
1576 && (XINT (lim) - PT != CHAR_TO_BYTE (XINT (lim)) - PT_BYTE));
1577 string_multibyte = SBYTES (string) > SCHARS (string);
1578
1579 memset (fastmap, 0, sizeof fastmap);
1580
1581 str = SDATA (string);
1582 size_byte = SBYTES (string);
1583
1584 i_byte = 0;
1585 if (i_byte < size_byte
1586 && SREF (string, 0) == '^')
1587 {
1588 negate = 1; i_byte++;
1589 }
1590
1591 /* Find the characters specified and set their elements of fastmap.
1592 Handle backslashes and ranges specially.
1593
1594 If STRING contains non-ASCII characters, setup char_ranges for
1595 them and use fastmap only for their leading codes. */
1596
1597 if (! string_multibyte)
1598 {
1599 bool string_has_eight_bit = 0;
1600
1601 /* At first setup fastmap. */
1602 while (i_byte < size_byte)
1603 {
1604 c = str[i_byte++];
1605
1606 if (handle_iso_classes && c == '['
1607 && i_byte < size_byte
1608 && str[i_byte] == ':')
1609 {
1610 const unsigned char *class_beg = str + i_byte + 1;
1611 const unsigned char *class_end = class_beg;
1612 const unsigned char *class_limit = str + size_byte - 2;
1613 /* Leave room for the null. */
1614 unsigned char class_name[CHAR_CLASS_MAX_LENGTH + 1];
1615 re_wctype_t cc;
1616
1617 if (class_limit - class_beg > CHAR_CLASS_MAX_LENGTH)
1618 class_limit = class_beg + CHAR_CLASS_MAX_LENGTH;
1619
1620 while (class_end < class_limit
1621 && *class_end >= 'a' && *class_end <= 'z')
1622 class_end++;
1623
1624 if (class_end == class_beg
1625 || *class_end != ':' || class_end[1] != ']')
1626 goto not_a_class_name;
1627
1628 memcpy (class_name, class_beg, class_end - class_beg);
1629 class_name[class_end - class_beg] = 0;
1630
1631 cc = re_wctype (class_name);
1632 if (cc == 0)
1633 error ("Invalid ISO C character class");
1634
1635 iso_classes = Fcons (make_number (cc), iso_classes);
1636
1637 i_byte = class_end + 2 - str;
1638 continue;
1639 }
1640
1641 not_a_class_name:
1642 if (c == '\\')
1643 {
1644 if (i_byte == size_byte)
1645 break;
1646
1647 c = str[i_byte++];
1648 }
1649 /* Treat `-' as range character only if another character
1650 follows. */
1651 if (i_byte + 1 < size_byte
1652 && str[i_byte] == '-')
1653 {
1654 int c2;
1655
1656 /* Skip over the dash. */
1657 i_byte++;
1658
1659 /* Get the end of the range. */
1660 c2 = str[i_byte++];
1661 if (c2 == '\\'
1662 && i_byte < size_byte)
1663 c2 = str[i_byte++];
1664
1665 if (c <= c2)
1666 {
1667 int lim2 = c2 + 1;
1668 while (c < lim2)
1669 fastmap[c++] = 1;
1670 if (! ASCII_CHAR_P (c2))
1671 string_has_eight_bit = 1;
1672 }
1673 }
1674 else
1675 {
1676 fastmap[c] = 1;
1677 if (! ASCII_CHAR_P (c))
1678 string_has_eight_bit = 1;
1679 }
1680 }
1681
1682 /* If the current range is multibyte and STRING contains
1683 eight-bit chars, arrange fastmap and setup char_ranges for
1684 the corresponding multibyte chars. */
1685 if (multibyte && string_has_eight_bit)
1686 {
1687 char *p1;
1688 char himap[0200 + 1];
1689 memcpy (himap, fastmap + 0200, 0200);
1690 himap[0200] = 0;
1691 memset (fastmap + 0200, 0, 0200);
1692 char_ranges = alloca (sizeof *char_ranges * 128 * 2);
1693 i = 0;
1694
1695 while ((p1 = memchr (himap + i, 1, 0200 - i)))
1696 {
1697 /* Deduce the next range C..C2 from the next clump of 1s
1698 in HIMAP starting with &HIMAP[I]. HIMAP is the high
1699 order half of the old FASTMAP. */
1700 int c2, leading_code;
1701 i = p1 - himap;
1702 c = BYTE8_TO_CHAR (i + 0200);
1703 i += strlen (p1);
1704 c2 = BYTE8_TO_CHAR (i + 0200 - 1);
1705
1706 char_ranges[n_char_ranges++] = c;
1707 char_ranges[n_char_ranges++] = c2;
1708 leading_code = CHAR_LEADING_CODE (c);
1709 memset (fastmap + leading_code, 1,
1710 CHAR_LEADING_CODE (c2) - leading_code + 1);
1711 }
1712 }
1713 }
1714 else /* STRING is multibyte */
1715 {
1716 char_ranges = alloca (sizeof *char_ranges * SCHARS (string) * 2);
1717
1718 while (i_byte < size_byte)
1719 {
1720 int leading_code = str[i_byte];
1721 c = STRING_CHAR_AND_LENGTH (str + i_byte, len);
1722 i_byte += len;
1723
1724 if (handle_iso_classes && c == '['
1725 && i_byte < size_byte
1726 && STRING_CHAR (str + i_byte) == ':')
1727 {
1728 const unsigned char *class_beg = str + i_byte + 1;
1729 const unsigned char *class_end = class_beg;
1730 const unsigned char *class_limit = str + size_byte - 2;
1731 /* Leave room for the null. */
1732 unsigned char class_name[CHAR_CLASS_MAX_LENGTH + 1];
1733 re_wctype_t cc;
1734
1735 if (class_limit - class_beg > CHAR_CLASS_MAX_LENGTH)
1736 class_limit = class_beg + CHAR_CLASS_MAX_LENGTH;
1737
1738 while (class_end < class_limit
1739 && *class_end >= 'a' && *class_end <= 'z')
1740 class_end++;
1741
1742 if (class_end == class_beg
1743 || *class_end != ':' || class_end[1] != ']')
1744 goto not_a_class_name_multibyte;
1745
1746 memcpy (class_name, class_beg, class_end - class_beg);
1747 class_name[class_end - class_beg] = 0;
1748
1749 cc = re_wctype (class_name);
1750 if (cc == 0)
1751 error ("Invalid ISO C character class");
1752
1753 iso_classes = Fcons (make_number (cc), iso_classes);
1754
1755 i_byte = class_end + 2 - str;
1756 continue;
1757 }
1758
1759 not_a_class_name_multibyte:
1760 if (c == '\\')
1761 {
1762 if (i_byte == size_byte)
1763 break;
1764
1765 leading_code = str[i_byte];
1766 c = STRING_CHAR_AND_LENGTH (str + i_byte, len);
1767 i_byte += len;
1768 }
1769 /* Treat `-' as range character only if another character
1770 follows. */
1771 if (i_byte + 1 < size_byte
1772 && str[i_byte] == '-')
1773 {
1774 int c2, leading_code2;
1775
1776 /* Skip over the dash. */
1777 i_byte++;
1778
1779 /* Get the end of the range. */
1780 leading_code2 = str[i_byte];
1781 c2 = STRING_CHAR_AND_LENGTH (str + i_byte, len);
1782 i_byte += len;
1783
1784 if (c2 == '\\'
1785 && i_byte < size_byte)
1786 {
1787 leading_code2 = str[i_byte];
1788 c2 = STRING_CHAR_AND_LENGTH (str + i_byte, len);
1789 i_byte += len;
1790 }
1791
1792 if (c > c2)
1793 continue;
1794 if (ASCII_CHAR_P (c))
1795 {
1796 while (c <= c2 && c < 0x80)
1797 fastmap[c++] = 1;
1798 leading_code = CHAR_LEADING_CODE (c);
1799 }
1800 if (! ASCII_CHAR_P (c))
1801 {
1802 int lim2 = leading_code2 + 1;
1803 while (leading_code < lim2)
1804 fastmap[leading_code++] = 1;
1805 if (c <= c2)
1806 {
1807 char_ranges[n_char_ranges++] = c;
1808 char_ranges[n_char_ranges++] = c2;
1809 }
1810 }
1811 }
1812 else
1813 {
1814 if (ASCII_CHAR_P (c))
1815 fastmap[c] = 1;
1816 else
1817 {
1818 fastmap[leading_code] = 1;
1819 char_ranges[n_char_ranges++] = c;
1820 char_ranges[n_char_ranges++] = c;
1821 }
1822 }
1823 }
1824
1825 /* If the current range is unibyte and STRING contains non-ASCII
1826 chars, arrange fastmap for the corresponding unibyte
1827 chars. */
1828
1829 if (! multibyte && n_char_ranges > 0)
1830 {
1831 memset (fastmap + 0200, 0, 0200);
1832 for (i = 0; i < n_char_ranges; i += 2)
1833 {
1834 int c1 = char_ranges[i];
1835 int lim2 = char_ranges[i + 1] + 1;
1836
1837 for (; c1 < lim2; c1++)
1838 {
1839 int b = CHAR_TO_BYTE_SAFE (c1);
1840 if (b >= 0)
1841 fastmap[b] = 1;
1842 }
1843 }
1844 }
1845 }
1846
1847 /* If ^ was the first character, complement the fastmap. */
1848 if (negate)
1849 {
1850 if (! multibyte)
1851 for (i = 0; i < sizeof fastmap; i++)
1852 fastmap[i] ^= 1;
1853 else
1854 {
1855 for (i = 0; i < 0200; i++)
1856 fastmap[i] ^= 1;
1857 /* All non-ASCII chars possibly match. */
1858 for (; i < sizeof fastmap; i++)
1859 fastmap[i] = 1;
1860 }
1861 }
1862
1863 {
1864 ptrdiff_t start_point = PT;
1865 ptrdiff_t pos = PT;
1866 ptrdiff_t pos_byte = PT_BYTE;
1867 unsigned char *p = PT_ADDR, *endp, *stop;
1868
1869 if (forwardp)
1870 {
1871 endp = (XINT (lim) == GPT) ? GPT_ADDR : CHAR_POS_ADDR (XINT (lim));
1872 stop = (pos < GPT && GPT < XINT (lim)) ? GPT_ADDR : endp;
1873 }
1874 else
1875 {
1876 endp = CHAR_POS_ADDR (XINT (lim));
1877 stop = (pos >= GPT && GPT > XINT (lim)) ? GAP_END_ADDR : endp;
1878 }
1879
1880 immediate_quit = 1;
1881 /* This code may look up syntax tables using functions that rely on the
1882 gl_state object. To make sure this object is not out of date,
1883 let's initialize it manually.
1884 We ignore syntax-table text-properties for now, since that's
1885 what we've done in the past. */
1886 SETUP_BUFFER_SYNTAX_TABLE ();
1887 if (forwardp)
1888 {
1889 if (multibyte)
1890 while (1)
1891 {
1892 int nbytes;
1893
1894 if (p >= stop)
1895 {
1896 if (p >= endp)
1897 break;
1898 p = GAP_END_ADDR;
1899 stop = endp;
1900 }
1901 c = STRING_CHAR_AND_LENGTH (p, nbytes);
1902 if (! NILP (iso_classes) && in_classes (c, iso_classes))
1903 {
1904 if (negate)
1905 break;
1906 else
1907 goto fwd_ok;
1908 }
1909
1910 if (! fastmap[*p])
1911 break;
1912 if (! ASCII_CHAR_P (c))
1913 {
1914 /* As we are looking at a multibyte character, we
1915 must look up the character in the table
1916 CHAR_RANGES. If there's no data in the table,
1917 that character is not what we want to skip. */
1918
1919 /* The following code do the right thing even if
1920 n_char_ranges is zero (i.e. no data in
1921 CHAR_RANGES). */
1922 for (i = 0; i < n_char_ranges; i += 2)
1923 if (c >= char_ranges[i] && c <= char_ranges[i + 1])
1924 break;
1925 if (!(negate ^ (i < n_char_ranges)))
1926 break;
1927 }
1928 fwd_ok:
1929 p += nbytes, pos++, pos_byte += nbytes;
1930 }
1931 else
1932 while (1)
1933 {
1934 if (p >= stop)
1935 {
1936 if (p >= endp)
1937 break;
1938 p = GAP_END_ADDR;
1939 stop = endp;
1940 }
1941
1942 if (!NILP (iso_classes) && in_classes (*p, iso_classes))
1943 {
1944 if (negate)
1945 break;
1946 else
1947 goto fwd_unibyte_ok;
1948 }
1949
1950 if (!fastmap[*p])
1951 break;
1952 fwd_unibyte_ok:
1953 p++, pos++, pos_byte++;
1954 }
1955 }
1956 else
1957 {
1958 if (multibyte)
1959 while (1)
1960 {
1961 unsigned char *prev_p;
1962
1963 if (p <= stop)
1964 {
1965 if (p <= endp)
1966 break;
1967 p = GPT_ADDR;
1968 stop = endp;
1969 }
1970 prev_p = p;
1971 while (--p >= stop && ! CHAR_HEAD_P (*p));
1972 c = STRING_CHAR (p);
1973
1974 if (! NILP (iso_classes) && in_classes (c, iso_classes))
1975 {
1976 if (negate)
1977 break;
1978 else
1979 goto back_ok;
1980 }
1981
1982 if (! fastmap[*p])
1983 break;
1984 if (! ASCII_CHAR_P (c))
1985 {
1986 /* See the comment in the previous similar code. */
1987 for (i = 0; i < n_char_ranges; i += 2)
1988 if (c >= char_ranges[i] && c <= char_ranges[i + 1])
1989 break;
1990 if (!(negate ^ (i < n_char_ranges)))
1991 break;
1992 }
1993 back_ok:
1994 pos--, pos_byte -= prev_p - p;
1995 }
1996 else
1997 while (1)
1998 {
1999 if (p <= stop)
2000 {
2001 if (p <= endp)
2002 break;
2003 p = GPT_ADDR;
2004 stop = endp;
2005 }
2006
2007 if (! NILP (iso_classes) && in_classes (p[-1], iso_classes))
2008 {
2009 if (negate)
2010 break;
2011 else
2012 goto back_unibyte_ok;
2013 }
2014
2015 if (!fastmap[p[-1]])
2016 break;
2017 back_unibyte_ok:
2018 p--, pos--, pos_byte--;
2019 }
2020 }
2021
2022 SET_PT_BOTH (pos, pos_byte);
2023 immediate_quit = 0;
2024
2025 return make_number (PT - start_point);
2026 }
2027 }
2028
2029
2030 static Lisp_Object
2031 skip_syntaxes (bool forwardp, Lisp_Object string, Lisp_Object lim)
2032 {
2033 int c;
2034 unsigned char fastmap[0400];
2035 bool negate = 0;
2036 ptrdiff_t i, i_byte;
2037 bool multibyte;
2038 ptrdiff_t size_byte;
2039 unsigned char *str;
2040
2041 CHECK_STRING (string);
2042
2043 if (NILP (lim))
2044 XSETINT (lim, forwardp ? ZV : BEGV);
2045 else
2046 CHECK_NUMBER_COERCE_MARKER (lim);
2047
2048 /* In any case, don't allow scan outside bounds of buffer. */
2049 if (XINT (lim) > ZV)
2050 XSETFASTINT (lim, ZV);
2051 if (XINT (lim) < BEGV)
2052 XSETFASTINT (lim, BEGV);
2053
2054 if (forwardp ? (PT >= XFASTINT (lim)) : (PT <= XFASTINT (lim)))
2055 return make_number (0);
2056
2057 multibyte = (!NILP (BVAR (current_buffer, enable_multibyte_characters))
2058 && (XINT (lim) - PT != CHAR_TO_BYTE (XINT (lim)) - PT_BYTE));
2059
2060 memset (fastmap, 0, sizeof fastmap);
2061
2062 if (SBYTES (string) > SCHARS (string))
2063 /* As this is very rare case (syntax spec is ASCII only), don't
2064 consider efficiency. */
2065 string = string_make_unibyte (string);
2066
2067 str = SDATA (string);
2068 size_byte = SBYTES (string);
2069
2070 i_byte = 0;
2071 if (i_byte < size_byte
2072 && SREF (string, 0) == '^')
2073 {
2074 negate = 1; i_byte++;
2075 }
2076
2077 /* Find the syntaxes specified and set their elements of fastmap. */
2078
2079 while (i_byte < size_byte)
2080 {
2081 c = str[i_byte++];
2082 fastmap[syntax_spec_code[c]] = 1;
2083 }
2084
2085 /* If ^ was the first character, complement the fastmap. */
2086 if (negate)
2087 for (i = 0; i < sizeof fastmap; i++)
2088 fastmap[i] ^= 1;
2089
2090 {
2091 ptrdiff_t start_point = PT;
2092 ptrdiff_t pos = PT;
2093 ptrdiff_t pos_byte = PT_BYTE;
2094 unsigned char *p = PT_ADDR, *endp, *stop;
2095
2096 if (forwardp)
2097 {
2098 endp = (XINT (lim) == GPT) ? GPT_ADDR : CHAR_POS_ADDR (XINT (lim));
2099 stop = (pos < GPT && GPT < XINT (lim)) ? GPT_ADDR : endp;
2100 }
2101 else
2102 {
2103 endp = CHAR_POS_ADDR (XINT (lim));
2104 stop = (pos >= GPT && GPT > XINT (lim)) ? GAP_END_ADDR : endp;
2105 }
2106
2107 immediate_quit = 1;
2108 SETUP_SYNTAX_TABLE (pos, forwardp ? 1 : -1);
2109 if (forwardp)
2110 {
2111 if (multibyte)
2112 {
2113 while (1)
2114 {
2115 int nbytes;
2116
2117 if (p >= stop)
2118 {
2119 if (p >= endp)
2120 break;
2121 p = GAP_END_ADDR;
2122 stop = endp;
2123 }
2124 c = STRING_CHAR_AND_LENGTH (p, nbytes);
2125 if (! fastmap[SYNTAX (c)])
2126 break;
2127 p += nbytes, pos++, pos_byte += nbytes;
2128 UPDATE_SYNTAX_TABLE_FORWARD (pos);
2129 }
2130 }
2131 else
2132 {
2133 while (1)
2134 {
2135 if (p >= stop)
2136 {
2137 if (p >= endp)
2138 break;
2139 p = GAP_END_ADDR;
2140 stop = endp;
2141 }
2142 if (! fastmap[SYNTAX (*p)])
2143 break;
2144 p++, pos++, pos_byte++;
2145 UPDATE_SYNTAX_TABLE_FORWARD (pos);
2146 }
2147 }
2148 }
2149 else
2150 {
2151 if (multibyte)
2152 {
2153 while (1)
2154 {
2155 unsigned char *prev_p;
2156
2157 if (p <= stop)
2158 {
2159 if (p <= endp)
2160 break;
2161 p = GPT_ADDR;
2162 stop = endp;
2163 }
2164 UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
2165 prev_p = p;
2166 while (--p >= stop && ! CHAR_HEAD_P (*p));
2167 c = STRING_CHAR (p);
2168 if (! fastmap[SYNTAX (c)])
2169 break;
2170 pos--, pos_byte -= prev_p - p;
2171 }
2172 }
2173 else
2174 {
2175 while (1)
2176 {
2177 if (p <= stop)
2178 {
2179 if (p <= endp)
2180 break;
2181 p = GPT_ADDR;
2182 stop = endp;
2183 }
2184 UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
2185 if (! fastmap[SYNTAX (p[-1])])
2186 break;
2187 p--, pos--, pos_byte--;
2188 }
2189 }
2190 }
2191
2192 SET_PT_BOTH (pos, pos_byte);
2193 immediate_quit = 0;
2194
2195 return make_number (PT - start_point);
2196 }
2197 }
2198
2199 /* Return true if character C belongs to one of the ISO classes
2200 in the list ISO_CLASSES. Each class is represented by an
2201 integer which is its type according to re_wctype. */
2202
2203 static bool
2204 in_classes (int c, Lisp_Object iso_classes)
2205 {
2206 bool fits_class = 0;
2207
2208 while (CONSP (iso_classes))
2209 {
2210 Lisp_Object elt;
2211 elt = XCAR (iso_classes);
2212 iso_classes = XCDR (iso_classes);
2213
2214 if (re_iswctype (c, XFASTINT (elt)))
2215 fits_class = 1;
2216 }
2217
2218 return fits_class;
2219 }
2220 \f
2221 /* Jump over a comment, assuming we are at the beginning of one.
2222 FROM is the current position.
2223 FROM_BYTE is the bytepos corresponding to FROM.
2224 Do not move past STOP (a charpos).
2225 The comment over which we have to jump is of style STYLE
2226 (either SYNTAX_FLAGS_COMMENT_STYLE (foo) or ST_COMMENT_STYLE).
2227 NESTING should be positive to indicate the nesting at the beginning
2228 for nested comments and should be zero or negative else.
2229 ST_COMMENT_STYLE cannot be nested.
2230 PREV_SYNTAX is the SYNTAX_WITH_FLAGS of the previous character
2231 (or 0 If the search cannot start in the middle of a two-character).
2232
2233 If successful, return true and store the charpos of the comment's end
2234 into *CHARPOS_PTR and the corresponding bytepos into *BYTEPOS_PTR.
2235 Else, return false and store the charpos STOP into *CHARPOS_PTR, the
2236 corresponding bytepos into *BYTEPOS_PTR and the current nesting
2237 (as defined for state.incomment) in *INCOMMENT_PTR.
2238
2239 The comment end is the last character of the comment rather than the
2240 character just after the comment.
2241
2242 Global syntax data is assumed to initially be valid for FROM and
2243 remains valid for forward search starting at the returned position. */
2244
2245 static bool
2246 forw_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
2247 EMACS_INT nesting, int style, int prev_syntax,
2248 ptrdiff_t *charpos_ptr, ptrdiff_t *bytepos_ptr,
2249 EMACS_INT *incomment_ptr)
2250 {
2251 register int c, c1;
2252 register enum syntaxcode code;
2253 register int syntax, other_syntax;
2254
2255 if (nesting <= 0) nesting = -1;
2256
2257 /* Enter the loop in the middle so that we find
2258 a 2-char comment ender if we start in the middle of it. */
2259 syntax = prev_syntax;
2260 if (syntax != 0) goto forw_incomment;
2261
2262 while (1)
2263 {
2264 if (from == stop)
2265 {
2266 *incomment_ptr = nesting;
2267 *charpos_ptr = from;
2268 *bytepos_ptr = from_byte;
2269 return 0;
2270 }
2271 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2272 syntax = SYNTAX_WITH_FLAGS (c);
2273 code = syntax & 0xff;
2274 if (code == Sendcomment
2275 && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
2276 && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
2277 (nesting > 0 && --nesting == 0) : nesting < 0))
2278 /* we have encountered a comment end of the same style
2279 as the comment sequence which began this comment
2280 section */
2281 break;
2282 if (code == Scomment_fence
2283 && style == ST_COMMENT_STYLE)
2284 /* we have encountered a comment end of the same style
2285 as the comment sequence which began this comment
2286 section. */
2287 break;
2288 if (nesting > 0
2289 && code == Scomment
2290 && SYNTAX_FLAGS_COMMENT_NESTED (syntax)
2291 && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style)
2292 /* we have encountered a nested comment of the same style
2293 as the comment sequence which began this comment section */
2294 nesting++;
2295 INC_BOTH (from, from_byte);
2296 UPDATE_SYNTAX_TABLE_FORWARD (from);
2297
2298 forw_incomment:
2299 if (from < stop && SYNTAX_FLAGS_COMEND_FIRST (syntax)
2300 && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
2301 other_syntax = SYNTAX_WITH_FLAGS (c1),
2302 SYNTAX_FLAGS_COMEND_SECOND (other_syntax))
2303 && SYNTAX_FLAGS_COMMENT_STYLE (syntax, other_syntax) == style
2304 && ((SYNTAX_FLAGS_COMMENT_NESTED (syntax) ||
2305 SYNTAX_FLAGS_COMMENT_NESTED (other_syntax))
2306 ? nesting > 0 : nesting < 0))
2307 {
2308 if (--nesting <= 0)
2309 /* we have encountered a comment end of the same style
2310 as the comment sequence which began this comment
2311 section */
2312 break;
2313 else
2314 {
2315 INC_BOTH (from, from_byte);
2316 UPDATE_SYNTAX_TABLE_FORWARD (from);
2317 }
2318 }
2319 if (nesting > 0
2320 && from < stop
2321 && SYNTAX_FLAGS_COMSTART_FIRST (syntax)
2322 && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
2323 other_syntax = SYNTAX_WITH_FLAGS (c1),
2324 SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax) == style
2325 && SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
2326 && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ||
2327 SYNTAX_FLAGS_COMMENT_NESTED (other_syntax)))
2328 /* we have encountered a nested comment of the same style
2329 as the comment sequence which began this comment
2330 section */
2331 {
2332 INC_BOTH (from, from_byte);
2333 UPDATE_SYNTAX_TABLE_FORWARD (from);
2334 nesting++;
2335 }
2336 }
2337 *charpos_ptr = from;
2338 *bytepos_ptr = from_byte;
2339 return 1;
2340 }
2341
2342 DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0,
2343 doc: /*
2344 Move forward across up to COUNT comments. If COUNT is negative, move backward.
2345 Stop scanning if we find something other than a comment or whitespace.
2346 Set point to where scanning stops.
2347 If COUNT comments are found as expected, with nothing except whitespace
2348 between them, return t; otherwise return nil. */)
2349 (Lisp_Object count)
2350 {
2351 ptrdiff_t from, from_byte, stop;
2352 int c, c1;
2353 enum syntaxcode code;
2354 int comstyle = 0; /* style of comment encountered */
2355 bool comnested = 0; /* whether the comment is nestable or not */
2356 bool found;
2357 EMACS_INT count1;
2358 ptrdiff_t out_charpos, out_bytepos;
2359 EMACS_INT dummy;
2360
2361 CHECK_NUMBER (count);
2362 count1 = XINT (count);
2363 stop = count1 > 0 ? ZV : BEGV;
2364
2365 immediate_quit = 1;
2366 QUIT;
2367
2368 from = PT;
2369 from_byte = PT_BYTE;
2370
2371 SETUP_SYNTAX_TABLE (from, count1);
2372 while (count1 > 0)
2373 {
2374 do
2375 {
2376 bool comstart_first;
2377 int syntax, other_syntax;
2378
2379 if (from == stop)
2380 {
2381 SET_PT_BOTH (from, from_byte);
2382 immediate_quit = 0;
2383 return Qnil;
2384 }
2385 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2386 syntax = SYNTAX_WITH_FLAGS (c);
2387 code = SYNTAX (c);
2388 comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
2389 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
2390 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
2391 INC_BOTH (from, from_byte);
2392 UPDATE_SYNTAX_TABLE_FORWARD (from);
2393 if (from < stop && comstart_first
2394 && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
2395 other_syntax = SYNTAX_WITH_FLAGS (c1),
2396 SYNTAX_FLAGS_COMSTART_SECOND (other_syntax)))
2397 {
2398 /* We have encountered a comment start sequence and we
2399 are ignoring all text inside comments. We must record
2400 the comment style this sequence begins so that later,
2401 only a comment end of the same style actually ends
2402 the comment section. */
2403 code = Scomment;
2404 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
2405 comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
2406 INC_BOTH (from, from_byte);
2407 UPDATE_SYNTAX_TABLE_FORWARD (from);
2408 }
2409 }
2410 while (code == Swhitespace || (code == Sendcomment && c == '\n'));
2411
2412 if (code == Scomment_fence)
2413 comstyle = ST_COMMENT_STYLE;
2414 else if (code != Scomment)
2415 {
2416 immediate_quit = 0;
2417 DEC_BOTH (from, from_byte);
2418 SET_PT_BOTH (from, from_byte);
2419 return Qnil;
2420 }
2421 /* We're at the start of a comment. */
2422 found = forw_comment (from, from_byte, stop, comnested, comstyle, 0,
2423 &out_charpos, &out_bytepos, &dummy);
2424 from = out_charpos; from_byte = out_bytepos;
2425 if (!found)
2426 {
2427 immediate_quit = 0;
2428 SET_PT_BOTH (from, from_byte);
2429 return Qnil;
2430 }
2431 INC_BOTH (from, from_byte);
2432 UPDATE_SYNTAX_TABLE_FORWARD (from);
2433 /* We have skipped one comment. */
2434 count1--;
2435 }
2436
2437 while (count1 < 0)
2438 {
2439 while (1)
2440 {
2441 bool quoted;
2442 int syntax;
2443
2444 if (from <= stop)
2445 {
2446 SET_PT_BOTH (BEGV, BEGV_BYTE);
2447 immediate_quit = 0;
2448 return Qnil;
2449 }
2450
2451 DEC_BOTH (from, from_byte);
2452 /* char_quoted does UPDATE_SYNTAX_TABLE_BACKWARD (from). */
2453 quoted = char_quoted (from, from_byte);
2454 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2455 syntax = SYNTAX_WITH_FLAGS (c);
2456 code = SYNTAX (c);
2457 comstyle = 0;
2458 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
2459 if (code == Sendcomment)
2460 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
2461 if (from > stop && SYNTAX_FLAGS_COMEND_SECOND (syntax)
2462 && prev_char_comend_first (from, from_byte)
2463 && !char_quoted (from - 1, dec_bytepos (from_byte)))
2464 {
2465 int other_syntax;
2466 /* We must record the comment style encountered so that
2467 later, we can match only the proper comment begin
2468 sequence of the same style. */
2469 DEC_BOTH (from, from_byte);
2470 code = Sendcomment;
2471 /* Calling char_quoted, above, set up global syntax position
2472 at the new value of FROM. */
2473 c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2474 other_syntax = SYNTAX_WITH_FLAGS (c1);
2475 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
2476 comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
2477 }
2478
2479 if (code == Scomment_fence)
2480 {
2481 /* Skip until first preceding unquoted comment_fence. */
2482 bool fence_found = 0;
2483 ptrdiff_t ini = from, ini_byte = from_byte;
2484
2485 while (1)
2486 {
2487 DEC_BOTH (from, from_byte);
2488 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2489 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2490 if (SYNTAX (c) == Scomment_fence
2491 && !char_quoted (from, from_byte))
2492 {
2493 fence_found = 1;
2494 break;
2495 }
2496 else if (from == stop)
2497 break;
2498 }
2499 if (fence_found == 0)
2500 {
2501 from = ini; /* Set point to ini + 1. */
2502 from_byte = ini_byte;
2503 goto leave;
2504 }
2505 else
2506 /* We have skipped one comment. */
2507 break;
2508 }
2509 else if (code == Sendcomment)
2510 {
2511 found = back_comment (from, from_byte, stop, comnested, comstyle,
2512 &out_charpos, &out_bytepos);
2513 if (!found)
2514 {
2515 if (c == '\n')
2516 /* This end-of-line is not an end-of-comment.
2517 Treat it like a whitespace.
2518 CC-mode (and maybe others) relies on this behavior. */
2519 ;
2520 else
2521 {
2522 /* Failure: we should go back to the end of this
2523 not-quite-endcomment. */
2524 if (SYNTAX (c) != code)
2525 /* It was a two-char Sendcomment. */
2526 INC_BOTH (from, from_byte);
2527 goto leave;
2528 }
2529 }
2530 else
2531 {
2532 /* We have skipped one comment. */
2533 from = out_charpos, from_byte = out_bytepos;
2534 break;
2535 }
2536 }
2537 else if (code != Swhitespace || quoted)
2538 {
2539 leave:
2540 immediate_quit = 0;
2541 INC_BOTH (from, from_byte);
2542 SET_PT_BOTH (from, from_byte);
2543 return Qnil;
2544 }
2545 }
2546
2547 count1++;
2548 }
2549
2550 SET_PT_BOTH (from, from_byte);
2551 immediate_quit = 0;
2552 return Qt;
2553 }
2554 \f
2555 /* Return syntax code of character C if C is an ASCII character
2556 or if MULTIBYTE_SYMBOL_P is false. Otherwise, return Ssymbol. */
2557
2558 static enum syntaxcode
2559 syntax_multibyte (int c, bool multibyte_symbol_p)
2560 {
2561 return ASCII_CHAR_P (c) || !multibyte_symbol_p ? SYNTAX (c) : Ssymbol;
2562 }
2563
2564 static Lisp_Object
2565 scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2566 {
2567 Lisp_Object val;
2568 ptrdiff_t stop = count > 0 ? ZV : BEGV;
2569 int c, c1;
2570 int stringterm;
2571 bool quoted;
2572 bool mathexit = 0;
2573 enum syntaxcode code;
2574 EMACS_INT min_depth = depth; /* Err out if depth gets less than this. */
2575 int comstyle = 0; /* style of comment encountered */
2576 bool comnested = 0; /* whether the comment is nestable or not */
2577 ptrdiff_t temp_pos;
2578 EMACS_INT last_good = from;
2579 bool found;
2580 ptrdiff_t from_byte;
2581 ptrdiff_t out_bytepos, out_charpos;
2582 EMACS_INT dummy;
2583 bool multibyte_symbol_p = sexpflag && multibyte_syntax_as_symbol;
2584
2585 if (depth > 0) min_depth = 0;
2586
2587 if (from > ZV) from = ZV;
2588 if (from < BEGV) from = BEGV;
2589
2590 from_byte = CHAR_TO_BYTE (from);
2591
2592 immediate_quit = 1;
2593 QUIT;
2594
2595 SETUP_SYNTAX_TABLE (from, count);
2596 while (count > 0)
2597 {
2598 while (from < stop)
2599 {
2600 bool comstart_first, prefix;
2601 int syntax, other_syntax;
2602 UPDATE_SYNTAX_TABLE_FORWARD (from);
2603 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2604 syntax = SYNTAX_WITH_FLAGS (c);
2605 code = syntax_multibyte (c, multibyte_symbol_p);
2606 comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
2607 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
2608 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
2609 prefix = SYNTAX_FLAGS_PREFIX (syntax);
2610 if (depth == min_depth)
2611 last_good = from;
2612 INC_BOTH (from, from_byte);
2613 UPDATE_SYNTAX_TABLE_FORWARD (from);
2614 if (from < stop && comstart_first
2615 && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte),
2616 other_syntax = SYNTAX_WITH_FLAGS (c),
2617 SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
2618 && parse_sexp_ignore_comments)
2619 {
2620 /* we have encountered a comment start sequence and we
2621 are ignoring all text inside comments. We must record
2622 the comment style this sequence begins so that later,
2623 only a comment end of the same style actually ends
2624 the comment section */
2625 code = Scomment;
2626 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
2627 comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
2628 INC_BOTH (from, from_byte);
2629 UPDATE_SYNTAX_TABLE_FORWARD (from);
2630 }
2631
2632 if (prefix)
2633 continue;
2634
2635 switch (code)
2636 {
2637 case Sescape:
2638 case Scharquote:
2639 if (from == stop)
2640 goto lose;
2641 INC_BOTH (from, from_byte);
2642 /* treat following character as a word constituent */
2643 case Sword:
2644 case Ssymbol:
2645 if (depth || !sexpflag) break;
2646 /* This word counts as a sexp; return at end of it. */
2647 while (from < stop)
2648 {
2649 UPDATE_SYNTAX_TABLE_FORWARD (from);
2650
2651 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2652 switch (syntax_multibyte (c, multibyte_symbol_p))
2653 {
2654 case Scharquote:
2655 case Sescape:
2656 INC_BOTH (from, from_byte);
2657 if (from == stop)
2658 goto lose;
2659 break;
2660 case Sword:
2661 case Ssymbol:
2662 case Squote:
2663 break;
2664 default:
2665 goto done;
2666 }
2667 INC_BOTH (from, from_byte);
2668 }
2669 goto done;
2670
2671 case Scomment_fence:
2672 comstyle = ST_COMMENT_STYLE;
2673 /* FALLTHROUGH */
2674 case Scomment:
2675 if (!parse_sexp_ignore_comments) break;
2676 UPDATE_SYNTAX_TABLE_FORWARD (from);
2677 found = forw_comment (from, from_byte, stop,
2678 comnested, comstyle, 0,
2679 &out_charpos, &out_bytepos, &dummy);
2680 from = out_charpos, from_byte = out_bytepos;
2681 if (!found)
2682 {
2683 if (depth == 0)
2684 goto done;
2685 goto lose;
2686 }
2687 INC_BOTH (from, from_byte);
2688 UPDATE_SYNTAX_TABLE_FORWARD (from);
2689 break;
2690
2691 case Smath:
2692 if (!sexpflag)
2693 break;
2694 if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (from_byte))
2695 {
2696 INC_BOTH (from, from_byte);
2697 }
2698 if (mathexit)
2699 {
2700 mathexit = 0;
2701 goto close1;
2702 }
2703 mathexit = 1;
2704
2705 case Sopen:
2706 if (!++depth) goto done;
2707 break;
2708
2709 case Sclose:
2710 close1:
2711 if (!--depth) goto done;
2712 if (depth < min_depth)
2713 xsignal3 (Qscan_error,
2714 build_string ("Containing expression ends prematurely"),
2715 make_number (last_good), make_number (from));
2716 break;
2717
2718 case Sstring:
2719 case Sstring_fence:
2720 temp_pos = dec_bytepos (from_byte);
2721 stringterm = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2722 while (1)
2723 {
2724 enum syntaxcode c_code;
2725 if (from >= stop)
2726 goto lose;
2727 UPDATE_SYNTAX_TABLE_FORWARD (from);
2728 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2729 c_code = syntax_multibyte (c, multibyte_symbol_p);
2730 if (code == Sstring
2731 ? c == stringterm && c_code == Sstring
2732 : c_code == Sstring_fence)
2733 break;
2734
2735 switch (c_code)
2736 {
2737 case Scharquote:
2738 case Sescape:
2739 INC_BOTH (from, from_byte);
2740 }
2741 INC_BOTH (from, from_byte);
2742 }
2743 INC_BOTH (from, from_byte);
2744 if (!depth && sexpflag) goto done;
2745 break;
2746 default:
2747 /* Ignore whitespace, punctuation, quote, endcomment. */
2748 break;
2749 }
2750 }
2751
2752 /* Reached end of buffer. Error if within object, return nil if between */
2753 if (depth)
2754 goto lose;
2755
2756 immediate_quit = 0;
2757 return Qnil;
2758
2759 /* End of object reached */
2760 done:
2761 count--;
2762 }
2763
2764 while (count < 0)
2765 {
2766 while (from > stop)
2767 {
2768 int syntax;
2769 DEC_BOTH (from, from_byte);
2770 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2771 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2772 syntax= SYNTAX_WITH_FLAGS (c);
2773 code = syntax_multibyte (c, multibyte_symbol_p);
2774 if (depth == min_depth)
2775 last_good = from;
2776 comstyle = 0;
2777 comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
2778 if (code == Sendcomment)
2779 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
2780 if (from > stop && SYNTAX_FLAGS_COMEND_SECOND (syntax)
2781 && prev_char_comend_first (from, from_byte)
2782 && parse_sexp_ignore_comments)
2783 {
2784 /* We must record the comment style encountered so that
2785 later, we can match only the proper comment begin
2786 sequence of the same style. */
2787 int c2, other_syntax;
2788 DEC_BOTH (from, from_byte);
2789 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2790 code = Sendcomment;
2791 c2 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2792 other_syntax = SYNTAX_WITH_FLAGS (c2);
2793 comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
2794 comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
2795 }
2796
2797 /* Quoting turns anything except a comment-ender
2798 into a word character. Note that this cannot be true
2799 if we decremented FROM in the if-statement above. */
2800 if (code != Sendcomment && char_quoted (from, from_byte))
2801 {
2802 DEC_BOTH (from, from_byte);
2803 code = Sword;
2804 }
2805 else if (SYNTAX_FLAGS_PREFIX (syntax))
2806 continue;
2807
2808 switch (code)
2809 {
2810 case Sword:
2811 case Ssymbol:
2812 case Sescape:
2813 case Scharquote:
2814 if (depth || !sexpflag) break;
2815 /* This word counts as a sexp; count object finished
2816 after passing it. */
2817 while (from > stop)
2818 {
2819 temp_pos = from_byte;
2820 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
2821 DEC_POS (temp_pos);
2822 else
2823 temp_pos--;
2824 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
2825 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2826 /* Don't allow comment-end to be quoted. */
2827 if (syntax_multibyte (c1, multibyte_symbol_p) == Sendcomment)
2828 goto done2;
2829 quoted = char_quoted (from - 1, temp_pos);
2830 if (quoted)
2831 {
2832 DEC_BOTH (from, from_byte);
2833 temp_pos = dec_bytepos (temp_pos);
2834 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
2835 }
2836 c1 = FETCH_CHAR_AS_MULTIBYTE (temp_pos);
2837 if (! quoted)
2838 switch (syntax_multibyte (c1, multibyte_symbol_p))
2839 {
2840 case Sword: case Ssymbol: case Squote: break;
2841 default: goto done2;
2842 }
2843 DEC_BOTH (from, from_byte);
2844 }
2845 goto done2;
2846
2847 case Smath:
2848 if (!sexpflag)
2849 break;
2850 temp_pos = dec_bytepos (from_byte);
2851 UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
2852 if (from != stop && c == FETCH_CHAR_AS_MULTIBYTE (temp_pos))
2853 DEC_BOTH (from, from_byte);
2854 if (mathexit)
2855 {
2856 mathexit = 0;
2857 goto open2;
2858 }
2859 mathexit = 1;
2860
2861 case Sclose:
2862 if (!++depth) goto done2;
2863 break;
2864
2865 case Sopen:
2866 open2:
2867 if (!--depth) goto done2;
2868 if (depth < min_depth)
2869 xsignal3 (Qscan_error,
2870 build_string ("Containing expression ends prematurely"),
2871 make_number (last_good), make_number (from));
2872 break;
2873
2874 case Sendcomment:
2875 if (!parse_sexp_ignore_comments)
2876 break;
2877 found = back_comment (from, from_byte, stop, comnested, comstyle,
2878 &out_charpos, &out_bytepos);
2879 /* FIXME: if !found, it really wasn't a comment-end.
2880 For single-char Sendcomment, we can't do much about it apart
2881 from skipping the char.
2882 For 2-char endcomments, we could try again, taking both
2883 chars as separate entities, but it's a lot of trouble
2884 for very little gain, so we don't bother either. -sm */
2885 if (found)
2886 from = out_charpos, from_byte = out_bytepos;
2887 break;
2888
2889 case Scomment_fence:
2890 case Sstring_fence:
2891 while (1)
2892 {
2893 if (from == stop)
2894 goto lose;
2895 DEC_BOTH (from, from_byte);
2896 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2897 if (!char_quoted (from, from_byte))
2898 {
2899 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2900 if (syntax_multibyte (c, multibyte_symbol_p) == code)
2901 break;
2902 }
2903 }
2904 if (code == Sstring_fence && !depth && sexpflag) goto done2;
2905 break;
2906
2907 case Sstring:
2908 stringterm = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2909 while (1)
2910 {
2911 if (from == stop)
2912 goto lose;
2913 DEC_BOTH (from, from_byte);
2914 UPDATE_SYNTAX_TABLE_BACKWARD (from);
2915 if (!char_quoted (from, from_byte))
2916 {
2917 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
2918 if (c == stringterm
2919 && (syntax_multibyte (c, multibyte_symbol_p)
2920 == Sstring))
2921 break;
2922 }
2923 }
2924 if (!depth && sexpflag) goto done2;
2925 break;
2926 default:
2927 /* Ignore whitespace, punctuation, quote, endcomment. */
2928 break;
2929 }
2930 }
2931
2932 /* Reached start of buffer. Error if within object, return nil if between */
2933 if (depth)
2934 goto lose;
2935
2936 immediate_quit = 0;
2937 return Qnil;
2938
2939 done2:
2940 count++;
2941 }
2942
2943
2944 immediate_quit = 0;
2945 XSETFASTINT (val, from);
2946 return val;
2947
2948 lose:
2949 xsignal3 (Qscan_error,
2950 build_string ("Unbalanced parentheses"),
2951 make_number (last_good), make_number (from));
2952 }
2953
2954 DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
2955 doc: /* Scan from character number FROM by COUNT lists.
2956 Scan forward if COUNT is positive, backward if COUNT is negative.
2957 Return the character number of the position thus found.
2958
2959 A \"list", in this context, refers to a balanced parenthetical
2960 grouping, as determined by the syntax table.
2961
2962 If DEPTH is nonzero, treat that as the nesting depth of the starting
2963 point (i.e. the starting point is DEPTH parentheses deep). This
2964 function scans over parentheses until the depth goes to zero COUNT
2965 times. Hence, positive DEPTH moves out that number of levels of
2966 parentheses, while negative DEPTH moves to a deeper level.
2967
2968 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.
2969
2970 If we reach the beginning or end of the accessible part of the buffer
2971 before we have scanned over COUNT lists, return nil if the depth at
2972 that point is zero, and signal a error if the depth is nonzero. */)
2973 (Lisp_Object from, Lisp_Object count, Lisp_Object depth)
2974 {
2975 CHECK_NUMBER (from);
2976 CHECK_NUMBER (count);
2977 CHECK_NUMBER (depth);
2978
2979 return scan_lists (XINT (from), XINT (count), XINT (depth), 0);
2980 }
2981
2982 DEFUN ("scan-sexps", Fscan_sexps, Sscan_sexps, 2, 2, 0,
2983 doc: /* Scan from character number FROM by COUNT balanced expressions.
2984 If COUNT is negative, scan backwards.
2985 Returns the character number of the position thus found.
2986
2987 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.
2988
2989 If the beginning or end of (the accessible part of) the buffer is reached
2990 in the middle of a parenthetical grouping, an error is signaled.
2991 If the beginning or end is reached between groupings
2992 but before count is used up, nil is returned. */)
2993 (Lisp_Object from, Lisp_Object count)
2994 {
2995 CHECK_NUMBER (from);
2996 CHECK_NUMBER (count);
2997
2998 return scan_lists (XINT (from), XINT (count), 0, 1);
2999 }
3000
3001 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
3002 0, 0, 0,
3003 doc: /* Move point backward over any number of chars with prefix syntax.
3004 This includes chars with "quote" or "prefix" syntax (' or p). */)
3005 (void)
3006 {
3007 ptrdiff_t beg = BEGV;
3008 ptrdiff_t opoint = PT;
3009 ptrdiff_t opoint_byte = PT_BYTE;
3010 ptrdiff_t pos = PT;
3011 ptrdiff_t pos_byte = PT_BYTE;
3012 int c;
3013
3014 if (pos <= beg)
3015 {
3016 SET_PT_BOTH (opoint, opoint_byte);
3017
3018 return Qnil;
3019 }
3020
3021 SETUP_SYNTAX_TABLE (pos, -1);
3022
3023 DEC_BOTH (pos, pos_byte);
3024
3025 while (!char_quoted (pos, pos_byte)
3026 /* Previous statement updates syntax table. */
3027 && ((c = FETCH_CHAR_AS_MULTIBYTE (pos_byte), SYNTAX (c) == Squote)
3028 || syntax_prefix_flag_p (c)))
3029 {
3030 opoint = pos;
3031 opoint_byte = pos_byte;
3032
3033 if (pos + 1 > beg)
3034 DEC_BOTH (pos, pos_byte);
3035 }
3036
3037 SET_PT_BOTH (opoint, opoint_byte);
3038
3039 return Qnil;
3040 }
3041 \f
3042 /* Parse forward from FROM / FROM_BYTE to END,
3043 assuming that FROM has state OLDSTATE (nil means FROM is start of function),
3044 and return a description of the state of the parse at END.
3045 If STOPBEFORE, stop at the start of an atom.
3046 If COMMENTSTOP is 1, stop at the start of a comment.
3047 If COMMENTSTOP is -1, stop at the start or end of a comment,
3048 after the beginning of a string, or after the end of a string. */
3049
3050 static void
3051 scan_sexps_forward (struct lisp_parse_state *stateptr,
3052 ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t end,
3053 EMACS_INT targetdepth, bool stopbefore,
3054 Lisp_Object oldstate, int commentstop)
3055 {
3056 struct lisp_parse_state state;
3057 enum syntaxcode code;
3058 int c1;
3059 bool comnested;
3060 struct level { ptrdiff_t last, prev; };
3061 struct level levelstart[100];
3062 struct level *curlevel = levelstart;
3063 struct level *endlevel = levelstart + 100;
3064 EMACS_INT depth; /* Paren depth of current scanning location.
3065 level - levelstart equals this except
3066 when the depth becomes negative. */
3067 EMACS_INT mindepth; /* Lowest DEPTH value seen. */
3068 bool start_quoted = 0; /* True means starting after a char quote. */
3069 Lisp_Object tem;
3070 ptrdiff_t prev_from; /* Keep one character before FROM. */
3071 ptrdiff_t prev_from_byte;
3072 int prev_from_syntax;
3073 bool boundary_stop = commentstop == -1;
3074 bool nofence;
3075 bool found;
3076 ptrdiff_t out_bytepos, out_charpos;
3077 int temp;
3078
3079 prev_from = from;
3080 prev_from_byte = from_byte;
3081 if (from != BEGV)
3082 DEC_BOTH (prev_from, prev_from_byte);
3083
3084 /* Use this macro instead of `from++'. */
3085 #define INC_FROM \
3086 do { prev_from = from; \
3087 prev_from_byte = from_byte; \
3088 temp = FETCH_CHAR_AS_MULTIBYTE (prev_from_byte); \
3089 prev_from_syntax = SYNTAX_WITH_FLAGS (temp); \
3090 INC_BOTH (from, from_byte); \
3091 if (from < end) \
3092 UPDATE_SYNTAX_TABLE_FORWARD (from); \
3093 } while (0)
3094
3095 immediate_quit = 1;
3096 QUIT;
3097
3098 if (NILP (oldstate))
3099 {
3100 depth = 0;
3101 state.instring = -1;
3102 state.incomment = 0;
3103 state.comstyle = 0; /* comment style a by default. */
3104 state.comstr_start = -1; /* no comment/string seen. */
3105 }
3106 else
3107 {
3108 tem = Fcar (oldstate);
3109 if (!NILP (tem))
3110 depth = XINT (tem);
3111 else
3112 depth = 0;
3113
3114 oldstate = Fcdr (oldstate);
3115 oldstate = Fcdr (oldstate);
3116 oldstate = Fcdr (oldstate);
3117 tem = Fcar (oldstate);
3118 /* Check whether we are inside string_fence-style string: */
3119 state.instring = (!NILP (tem)
3120 ? (CHARACTERP (tem) ? XFASTINT (tem) : ST_STRING_STYLE)
3121 : -1);
3122
3123 oldstate = Fcdr (oldstate);
3124 tem = Fcar (oldstate);
3125 state.incomment = (!NILP (tem)
3126 ? (INTEGERP (tem) ? XINT (tem) : -1)
3127 : 0);
3128
3129 oldstate = Fcdr (oldstate);
3130 tem = Fcar (oldstate);
3131 start_quoted = !NILP (tem);
3132
3133 /* if the eighth element of the list is nil, we are in comment
3134 style a. If it is non-nil, we are in comment style b */
3135 oldstate = Fcdr (oldstate);
3136 oldstate = Fcdr (oldstate);
3137 tem = Fcar (oldstate);
3138 state.comstyle = (NILP (tem)
3139 ? 0
3140 : (RANGED_INTEGERP (0, tem, ST_COMMENT_STYLE)
3141 ? XINT (tem)
3142 : ST_COMMENT_STYLE));
3143
3144 oldstate = Fcdr (oldstate);
3145 tem = Fcar (oldstate);
3146 state.comstr_start =
3147 RANGED_INTEGERP (PTRDIFF_MIN, tem, PTRDIFF_MAX) ? XINT (tem) : -1;
3148 oldstate = Fcdr (oldstate);
3149 tem = Fcar (oldstate);
3150 while (!NILP (tem)) /* >= second enclosing sexps. */
3151 {
3152 Lisp_Object temhd = Fcar (tem);
3153 if (RANGED_INTEGERP (PTRDIFF_MIN, temhd, PTRDIFF_MAX))
3154 curlevel->last = XINT (temhd);
3155 if (++curlevel == endlevel)
3156 curlevel--; /* error ("Nesting too deep for parser"); */
3157 curlevel->prev = -1;
3158 curlevel->last = -1;
3159 tem = Fcdr (tem);
3160 }
3161 }
3162 state.quoted = 0;
3163 mindepth = depth;
3164
3165 curlevel->prev = -1;
3166 curlevel->last = -1;
3167
3168 SETUP_SYNTAX_TABLE (prev_from, 1);
3169 temp = FETCH_CHAR (prev_from_byte);
3170 prev_from_syntax = SYNTAX_WITH_FLAGS (temp);
3171 UPDATE_SYNTAX_TABLE_FORWARD (from);
3172
3173 /* Enter the loop at a place appropriate for initial state. */
3174
3175 if (state.incomment)
3176 goto startincomment;
3177 if (state.instring >= 0)
3178 {
3179 nofence = state.instring != ST_STRING_STYLE;
3180 if (start_quoted)
3181 goto startquotedinstring;
3182 goto startinstring;
3183 }
3184 else if (start_quoted)
3185 goto startquoted;
3186
3187 while (from < end)
3188 {
3189 int syntax;
3190 INC_FROM;
3191 code = prev_from_syntax & 0xff;
3192
3193 if (from < end
3194 && SYNTAX_FLAGS_COMSTART_FIRST (prev_from_syntax)
3195 && (c1 = FETCH_CHAR (from_byte),
3196 syntax = SYNTAX_WITH_FLAGS (c1),
3197 SYNTAX_FLAGS_COMSTART_SECOND (syntax)))
3198 /* Duplicate code to avoid a complex if-expression
3199 which causes trouble for the SGI compiler. */
3200 {
3201 /* Record the comment style we have entered so that only
3202 the comment-end sequence of the same style actually
3203 terminates the comment section. */
3204 state.comstyle
3205 = SYNTAX_FLAGS_COMMENT_STYLE (syntax, prev_from_syntax);
3206 comnested = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax)
3207 | SYNTAX_FLAGS_COMMENT_NESTED (syntax));
3208 state.incomment = comnested ? 1 : -1;
3209 state.comstr_start = prev_from;
3210 INC_FROM;
3211 code = Scomment;
3212 }
3213 else if (code == Scomment_fence)
3214 {
3215 /* Record the comment style we have entered so that only
3216 the comment-end sequence of the same style actually
3217 terminates the comment section. */
3218 state.comstyle = ST_COMMENT_STYLE;
3219 state.incomment = -1;
3220 state.comstr_start = prev_from;
3221 code = Scomment;
3222 }
3223 else if (code == Scomment)
3224 {
3225 state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax, 0);
3226 state.incomment = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax) ?
3227 1 : -1);
3228 state.comstr_start = prev_from;
3229 }
3230
3231 if (SYNTAX_FLAGS_PREFIX (prev_from_syntax))
3232 continue;
3233 switch (code)
3234 {
3235 case Sescape:
3236 case Scharquote:
3237 if (stopbefore) goto stop; /* this arg means stop at sexp start */
3238 curlevel->last = prev_from;
3239 startquoted:
3240 if (from == end) goto endquoted;
3241 INC_FROM;
3242 goto symstarted;
3243 /* treat following character as a word constituent */
3244 case Sword:
3245 case Ssymbol:
3246 if (stopbefore) goto stop; /* this arg means stop at sexp start */
3247 curlevel->last = prev_from;
3248 symstarted:
3249 while (from < end)
3250 {
3251 int symchar = FETCH_CHAR_AS_MULTIBYTE (from_byte);
3252 switch (SYNTAX (symchar))
3253 {
3254 case Scharquote:
3255 case Sescape:
3256 INC_FROM;
3257 if (from == end) goto endquoted;
3258 break;
3259 case Sword:
3260 case Ssymbol:
3261 case Squote:
3262 break;
3263 default:
3264 goto symdone;
3265 }
3266 INC_FROM;
3267 }
3268 symdone:
3269 curlevel->prev = curlevel->last;
3270 break;
3271
3272 case Scomment_fence: /* Can't happen because it's handled above. */
3273 case Scomment:
3274 if (commentstop || boundary_stop) goto done;
3275 startincomment:
3276 /* The (from == BEGV) test was to enter the loop in the middle so
3277 that we find a 2-char comment ender even if we start in the
3278 middle of it. We don't want to do that if we're just at the
3279 beginning of the comment (think of (*) ... (*)). */
3280 found = forw_comment (from, from_byte, end,
3281 state.incomment, state.comstyle,
3282 (from == BEGV || from < state.comstr_start + 3)
3283 ? 0 : prev_from_syntax,
3284 &out_charpos, &out_bytepos, &state.incomment);
3285 from = out_charpos; from_byte = out_bytepos;
3286 /* Beware! prev_from and friends are invalid now.
3287 Luckily, the `done' doesn't use them and the INC_FROM
3288 sets them to a sane value without looking at them. */
3289 if (!found) goto done;
3290 INC_FROM;
3291 state.incomment = 0;
3292 state.comstyle = 0; /* reset the comment style */
3293 if (boundary_stop) goto done;
3294 break;
3295
3296 case Sopen:
3297 if (stopbefore) goto stop; /* this arg means stop at sexp start */
3298 depth++;
3299 /* curlevel++->last ran into compiler bug on Apollo */
3300 curlevel->last = prev_from;
3301 if (++curlevel == endlevel)
3302 curlevel--; /* error ("Nesting too deep for parser"); */
3303 curlevel->prev = -1;
3304 curlevel->last = -1;
3305 if (targetdepth == depth) goto done;
3306 break;
3307
3308 case Sclose:
3309 depth--;
3310 if (depth < mindepth)
3311 mindepth = depth;
3312 if (curlevel != levelstart)
3313 curlevel--;
3314 curlevel->prev = curlevel->last;
3315 if (targetdepth == depth) goto done;
3316 break;
3317
3318 case Sstring:
3319 case Sstring_fence:
3320 state.comstr_start = from - 1;
3321 if (stopbefore) goto stop; /* this arg means stop at sexp start */
3322 curlevel->last = prev_from;
3323 state.instring = (code == Sstring
3324 ? (FETCH_CHAR_AS_MULTIBYTE (prev_from_byte))
3325 : ST_STRING_STYLE);
3326 if (boundary_stop) goto done;
3327 startinstring:
3328 {
3329 nofence = state.instring != ST_STRING_STYLE;
3330
3331 while (1)
3332 {
3333 int c;
3334 enum syntaxcode c_code;
3335
3336 if (from >= end) goto done;
3337 c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
3338 c_code = SYNTAX (c);
3339
3340 /* Check C_CODE here so that if the char has
3341 a syntax-table property which says it is NOT
3342 a string character, it does not end the string. */
3343 if (nofence && c == state.instring && c_code == Sstring)
3344 break;
3345
3346 switch (c_code)
3347 {
3348 case Sstring_fence:
3349 if (!nofence) goto string_end;
3350 break;
3351 case Scharquote:
3352 case Sescape:
3353 INC_FROM;
3354 startquotedinstring:
3355 if (from >= end) goto endquoted;
3356 }
3357 INC_FROM;
3358 }
3359 }
3360 string_end:
3361 state.instring = -1;
3362 curlevel->prev = curlevel->last;
3363 INC_FROM;
3364 if (boundary_stop) goto done;
3365 break;
3366
3367 case Smath:
3368 /* FIXME: We should do something with it. */
3369 break;
3370 default:
3371 /* Ignore whitespace, punctuation, quote, endcomment. */
3372 break;
3373 }
3374 }
3375 goto done;
3376
3377 stop: /* Here if stopping before start of sexp. */
3378 from = prev_from; /* We have just fetched the char that starts it; */
3379 from_byte = prev_from_byte;
3380 goto done; /* but return the position before it. */
3381
3382 endquoted:
3383 state.quoted = 1;
3384 done:
3385 state.depth = depth;
3386 state.mindepth = mindepth;
3387 state.thislevelstart = curlevel->prev;
3388 state.prevlevelstart
3389 = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
3390 state.location = from;
3391 state.location_byte = from_byte;
3392 state.levelstarts = Qnil;
3393 while (curlevel > levelstart)
3394 state.levelstarts = Fcons (make_number ((--curlevel)->last),
3395 state.levelstarts);
3396 immediate_quit = 0;
3397
3398 *stateptr = state;
3399 }
3400
3401 DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0,
3402 doc: /* Parse Lisp syntax starting at FROM until TO; return status of parse at TO.
3403 Parsing stops at TO or when certain criteria are met;
3404 point is set to where parsing stops.
3405 If fifth arg OLDSTATE is omitted or nil,
3406 parsing assumes that FROM is the beginning of a function.
3407 Value is a list of elements describing final state of parsing:
3408 0. depth in parens.
3409 1. character address of start of innermost containing list; nil if none.
3410 2. character address of start of last complete sexp terminated.
3411 3. non-nil if inside a string.
3412 (it is the character that will terminate the string,
3413 or t if the string should be terminated by a generic string delimiter.)
3414 4. nil if outside a comment, t if inside a non-nestable comment,
3415 else an integer (the current comment nesting).
3416 5. t if following a quote character.
3417 6. the minimum paren-depth encountered during this scan.
3418 7. style of comment, if any.
3419 8. character address of start of comment or string; nil if not in one.
3420 9. Intermediate data for continuation of parsing (subject to change).
3421 If third arg TARGETDEPTH is non-nil, parsing stops if the depth
3422 in parentheses becomes equal to TARGETDEPTH.
3423 Fourth arg STOPBEFORE non-nil means stop when come to
3424 any character that starts a sexp.
3425 Fifth arg OLDSTATE is a list like what this function returns.
3426 It is used to initialize the state of the parse. Elements number 1, 2, 6
3427 are ignored.
3428 Sixth arg COMMENTSTOP non-nil means stop at the start of a comment.
3429 If it is symbol `syntax-table', stop after the start of a comment or a
3430 string, or after end of a comment or a string. */)
3431 (Lisp_Object from, Lisp_Object to, Lisp_Object targetdepth,
3432 Lisp_Object stopbefore, Lisp_Object oldstate, Lisp_Object commentstop)
3433 {
3434 struct lisp_parse_state state;
3435 EMACS_INT target;
3436
3437 if (!NILP (targetdepth))
3438 {
3439 CHECK_NUMBER (targetdepth);
3440 target = XINT (targetdepth);
3441 }
3442 else
3443 target = TYPE_MINIMUM (EMACS_INT); /* We won't reach this depth */
3444
3445 validate_region (&from, &to);
3446 scan_sexps_forward (&state, XINT (from), CHAR_TO_BYTE (XINT (from)),
3447 XINT (to),
3448 target, !NILP (stopbefore), oldstate,
3449 (NILP (commentstop)
3450 ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1)));
3451
3452 SET_PT_BOTH (state.location, state.location_byte);
3453
3454 return Fcons (make_number (state.depth),
3455 Fcons (state.prevlevelstart < 0
3456 ? Qnil : make_number (state.prevlevelstart),
3457 Fcons (state.thislevelstart < 0
3458 ? Qnil : make_number (state.thislevelstart),
3459 Fcons (state.instring >= 0
3460 ? (state.instring == ST_STRING_STYLE
3461 ? Qt : make_number (state.instring)) : Qnil,
3462 Fcons (state.incomment < 0 ? Qt :
3463 (state.incomment == 0 ? Qnil :
3464 make_number (state.incomment)),
3465 Fcons (state.quoted ? Qt : Qnil,
3466 Fcons (make_number (state.mindepth),
3467 Fcons ((state.comstyle
3468 ? (state.comstyle == ST_COMMENT_STYLE
3469 ? Qsyntax_table
3470 : make_number (state.comstyle))
3471 : Qnil),
3472 Fcons (((state.incomment
3473 || (state.instring >= 0))
3474 ? make_number (state.comstr_start)
3475 : Qnil),
3476 Fcons (state.levelstarts, Qnil))))))))));
3477 }
3478 \f
3479 void
3480 init_syntax_once (void)
3481 {
3482 register int i, c;
3483 Lisp_Object temp;
3484
3485 /* This has to be done here, before we call Fmake_char_table. */
3486 DEFSYM (Qsyntax_table, "syntax-table");
3487
3488 /* Intern_C_String this now in case it isn't already done.
3489 Setting this variable twice is harmless.
3490 But don't staticpro it here--that is done in alloc.c. */
3491 Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots");
3492
3493 /* Create objects which can be shared among syntax tables. */
3494 Vsyntax_code_object = make_uninit_vector (Smax);
3495 for (i = 0; i < Smax; i++)
3496 ASET (Vsyntax_code_object, i, Fcons (make_number (i), Qnil));
3497
3498 /* Now we are ready to set up this property, so we can
3499 create syntax tables. */
3500 Fput (Qsyntax_table, Qchar_table_extra_slots, make_number (0));
3501
3502 temp = AREF (Vsyntax_code_object, Swhitespace);
3503
3504 Vstandard_syntax_table = Fmake_char_table (Qsyntax_table, temp);
3505
3506 /* Control characters should not be whitespace. */
3507 temp = AREF (Vsyntax_code_object, Spunct);
3508 for (i = 0; i <= ' ' - 1; i++)
3509 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
3510 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 0177, temp);
3511
3512 /* Except that a few really are whitespace. */
3513 temp = AREF (Vsyntax_code_object, Swhitespace);
3514 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ' ', temp);
3515 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\t', temp);
3516 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\n', temp);
3517 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 015, temp);
3518 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, 014, temp);
3519
3520 temp = AREF (Vsyntax_code_object, Sword);
3521 for (i = 'a'; i <= 'z'; i++)
3522 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
3523 for (i = 'A'; i <= 'Z'; i++)
3524 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
3525 for (i = '0'; i <= '9'; i++)
3526 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, i, temp);
3527
3528 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '$', temp);
3529 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '%', temp);
3530
3531 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '(',
3532 Fcons (make_number (Sopen), make_number (')')));
3533 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ')',
3534 Fcons (make_number (Sclose), make_number ('(')));
3535 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '[',
3536 Fcons (make_number (Sopen), make_number (']')));
3537 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, ']',
3538 Fcons (make_number (Sclose), make_number ('[')));
3539 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '{',
3540 Fcons (make_number (Sopen), make_number ('}')));
3541 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '}',
3542 Fcons (make_number (Sclose), make_number ('{')));
3543 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '"',
3544 Fcons (make_number (Sstring), Qnil));
3545 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, '\\',
3546 Fcons (make_number (Sescape), Qnil));
3547
3548 temp = AREF (Vsyntax_code_object, Ssymbol);
3549 for (i = 0; i < 10; i++)
3550 {
3551 c = "_-+*/&|<>="[i];
3552 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, c, temp);
3553 }
3554
3555 temp = AREF (Vsyntax_code_object, Spunct);
3556 for (i = 0; i < 12; i++)
3557 {
3558 c = ".,;:?!#@~^'`"[i];
3559 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, c, temp);
3560 }
3561
3562 /* All multibyte characters have syntax `word' by default. */
3563 temp = AREF (Vsyntax_code_object, Sword);
3564 char_table_set_range (Vstandard_syntax_table, 0x80, MAX_CHAR, temp);
3565 }
3566
3567 void
3568 syms_of_syntax (void)
3569 {
3570 DEFSYM (Qsyntax_table_p, "syntax-table-p");
3571
3572 staticpro (&Vsyntax_code_object);
3573
3574 staticpro (&gl_state.object);
3575 staticpro (&gl_state.global_code);
3576 staticpro (&gl_state.current_syntax_table);
3577 staticpro (&gl_state.old_prop);
3578
3579 /* Defined in regex.c */
3580 staticpro (&re_match_object);
3581
3582 DEFSYM (Qscan_error, "scan-error");
3583 Fput (Qscan_error, Qerror_conditions,
3584 listn (CONSTYPE_PURE, 2, Qscan_error, Qerror));
3585 Fput (Qscan_error, Qerror_message,
3586 build_pure_c_string ("Scan error"));
3587
3588 DEFVAR_BOOL ("parse-sexp-ignore-comments", parse_sexp_ignore_comments,
3589 doc: /* Non-nil means `forward-sexp', etc., should treat comments as whitespace. */);
3590
3591 DEFVAR_BOOL ("parse-sexp-lookup-properties", parse_sexp_lookup_properties,
3592 doc: /* Non-nil means `forward-sexp', etc., obey `syntax-table' property.
3593 Otherwise, that text property is simply ignored.
3594 See the info node `(elisp)Syntax Properties' for a description of the
3595 `syntax-table' property. */);
3596
3597 words_include_escapes = 0;
3598 DEFVAR_BOOL ("words-include-escapes", words_include_escapes,
3599 doc: /* Non-nil means `forward-word', etc., should treat escape chars part of words. */);
3600
3601 DEFVAR_BOOL ("multibyte-syntax-as-symbol", multibyte_syntax_as_symbol,
3602 doc: /* Non-nil means `scan-sexps' treats all multibyte characters as symbol. */);
3603 multibyte_syntax_as_symbol = 0;
3604
3605 DEFVAR_BOOL ("open-paren-in-column-0-is-defun-start",
3606 open_paren_in_column_0_is_defun_start,
3607 doc: /* Non-nil means an open paren in column 0 denotes the start of a defun. */);
3608 open_paren_in_column_0_is_defun_start = 1;
3609
3610
3611 DEFVAR_LISP ("find-word-boundary-function-table",
3612 Vfind_word_boundary_function_table,
3613 doc: /*
3614 Char table of functions to search for the word boundary.
3615 Each function is called with two arguments; POS and LIMIT.
3616 POS and LIMIT are character positions in the current buffer.
3617
3618 If POS is less than LIMIT, POS is at the first character of a word,
3619 and the return value of a function is a position after the last
3620 character of that word.
3621
3622 If POS is not less than LIMIT, POS is at the last character of a word,
3623 and the return value of a function is a position at the first
3624 character of that word.
3625
3626 In both cases, LIMIT bounds the search. */);
3627 Vfind_word_boundary_function_table = Fmake_char_table (Qnil, Qnil);
3628
3629 defsubr (&Ssyntax_table_p);
3630 defsubr (&Ssyntax_table);
3631 defsubr (&Sstandard_syntax_table);
3632 defsubr (&Scopy_syntax_table);
3633 defsubr (&Sset_syntax_table);
3634 defsubr (&Schar_syntax);
3635 defsubr (&Smatching_paren);
3636 defsubr (&Sstring_to_syntax);
3637 defsubr (&Smodify_syntax_entry);
3638 defsubr (&Sinternal_describe_syntax_value);
3639
3640 defsubr (&Sforward_word);
3641
3642 defsubr (&Sskip_chars_forward);
3643 defsubr (&Sskip_chars_backward);
3644 defsubr (&Sskip_syntax_forward);
3645 defsubr (&Sskip_syntax_backward);
3646
3647 defsubr (&Sforward_comment);
3648 defsubr (&Sscan_lists);
3649 defsubr (&Sscan_sexps);
3650 defsubr (&Sbackward_prefix_chars);
3651 defsubr (&Sparse_partial_sexp);
3652 }