1 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985, 1987, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
28 Lisp_Object Qsyntax_table_p
;
30 int words_include_escapes
;
32 /* This is the internal form of the parse state used in parse-partial-sexp. */
34 struct lisp_parse_state
36 int depth
; /* Depth at end of parsing */
37 int instring
; /* -1 if not within string, else desired terminator. */
38 int incomment
; /* Nonzero if within a comment at end of parsing */
39 int comstyle
; /* comment style a=0, or b=1 */
40 int quoted
; /* Nonzero if just after an escape char at end of parsing */
41 int thislevelstart
; /* Char number of most recent start-of-expression at current level */
42 int prevlevelstart
; /* Char number of start of containing expression */
43 int location
; /* Char number at which parsing stopped. */
44 int mindepth
; /* Minimum depth seen while scanning. */
45 int comstart
; /* Position just after last comment starter. */
48 /* These variables are a cache for finding the start of a defun.
49 find_start_pos is the place for which the defun start was found.
50 find_start_value is the defun start position found for it.
51 find_start_buffer is the buffer it was found in.
52 find_start_begv is the BEGV value when it was found.
53 find_start_modiff is the value of MODIFF when it was found. */
55 static int find_start_pos
;
56 static int find_start_value
;
57 static struct buffer
*find_start_buffer
;
58 static int find_start_begv
;
59 static int find_start_modiff
;
61 /* Find a defun-start that is the last one before POS (or nearly the last).
62 We record what we find, so that another call in the same area
63 can return the same value right away. */
66 find_defun_start (pos
)
72 /* Use previous finding, if it's valid and applies to this inquiry. */
73 if (current_buffer
== find_start_buffer
74 /* Reuse the defun-start even if POS is a little farther on.
75 POS might be in the next defun, but that's ok.
76 Our value may not be the best possible, but will still be usable. */
77 && pos
<= find_start_pos
+ 1000
78 && pos
>= find_start_value
79 && BEGV
== find_start_begv
80 && MODIFF
== find_start_modiff
)
81 return find_start_value
;
83 /* Back up to start of line. */
84 tem
= scan_buffer ('\n', pos
, -1, &shortage
);
88 /* Open-paren at start of line means we found our defun-start. */
89 if (SYNTAX (FETCH_CHAR (tem
)) == Sopen
)
91 /* Move to beg of previous line. */
92 tem
= scan_buffer ('\n', tem
, -2, &shortage
);
95 /* Record what we found, for the next try. */
96 find_start_value
= tem
;
97 find_start_buffer
= current_buffer
;
98 find_start_modiff
= MODIFF
;
99 find_start_begv
= BEGV
;
100 find_start_pos
= pos
;
102 return find_start_value
;
105 DEFUN ("syntax-table-p", Fsyntax_table_p
, Ssyntax_table_p
, 1, 1, 0,
106 "Return t if ARG is a syntax table.\n\
107 Any vector of 256 elements will do.")
111 if (XTYPE (obj
) == Lisp_Vector
&& XVECTOR (obj
)->size
== 0400)
117 check_syntax_table (obj
)
120 register Lisp_Object tem
;
121 while (tem
= Fsyntax_table_p (obj
),
123 obj
= wrong_type_argument (Qsyntax_table_p
, obj
, 0);
128 DEFUN ("syntax-table", Fsyntax_table
, Ssyntax_table
, 0, 0, 0,
129 "Return the current syntax table.\n\
130 This is the one specified by the current buffer.")
133 return current_buffer
->syntax_table
;
136 DEFUN ("standard-syntax-table", Fstandard_syntax_table
,
137 Sstandard_syntax_table
, 0, 0, 0,
138 "Return the standard syntax table.\n\
139 This is the one used for new buffers.")
142 return Vstandard_syntax_table
;
145 DEFUN ("copy-syntax-table", Fcopy_syntax_table
, Scopy_syntax_table
, 0, 1, 0,
146 "Construct a new syntax table and return it.\n\
147 It is a copy of the TABLE, which defaults to the standard syntax table.")
151 Lisp_Object size
, val
;
152 XFASTINT (size
) = 0400;
154 val
= Fmake_vector (size
, val
);
156 table
= check_syntax_table (table
);
157 else if (NILP (Vstandard_syntax_table
))
158 /* Can only be null during initialization */
160 else table
= Vstandard_syntax_table
;
162 bcopy (XVECTOR (table
)->contents
,
163 XVECTOR (val
)->contents
, 0400 * sizeof (Lisp_Object
));
167 DEFUN ("set-syntax-table", Fset_syntax_table
, Sset_syntax_table
, 1, 1, 0,
168 "Select a new syntax table for the current buffer.\n\
169 One argument, a syntax table.")
173 table
= check_syntax_table (table
);
174 current_buffer
->syntax_table
= table
;
175 /* Indicate that this buffer now has a specified syntax table. */
176 current_buffer
->local_var_flags
|= buffer_local_flags
.syntax_table
;
180 /* Convert a letter which signifies a syntax code
181 into the code it signifies.
182 This is used by modify-syntax-entry, and other things. */
184 unsigned char syntax_spec_code
[0400] =
185 { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
186 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
187 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
188 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
189 (char) Swhitespace
, 0377, (char) Sstring
, 0377,
190 (char) Smath
, 0377, 0377, (char) Squote
,
191 (char) Sopen
, (char) Sclose
, 0377, 0377,
192 0377, (char) Swhitespace
, (char) Spunct
, (char) Scharquote
,
193 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
194 0377, 0377, 0377, 0377,
195 (char) Scomment
, 0377, (char) Sendcomment
, 0377,
196 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A, ... */
197 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
198 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
199 0377, 0377, 0377, 0377, (char) Sescape
, 0377, 0377, (char) Ssymbol
,
200 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */
201 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
202 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword
,
203 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377
206 /* Indexed by syntax code, give the letter that describes it. */
208 char syntax_code_spec
[13] =
210 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>'
213 DEFUN ("char-syntax", Fchar_syntax
, Schar_syntax
, 1, 1, 0,
214 "Return the syntax code of CHAR, described by a character.\n\
215 For example, if CHAR is a word constituent, the character `?w' is returned.\n\
216 The characters that correspond to various syntax codes\n\
217 are listed in the documentation of `modify-syntax-entry'.")
221 CHECK_NUMBER (ch
, 0);
222 return make_number (syntax_code_spec
[(int) SYNTAX (0xFF & XINT (ch
))]);
225 /* This comment supplies the doc string for modify-syntax-entry,
226 for make-docfile to see. We cannot put this in the real DEFUN
227 due to limits in the Unix cpp.
229 DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0,
230 "Set syntax for character CHAR according to string S.\n\
231 The syntax is changed only for table TABLE, which defaults to\n\
232 the current buffer's syntax table.\n\
233 The first character of S should be one of the following:\n\
234 Space or - whitespace syntax. w word constituent.\n\
235 _ symbol constituent. . punctuation.\n\
236 ( open-parenthesis. ) close-parenthesis.\n\
237 \" string quote. \\ escape.\n\
238 $ paired delimiter. ' expression quote or prefix operator.\n\
239 < comment starter. > comment ender.\n\
240 / character-quote.\n\
241 Only single-character comment start and end sequences are represented thus.\n\
242 Two-character sequences are represented as described below.\n\
243 The second character of S is the matching parenthesis,\n\
244 used only if the first character is `(' or `)'.\n\
245 Any additional characters are flags.\n\
246 Defined flags are the characters 1, 2, 3, 4, b, and p.\n\
247 1 means C is the start of a two-char comment start sequence.\n\
248 2 means C is the second character of such a sequence.\n\
249 3 means C is the start of a two-char comment end sequence.\n\
250 4 means C is the second character of such a sequence.\n\
252 There can be up to two orthogonal comment sequences. This is to support\n\
253 language modes such as C++. By default, all comment sequences are of style\n\
254 a, but you can set the comment sequence style to b (on the second character of a\n\
255 comment-start, or the first character of a comment-end sequence) by using\n\
257 b means C is part of comment sequence b.\n\
259 p means C is a prefix character for `backward-prefix-chars';\n\
260 such characters are treated as whitespace when they occur\n\
261 between expressions.")
265 DEFUN ("modify-syntax-entry", Fmodify_syntax_entry
, Smodify_syntax_entry
, 2, 3,
266 /* I really don't know why this is interactive
267 help-form should at least be made useful whilst reading the second arg
269 "cSet syntax for character: \nsSet syntax for %s to: ",
270 0 /* See immediately above */)
271 (c
, newentry
, syntax_table
)
272 Lisp_Object c
, newentry
, syntax_table
;
274 register unsigned char *p
, match
;
275 register enum syntaxcode code
;
279 CHECK_STRING (newentry
, 1);
280 if (NILP (syntax_table
))
281 syntax_table
= current_buffer
->syntax_table
;
283 syntax_table
= check_syntax_table (syntax_table
);
285 p
= XSTRING (newentry
)->data
;
286 code
= (enum syntaxcode
) syntax_spec_code
[*p
++];
287 if (((int) code
& 0377) == 0377)
288 error ("invalid syntax description letter: %c", c
);
292 if (match
== ' ') match
= 0;
294 XFASTINT (val
) = (match
<< 8) + (int) code
;
299 XFASTINT (val
) |= 1 << 16;
303 XFASTINT (val
) |= 1 << 17;
307 XFASTINT (val
) |= 1 << 18;
311 XFASTINT (val
) |= 1 << 19;
315 XFASTINT (val
) |= 1 << 20;
319 XFASTINT (val
) |= 1 << 21;
323 XVECTOR (syntax_table
)->contents
[0xFF & XINT (c
)] = val
;
328 /* Dump syntax table to buffer in human-readable format */
330 describe_syntax (value
)
333 register enum syntaxcode code
;
334 char desc
, match
, start1
, start2
, end1
, end2
, prefix
, comstyle
;
337 Findent_to (make_number (16), make_number (1));
339 if (XTYPE (value
) != Lisp_Int
)
341 insert_string ("invalid");
345 code
= (enum syntaxcode
) (XINT (value
) & 0377);
346 match
= (XINT (value
) >> 8) & 0377;
347 start1
= (XINT (value
) >> 16) & 1;
348 start2
= (XINT (value
) >> 17) & 1;
349 end1
= (XINT (value
) >> 18) & 1;
350 end2
= (XINT (value
) >> 19) & 1;
351 prefix
= (XINT (value
) >> 20) & 1;
352 comstyle
= (XINT (value
) >> 21) & 1;
354 if ((int) code
< 0 || (int) code
>= (int) Smax
)
356 insert_string ("invalid");
359 desc
= syntax_code_spec
[(int) code
];
361 str
[0] = desc
, str
[1] = 0;
364 str
[0] = match
? match
: ' ';
383 insert_string ("\twhich means: ");
385 #ifdef SWITCH_ENUM_BUG
392 insert_string ("whitespace"); break;
394 insert_string ("punctuation"); break;
396 insert_string ("word"); break;
398 insert_string ("symbol"); break;
400 insert_string ("open"); break;
402 insert_string ("close"); break;
404 insert_string ("quote"); break;
406 insert_string ("string"); break;
408 insert_string ("math"); break;
410 insert_string ("escape"); break;
412 insert_string ("charquote"); break;
414 insert_string ("comment"); break;
416 insert_string ("endcomment"); break;
418 insert_string ("invalid");
424 insert_string (", matches ");
429 insert_string (",\n\t is the first character of a comment-start sequence");
431 insert_string (",\n\t is the second character of a comment-start sequence");
434 insert_string (",\n\t is the first character of a comment-end sequence");
436 insert_string (",\n\t is the second character of a comment-end sequence");
438 insert_string (" (comment style b)");
441 insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
443 insert_string ("\n");
447 describe_syntax_1 (vector
)
450 struct buffer
*old
= current_buffer
;
451 set_buffer_internal (XBUFFER (Vstandard_output
));
452 describe_vector (vector
, Qnil
, describe_syntax
, 0, Qnil
, Qnil
);
453 set_buffer_internal (old
);
457 DEFUN ("describe-syntax", Fdescribe_syntax
, Sdescribe_syntax
, 0, 0, "",
458 "Describe the syntax specifications in the syntax table.\n\
459 The descriptions are inserted in a buffer, which is then displayed.")
462 internal_with_output_to_temp_buffer
463 ("*Help*", describe_syntax_1
, current_buffer
->syntax_table
);
468 /* Return the position across COUNT words from FROM.
469 If that many words cannot be found before the end of the buffer, return 0.
470 COUNT negative means scan backward and stop at word beginning. */
472 scan_words (from
, count
)
473 register int from
, count
;
475 register int beg
= BEGV
;
476 register int end
= ZV
;
491 code
= SYNTAX (FETCH_CHAR (from
));
492 if (words_include_escapes
493 && (code
== Sescape
|| code
== Scharquote
))
501 if (from
== end
) break;
502 code
= SYNTAX (FETCH_CHAR (from
));
503 if (!(words_include_escapes
504 && (code
== Sescape
|| code
== Scharquote
)))
520 code
= SYNTAX (FETCH_CHAR (from
- 1));
521 if (words_include_escapes
522 && (code
== Sescape
|| code
== Scharquote
))
530 if (from
== beg
) break;
531 code
= SYNTAX (FETCH_CHAR (from
- 1));
532 if (!(words_include_escapes
533 && (code
== Sescape
|| code
== Scharquote
)))
546 DEFUN ("forward-word", Fforward_word
, Sforward_word
, 1, 1, "p",
547 "Move point forward ARG words (backward if ARG is negative).\n\
548 Normally returns t.\n\
549 If an edge of the buffer is reached, point is left there\n\
550 and nil is returned.")
555 CHECK_NUMBER (count
, 0);
557 if (!(val
= scan_words (point
, XINT (count
))))
559 SET_PT (XINT (count
) > 0 ? ZV
: BEGV
);
566 int parse_sexp_ignore_comments
;
569 scan_lists (from
, count
, depth
, sexpflag
)
571 int count
, depth
, sexpflag
;
579 register enum syntaxcode code
;
580 int min_depth
= depth
; /* Err out if depth gets less than this. */
581 int comstyle
= 0; /* style of comment encountered */
583 if (depth
> 0) min_depth
= 0;
593 c
= FETCH_CHAR (from
);
596 if (from
< stop
&& SYNTAX_COMSTART_FIRST (c
)
597 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
))
598 && parse_sexp_ignore_comments
)
600 /* we have encountered a comment start sequence and we
601 are ignoring all text inside comments. we must record
602 the comment style this sequence begins so that later,
603 only a comment end of the same style actually ends
604 the comment section */
606 comstyle
= SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
));
610 if (SYNTAX_PREFIX (c
))
613 #ifdef SWITCH_ENUM_BUG
621 if (from
== stop
) goto lose
;
623 /* treat following character as a word constituent */
626 if (depth
|| !sexpflag
) break;
627 /* This word counts as a sexp; return at end of it. */
630 #ifdef SWITCH_ENUM_BUG
631 switch ((int) SYNTAX (FETCH_CHAR (from
)))
633 switch (SYNTAX (FETCH_CHAR (from
)))
639 if (from
== stop
) goto lose
;
653 if (!parse_sexp_ignore_comments
) break;
656 if (from
== stop
) goto done
;
657 c
= FETCH_CHAR (from
);
658 if (SYNTAX (c
) == Sendcomment
659 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
660 /* we have encountered a comment end of the same style
661 as the comment sequence which began this comment
665 if (from
< stop
&& SYNTAX_COMEND_FIRST (c
)
666 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
))
667 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
668 /* we have encountered a comment end of the same style
669 as the comment sequence which began this comment
678 if (from
!= stop
&& c
== FETCH_CHAR (from
))
688 if (!++depth
) goto done
;
693 if (!--depth
) goto done
;
694 if (depth
< min_depth
)
695 error ("Containing expression ends prematurely");
699 stringterm
= FETCH_CHAR (from
- 1);
702 if (from
>= stop
) goto lose
;
703 if (FETCH_CHAR (from
) == stringterm
) break;
704 #ifdef SWITCH_ENUM_BUG
705 switch ((int) SYNTAX (FETCH_CHAR (from
)))
707 switch (SYNTAX (FETCH_CHAR (from
)))
717 if (!depth
&& sexpflag
) goto done
;
722 /* Reached end of buffer. Error if within object, return nil if between */
723 if (depth
) goto lose
;
728 /* End of object reached */
739 if (quoted
= char_quoted (from
))
741 c
= FETCH_CHAR (from
);
743 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
744 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from
- 1))
745 && !char_quoted (from
- 1)
746 && parse_sexp_ignore_comments
)
748 /* we must record the comment style encountered so that
749 later, we can match only the proper comment begin
750 sequence of the same style */
752 comstyle
= SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
- 1));
756 if (SYNTAX_PREFIX (c
))
759 #ifdef SWITCH_ENUM_BUG
760 switch ((int) (quoted
? Sword
: code
))
762 switch (quoted
? Sword
: code
)
767 if (depth
|| !sexpflag
) break;
768 /* This word counts as a sexp; count object finished after passing it. */
771 quoted
= char_quoted (from
- 1);
774 if (! (quoted
|| SYNTAX (FETCH_CHAR (from
- 1)) == Sword
775 || SYNTAX (FETCH_CHAR (from
- 1)) == Ssymbol
776 || SYNTAX (FETCH_CHAR (from
- 1)) == Squote
))
785 if (from
!= stop
&& c
== FETCH_CHAR (from
- 1))
795 if (!++depth
) goto done2
;
800 if (!--depth
) goto done2
;
801 if (depth
< min_depth
)
802 error ("Containing expression ends prematurely");
806 if (!parse_sexp_ignore_comments
)
808 if (code
!= SYNTAX (c
))
809 /* For a two-char comment ender, we can assume
810 it does end a comment. So scan back in a simple way. */
812 if (from
!= stop
) from
--;
815 if (SYNTAX (c
= FETCH_CHAR (from
)) == Scomment
816 && SYNTAX_COMMENT_STYLE (c
) == comstyle
)
818 if (from
== stop
) goto done
;
820 if (SYNTAX_COMSTART_SECOND (c
)
821 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
))
822 && SYNTAX_COMMENT_STYLE (c
) == comstyle
823 && !char_quoted (from
))
829 /* Look back, counting the parity of string-quotes,
830 and recording the comment-starters seen.
831 When we reach a safe place, assume that's not in a string;
832 then step the main scan to the earliest comment-starter seen
833 an even number of string quotes away from the safe place.
835 OFROM[I] is position of the earliest comment-starter seen
836 which is I+2X quotes from the comment-end.
837 PARITY is current parity of quotes from the comment end. */
840 char my_stringend
= 0;
841 int string_lossage
= 0;
842 int comment_end
= from
;
843 int comstart_pos
= 0;
844 int comstart_parity
= 0;
846 /* At beginning of range to scan, we're outside of strings;
847 that determines quote parity to the comment-end. */
850 /* Move back and examine a character. */
853 c
= FETCH_CHAR (from
);
856 /* If this char is the second of a 2-char comment sequence,
857 back up and give the pair the appropriate syntax. */
858 if (from
> stop
&& SYNTAX_COMEND_SECOND (c
)
859 && SYNTAX_COMEND_FIRST (FETCH_CHAR (from
- 1)))
865 else if (from
> stop
&& SYNTAX_COMSTART_SECOND (c
)
866 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
- 1))
867 && comstyle
== SYNTAX_COMMENT_STYLE (c
))
873 /* Ignore escaped characters. */
874 if (char_quoted (from
))
877 /* Track parity of quotes. */
881 if (my_stringend
== 0)
883 /* If we have two kinds of string delimiters.
884 There's no way to grok this scanning backwards. */
885 else if (my_stringend
!= c
)
889 /* Record comment-starters according to that
890 quote-parity to the comment-end. */
891 if (code
== Scomment
)
893 comstart_parity
= parity
;
897 /* If we find another earlier comment-ender,
898 any comment-starts earier than that don't count
899 (because they go with the earlier comment-ender). */
900 if (code
== Sendcomment
901 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
)) == comstyle
)
904 /* Assume a defun-start point is outside of strings. */
906 && (from
== stop
|| FETCH_CHAR (from
- 1) == '\n'))
910 if (comstart_pos
== 0)
912 /* If the earliest comment starter
913 is followed by uniform paired string quotes or none,
914 we know it can't be inside a string
915 since if it were then the comment ender would be inside one.
916 So it does start a comment. Skip back to it. */
917 else if (comstart_parity
== 0 && !string_lossage
)
921 /* We had two kinds of string delimiters mixed up
922 together. Decode this going forwards.
923 Scan fwd from the previous comment ender
924 to the one in question; this records where we
925 last passed a comment starter. */
926 struct lisp_parse_state state
;
927 scan_sexps_forward (&state
, find_defun_start (comment_end
),
928 comment_end
- 1, -10000, 0, Qnil
);
930 from
= state
.comstart
;
932 /* We can't grok this as a comment; scan it normally. */
939 stringterm
= FETCH_CHAR (from
);
942 if (from
== stop
) goto lose
;
943 if (!char_quoted (from
- 1)
944 && stringterm
== FETCH_CHAR (from
- 1))
949 if (!depth
&& sexpflag
) goto done2
;
954 /* Reached start of buffer. Error if within object, return nil if between */
955 if (depth
) goto lose
;
966 XFASTINT (val
) = from
;
970 error ("Unbalanced parentheses");
977 register enum syntaxcode code
;
978 register int beg
= BEGV
;
979 register int quoted
= 0;
982 && ((code
= SYNTAX (FETCH_CHAR (pos
- 1))) == Scharquote
984 pos
--, quoted
= !quoted
;
988 DEFUN ("scan-lists", Fscan_lists
, Sscan_lists
, 3, 3, 0,
989 "Scan from character number FROM by COUNT lists.\n\
990 Returns the character number of the position thus found.\n\
992 If DEPTH is nonzero, paren depth begins counting from that value,\n\
993 only places where the depth in parentheses becomes zero\n\
994 are candidates for stopping; COUNT such places are counted.\n\
995 Thus, a positive value for DEPTH means go out levels.\n\
997 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
999 If the beginning or end of (the accessible part of) the buffer is reached\n\
1000 and the depth is wrong, an error is signaled.\n\
1001 If the depth is right but the count is not used up, nil is returned.")
1002 (from
, count
, depth
)
1003 Lisp_Object from
, count
, depth
;
1005 CHECK_NUMBER (from
, 0);
1006 CHECK_NUMBER (count
, 1);
1007 CHECK_NUMBER (depth
, 2);
1009 return scan_lists (XINT (from
), XINT (count
), XINT (depth
), 0);
1012 DEFUN ("scan-sexps", Fscan_sexps
, Sscan_sexps
, 2, 2, 0,
1013 "Scan from character number FROM by COUNT balanced expressions.\n\
1014 If COUNT is negative, scan backwards.\n\
1015 Returns the character number of the position thus found.\n\
1017 Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
1019 If the beginning or end of (the accessible part of) the buffer is reached\n\
1020 in the middle of a parenthetical grouping, an error is signaled.\n\
1021 If the beginning or end is reached between groupings\n\
1022 but before count is used up, nil is returned.")
1024 Lisp_Object from
, count
;
1026 CHECK_NUMBER (from
, 0);
1027 CHECK_NUMBER (count
, 1);
1029 return scan_lists (XINT (from
), XINT (count
), 0, 1);
1032 DEFUN ("backward-prefix-chars", Fbackward_prefix_chars
, Sbackward_prefix_chars
,
1034 "Move point backward over any number of chars with prefix syntax.\n\
1035 This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
1041 while (pos
> beg
&& !char_quoted (pos
- 1)
1042 && (SYNTAX (FETCH_CHAR (pos
- 1)) == Squote
1043 || SYNTAX_PREFIX (FETCH_CHAR (pos
- 1))))
1051 /* Parse forward from FROM to END,
1052 assuming that FROM has state OLDSTATE (nil means FROM is start of function),
1053 and return a description of the state of the parse at END.
1054 If STOPBEFORE is nonzero, stop at the start of an atom. */
1056 scan_sexps_forward (stateptr
, from
, end
, targetdepth
, stopbefore
, oldstate
)
1057 struct lisp_parse_state
*stateptr
;
1059 int end
, targetdepth
, stopbefore
;
1060 Lisp_Object oldstate
;
1062 struct lisp_parse_state state
;
1064 register enum syntaxcode code
;
1065 struct level
{ int last
, prev
; };
1066 struct level levelstart
[100];
1067 register struct level
*curlevel
= levelstart
;
1068 struct level
*endlevel
= levelstart
+ 100;
1070 register int depth
; /* Paren depth of current scanning location.
1071 level - levelstart equals this except
1072 when the depth becomes negative. */
1073 int mindepth
; /* Lowest DEPTH value seen. */
1074 int start_quoted
= 0; /* Nonzero means starting after a char quote */
1080 if (NILP (oldstate
))
1083 state
.instring
= -1;
1084 state
.incomment
= 0;
1085 state
.comstyle
= 0; /* comment style a by default */
1089 tem
= Fcar (oldstate
);
1095 oldstate
= Fcdr (oldstate
);
1096 oldstate
= Fcdr (oldstate
);
1097 oldstate
= Fcdr (oldstate
);
1098 tem
= Fcar (oldstate
);
1099 state
.instring
= !NILP (tem
) ? XINT (tem
) : -1;
1101 oldstate
= Fcdr (oldstate
);
1102 tem
= Fcar (oldstate
);
1103 state
.incomment
= !NILP (tem
);
1105 oldstate
= Fcdr (oldstate
);
1106 tem
= Fcar (oldstate
);
1107 start_quoted
= !NILP (tem
);
1109 /* if the eight element of the list is nil, we are in comment
1110 style a. if it is non-nil, we are in comment style b */
1111 oldstate
= Fcdr (oldstate
);
1112 oldstate
= Fcdr (oldstate
);
1113 oldstate
= Fcdr (oldstate
);
1114 tem
= Fcar (oldstate
);
1115 state
.comstyle
= !NILP (tem
);
1120 curlevel
->prev
= -1;
1121 curlevel
->last
= -1;
1123 /* Enter the loop at a place appropriate for initial state. */
1125 if (state
.incomment
) goto startincomment
;
1126 if (state
.instring
>= 0)
1128 if (start_quoted
) goto startquotedinstring
;
1131 if (start_quoted
) goto startquoted
;
1135 code
= SYNTAX (FETCH_CHAR (from
));
1137 if (from
< end
&& SYNTAX_COMSTART_FIRST (FETCH_CHAR (from
- 1))
1138 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from
)))
1140 /* Record the comment style we have entered so that only
1141 the comment-end sequence of the same style actually
1142 terminates the comment section. */
1144 state
.comstyle
= SYNTAX_COMMENT_STYLE (FETCH_CHAR (from
));
1148 if (SYNTAX_PREFIX (FETCH_CHAR (from
- 1)))
1150 #ifdef SWITCH_ENUM_BUG
1158 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1159 curlevel
->last
= from
- 1;
1161 if (from
== end
) goto endquoted
;
1164 /* treat following character as a word constituent */
1167 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1168 curlevel
->last
= from
- 1;
1172 #ifdef SWITCH_ENUM_BUG
1173 switch ((int) SYNTAX (FETCH_CHAR (from
)))
1175 switch (SYNTAX (FETCH_CHAR (from
)))
1181 if (from
== end
) goto endquoted
;
1193 curlevel
->prev
= curlevel
->last
;
1197 state
.incomment
= 1;
1198 state
.comstart
= from
;
1202 if (from
== end
) goto done
;
1203 prev
= FETCH_CHAR (from
);
1204 if (SYNTAX (prev
) == Sendcomment
1205 && SYNTAX_COMMENT_STYLE (prev
) == state
.comstyle
)
1206 /* Only terminate the comment section if the endcomment
1207 of the same style as the start sequence has been
1211 if (from
< end
&& SYNTAX_COMEND_FIRST (prev
)
1212 && SYNTAX_COMEND_SECOND (FETCH_CHAR (from
))
1213 && SYNTAX_COMMENT_STYLE (prev
) == state
.comstyle
)
1214 /* Only terminate the comment section if the end-comment
1215 sequence of the same style as the start sequence has
1216 been encountered. */
1219 state
.incomment
= 0;
1220 state
.comstyle
= 0; /* reset the comment style */
1224 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1226 /* curlevel++->last ran into compiler bug on Apollo */
1227 curlevel
->last
= from
- 1;
1228 if (++curlevel
== endlevel
)
1229 error ("Nesting too deep for parser");
1230 curlevel
->prev
= -1;
1231 curlevel
->last
= -1;
1232 if (!--targetdepth
) goto done
;
1237 if (depth
< mindepth
)
1239 if (curlevel
!= levelstart
)
1241 curlevel
->prev
= curlevel
->last
;
1242 if (!++targetdepth
) goto done
;
1246 if (stopbefore
) goto stop
; /* this arg means stop at sexp start */
1247 curlevel
->last
= from
- 1;
1248 state
.instring
= FETCH_CHAR (from
- 1);
1252 if (from
>= end
) goto done
;
1253 if (FETCH_CHAR (from
) == state
.instring
) break;
1254 #ifdef SWITCH_ENUM_BUG
1255 switch ((int) SYNTAX (FETCH_CHAR (from
)))
1257 switch (SYNTAX (FETCH_CHAR (from
)))
1263 startquotedinstring
:
1264 if (from
>= end
) goto endquoted
;
1268 state
.instring
= -1;
1269 curlevel
->prev
= curlevel
->last
;
1279 stop
: /* Here if stopping before start of sexp. */
1280 from
--; /* We have just fetched the char that starts it; */
1281 goto done
; /* but return the position before it. */
1286 state
.depth
= depth
;
1287 state
.mindepth
= mindepth
;
1288 state
.thislevelstart
= curlevel
->prev
;
1289 state
.prevlevelstart
1290 = (curlevel
== levelstart
) ? -1 : (curlevel
- 1)->last
;
1291 state
.location
= from
;
1297 /* This comment supplies the doc string for parse-partial-sexp,
1298 for make-docfile to see. We cannot put this in the real DEFUN
1299 due to limits in the Unix cpp.
1301 DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 5, 0,
1302 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
1303 Parsing stops at TO or when certain criteria are met;\n\
1304 point is set to where parsing stops.\n\
1305 If fifth arg STATE is omitted or nil,\n\
1306 parsing assumes that FROM is the beginning of a function.\n\
1307 Value is a list of eight elements describing final state of parsing:\n\
1308 1. depth in parens.\n\
1309 2. character address of start of innermost containing list; nil if none.\n\
1310 3. character address of start of last complete sexp terminated.\n\
1311 4. non-nil if inside a string.\n\
1312 (it is the character that will terminate the string.)\n\
1313 5. t if inside a comment.\n\
1314 6. t if following a quote character.\n\
1315 7. the minimum paren-depth encountered during this scan.\n\
1316 8. t if in a comment of style `b'.\n\
1317 If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
1318 in parentheses becomes equal to TARGETDEPTH.\n\
1319 Fourth arg STOPBEFORE non-nil means stop when come to\n\
1320 any character that starts a sexp.\n\
1321 Fifth arg STATE is a seven-list like what this function returns.\n\
1322 It is used to initialize the state of the parse. Its second and third
1323 elements are ignored.")
1324 (from, to, targetdepth, stopbefore, state)
1327 DEFUN ("parse-partial-sexp", Fparse_partial_sexp
, Sparse_partial_sexp
, 2, 5, 0,
1328 0 /* See immediately above */)
1329 (from
, to
, targetdepth
, stopbefore
, oldstate
)
1330 Lisp_Object from
, to
, targetdepth
, stopbefore
, oldstate
;
1332 struct lisp_parse_state state
;
1335 if (!NILP (targetdepth
))
1337 CHECK_NUMBER (targetdepth
, 3);
1338 target
= XINT (targetdepth
);
1341 target
= -100000; /* We won't reach this depth */
1343 validate_region (&from
, &to
);
1344 scan_sexps_forward (&state
, XINT (from
), XINT (to
),
1345 target
, !NILP (stopbefore
), oldstate
);
1347 SET_PT (state
.location
);
1349 return Fcons (make_number (state
.depth
),
1350 Fcons (state
.prevlevelstart
< 0 ? Qnil
: make_number (state
.prevlevelstart
),
1351 Fcons (state
.thislevelstart
< 0 ? Qnil
: make_number (state
.thislevelstart
),
1352 Fcons (state
.instring
>= 0 ? make_number (state
.instring
) : Qnil
,
1353 Fcons (state
.incomment
? Qt
: Qnil
,
1354 Fcons (state
.quoted
? Qt
: Qnil
,
1355 Fcons (make_number (state
.mindepth
),
1356 Fcons (state
.comstyle
? Qt
: Qnil
,
1363 register struct Lisp_Vector
*v
;
1365 /* Set this now, so first buffer creation can refer to it. */
1366 /* Make it nil before calling copy-syntax-table
1367 so that copy-syntax-table will know not to try to copy from garbage */
1368 Vstandard_syntax_table
= Qnil
;
1369 Vstandard_syntax_table
= Fcopy_syntax_table (Qnil
);
1371 v
= XVECTOR (Vstandard_syntax_table
);
1373 for (i
= 'a'; i
<= 'z'; i
++)
1374 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1375 for (i
= 'A'; i
<= 'Z'; i
++)
1376 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1377 for (i
= '0'; i
<= '9'; i
++)
1378 XFASTINT (v
->contents
[i
]) = (int) Sword
;
1379 XFASTINT (v
->contents
['$']) = (int) Sword
;
1380 XFASTINT (v
->contents
['%']) = (int) Sword
;
1382 XFASTINT (v
->contents
['(']) = (int) Sopen
+ (')' << 8);
1383 XFASTINT (v
->contents
[')']) = (int) Sclose
+ ('(' << 8);
1384 XFASTINT (v
->contents
['[']) = (int) Sopen
+ (']' << 8);
1385 XFASTINT (v
->contents
[']']) = (int) Sclose
+ ('[' << 8);
1386 XFASTINT (v
->contents
['{']) = (int) Sopen
+ ('}' << 8);
1387 XFASTINT (v
->contents
['}']) = (int) Sclose
+ ('{' << 8);
1388 XFASTINT (v
->contents
['"']) = (int) Sstring
;
1389 XFASTINT (v
->contents
['\\']) = (int) Sescape
;
1391 for (i
= 0; i
< 10; i
++)
1392 XFASTINT (v
->contents
["_-+*/&|<>="[i
]]) = (int) Ssymbol
;
1394 for (i
= 0; i
< 12; i
++)
1395 XFASTINT (v
->contents
[".,;:?!#@~^'`"[i
]]) = (int) Spunct
;
1400 Qsyntax_table_p
= intern ("syntax-table-p");
1401 staticpro (&Qsyntax_table_p
);
1403 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments
,
1404 "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
1406 words_include_escapes
= 0;
1407 DEFVAR_BOOL ("words-include-escapes", &words_include_escapes
,
1408 "Non-nil means `forward-word', etc., should treat escape chars part of words.");
1410 defsubr (&Ssyntax_table_p
);
1411 defsubr (&Ssyntax_table
);
1412 defsubr (&Sstandard_syntax_table
);
1413 defsubr (&Scopy_syntax_table
);
1414 defsubr (&Sset_syntax_table
);
1415 defsubr (&Schar_syntax
);
1416 defsubr (&Smodify_syntax_entry
);
1417 defsubr (&Sdescribe_syntax
);
1419 defsubr (&Sforward_word
);
1421 defsubr (&Sscan_lists
);
1422 defsubr (&Sscan_sexps
);
1423 defsubr (&Sbackward_prefix_chars
);
1424 defsubr (&Sparse_partial_sexp
);