1 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985, 87, 93, 94, 95, 1997 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
29 /* Make syntax table lookup grant data in gl_state. */
30 #define SYNTAX_ENTRY_VIA_PROPERTY
33 #include "intervals.h"
35 /* We use these constants in place for comment-style and
36 string-ender-char to distinguish comments/strings started by
37 comment_fence and string_fence codes. */
39 #define ST_COMMENT_STYLE (256 + 1)
40 #define ST_STRING_STYLE (256 + 2)
43 Lisp_Object Qsyntax_table_p
, Qsyntax_table
, Qscan_error
;
45 static void scan_sexps_forward ();
46 static int char_quoted ();
48 int words_include_escapes
;
49 int parse_sexp_lookup_properties
;
51 /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
52 if not compiled with GCC. No need to mark it, since it is used
53 only very temporarily. */
54 Lisp_Object syntax_temp
;
56 /* This is the internal form of the parse state used in parse-partial-sexp. */
58 struct lisp_parse_state
60 int depth
; /* Depth at end of parsing. */
61 int instring
; /* -1 if not within string, else desired terminator. */
62 int incomment
; /* Nonzero if within a comment at end of parsing. */
63 int comstyle
; /* comment style a=0, or b=1, or ST_COMMENT_STYLE. */
64 int quoted
; /* Nonzero if just after an escape char at end of parsing */
65 int thislevelstart
; /* Char number of most recent start-of-expression at current level */
66 int prevlevelstart
; /* Char number of start of containing expression */
67 int location
; /* Char number at which parsing stopped. */
68 int mindepth
; /* Minimum depth seen while scanning. */
69 int comstr_start
; /* Position just after last comment/string starter. */
72 /* These variables are a cache for finding the start of a defun.
73 find_start_pos is the place for which the defun start was found.
74 find_start_value is the defun start position found for it.
75 find_start_buffer is the buffer it was found in.
76 find_start_begv is the BEGV value when it was found.
77 find_start_modiff is the value of MODIFF when it was found. */
79 static int find_start_pos
;
80 static int find_start_value
;
81 static struct buffer
*find_start_buffer
;
82 static int find_start_begv
;
83 static int find_start_modiff
;
86 struct gl_state_s gl_state
; /* Global state of syntax parser. */
88 INTERVAL
interval_of ();
89 #define INTERVALS_AT_ONCE 10 /* 1 + max-number of intervals
90 to scan to property-change. */
93 Update gl_state to an appropriate interval which contains POS. The
94 sign of COUNT give the relative position of POS wrt the previously
95 valid interval. If INIT, only [be]_property fields of gl_state are
96 valid at start, the rest is filled basing on OBJECT.
98 `gl_state.*_i' are the intervals, and pos is further in the search
99 direction than the intervals - or in an interval. We update the
100 current syntax-table basing on the property of this interval, and
101 update the interval to start further than POS - or be
102 NULL_INTERVAL. We also update lim_property to be the next value of
103 pos to call this subroutine again - or be before/after the
104 start/end of OBJECT. */
107 update_syntax_table (pos
, count
, init
, object
)
108 int pos
, count
, init
;
111 Lisp_Object tmp_table
;
112 int cnt
= 0, doing_extra
= 0, invalidate
= 1;
117 gl_state
.start
= gl_state
.b_property
;
118 gl_state
.stop
= gl_state
.e_property
;
119 gl_state
.forward_i
= interval_of (pos
, object
);
120 i
= gl_state
.backward_i
= gl_state
.forward_i
;
121 gl_state
.left_ok
= gl_state
.right_ok
= 1;
123 if (NULL_INTERVAL_P (i
))
125 gl_state
.b_property
= i
->position
- 1;
126 gl_state
.e_property
= INTERVAL_LAST_POS (i
);
129 oldi
= i
= count
> 0 ? gl_state
.forward_i
: gl_state
.backward_i
;
131 /* We are guarantied to be called with pos either in i, of further off. */
132 if (NULL_INTERVAL_P (i
))
133 error ("Error in syntax_table logic for to-the-end intervals");
134 else if (pos
< i
->position
) /* Move left. */
137 error ("Error in syntax_table logic for intervals <-.");
138 /* Update the interval. */
139 i
= update_interval (i
, pos
);
140 if (oldi
->position
!= INTERVAL_LAST_POS (i
))
143 gl_state
.right_ok
= 1; /* Invalidate the other end. */
144 gl_state
.forward_i
= i
;
145 gl_state
.e_property
= INTERVAL_LAST_POS (i
);
148 else if (pos
>= INTERVAL_LAST_POS (i
)) /* Move right. */
151 error ("Error in syntax_table logic for intervals ->.");
152 /* Update the interval. */
153 i
= update_interval (i
, pos
);
154 if (i
->position
!= INTERVAL_LAST_POS (oldi
))
157 gl_state
.left_ok
= 1; /* Invalidate the other end. */
158 gl_state
.backward_i
= i
;
159 gl_state
.b_property
= i
->position
- 1;
162 else if (count
> 0 ? gl_state
.right_ok
: gl_state
.left_ok
)
164 /* We do not need to recalculate tmp_table. */
165 tmp_table
= gl_state
.old_prop
;
169 tmp_table
= textget (i
->plist
, Qsyntax_table
);
172 invalidate
= !EQ (tmp_table
, gl_state
.old_prop
); /* Need to invalidate? */
174 if (invalidate
) /* Did not get to adjacent interval. */
175 { /* with the same table => */
176 /* invalidate the old range. */
179 gl_state
.backward_i
= i
;
180 gl_state
.left_ok
= 1; /* Invalidate the other end. */
181 gl_state
.b_property
= i
->position
- 1;
185 gl_state
.forward_i
= i
;
186 gl_state
.right_ok
= 1; /* Invalidate the other end. */
187 gl_state
.e_property
= INTERVAL_LAST_POS (i
);
191 gl_state
.current_syntax_table
= tmp_table
;
192 gl_state
.old_prop
= tmp_table
;
193 if (EQ (Fsyntax_table_p (tmp_table
), Qt
))
195 gl_state
.use_global
= 0;
197 else if (CONSP (tmp_table
))
199 gl_state
.use_global
= 1;
200 gl_state
.global_code
= tmp_table
;
204 gl_state
.use_global
= 0;
205 gl_state
.current_syntax_table
= current_buffer
->syntax_table
;
208 while (!NULL_INTERVAL_P (i
))
210 if (cnt
&& !EQ (tmp_table
, textget (i
->plist
, Qsyntax_table
)))
213 gl_state
.right_ok
= 0;
215 gl_state
.left_ok
= 0;
218 else if (cnt
== INTERVALS_AT_ONCE
)
221 gl_state
.right_ok
= 1;
223 gl_state
.left_ok
= 1;
227 i
= count
> 0 ? next_interval (i
) : previous_interval (i
);
229 if (NULL_INTERVAL_P (i
))
230 { /* This property goes to the end. */
232 gl_state
.e_property
= gl_state
.stop
;
234 gl_state
.b_property
= gl_state
.start
;
240 gl_state
.e_property
= i
->position
;
241 gl_state
.forward_i
= i
;
245 gl_state
.b_property
= i
->position
+ LENGTH (i
) - 1;
246 gl_state
.backward_i
= i
;
251 /* Returns TRUE if char at POS is quoted.
252 Global syntax-table data should be set up already to be good at pos
253 or after. On return global syntax data is good for lookup at POS. */
259 register enum syntaxcode code
;
260 register int beg
= BEGV
;
261 register int quoted
= 0;
265 while (temp_pos
>= beg
266 && ( UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos
), 1)
267 && ((code
= SYNTAX (FETCH_CHAR (temp_pos
))) == Scharquote
270 temp_pos
--, quoted
= !quoted
;
272 UPDATE_SYNTAX_TABLE (pos
);
276 /* Find a defun-start that is the last one before POS (or nearly the last).
277 We record what we find, so that another call in the same area
278 can return the same value right away.
280 There is no promise at which position the global syntax data is
281 valid on return from the subroutine, so the caller should explicitly
282 update the global data. */
285 find_defun_start (pos
)
291 /* Use previous finding, if it's valid and applies to this inquiry. */
292 if (current_buffer
== find_start_buffer
293 /* Reuse the defun-start even if POS is a little farther on.
294 POS might be in the next defun, but that's ok.
295 Our value may not be the best possible, but will still be usable. */
296 && pos
<= find_start_pos
+ 1000
297 && pos
>= find_start_value
298 && BEGV
== find_start_begv
299 && MODIFF
== find_start_modiff
)
300 return find_start_value
;
302 /* Back up to start of line. */
303 tem
= scan_buffer ('\n', pos
, BEGV
, -1, &shortage
, 1);
305 /* We optimize syntax-table lookup for rare updates. Thus we accept
306 only those `^\s(' which are good in global _and_ text-property
308 gl_state
.current_syntax_table
= current_buffer
->syntax_table
;
309 gl_state
.use_global
= 0;
312 /* Open-paren at start of line means we found our defun-start. */
313 if (SYNTAX (FETCH_CHAR (tem
)) == Sopen
)
315 SETUP_SYNTAX_TABLE (tem
+ 1, -1); /* Try again... */
316 if (SYNTAX (FETCH_CHAR (tem
)) == Sopen
)
318 /* Now fallback to the default value. */
319 gl_state
.current_syntax_table
= current_buffer
->syntax_table
;
320 gl_state
.use_global
= 0;
322 /* Move to beg of previous line. */
323 tem
= scan_buffer ('\n', tem
, BEGV
, -2, &shortage
, 1);
326 /* Record what we found, for the next try. */
327 find_start_value
= tem
;
328 find_start_buffer
= current_buffer
;
329 find_start_modiff
= MODIFF
;
330 find_start_begv
= BEGV
;
331 find_start_pos
= pos
;
333 return find_start_value
;
336 /* Checks whether FROM is at the end of a comment;
337 and if so, returns position of the start of the comment.
338 But does not move back before STOP.
339 Returns -1 if there is no comment ending at FROM.
341 Global syntax data remains valid for backward search starting at
342 the returned value (or at FROM, if the search was not successful). */
345 back_comment (from
, stop
, comstyle
)
346 int from
, stop
, comstyle
;
348 /* Look back, counting the parity of string-quotes,
349 and recording the comment-starters seen.
350 When we reach a safe place, assume that's not in a string;
351 then step the main scan to the earliest comment-starter seen
352 an even number of string quotes away from the safe place.
354 OFROM[I] is position of the earliest comment-starter seen
355 which is I+2X quotes from the comment-end.
356 PARITY is current parity of quotes from the comment end. */
358 int my_stringend
= 0;
359 int string_lossage
= 0;
360 int comment_end
= from
;
361 int comstart_pos
= 0;
362 int comstart_parity
= 0;
363 int scanstart
= from
- 1;
364 register enum syntaxcode code
;
367 /* At beginning of range to scan, we're outside of strings;
368 that determines quote parity to the comment-end. */
371 /* Move back and examine a character. */
373 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
375 c
= FETCH_CHAR (from
);
378 /* If this char is the second of a 2-char comment end sequence,
379 back up and give the pair the appropriate syntax. */
380 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
381 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from
- 1)))
385 /* This is apparently the best we can do: */
386 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
387 c
= FETCH_CHAR (from
);
390 /* If this char starts a 2-char comment start sequence,
391 treat it like a 1-char comment starter. */
392 if (from
< scanstart
&& SYNTAX_COMSTART_FIRST (c
)
393 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
+ 1))
394 && comstyle
== SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
+ 1)))
397 /* Ignore escaped characters. */
398 if (char_quoted (from
))
401 /* Track parity of quotes. */
405 if (my_stringend
== 0)
407 /* If we have two kinds of string delimiters.
408 There's no way to grok this scanning backwards. */
409 else if (my_stringend
!= c
)
413 if (code
== Sstring_fence
|| code
== Scomment_fence
)
416 if (my_stringend
== 0)
418 code
== Sstring_fence
? ST_STRING_STYLE
: ST_COMMENT_STYLE
;
419 /* If we have two kinds of string delimiters.
420 There's no way to grok this scanning backwards. */
421 else if (my_stringend
!= (code
== Sstring_fence
422 ? ST_STRING_STYLE
: ST_COMMENT_STYLE
))
426 /* Record comment-starters according to that
427 quote-parity to the comment-end. */
428 if (code
== Scomment
)
430 comstart_parity
= parity
;
434 /* If we find another earlier comment-ender,
435 any comment-starts earlier than that don't count
436 (because they go with the earlier comment-ender). */
437 if (code
== Sendcomment
438 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)) == comstyle
)
441 /* Assume a defun-start point is outside of strings. */
443 && (from
== stop
|| FETCH_CHAR (from
- 1) == '\n'))
447 if (comstart_pos
== 0)
450 UPDATE_SYNTAX_TABLE_FORWARD (comment_end
- 1);
452 /* If the earliest comment starter
453 is followed by uniform paired string quotes or none,
454 we know it can't be inside a string
455 since if it were then the comment ender would be inside one.
456 So it does start a comment. Skip back to it. */
457 else if (comstart_parity
== 0 && !string_lossage
)
460 /* Globals are correct now. */
464 /* We had two kinds of string delimiters mixed up
465 together. Decode this going forwards.
466 Scan fwd from the previous comment ender
467 to the one in question; this records where we
468 last passed a comment starter. */
469 struct lisp_parse_state state
;
470 scan_sexps_forward (&state
, find_defun_start (comment_end
),
471 comment_end
- 1, -10000, 0, Qnil
, 0);
474 /* scan_sexps_forward changed the direction of search in
475 global variables, so we need to update it completely. */
477 from
= state
.comstr_start
;
483 UPDATE_SYNTAX_TABLE_FORWARD (from
- 1);
489 DEFUN ("syntax-table-p", Fsyntax_table_p
, Ssyntax_table_p
, 1, 1, 0,
490 "Return t if OBJECT is a syntax table.\n\
491 Currently, any char-table counts as a syntax table.")
495 if (CHAR_TABLE_P (object
)
496 && EQ (XCHAR_TABLE (object
)->purpose
, Qsyntax_table
))
502 check_syntax_table (obj
)
505 if (!(CHAR_TABLE_P (obj
)
506 && EQ (XCHAR_TABLE (obj
)->purpose
, Qsyntax_table
)))
507 wrong_type_argument (Qsyntax_table_p
, obj
);
510 DEFUN ("syntax-table", Fsyntax_table
, Ssyntax_table
, 0, 0, 0,
511 "Return the current syntax table.\n\
512 This is the one specified by the current buffer.")
515 return current_buffer
->syntax_table
;
518 DEFUN ("standard-syntax-table", Fstandard_syntax_table
,
519 Sstandard_syntax_table
, 0, 0, 0,
520 "Return the standard syntax table.\n\
521 This is the one used for new buffers.")
524 return Vstandard_syntax_table
;
527 DEFUN ("copy-syntax-table", Fcopy_syntax_table
, Scopy_syntax_table
, 0, 1, 0,
528 "Construct a new syntax table and return it.\n\
529 It is a copy of the TABLE, which defaults to the standard syntax table.")
536 check_syntax_table (table
);
538 table
= Vstandard_syntax_table
;
540 copy
= Fcopy_sequence (table
);
542 /* Only the standard syntax table should have a default element.
543 Other syntax tables should inherit from parents instead. */
544 XCHAR_TABLE (copy
)->defalt
= Qnil
;
546 /* Copied syntax tables should all have parents.
547 If we copied one with no parent, such as the standard syntax table,
548 use the standard syntax table as the copy's parent. */
549 if (NILP (XCHAR_TABLE (copy
)->parent
))
550 Fset_char_table_parent (copy
, Vstandard_syntax_table
);
554 DEFUN ("set-syntax-table", Fset_syntax_table
, Sset_syntax_table
, 1, 1, 0,
555 "Select a new syntax table for the current buffer.\n\
556 One argument, a syntax table.")
560 check_syntax_table (table
);
561 current_buffer
->syntax_table
= table
;
562 /* Indicate that this buffer now has a specified syntax table. */
563 current_buffer
->local_var_flags
564 |= XFASTINT (buffer_local_flags
.syntax_table
);
568 /* Convert a letter which signifies a syntax code
569 into the code it signifies.
570 This is used by modify-syntax-entry, and other things. */
572 unsigned char syntax_spec_code
[0400] =
573 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
574 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
575 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
576 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
577 (char) Swhitespace
, (char) Scomment_fence
, (char) Sstring
, 0377,
578 (char) Smath
, 0377, 0377, (char) Squote
,
579 (char) Sopen
, (char) Sclose
, 0377, 0377,
580 0377, (char) Swhitespace
, (char) Spunct
, (char) Scharquote
,
581 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
582 0377, 0377, 0377, 0377,
583 (char) Scomment
, 0377, (char) Sendcomment
, 0377,
584 (char) Sinherit
, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A ... */
585 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
586 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
587 0377, 0377, 0377, 0377, (char) Sescape
, 0377, 0377, (char) Ssymbol
,
588 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
589 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
590 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
591 0377, 0377, 0377, 0377, (char) Sstring_fence
, 0377, 0377, 0377
594 /* Indexed by syntax code, give the letter that describes it. */
596 char syntax_code_spec
[16] =
598 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@',
602 /* Indexed by syntax code, give the object (cons of syntax code and
603 nil) to be stored in syntax table. Since these objects can be
604 shared among syntax tables, we generate them in advance. By
605 sharing objects, the function `describe-syntax' can give a more
607 static Lisp_Object Vsyntax_code_object
;
610 /* Look up the value for CHARACTER in syntax table TABLE's parent
611 and its parents. SYNTAX_ENTRY calls this, when TABLE itself has nil
612 for CHARACTER. It's actually used only when not compiled with GCC. */
615 syntax_parent_lookup (table
, character
)
623 table
= XCHAR_TABLE (table
)->parent
;
627 value
= XCHAR_TABLE (table
)->contents
[character
];
633 DEFUN ("char-syntax", Fchar_syntax
, Schar_syntax
, 1, 1, 0,
634 "Return the syntax code of CHARACTER, described by a character.\n\
635 For example, if CHARACTER is a word constituent,\n\
636 the character `w' is returned.\n\
637 The characters that correspond to various syntax codes\n\
638 are listed in the documentation of `modify-syntax-entry'.")
640 Lisp_Object character
;
643 gl_state
.current_syntax_table
= current_buffer
->syntax_table
;
645 gl_state
.use_global
= 0;
646 CHECK_NUMBER (character
, 0);
647 char_int
= XINT (character
);
648 return make_number (syntax_code_spec
[(int) SYNTAX (char_int
)]);
651 DEFUN ("matching-paren", Fmatching_paren
, Smatching_paren
, 1, 1, 0,
652 "Return the matching parenthesis of CHARACTER, or nil if none.")
654 Lisp_Object character
;
657 gl_state
.current_syntax_table
= current_buffer
->syntax_table
;
658 gl_state
.use_global
= 0;
659 CHECK_NUMBER (character
, 0);
660 char_int
= XINT (character
);
661 code
= SYNTAX (char_int
);
662 if (code
== Sopen
|| code
== Sclose
)
663 return SYNTAX_MATCH (char_int
);
667 /* This comment supplies the doc string for modify-syntax-entry,
668 for make-docfile to see. We cannot put this in the real DEFUN
669 due to limits in the Unix cpp.
671 DEFUN ("modify-syntax-entry", foo, bar, 2, 3, 0,
672 "Set syntax for character CHAR according to string S.\n\
673 The syntax is changed only for table TABLE, which defaults to\n\
674 the current buffer's syntax table.\n\
675 The first character of S should be one of the following:\n\
676 Space or - whitespace syntax. w word constituent.\n\
677 _ symbol constituent. . punctuation.\n\
678 ( open-parenthesis. ) close-parenthesis.\n\
679 \" string quote. \\ escape.\n\
680 $ paired delimiter. ' expression quote or prefix operator.\n\
681 < comment starter. > comment ender.\n\
682 / character-quote. @ inherit from `standard-syntax-table'.\n\
684 Only single-character comment start and end sequences are represented thus.\n\
685 Two-character sequences are represented as described below.\n\
686 The second character of S is the matching parenthesis,\n\
687 used only if the first character is `(' or `)'.\n\
688 Any additional characters are flags.\n\
689 Defined flags are the characters 1, 2, 3, 4, b, and p.\n\
690 1 means CHAR is the start of a two-char comment start sequence.\n\
691 2 means CHAR is the second character of such a sequence.\n\
692 3 means CHAR is the start of a two-char comment end sequence.\n\
693 4 means CHAR is the second character of such a sequence.\n\
695 There can be up to two orthogonal comment sequences. This is to support\n\
696 language modes such as C++. By default, all comment sequences are of style\n\
697 a, but you can set the comment sequence style to b (on the second character\n\
698 of a comment-start, or the first character of a comment-end sequence) using\n\
700 b means CHAR is part of comment sequence b.\n\
702 p means CHAR is a prefix character for `backward-prefix-chars';\n\
703 such characters are treated as whitespace when they occur\n\
704 between expressions.")
708 DEFUN ("modify-syntax-entry", Fmodify_syntax_entry
, Smodify_syntax_entry
, 2, 3,
709 /* I really don't know why this is interactive
710 help-form should at least be made useful whilst reading the second arg
712 "cSet syntax for character: \nsSet syntax for %s to: ",
713 0 /* See immediately above */)
714 (c
, newentry
, syntax_table
)
715 Lisp_Object c
, newentry
, syntax_table
;
717 register unsigned char *p
;
718 register enum syntaxcode code
;
723 CHECK_STRING (newentry
, 1);
725 if (NILP (syntax_table
))
726 syntax_table
= current_buffer
->syntax_table
;
728 check_syntax_table (syntax_table
);
730 p
= XSTRING (newentry
)->data
;
731 code
= (enum syntaxcode
) syntax_spec_code
[*p
++];
732 if (((int) code
& 0377) == 0377)
733 error ("invalid syntax description letter: %c", p
[-1]);
735 if (code
== Sinherit
)
737 SET_RAW_SYNTAX_ENTRY (syntax_table
, XINT (c
), Qnil
);
744 int character
= STRING_CHAR_AND_LENGTH (p
, XSTRING (newentry
)->size
- 1,
746 XSETINT (match
, character
);
747 if (XFASTINT (match
) == ' ')
783 if (val
< XVECTOR (Vsyntax_code_object
)->size
&& NILP (match
))
784 newentry
= XVECTOR (Vsyntax_code_object
)->contents
[val
];
786 /* Since we can't use a shared object, let's make a new one. */
787 newentry
= Fcons (make_number (val
), match
);
789 SET_RAW_SYNTAX_ENTRY (syntax_table
, XINT (c
), newentry
);
794 /* Dump syntax table to buffer in human-readable format */
797 describe_syntax (value
)
800 register enum syntaxcode code
;
801 char desc
, match
, start1
, start2
, end1
, end2
, prefix
, comstyle
;
803 Lisp_Object first
, match_lisp
;
805 Findent_to (make_number (16), make_number (1));
809 insert_string ("default\n");
813 if (CHAR_TABLE_P (value
))
815 insert_string ("deeper char-table ...\n");
821 insert_string ("invalid\n");
825 first
= XCONS (value
)->car
;
826 match_lisp
= XCONS (value
)->cdr
;
828 if (!INTEGERP (first
) || !(NILP (match_lisp
) || INTEGERP (match_lisp
)))
830 insert_string ("invalid\n");
834 code
= (enum syntaxcode
) (XINT (first
) & 0377);
835 start1
= (XINT (first
) >> 16) & 1;
836 start2
= (XINT (first
) >> 17) & 1;
837 end1
= (XINT (first
) >> 18) & 1;
838 end2
= (XINT (first
) >> 19) & 1;
839 prefix
= (XINT (first
) >> 20) & 1;
840 comstyle
= (XINT (first
) >> 21) & 1;
842 if ((int) code
< 0 || (int) code
>= (int) Smax
)
844 insert_string ("invalid");
847 desc
= syntax_code_spec
[(int) code
];
849 str
[0] = desc
, str
[1] = 0;
852 if (NILP (match_lisp
))
855 insert_char (XINT (match_lisp
));
872 insert_string ("\twhich means: ");
874 switch (SWITCH_ENUM_CAST (code
))
877 insert_string ("whitespace"); break;
879 insert_string ("punctuation"); break;
881 insert_string ("word"); break;
883 insert_string ("symbol"); break;
885 insert_string ("open"); break;
887 insert_string ("close"); break;
889 insert_string ("quote"); break;
891 insert_string ("string"); break;
893 insert_string ("math"); break;
895 insert_string ("escape"); break;
897 insert_string ("charquote"); break;
899 insert_string ("comment"); break;
901 insert_string ("endcomment"); break;
903 insert_string ("invalid");
907 if (!NILP (match_lisp
))
909 insert_string (", matches ");
910 insert_char (XINT (match_lisp
));
914 insert_string (",\n\t is the first character of a comment-start sequence");
916 insert_string (",\n\t is the second character of a comment-start sequence");
919 insert_string (",\n\t is the first character of a comment-end sequence");
921 insert_string (",\n\t is the second character of a comment-end sequence");
923 insert_string (" (comment style b)");
926 insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
928 insert_string ("\n");
932 describe_syntax_1 (vector
)
935 struct buffer
*old
= current_buffer
;
936 set_buffer_internal (XBUFFER (Vstandard_output
));
937 describe_vector (vector
, Qnil
, describe_syntax
, 0, Qnil
, Qnil
, (int *) 0, 0);
938 while (! NILP (XCHAR_TABLE (vector
)->parent
))
940 vector
= XCHAR_TABLE (vector
)->parent
;
941 insert_string ("\nThe parent syntax table is:");
942 describe_vector (vector
, Qnil
, describe_syntax
, 0, Qnil
, Qnil
,
946 call0 (intern ("help-mode"));
947 set_buffer_internal (old
);
951 DEFUN ("describe-syntax", Fdescribe_syntax
, Sdescribe_syntax
, 0, 0, "",
952 "Describe the syntax specifications in the syntax table.\n\
953 The descriptions are inserted in a buffer, which is then displayed.")
956 internal_with_output_to_temp_buffer
957 ("*Help*", describe_syntax_1
, current_buffer
->syntax_table
);
962 int parse_sexp_ignore_comments
;
964 /* Return the position across COUNT words from FROM.
965 If that many words cannot be found before the end of the buffer, return 0.
966 COUNT negative means scan backward and stop at word beginning. */
968 scan_words (from
, count
)
969 register int from
, count
;
971 register int beg
= BEGV
;
972 register int end
= ZV
;
973 register enum syntaxcode code
;
980 SETUP_SYNTAX_TABLE (from
, count
);
991 UPDATE_SYNTAX_TABLE_FORWARD (from
);
992 ch0
= FETCH_CHAR (from
);
995 if (words_include_escapes
996 && (code
== Sescape
|| code
== Scharquote
))
1001 /* Now CH0 is a character which begins a word and FROM is the
1002 position of the next character. */
1005 if (from
== end
) break;
1006 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1007 ch1
= FETCH_CHAR (from
);
1008 code
= SYNTAX (ch1
);
1009 if (!(words_include_escapes
1010 && (code
== Sescape
|| code
== Scharquote
)))
1011 if (code
!= Sword
|| WORD_BOUNDARY_P (ch0
, ch1
))
1028 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1029 ch1
= FETCH_CHAR (from
);
1030 code
= SYNTAX (ch1
);
1031 if (words_include_escapes
1032 && (code
== Sescape
|| code
== Scharquote
))
1037 /* Now CH1 is a character which ends a word and FROM is the
1041 if (from
== beg
) break;
1044 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1045 ch0
= FETCH_CHAR (temp_pos
);
1046 code
= SYNTAX (ch0
);
1047 if (!(words_include_escapes
1048 && (code
== Sescape
|| code
== Scharquote
)))
1049 if (code
!= Sword
|| WORD_BOUNDARY_P (ch0
, ch1
))
1062 DEFUN ("forward-word", Fforward_word
, Sforward_word
, 1, 1, "p",
1063 "Move point forward ARG words (backward if ARG is negative).\n\
1064 Normally returns t.\n\
1065 If an edge of the buffer is reached, point is left there\n\
1066 and nil is returned.")
1071 CHECK_NUMBER (count
, 0);
1073 if (!(val
= scan_words (PT
, XINT (count
))))
1075 SET_PT (XINT (count
) > 0 ? ZV
: BEGV
);
1082 Lisp_Object
skip_chars ();
1084 DEFUN ("skip-chars-forward", Fskip_chars_forward
, Sskip_chars_forward
, 1, 2, 0,
1085 "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\
1086 STRING is like the inside of a `[...]' in a regular expression\n\
1087 except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\
1088 Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\
1089 With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\
1090 Returns the distance traveled, either zero or positive.")
1092 Lisp_Object string
, lim
;
1094 return skip_chars (1, 0, string
, lim
);
1097 DEFUN ("skip-chars-backward", Fskip_chars_backward
, Sskip_chars_backward
, 1, 2, 0,
1098 "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\
1099 See `skip-chars-forward' for details.\n\
1100 Returns the distance traveled, either zero or negative.")
1102 Lisp_Object string
, lim
;
1104 return skip_chars (0, 0, string
, lim
);
1107 DEFUN ("skip-syntax-forward", Fskip_syntax_forward
, Sskip_syntax_forward
, 1, 2, 0,
1108 "Move point forward across chars in specified syntax classes.\n\
1109 SYNTAX is a string of syntax code characters.\n\
1110 Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\
1111 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1112 This function returns the distance traveled, either zero or positive.")
1114 Lisp_Object syntax
, lim
;
1116 return skip_chars (1, 1, syntax
, lim
);
1119 DEFUN ("skip-syntax-backward", Fskip_syntax_backward
, Sskip_syntax_backward
, 1, 2, 0,
1120 "Move point backward across chars in specified syntax classes.\n\
1121 SYNTAX is a string of syntax code characters.\n\
1122 Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\
1123 If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\
1124 This function returns the distance traveled, either zero or negative.")
1126 Lisp_Object syntax
, lim
;
1128 return skip_chars (0, 1, syntax
, lim
);
1132 skip_chars (forwardp
, syntaxp
, string
, lim
)
1133 int forwardp
, syntaxp
;
1134 Lisp_Object string
, lim
;
1136 register unsigned char *p
, *pend
;
1137 register unsigned int c
;
1139 unsigned char fastmap
[0400];
1140 /* If SYNTAXP is 0, STRING may contain multi-byte form of characters
1141 of which codes don't fit in FASTMAP. In that case, we set the
1142 first byte of multibyte form (i.e. base leading-code) in FASTMAP
1143 and set the actual ranges of characters in CHAR_RANGES. In the
1144 form "X-Y" of STRING, both X and Y must belong to the same
1145 character set because a range striding across character sets is
1148 int n_char_ranges
= 0;
1151 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
1153 CHECK_STRING (string
, 0);
1154 char_ranges
= (int *) alloca (XSTRING (string
)->size
* (sizeof (int)) * 2);
1157 XSETINT (lim
, forwardp
? ZV
: BEGV
);
1159 CHECK_NUMBER_COERCE_MARKER (lim
, 1);
1161 /* In any case, don't allow scan outside bounds of buffer. */
1162 /* jla turned this off, for no known reason.
1163 bfox turned the ZV part on, and rms turned the
1164 BEGV part back on. */
1165 if (XINT (lim
) > ZV
)
1166 XSETFASTINT (lim
, ZV
);
1167 if (XINT (lim
) < BEGV
)
1168 XSETFASTINT (lim
, BEGV
);
1170 p
= XSTRING (string
)->data
;
1171 pend
= p
+ XSTRING (string
)->size
;
1172 bzero (fastmap
, sizeof fastmap
);
1174 if (p
!= pend
&& *p
== '^')
1179 /* Find the characters specified and set their elements of fastmap.
1180 If syntaxp, each character counts as itself.
1181 Otherwise, handle backslashes and ranges specially. */
1188 ch
= STRING_CHAR (p
, pend
- p
);
1189 p
+= BYTES_BY_CHAR_HEAD (*p
);
1197 fastmap
[syntax_spec_code
[c
]] = 1;
1202 if (p
== pend
) break;
1205 if (p
!= pend
&& *p
== '-')
1210 if (p
== pend
) break;
1211 if (SINGLE_BYTE_CHAR_P (ch
))
1219 fastmap
[c
] = 1; /* C is the base leading-code. */
1220 ch2
= STRING_CHAR (p
, pend
- p
);
1222 char_ranges
[n_char_ranges
++] = ch
,
1223 char_ranges
[n_char_ranges
++] = ch2
;
1225 p
+= multibyte
? BYTES_BY_CHAR_HEAD (*p
) : 1;
1230 if (!SINGLE_BYTE_CHAR_P (ch
))
1232 char_ranges
[n_char_ranges
++] = ch
;
1233 char_ranges
[n_char_ranges
++] = ch
;
1239 /* If ^ was the first character, complement the fastmap. In
1240 addition, as all multibyte characters have possibility of
1241 matching, set all entries for base leading codes, which is
1242 harmless even if SYNTAXP is 1. */
1245 for (i
= 0; i
< sizeof fastmap
; i
++)
1247 if (!multibyte
|| !BASE_LEADING_CODE_P (i
))
1254 int start_point
= PT
;
1260 SETUP_SYNTAX_TABLE (pos
, forwardp
? 1 : -1);
1265 while (pos
< XINT (lim
)
1266 && fastmap
[(int) SYNTAX (FETCH_CHAR (pos
))])
1269 UPDATE_SYNTAX_TABLE_FORWARD (pos
);
1274 while (pos
< XINT (lim
)
1275 && fastmap
[(int) SYNTAX (FETCH_BYTE (pos
))])
1278 UPDATE_SYNTAX_TABLE_FORWARD (pos
);
1286 while (pos
> XINT (lim
))
1290 UPDATE_SYNTAX_TABLE_BACKWARD (pos
);
1291 if (!fastmap
[(int) SYNTAX (FETCH_CHAR (pos
))])
1300 while (pos
> XINT (lim
))
1303 UPDATE_SYNTAX_TABLE_BACKWARD (pos
);
1304 if (!fastmap
[(int) SYNTAX (FETCH_BYTE (pos
))])
1318 while (pos
< XINT (lim
) && fastmap
[(c
= FETCH_BYTE (pos
))])
1320 if (!BASE_LEADING_CODE_P (c
))
1322 else if (n_char_ranges
)
1324 /* We much check CHAR_RANGES for a multibyte
1326 ch
= FETCH_MULTIBYTE_CHAR (pos
);
1327 for (i
= 0; i
< n_char_ranges
; i
+= 2)
1328 if ((ch
>= char_ranges
[i
] && ch
<= char_ranges
[i
+ 1]))
1330 if (!(negate
^ (i
< n_char_ranges
)))
1342 while (pos
< XINT (lim
) && fastmap
[FETCH_BYTE (pos
)])
1348 while (pos
> XINT (lim
))
1352 if (fastmap
[(c
= FETCH_BYTE (pos
))])
1354 if (!BASE_LEADING_CODE_P (c
))
1356 else if (n_char_ranges
)
1358 /* We much check CHAR_RANGES for a multibyte
1360 ch
= FETCH_MULTIBYTE_CHAR (pos
);
1361 for (i
= 0; i
< n_char_ranges
; i
+= 2)
1362 if (ch
>= char_ranges
[i
] && ch
<= char_ranges
[i
+ 1])
1364 if (!(negate
^ (i
< n_char_ranges
)))
1384 while (pos
> XINT (lim
) && fastmap
[FETCH_BYTE (pos
- 1)])
1390 /* INC_POS or DEC_POS might have moved POS over LIM. */
1391 && (forwardp
? (pos
> XINT (lim
)) : (pos
< XINT (lim
))))
1397 return make_number (PT
- start_point
);
1401 DEFUN ("forward-comment", Fforward_comment
, Sforward_comment
, 1, 1, 0,
1402 "Move forward across up to N comments. If N is negative, move backward.\n\
1403 Stop scanning if we find something other than a comment or whitespace.\n\
1404 Set point to where scanning stops.\n\
1405 If N comments are found as expected, with nothing except whitespace\n\
1406 between them, return t; otherwise return nil.")
1413 register enum syntaxcode code
;
1414 int comstyle
= 0; /* style of comment encountered */
1419 CHECK_NUMBER (count
, 0);
1420 count1
= XINT (count
);
1421 stop
= count1
> 0 ? ZV
: BEGV
;
1428 SETUP_SYNTAX_TABLE (from
, count1
);
1439 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1440 c
= FETCH_CHAR (from
);
1444 if (from
< stop
&& SYNTAX_COMSTART_FIRST (c
)
1445 && (c1
= FETCH_CHAR (from
),
1446 SYNTAX_COMSTART_SECOND (c1
)))
1448 /* We have encountered a comment start sequence and we
1449 are ignoring all text inside comments. We must record
1450 the comment style this sequence begins so that later,
1451 only a comment end of the same style actually ends
1452 the comment section. */
1454 comstyle
= SYNTAX_COMMENT_STYLE (c1
);
1458 while (code
== Swhitespace
|| code
== Sendcomment
);
1459 if (code
!= Scomment
&& code
!= Scomment_fence
)
1466 /* We're at the start of a comment. */
1475 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1476 c
= FETCH_CHAR (from
);
1478 if (SYNTAX (c
) == Sendcomment
1479 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
1480 /* we have encountered a comment end of the same style
1481 as the comment sequence which began this comment
1484 if (SYNTAX (c
) == Scomment_fence
1485 && comstyle
== ST_COMMENT_STYLE
)
1486 /* we have encountered a comment end of the same style
1487 as the comment sequence which began this comment
1490 if (from
< stop
&& SYNTAX_COMEND_FIRST (c
)
1491 && (c1
= FETCH_CHAR (from
),
1492 SYNTAX_COMEND_SECOND (c1
))
1493 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
1494 /* we have encountered a comment end of the same style
1495 as the comment sequence which began this comment
1497 { INC_POS (from
); break; }
1499 /* We have skipped one comment. */
1516 quoted
= char_quoted (from
);
1520 goto leave
; /* ????? XXXXX */
1522 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1523 c
= FETCH_CHAR (from
);
1526 if (code
== Sendcomment
)
1527 comstyle
= SYNTAX_COMMENT_STYLE (c
);
1530 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
1531 && (c1
= FETCH_CHAR (temp_pos
),
1532 SYNTAX_COMEND_FIRST (c1
))
1533 && !char_quoted (temp_pos
))
1535 /* We must record the comment style encountered so that
1536 later, we can match only the proper comment begin
1537 sequence of the same style. */
1539 comstyle
= SYNTAX_COMMENT_STYLE (c1
);
1542 if (from
> stop
&& SYNTAX_COMSTART_SECOND (c
)
1543 && (c1
= FETCH_CHAR (temp_pos
),
1544 SYNTAX_COMSTART_FIRST (c1
))
1545 && !char_quoted (temp_pos
))
1547 /* We must record the comment style encountered so that
1548 later, we can match only the proper comment begin
1549 sequence of the same style. */
1554 if (code
== Scomment_fence
)
1556 /* Skip until first preceding unquoted comment_fence. */
1557 int found
= 0, ini
= from
;
1559 while (--from
!= stop
)
1561 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1562 c
= FETCH_CHAR (from
);
1563 if (SYNTAX (c
) == Scomment_fence
&& !char_quoted (from
))
1571 from
= ini
; /* Set point to ini + 1. */
1575 else if (code
== Sendcomment
)
1578 if (code
!= SYNTAX (c
))
1579 /* For a two-char comment ender, we can assume
1580 it does end a comment. So scan back in a simple way. */
1582 if (from
!= stop
) DEC_POS (from
);
1585 if ((c
= FETCH_CHAR (from
),
1586 SYNTAX (c
) == Scomment
)
1587 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
1596 if (SYNTAX_COMSTART_SECOND (c
)
1597 && (c1
= FETCH_CHAR (from
),
1598 SYNTAX_COMSTART_FIRST (c1
))
1599 && SYNTAX_COMMENT_STYLE (c
) == comstyle
1600 && !char_quoted (from
))
1606 found
= back_comment (from
, stop
, comstyle
);
1607 if (found
!= -1) from
= found
;
1609 /* Look back, counting the parity of string-quotes,
1610 and recording the comment-starters seen.
1611 When we reach a safe place, assume that's not in a string;
1612 then step the main scan to the earliest comment-starter seen
1613 an even number of string quotes away from the safe place.
1615 OFROM[I] is position of the earliest comment-starter seen
1616 which is I+2X quotes from the comment-end.
1617 PARITY is current parity of quotes from the comment end. */
1620 char my_stringend
= 0;
1621 int string_lossage
= 0;
1622 int comment_end
= from
;
1623 int comstart_pos
= 0;
1624 int comstart_parity
= 0;
1625 int scanstart
= from
;
1627 DEC_POS (scanstart
);
1628 /* At beginning of range to scan, we're outside of strings;
1629 that determines quote parity to the comment-end. */
1630 while (from
!= stop
)
1632 /* Move back and examine a character. */
1635 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1636 c
= FETCH_CHAR (from
);
1639 /* If this char is the second of a 2-char comment sequence,
1640 back up and give the pair the appropriate syntax. */
1643 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
1644 && (c1
= FETCH_CHAR (temp_pos
),
1645 SYNTAX_COMEND_FIRST (c1
)))
1654 /* If this char starts a 2-char comment start sequence,
1655 treat it like a 1-char comment starter. */
1656 if (from
< scanstart
&& SYNTAX_COMSTART_FIRST (c
)
1657 && (c1
= FETCH_CHAR (temp_pos
),
1658 SYNTAX_COMSTART_SECOND (c1
))
1659 && comstyle
== SYNTAX_COMMENT_STYLE (c1
))
1662 /* Ignore escaped characters. */
1663 if (char_quoted (from
))
1666 /* Track parity of quotes. */
1667 if (code
== Sstring
)
1670 if (my_stringend
== 0)
1672 /* If we have two kinds of string delimiters.
1673 There's no way to grok this scanning backwards. */
1674 else if (my_stringend
!= c
)
1678 /* Record comment-starters according to that
1679 quote-parity to the comment-end. */
1680 if (code
== Scomment
)
1682 comstart_parity
= parity
;
1683 comstart_pos
= from
;
1686 /* If we find another earlier comment-ender,
1687 any comment-starts earlier than that don't count
1688 (because they go with the earlier comment-ender). */
1689 if (code
== Sendcomment
1690 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)) == comstyle
)
1693 /* Assume a defun-start point is outside of strings. */
1695 && (from
== stop
|| FETCH_BYTE (from
- 1) == '\n'))
1699 if (comstart_pos
== 0)
1701 /* If the earliest comment starter
1702 is followed by uniform paired string quotes or none,
1703 we know it can't be inside a string
1704 since if it were then the comment ender would be inside one.
1705 So it does start a comment. Skip back to it. */
1706 else if (comstart_parity
== 0 && !string_lossage
)
1707 from
= comstart_pos
;
1710 /* We had two kinds of string delimiters mixed up
1711 together. Decode this going forwards.
1712 Scan fwd from the previous comment ender
1713 to the one in question; this records where we
1714 last passed a comment starter. */
1715 struct lisp_parse_state state
;
1716 scan_sexps_forward (&state
, find_defun_start (comment_end
),
1717 comment_end
- 1, -10000, 0, Qnil
, 0);
1718 if (state
.incomment
)
1719 from
= state
.comstr_start
;
1721 /* We can't grok this as a comment; scan it normally. */
1726 /* We have skipped one comment. */
1729 else if (code
!= Swhitespace
&& code
!= Scomment
)
1748 scan_lists (from
, count
, depth
, sexpflag
)
1750 int count
, depth
, sexpflag
;
1753 register int stop
= count
> 0 ? ZV
: BEGV
;
1758 register enum syntaxcode code
, temp_code
;
1759 int min_depth
= depth
; /* Err out if depth gets less than this. */
1760 int comstyle
= 0; /* style of comment encountered */
1762 int last_good
= from
;
1765 if (depth
> 0) min_depth
= 0;
1770 SETUP_SYNTAX_TABLE (from
, count
);
1775 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1776 c
= FETCH_CHAR (from
);
1778 if (depth
== min_depth
)
1781 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1782 if (from
< stop
&& SYNTAX_COMSTART_FIRST (c
)
1783 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
))
1784 && parse_sexp_ignore_comments
)
1786 /* we have encountered a comment start sequence and we
1787 are ignoring all text inside comments. We must record
1788 the comment style this sequence begins so that later,
1789 only a comment end of the same style actually ends
1790 the comment section */
1792 comstyle
= SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
));
1796 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1797 if (SYNTAX_PREFIX (c
))
1800 switch (SWITCH_ENUM_CAST (code
))
1804 if (from
== stop
) goto lose
;
1806 /* treat following character as a word constituent */
1809 if (depth
|| !sexpflag
) break;
1810 /* This word counts as a sexp; return at end of it. */
1813 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1814 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from
))))
1819 if (from
== stop
) goto lose
;
1833 case Scomment_fence
:
1834 if (!parse_sexp_ignore_comments
) break;
1843 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1844 c
= FETCH_CHAR (from
);
1845 if (code
== Scomment
1846 ? (SYNTAX (c
) == Sendcomment
1847 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
1848 : (SYNTAX (c
) == Scomment_fence
))
1849 /* we have encountered a comment end of the same style
1850 as the comment sequence which began this comment
1854 if (from
< stop
&& SYNTAX_COMEND_FIRST (c
)
1855 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
))
1856 && SYNTAX_COMMENT_STYLE (c
) == comstyle
1857 && code
== Scomment
)
1858 /* we have encountered a comment end of the same style
1859 as the comment sequence which began this comment
1861 { INC_POS (from
); break; }
1868 if (from
!= stop
&& c
== FETCH_CHAR (from
))
1878 if (!++depth
) goto done
;
1883 if (!--depth
) goto done
;
1884 if (depth
< min_depth
)
1885 Fsignal (Qscan_error
,
1886 Fcons (build_string ("Containing expression ends prematurely"),
1887 Fcons (make_number (last_good
),
1888 Fcons (make_number (from
), Qnil
))));
1895 stringterm
= FETCH_CHAR (temp_pos
);
1898 if (from
>= stop
) goto lose
;
1899 UPDATE_SYNTAX_TABLE_FORWARD (from
);
1901 ? (FETCH_CHAR (from
) == stringterm
)
1902 : SYNTAX (FETCH_CHAR (from
)) == Sstring_fence
)
1904 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from
))))
1913 if (!depth
&& sexpflag
) goto done
;
1918 /* Reached end of buffer. Error if within object, return nil if between */
1919 if (depth
) goto lose
;
1924 /* End of object reached */
1934 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1935 if (quoted
= char_quoted (from
))
1938 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
1940 c
= FETCH_CHAR (from
);
1942 if (depth
== min_depth
)
1945 if (code
== Sendcomment
)
1946 comstyle
= SYNTAX_COMMENT_STYLE (c
);
1949 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
1950 && (c1
= FETCH_CHAR (temp_pos
), SYNTAX_COMEND_FIRST (c1
))
1951 && !char_quoted (temp_pos
)
1952 && parse_sexp_ignore_comments
)
1954 /* we must record the comment style encountered so that
1955 later, we can match only the proper comment begin
1956 sequence of the same style */
1958 comstyle
= SYNTAX_COMMENT_STYLE (c1
);
1962 if (SYNTAX_PREFIX (c
))
1965 switch (SWITCH_ENUM_CAST (quoted
? Sword
: code
))
1969 if (depth
|| !sexpflag
) break;
1970 /* This word counts as a sexp; count object finished
1971 after passing it. */
1976 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos
);
1977 quoted
= char_quoted (temp_pos
);
1982 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos
);
1984 c1
= FETCH_CHAR (temp_pos
);
1985 temp_code
= SYNTAX (c1
);
1986 if (! (quoted
|| temp_code
== Sword
1987 || temp_code
== Ssymbol
1988 || temp_code
== Squote
))
1999 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos
);
2000 if (from
!= stop
&& c
== FETCH_CHAR (temp_pos
))
2010 if (!++depth
) goto done2
;
2015 if (!--depth
) goto done2
;
2016 if (depth
< min_depth
)
2017 Fsignal (Qscan_error
,
2018 Fcons (build_string ("Containing expression ends prematurely"),
2019 Fcons (make_number (last_good
),
2020 Fcons (make_number (from
), Qnil
))));
2024 if (!parse_sexp_ignore_comments
)
2027 if (code
!= SYNTAX (c
))
2028 /* For a two-char comment ender, we can assume
2029 it does end a comment. So scan back in a simple way. */
2031 if (from
!= stop
) DEC_POS (from
);
2034 if (SYNTAX (c
= FETCH_CHAR (from
)) == Scomment
2035 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
2044 if (SYNTAX_COMSTART_SECOND (c
)
2045 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
))
2046 && SYNTAX_COMMENT_STYLE (c
) == comstyle
2047 && !char_quoted (from
))
2053 found
= back_comment (from
, stop
, comstyle
);
2054 if (found
!= -1) from
= found
;
2056 /* Look back, counting the parity of string-quotes,
2057 and recording the comment-starters seen.
2058 When we reach a safe place, assume that's not in a string;
2059 then step the main scan to the earliest comment-starter seen
2060 an even number of string quotes away from the safe place.
2062 OFROM[I] is position of the earliest comment-starter seen
2063 which is I+2X quotes from the comment-end.
2064 PARITY is current parity of quotes from the comment end. */
2067 char my_stringend
= 0;
2068 int string_lossage
= 0;
2069 int comment_end
= from
;
2070 int comstart_pos
= 0;
2071 int comstart_parity
= 0;
2072 int scanstart
= from
;
2074 DEC_POS (scanstart
);
2076 /* At beginning of range to scan, we're outside of strings;
2077 that determines quote parity to the comment-end. */
2078 while (from
!= stop
)
2080 /* Move back and examine a character. */
2083 c
= FETCH_CHAR (from
);
2086 /* If this char is the second of a 2-char comment sequence,
2087 back up and give the pair the appropriate syntax. */
2090 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
2091 && (c1
= FETCH_CHAR (temp_pos
),
2092 SYNTAX_COMEND_FIRST (c1
)))
2099 /* If this char starts a 2-char comment start sequence,
2100 treat it like a 1-char comment starter. */
2103 if (from
< scanstart
&& SYNTAX_COMSTART_FIRST (c
)
2104 && (c1
= FETCH_CHAR (temp_pos
),
2105 SYNTAX_COMSTART_SECOND (c1
))
2106 && comstyle
== SYNTAX_COMMENT_STYLE (c1
))
2109 /* Ignore escaped characters. */
2110 if (char_quoted (from
))
2113 /* Track parity of quotes. */
2114 if (code
== Sstring
)
2117 if (my_stringend
== 0)
2119 /* If we have two kinds of string delimiters.
2120 There's no way to grok this scanning backwards. */
2121 else if (my_stringend
!= c
)
2125 /* Record comment-starters according to that
2126 quote-parity to the comment-end. */
2127 if (code
== Scomment
)
2129 comstart_parity
= parity
;
2130 comstart_pos
= from
;
2133 /* If we find another earlier comment-ender,
2134 any comment-starts earlier than that don't count
2135 (because they go with the earlier comment-ender). */
2136 if (code
== Sendcomment
2137 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)) == comstyle
)
2140 /* Assume a defun-start point is outside of strings. */
2142 && (from
== stop
|| FETCH_BYTE (from
- 1) == '\n'))
2146 if (comstart_pos
== 0)
2148 /* If the earliest comment starter
2149 is followed by uniform paired string quotes or none,
2150 we know it can't be inside a string
2151 since if it were then the comment ender would be inside one.
2152 So it does start a comment. Skip back to it. */
2153 else if (comstart_parity
== 0 && !string_lossage
)
2154 from
= comstart_pos
;
2157 /* We had two kinds of string delimiters mixed up
2158 together. Decode this going forwards.
2159 Scan fwd from the previous comment ender
2160 to the one in question; this records where we
2161 last passed a comment starter. */
2162 struct lisp_parse_state state
;
2163 scan_sexps_forward (&state
, find_defun_start (comment_end
),
2164 comment_end
- 1, -10000, 0, Qnil
, 0);
2165 if (state
.incomment
)
2166 from
= state
.comstr_start
;
2168 /* We can't grok this as a comment; scan it normally. */
2175 case Scomment_fence
:
2180 if (from
== stop
) goto lose
;
2181 UPDATE_SYNTAX_TABLE_BACKWARD (from
);
2182 if (!char_quoted (from
)
2183 && SYNTAX (FETCH_CHAR (from
)) == code
)
2186 if (code
== Sstring_fence
&& !depth
&& sexpflag
) goto done2
;
2190 stringterm
= FETCH_CHAR (from
);
2193 if (from
== stop
) goto lose
;
2196 UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos
);
2197 if (!char_quoted (temp_pos
)
2198 && stringterm
== FETCH_CHAR (temp_pos
))
2203 if (!depth
&& sexpflag
) goto done2
;
2208 /* Reached start of buffer. Error if within object, return nil if between */
2209 if (depth
) goto lose
;
2220 XSETFASTINT (val
, from
);
2224 Fsignal (Qscan_error
,
2225 Fcons (build_string ("Unbalanced parentheses"),
2226 Fcons (make_number (last_good
),
2227 Fcons (make_number (from
), Qnil
))));
2232 DEFUN ("scan-lists", Fscan_lists
, Sscan_lists
, 3, 3, 0,
2233 "Scan from character number FROM by COUNT lists.\n\
2234 Returns the character number of the position thus found.\n\
2236 If DEPTH is nonzero, paren depth begins counting from that value,\n\
2237 only places where the depth in parentheses becomes zero\n\
2238 are candidates for stopping; COUNT such places are counted.\n\
2239 Thus, a positive value for DEPTH means go out levels.\n\
2241 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
2243 If the beginning or end of (the accessible part of) the buffer is reached\n\
2244 and the depth is wrong, an error is signaled.\n\
2245 If the depth is right but the count is not used up, nil is returned.")
2246 (from
, count
, depth
)
2247 Lisp_Object from
, count
, depth
;
2249 CHECK_NUMBER (from
, 0);
2250 CHECK_NUMBER (count
, 1);
2251 CHECK_NUMBER (depth
, 2);
2253 return scan_lists (XINT (from
), XINT (count
), XINT (depth
), 0);
2256 DEFUN ("scan-sexps", Fscan_sexps
, Sscan_sexps
, 2, 2, 0,
2257 "Scan from character number FROM by COUNT balanced expressions.\n\
2258 If COUNT is negative, scan backwards.\n\
2259 Returns the character number of the position thus found.\n\
2261 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
2263 If the beginning or end of (the accessible part of) the buffer is reached\n\
2264 in the middle of a parenthetical grouping, an error is signaled.\n\
2265 If the beginning or end is reached between groupings\n\
2266 but before count is used up, nil is returned.")
2268 Lisp_Object from
, count
;
2270 CHECK_NUMBER (from
, 0);
2271 CHECK_NUMBER (count
, 1);
2273 return scan_lists (XINT (from
), XINT (count
), 0, 1);
2276 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars
, Sbackward_prefix_chars
,
2278 "Move point backward over any number of chars with prefix syntax.\n\
2279 This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
2289 SETUP_SYNTAX_TABLE (pos
, -1);
2293 while (pos
> beg
&& !char_quoted (temp_pos
)
2294 /* Previous statement updates syntax table. */
2295 && ((c
= FETCH_CHAR (temp_pos
), SYNTAX (c
) == Squote
)
2296 || SYNTAX_PREFIX (c
)))
2307 /* Parse forward from FROM to END,
2308 assuming that FROM has state OLDSTATE (nil means FROM is start of function),
2309 and return a description of the state of the parse at END.
2310 If STOPBEFORE is nonzero, stop at the start of an atom.
2311 If COMMENTSTOP is 1, stop at the start of a comment.
2312 If COMMENTSTOP is -1, stop at the start or end of a comment,
2313 after the beginning of a string, or after the end of a string. */
2316 scan_sexps_forward (stateptr
, from
, end
, targetdepth
,
2317 stopbefore
, oldstate
, commentstop
)
2318 struct lisp_parse_state
*stateptr
;
2320 int end
, targetdepth
, stopbefore
;
2321 Lisp_Object oldstate
;
2324 struct lisp_parse_state state
;
2326 register enum syntaxcode code
;
2327 struct level
{ int last
, prev
; };
2328 struct level levelstart
[100];
2329 register struct level
*curlevel
= levelstart
;
2330 struct level
*endlevel
= levelstart
+ 100;
2332 register int depth
; /* Paren depth of current scanning location.
2333 level - levelstart equals this except
2334 when the depth becomes negative. */
2335 int mindepth
; /* Lowest DEPTH value seen. */
2336 int start_quoted
= 0; /* Nonzero means starting after a char quote */
2338 int prev_from
; /* Keep one character before FROM. */
2339 int boundary_stop
= commentstop
== -1;
2343 DEC_POS (prev_from
);
2345 /* Use this macro instead of `from++'. */
2346 #define INC_FROM do { prev_from = from; INC_POS (from); } while (0)
2351 SETUP_SYNTAX_TABLE (from
, 1);
2353 if (NILP (oldstate
))
2356 state
.instring
= -1;
2357 state
.incomment
= 0;
2358 state
.comstyle
= 0; /* comment style a by default. */
2359 state
.comstr_start
= -1; /* no comment/string seen. */
2363 tem
= Fcar (oldstate
);
2369 oldstate
= Fcdr (oldstate
);
2370 oldstate
= Fcdr (oldstate
);
2371 oldstate
= Fcdr (oldstate
);
2372 tem
= Fcar (oldstate
);
2373 /* Check whether we are inside string_fence-style string: */
2374 state
.instring
= ( !NILP (tem
)
2375 ? ( INTEGERP (tem
) ? XINT (tem
) : ST_STRING_STYLE
)
2378 oldstate
= Fcdr (oldstate
);
2379 tem
= Fcar (oldstate
);
2380 state
.incomment
= !NILP (tem
);
2382 oldstate
= Fcdr (oldstate
);
2383 tem
= Fcar (oldstate
);
2384 start_quoted
= !NILP (tem
);
2386 /* if the eight element of the list is nil, we are in comment
2387 style a. If it is non-nil, we are in comment style b */
2388 oldstate
= Fcdr (oldstate
);
2389 oldstate
= Fcdr (oldstate
);
2390 tem
= Fcar (oldstate
);
2391 state
.comstyle
= NILP (tem
) ? 0 : ( EQ (tem
, Qsyntax_table
)
2392 ? ST_COMMENT_STYLE
: 1 );
2394 oldstate
= Fcdr (oldstate
);
2395 tem
= Fcar (oldstate
);
2396 state
.comstr_start
= NILP (tem
) ? -1 : XINT (tem
) ;
2401 curlevel
->prev
= -1;
2402 curlevel
->last
= -1;
2404 /* Enter the loop at a place appropriate for initial state. */
2406 if (state
.incomment
) goto startincomment
;
2407 if (state
.instring
>= 0)
2409 nofence
= state
.instring
!= ST_STRING_STYLE
;
2410 if (start_quoted
) goto startquotedinstring
;
2413 if (start_quoted
) goto startquoted
;
2417 UPDATE_SYNTAX_TABLE_FORWARD (from
);
2418 code
= SYNTAX (FETCH_CHAR (from
));
2421 if (code
== Scomment
)
2422 state
.comstr_start
= prev_from
;
2423 else if (code
== Scomment_fence
)
2425 /* Record the comment style we have entered so that only
2426 the comment-end sequence of the same style actually
2427 terminates the comment section. */
2428 state
.comstyle
= ( code
== Scomment_fence
2430 : SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)));
2431 state
.comstr_start
= prev_from
;
2432 if (code
!= Scomment_fence
) INC_FROM
;
2435 else if (from
< end
)
2436 if (SYNTAX_COMSTART_FIRST (FETCH_CHAR (prev_from
)))
2437 if (SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
)))
2438 /* Duplicate code to avoid a very complex if-expression
2439 which causes trouble for the SGI compiler. */
2441 /* Record the comment style we have entered so that only
2442 the comment-end sequence of the same style actually
2443 terminates the comment section. */
2444 state
.comstyle
= ( code
== Scomment_fence
2446 : SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)));
2447 state
.comstr_start
= prev_from
;
2448 if (code
!= Scomment_fence
) INC_FROM
;
2452 if (SYNTAX_PREFIX (FETCH_CHAR (prev_from
)))
2454 switch (SWITCH_ENUM_CAST (code
))
2458 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
2459 curlevel
->last
= prev_from
;
2461 if (from
== end
) goto endquoted
;
2464 /* treat following character as a word constituent */
2467 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
2468 curlevel
->last
= prev_from
;
2472 UPDATE_SYNTAX_TABLE_FORWARD (from
);
2473 switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from
))))
2478 if (from
== end
) goto endquoted
;
2490 curlevel
->prev
= curlevel
->last
;
2494 if (commentstop
== 1)
2498 /* Enter the loop in the middle so that we find
2499 a 2-char comment ender if we start in the middle of it. */
2500 prev
= FETCH_CHAR (prev_from
);
2501 goto startincomment_1
;
2503 /* At beginning of buffer, enter the loop the ordinary way. */
2504 state
.incomment
= 1;
2508 state
.incomment
= 1;
2509 if (commentstop
|| boundary_stop
) goto done
;
2513 if (from
== end
) goto done
;
2514 UPDATE_SYNTAX_TABLE_FORWARD (from
);
2515 prev
= FETCH_CHAR (from
);
2516 if (SYNTAX (prev
) == Sendcomment
2517 && SYNTAX_COMMENT_STYLE (prev
) == state
.comstyle
)
2518 /* Only terminate the comment section if the endcomment
2519 of the same style as the start sequence has been
2522 if (state
.comstyle
== ST_COMMENT_STYLE
2523 && SYNTAX (prev
) == Scomment_fence
)
2527 if (from
< end
&& SYNTAX_COMEND_FIRST (prev
)
2528 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
))
2529 && SYNTAX_COMMENT_STYLE (prev
) == state
.comstyle
)
2530 /* Only terminate the comment section if the end-comment
2531 sequence of the same style as the start sequence has
2532 been encountered. */
2536 state
.incomment
= 0;
2537 state
.comstyle
= 0; /* reset the comment style */
2538 if (boundary_stop
) goto done
;
2542 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
2544 /* curlevel++->last ran into compiler bug on Apollo */
2545 curlevel
->last
= prev_from
;
2546 if (++curlevel
== endlevel
)
2547 error ("Nesting too deep for parser");
2548 curlevel
->prev
= -1;
2549 curlevel
->last
= -1;
2550 if (targetdepth
== depth
) goto done
;
2555 if (depth
< mindepth
)
2557 if (curlevel
!= levelstart
)
2559 curlevel
->prev
= curlevel
->last
;
2560 if (targetdepth
== depth
) goto done
;
2565 state
.comstr_start
= from
- 1;
2566 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
2567 curlevel
->last
= prev_from
;
2568 state
.instring
= (code
== Sstring
2569 ? (FETCH_CHAR (prev_from
))
2571 if (boundary_stop
) goto done
;
2574 nofence
= state
.instring
!= ST_STRING_STYLE
;
2580 if (from
>= end
) goto done
;
2581 c
= FETCH_CHAR (from
);
2582 if (nofence
&& c
== state
.instring
) break;
2583 UPDATE_SYNTAX_TABLE_FORWARD (from
);
2584 switch (SWITCH_ENUM_CAST (SYNTAX (c
)))
2587 if (!nofence
) goto string_end
;
2592 startquotedinstring
:
2593 if (from
>= end
) goto endquoted
;
2599 state
.instring
= -1;
2600 curlevel
->prev
= curlevel
->last
;
2602 if (boundary_stop
) goto done
;
2611 stop
: /* Here if stopping before start of sexp. */
2612 from
= prev_from
; /* We have just fetched the char that starts it; */
2613 goto done
; /* but return the position before it. */
2618 state
.depth
= depth
;
2619 state
.mindepth
= mindepth
;
2620 state
.thislevelstart
= curlevel
->prev
;
2621 state
.prevlevelstart
2622 = (curlevel
== levelstart
) ? -1 : (curlevel
- 1)->last
;
2623 state
.location
= from
;
2629 /* This comment supplies the doc string for parse-partial-sexp,
2630 for make-docfile to see. We cannot put this in the real DEFUN
2631 due to limits in the Unix cpp.
2633 DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 6, 0,
2634 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
2635 Parsing stops at TO or when certain criteria are met;\n\
2636 point is set to where parsing stops.\n\
2637 If fifth arg STATE is omitted or nil,\n\
2638 parsing assumes that FROM is the beginning of a function.\n\
2639 Value is a list of nine elements describing final state of parsing:\n\
2640 0. depth in parens.\n\
2641 1. character address of start of innermost containing list; nil if none.\n\
2642 2. character address of start of last complete sexp terminated.\n\
2643 3. non-nil if inside a string.\n\
2644 (it is the character that will terminate the string,\n\
2645 or t if the string should be terminated by a generic string delimiter.)\n\
2646 4. t if inside a comment.\n\
2647 5. t if following a quote character.\n\
2648 6. the minimum paren-depth encountered during this scan.\n\
2649 7. t if in a comment of style b; `syntax-table' if the comment\n\
2650 should be terminated by a generic comment delimiter.\n\
2651 8. character address of start of comment or string; nil if not in one.\n\
2652 If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
2653 in parentheses becomes equal to TARGETDEPTH.\n\
2654 Fourth arg STOPBEFORE non-nil means stop when come to\n\
2655 any character that starts a sexp.\n\
2656 Fifth arg STATE is a nine-element list like what this function returns.\n\
2657 It is used to initialize the state of the parse. Elements number 1, 2, 6\n\
2658 and 8 are ignored; you can leave off element 8 (the last) entirely.\n\
2659 Sixth arg COMMENTSTOP non-nil means stop at the start of a comment.\n\
2660 If it is `syntax-table', stop after the start of a comment or a string,\n\
2661 or after end of a comment or a string.")
2662 (from, to, targetdepth, stopbefore, state, commentstop)
2665 DEFUN ("parse-partial-sexp", Fparse_partial_sexp
, Sparse_partial_sexp
, 2, 6, 0,
2666 0 /* See immediately above */)
2667 (from
, to
, targetdepth
, stopbefore
, oldstate
, commentstop
)
2668 Lisp_Object from
, to
, targetdepth
, stopbefore
, oldstate
, commentstop
;
2670 struct lisp_parse_state state
;
2673 if (!NILP (targetdepth
))
2675 CHECK_NUMBER (targetdepth
, 3);
2676 target
= XINT (targetdepth
);
2679 target
= -100000; /* We won't reach this depth */
2681 validate_region (&from
, &to
);
2682 scan_sexps_forward (&state
, XINT (from
), XINT (to
),
2683 target
, !NILP (stopbefore
), oldstate
,
2685 ? 0 : (EQ (commentstop
, Qsyntax_table
) ? -1 : 1)));
2687 SET_PT (state
.location
);
2689 return Fcons (make_number (state
.depth
),
2690 Fcons (state
.prevlevelstart
< 0 ? Qnil
: make_number (state
.prevlevelstart
),
2691 Fcons (state
.thislevelstart
< 0 ? Qnil
: make_number (state
.thislevelstart
),
2692 Fcons (state
.instring
>= 0
2693 ? (state
.instring
== ST_STRING_STYLE
2694 ? Qt
: make_number (state
.instring
)) : Qnil
,
2695 Fcons (state
.incomment
? Qt
: Qnil
,
2696 Fcons (state
.quoted
? Qt
: Qnil
,
2697 Fcons (make_number (state
.mindepth
),
2698 Fcons ((state
.comstyle
2699 ? (state
.comstyle
== ST_COMMENT_STYLE
2700 ? Qsyntax_table
: Qt
) :
2702 Fcons ((state
.incomment
|| state
.instring
2703 ? make_number (state
.comstr_start
)
2713 /* This has to be done here, before we call Fmake_char_table. */
2714 Qsyntax_table
= intern ("syntax-table");
2715 staticpro (&Qsyntax_table
);
2717 /* Intern this now in case it isn't already done.
2718 Setting this variable twice is harmless.
2719 But don't staticpro it here--that is done in alloc.c. */
2720 Qchar_table_extra_slots
= intern ("char-table-extra-slots");
2722 /* Create objects which can be shared among syntax tables. */
2723 Vsyntax_code_object
= Fmake_vector (make_number (13), Qnil
);
2724 for (i
= 0; i
< XVECTOR (Vsyntax_code_object
)->size
; i
++)
2725 XVECTOR (Vsyntax_code_object
)->contents
[i
]
2726 = Fcons (make_number (i
), Qnil
);
2728 /* Now we are ready to set up this property, so we can
2729 create syntax tables. */
2730 Fput (Qsyntax_table
, Qchar_table_extra_slots
, make_number (0));
2732 temp
= XVECTOR (Vsyntax_code_object
)->contents
[(int) Swhitespace
];
2734 Vstandard_syntax_table
= Fmake_char_table (Qsyntax_table
, temp
);
2736 temp
= XVECTOR (Vsyntax_code_object
)->contents
[(int) Sword
];
2737 for (i
= 'a'; i
<= 'z'; i
++)
2738 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, i
, temp
);
2739 for (i
= 'A'; i
<= 'Z'; i
++)
2740 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, i
, temp
);
2741 for (i
= '0'; i
<= '9'; i
++)
2742 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, i
, temp
);
2744 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '$', temp
);
2745 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '%', temp
);
2747 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '(',
2748 Fcons (make_number (Sopen
), make_number (')')));
2749 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, ')',
2750 Fcons (make_number (Sclose
), make_number ('(')));
2751 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '[',
2752 Fcons (make_number (Sopen
), make_number (']')));
2753 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, ']',
2754 Fcons (make_number (Sclose
), make_number ('[')));
2755 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '{',
2756 Fcons (make_number (Sopen
), make_number ('}')));
2757 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '}',
2758 Fcons (make_number (Sclose
), make_number ('{')));
2759 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '"',
2760 Fcons (make_number ((int) Sstring
), Qnil
));
2761 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, '\\',
2762 Fcons (make_number ((int) Sescape
), Qnil
));
2764 temp
= XVECTOR (Vsyntax_code_object
)->contents
[(int) Ssymbol
];
2765 for (i
= 0; i
< 10; i
++)
2767 c
= "_-+*/&|<>="[i
];
2768 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, c
, temp
);
2771 temp
= XVECTOR (Vsyntax_code_object
)->contents
[(int) Spunct
];
2772 for (i
= 0; i
< 12; i
++)
2774 c
= ".,;:?!#@~^'`"[i
];
2775 SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table
, c
, temp
);
2781 Qsyntax_table_p
= intern ("syntax-table-p");
2782 staticpro (&Qsyntax_table_p
);
2784 staticpro (&Vsyntax_code_object
);
2786 Qscan_error
= intern ("scan-error");
2787 staticpro (&Qscan_error
);
2788 Fput (Qscan_error
, Qerror_conditions
,
2789 Fcons (Qerror
, Qnil
));
2790 Fput (Qscan_error
, Qerror_message
,
2791 build_string ("Scan error"));
2793 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments
,
2794 "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
2796 DEFVAR_BOOL ("parse-sexp-lookup-properties", &parse_sexp_lookup_properties
,
2797 "Non-nil means `forward-sexp', etc., grant `syntax-table' property.\n\
2798 The value of this property should be either a syntax table, or a cons\n\
2799 of the form (SYNTAXCODE . MATCHCHAR), SYNTAXCODE being the numeric\n\
2800 syntax code, MATCHCHAR being nil or the character to match (which is\n\
2801 relevant only for open/close type.");
2803 words_include_escapes
= 0;
2804 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes
,
2805 "Non-nil means `forward-word', etc., should treat escape chars part of words.");
2807 defsubr (&Ssyntax_table_p
);
2808 defsubr (&Ssyntax_table
);
2809 defsubr (&Sstandard_syntax_table
);
2810 defsubr (&Scopy_syntax_table
);
2811 defsubr (&Sset_syntax_table
);
2812 defsubr (&Schar_syntax
);
2813 defsubr (&Smatching_paren
);
2814 defsubr (&Smodify_syntax_entry
);
2815 defsubr (&Sdescribe_syntax
);
2817 defsubr (&Sforward_word
);
2819 defsubr (&Sskip_chars_forward
);
2820 defsubr (&Sskip_chars_backward
);
2821 defsubr (&Sskip_syntax_forward
);
2822 defsubr (&Sskip_syntax_backward
);
2824 defsubr (&Sforward_comment
);
2825 defsubr (&Sscan_lists
);
2826 defsubr (&Sscan_sexps
);
2827 defsubr (&Sbackward_prefix_chars
);
2828 defsubr (&Sparse_partial_sexp
);