(tags-loop-scan): Set default value to an error form.
[bpt/emacs.git] / src / syntax.c
CommitLineData
8489eb67 1/* GNU Emacs routines to deal with syntax tables; also word and list parsing.
a4275ad1 2 Copyright (C) 1985, 1987, 1992 Free Software Foundation, Inc.
8489eb67
RS
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
a4275ad1 8the Free Software Foundation; either version 2, or (at your option)
8489eb67
RS
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include <ctype.h>
23#include "lisp.h"
24#include "commands.h"
25#include "buffer.h"
26#include "syntax.h"
27
28Lisp_Object Qsyntax_table_p;
29
30int words_include_escapes;
31
e5d4f4dc
RS
32/* This is the internal form of the parse state used in parse-partial-sexp. */
33
34struct lisp_parse_state
35 {
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. */
46 };
47\f
37bef230
RS
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. */
54
55static int find_start_pos;
56static int find_start_value;
57static struct buffer *find_start_buffer;
58static int find_start_begv;
59static int find_start_modiff;
60
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. */
64
65static int
66find_defun_start (pos)
67 int pos;
68{
69 int tem;
70 int shortage;
71
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;
82
83 /* Back up to start of line. */
84 tem = scan_buffer ('\n', pos, -1, &shortage);
37bef230
RS
85
86 while (tem > BEGV)
87 {
88 /* Open-paren at start of line means we found our defun-start. */
89 if (SYNTAX (FETCH_CHAR (tem)) == Sopen)
90 break;
91 /* Move to beg of previous line. */
92 tem = scan_buffer ('\n', tem, -2, &shortage);
37bef230
RS
93 }
94
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;
101
102 return find_start_value;
103}
104\f
8489eb67
RS
105DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
106 "Return t if ARG is a syntax table.\n\
107Any vector of 256 elements will do.")
108 (obj)
109 Lisp_Object obj;
110{
111 if (XTYPE (obj) == Lisp_Vector && XVECTOR (obj)->size == 0400)
112 return Qt;
113 return Qnil;
114}
115
116Lisp_Object
117check_syntax_table (obj)
118 Lisp_Object obj;
119{
120 register Lisp_Object tem;
121 while (tem = Fsyntax_table_p (obj),
265a9e55 122 NILP (tem))
8489eb67
RS
123 obj = wrong_type_argument (Qsyntax_table_p, obj, 0);
124 return obj;
125}
126
127
128DEFUN ("syntax-table", Fsyntax_table, Ssyntax_table, 0, 0, 0,
129 "Return the current syntax table.\n\
130This is the one specified by the current buffer.")
131 ()
132{
133 return current_buffer->syntax_table;
134}
135
136DEFUN ("standard-syntax-table", Fstandard_syntax_table,
137 Sstandard_syntax_table, 0, 0, 0,
138 "Return the standard syntax table.\n\
139This is the one used for new buffers.")
140 ()
141{
142 return Vstandard_syntax_table;
143}
144
145DEFUN ("copy-syntax-table", Fcopy_syntax_table, Scopy_syntax_table, 0, 1, 0,
146 "Construct a new syntax table and return it.\n\
147It is a copy of the TABLE, which defaults to the standard syntax table.")
148 (table)
149 Lisp_Object table;
150{
151 Lisp_Object size, val;
152 XFASTINT (size) = 0400;
153 XFASTINT (val) = 0;
154 val = Fmake_vector (size, val);
265a9e55 155 if (!NILP (table))
8489eb67 156 table = check_syntax_table (table);
265a9e55 157 else if (NILP (Vstandard_syntax_table))
8489eb67
RS
158 /* Can only be null during initialization */
159 return val;
160 else table = Vstandard_syntax_table;
161
162 bcopy (XVECTOR (table)->contents,
163 XVECTOR (val)->contents, 0400 * sizeof (Lisp_Object));
164 return val;
165}
166
167DEFUN ("set-syntax-table", Fset_syntax_table, Sset_syntax_table, 1, 1, 0,
168 "Select a new syntax table for the current buffer.\n\
169One argument, a syntax table.")
170 (table)
171 Lisp_Object table;
172{
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;
177 return table;
178}
179\f
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. */
183
184unsigned 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
204 };
205
206/* Indexed by syntax code, give the letter that describes it. */
207
208char syntax_code_spec[13] =
209 {
210 ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>'
211 };
212\f
213DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0,
214 "Return the syntax code of CHAR, described by a character.\n\
215For example, if CHAR is a word constituent, the character `?w' is returned.\n\
216The characters that correspond to various syntax codes\n\
217are listed in the documentation of `modify-syntax-entry'.")
218 (ch)
219 Lisp_Object ch;
220{
221 CHECK_NUMBER (ch, 0);
222 return make_number (syntax_code_spec[(int) SYNTAX (0xFF & XINT (ch))]);
223}
224
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.
228
229DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0,
230 "Set syntax for character CHAR according to string S.\n\
231The syntax is changed only for table TABLE, which defaults to\n\
232 the current buffer's syntax table.\n\
233The first character of S should be one of the following:\n\
32676c08
JB
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\
8489eb67
RS
241Only single-character comment start and end sequences are represented thus.\n\
242Two-character sequences are represented as described below.\n\
243The second character of S is the matching parenthesis,\n\
244 used only if the first character is `(' or `)'.\n\
245Any additional characters are flags.\n\
e5d4f4dc 246Defined flags are the characters 1, 2, 3, 4, b, and p.\n\
8489eb67
RS
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\
e5d4f4dc
RS
251\n\
252There can be up to two orthogonal comment sequences. This is to support\n\
253language modes such as C++. By default, all comment sequences are of style\n\
254a, but you can set the comment sequence style to b (on the second character of a\n\
255comment-start, or the first character of a comment-end sequence) by using\n\
256this flag:\n\
257 b means C is part of comment sequence b.\n\
258\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\
8489eb67
RS
261 between expressions.")
262
263*/
264
265DEFUN ("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
268 */
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;
273{
274 register unsigned char *p, match;
275 register enum syntaxcode code;
276 Lisp_Object val;
277
278 CHECK_NUMBER (c, 0);
279 CHECK_STRING (newentry, 1);
265a9e55 280 if (NILP (syntax_table))
8489eb67
RS
281 syntax_table = current_buffer->syntax_table;
282 else
283 syntax_table = check_syntax_table (syntax_table);
284
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);
289
290 match = *p;
291 if (match) p++;
292 if (match == ' ') match = 0;
293
294 XFASTINT (val) = (match << 8) + (int) code;
295 while (*p)
296 switch (*p++)
297 {
298 case '1':
299 XFASTINT (val) |= 1 << 16;
300 break;
301
302 case '2':
303 XFASTINT (val) |= 1 << 17;
304 break;
305
306 case '3':
307 XFASTINT (val) |= 1 << 18;
308 break;
309
310 case '4':
311 XFASTINT (val) |= 1 << 19;
312 break;
313
314 case 'p':
315 XFASTINT (val) |= 1 << 20;
316 break;
e5d4f4dc
RS
317
318 case 'b':
319 XFASTINT (val) |= 1 << 21;
320 break;
8489eb67
RS
321 }
322
323 XVECTOR (syntax_table)->contents[0xFF & XINT (c)] = val;
324
325 return Qnil;
326}
327\f
328/* Dump syntax table to buffer in human-readable format */
329
330describe_syntax (value)
331 Lisp_Object value;
332{
333 register enum syntaxcode code;
e5d4f4dc 334 char desc, match, start1, start2, end1, end2, prefix, comstyle;
8489eb67
RS
335 char str[2];
336
337 Findent_to (make_number (16), make_number (1));
338
339 if (XTYPE (value) != Lisp_Int)
340 {
341 insert_string ("invalid");
342 return;
343 }
344
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;
e5d4f4dc 352 comstyle = (XINT (value) >> 21) & 1;
8489eb67
RS
353
354 if ((int) code < 0 || (int) code >= (int) Smax)
355 {
356 insert_string ("invalid");
357 return;
358 }
359 desc = syntax_code_spec[(int) code];
360
361 str[0] = desc, str[1] = 0;
362 insert (str, 1);
363
364 str[0] = match ? match : ' ';
365 insert (str, 1);
366
367
368 if (start1)
369 insert ("1", 1);
370 if (start2)
371 insert ("2", 1);
372
373 if (end1)
374 insert ("3", 1);
375 if (end2)
376 insert ("4", 1);
377
378 if (prefix)
379 insert ("p", 1);
e5d4f4dc
RS
380 if (comstyle)
381 insert ("b", 1);
8489eb67
RS
382
383 insert_string ("\twhich means: ");
384
385#ifdef SWITCH_ENUM_BUG
386 switch ((int) code)
387#else
388 switch (code)
389#endif
390 {
391 case Swhitespace:
392 insert_string ("whitespace"); break;
393 case Spunct:
394 insert_string ("punctuation"); break;
395 case Sword:
396 insert_string ("word"); break;
397 case Ssymbol:
398 insert_string ("symbol"); break;
399 case Sopen:
400 insert_string ("open"); break;
401 case Sclose:
402 insert_string ("close"); break;
403 case Squote:
404 insert_string ("quote"); break;
405 case Sstring:
406 insert_string ("string"); break;
407 case Smath:
408 insert_string ("math"); break;
409 case Sescape:
410 insert_string ("escape"); break;
411 case Scharquote:
412 insert_string ("charquote"); break;
413 case Scomment:
414 insert_string ("comment"); break;
415 case Sendcomment:
416 insert_string ("endcomment"); break;
417 default:
418 insert_string ("invalid");
419 return;
420 }
421
422 if (match)
423 {
424 insert_string (", matches ");
410e16ff 425 insert_char (match);
8489eb67
RS
426 }
427
428 if (start1)
429 insert_string (",\n\t is the first character of a comment-start sequence");
430 if (start2)
431 insert_string (",\n\t is the second character of a comment-start sequence");
432
433 if (end1)
434 insert_string (",\n\t is the first character of a comment-end sequence");
435 if (end2)
436 insert_string (",\n\t is the second character of a comment-end sequence");
e5d4f4dc
RS
437 if (comstyle)
438 insert_string (" (comment style b)");
439
8489eb67
RS
440 if (prefix)
441 insert_string (",\n\t is a prefix character for `backward-prefix-chars'");
442
443 insert_string ("\n");
444}
445
446Lisp_Object
447describe_syntax_1 (vector)
448 Lisp_Object vector;
449{
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);
454 return Qnil;
455}
456
457DEFUN ("describe-syntax", Fdescribe_syntax, Sdescribe_syntax, 0, 0, "",
458 "Describe the syntax specifications in the syntax table.\n\
459The descriptions are inserted in a buffer, which is then displayed.")
460 ()
461{
462 internal_with_output_to_temp_buffer
463 ("*Help*", describe_syntax_1, current_buffer->syntax_table);
464
465 return Qnil;
466}
467\f
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. */
471
472scan_words (from, count)
473 register int from, count;
474{
475 register int beg = BEGV;
476 register int end = ZV;
477 register int code;
478
479 immediate_quit = 1;
480 QUIT;
481
482 while (count > 0)
483 {
484 while (1)
485 {
486 if (from == end)
487 {
488 immediate_quit = 0;
489 return 0;
490 }
491 code = SYNTAX (FETCH_CHAR (from));
492 if (words_include_escapes
493 && (code == Sescape || code == Scharquote))
494 break;
495 if (code == Sword)
496 break;
497 from++;
498 }
499 while (1)
500 {
501 if (from == end) break;
502 code = SYNTAX (FETCH_CHAR (from));
503 if (!(words_include_escapes
504 && (code == Sescape || code == Scharquote)))
505 if (code != Sword)
506 break;
507 from++;
508 }
509 count--;
510 }
511 while (count < 0)
512 {
513 while (1)
514 {
515 if (from == beg)
516 {
517 immediate_quit = 0;
518 return 0;
519 }
520 code = SYNTAX (FETCH_CHAR (from - 1));
521 if (words_include_escapes
522 && (code == Sescape || code == Scharquote))
523 break;
524 if (code == Sword)
525 break;
526 from--;
527 }
528 while (1)
529 {
530 if (from == beg) break;
531 code = SYNTAX (FETCH_CHAR (from - 1));
532 if (!(words_include_escapes
533 && (code == Sescape || code == Scharquote)))
534 if (code != Sword)
535 break;
536 from--;
537 }
538 count++;
539 }
540
541 immediate_quit = 0;
542
543 return from;
544}
545
546DEFUN ("forward-word", Fforward_word, Sforward_word, 1, 1, "p",
547 "Move point forward ARG words (backward if ARG is negative).\n\
548Normally returns t.\n\
549If an edge of the buffer is reached, point is left there\n\
550and nil is returned.")
551 (count)
552 Lisp_Object count;
553{
554 int val;
555 CHECK_NUMBER (count, 0);
556
557 if (!(val = scan_words (point, XINT (count))))
558 {
559 SET_PT (XINT (count) > 0 ? ZV : BEGV);
560 return Qnil;
561 }
562 SET_PT (val);
563 return Qt;
564}
565\f
566int parse_sexp_ignore_comments;
567
568Lisp_Object
569scan_lists (from, count, depth, sexpflag)
570 register int from;
571 int count, depth, sexpflag;
572{
573 Lisp_Object val;
574 register int stop;
575 register int c;
576 char stringterm;
577 int quoted;
578 int mathexit = 0;
579 register enum syntaxcode code;
580 int min_depth = depth; /* Err out if depth gets less than this. */
e5d4f4dc 581 int comstyle = 0; /* style of comment encountered */
8489eb67
RS
582
583 if (depth > 0) min_depth = 0;
584
585 immediate_quit = 1;
586 QUIT;
587
588 while (count > 0)
589 {
590 stop = ZV;
591 while (from < stop)
592 {
593 c = FETCH_CHAR (from);
e5d4f4dc 594 code = SYNTAX (c);
8489eb67
RS
595 from++;
596 if (from < stop && SYNTAX_COMSTART_FIRST (c)
597 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))
598 && parse_sexp_ignore_comments)
e5d4f4dc
RS
599 {
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 */
605 code = Scomment;
606 comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
607 from++;
608 }
609
8489eb67
RS
610 if (SYNTAX_PREFIX (c))
611 continue;
612
613#ifdef SWITCH_ENUM_BUG
614 switch ((int) code)
615#else
616 switch (code)
617#endif
618 {
619 case Sescape:
620 case Scharquote:
621 if (from == stop) goto lose;
622 from++;
623 /* treat following character as a word constituent */
624 case Sword:
625 case Ssymbol:
626 if (depth || !sexpflag) break;
627 /* This word counts as a sexp; return at end of it. */
628 while (from < stop)
629 {
630#ifdef SWITCH_ENUM_BUG
e5d4f4dc 631 switch ((int) SYNTAX (FETCH_CHAR (from)))
8489eb67 632#else
e5d4f4dc 633 switch (SYNTAX (FETCH_CHAR (from)))
8489eb67
RS
634#endif
635 {
636 case Scharquote:
637 case Sescape:
638 from++;
639 if (from == stop) goto lose;
640 break;
641 case Sword:
642 case Ssymbol:
643 case Squote:
644 break;
645 default:
646 goto done;
647 }
648 from++;
649 }
650 goto done;
651
652 case Scomment:
653 if (!parse_sexp_ignore_comments) break;
654 while (1)
655 {
656 if (from == stop) goto done;
e5d4f4dc
RS
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
662 section */
8489eb67
RS
663 break;
664 from++;
665 if (from < stop && SYNTAX_COMEND_FIRST (c)
e5d4f4dc
RS
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
670 section */
8489eb67
RS
671 { from++; break; }
672 }
673 break;
674
675 case Smath:
676 if (!sexpflag)
677 break;
678 if (from != stop && c == FETCH_CHAR (from))
679 from++;
680 if (mathexit)
681 {
682 mathexit = 0;
683 goto close1;
684 }
685 mathexit = 1;
686
687 case Sopen:
688 if (!++depth) goto done;
689 break;
690
691 case Sclose:
692 close1:
693 if (!--depth) goto done;
694 if (depth < min_depth)
695 error ("Containing expression ends prematurely");
696 break;
697
698 case Sstring:
699 stringterm = FETCH_CHAR (from - 1);
700 while (1)
701 {
702 if (from >= stop) goto lose;
703 if (FETCH_CHAR (from) == stringterm) break;
704#ifdef SWITCH_ENUM_BUG
e5d4f4dc 705 switch ((int) SYNTAX (FETCH_CHAR (from)))
8489eb67 706#else
e5d4f4dc 707 switch (SYNTAX (FETCH_CHAR (from)))
8489eb67
RS
708#endif
709 {
710 case Scharquote:
711 case Sescape:
712 from++;
713 }
714 from++;
715 }
716 from++;
717 if (!depth && sexpflag) goto done;
718 break;
719 }
720 }
721
722 /* Reached end of buffer. Error if within object, return nil if between */
723 if (depth) goto lose;
724
725 immediate_quit = 0;
726 return Qnil;
727
728 /* End of object reached */
729 done:
730 count--;
731 }
732
733 while (count < 0)
734 {
735 stop = BEGV;
736 while (from > stop)
737 {
738 from--;
739 if (quoted = char_quoted (from))
740 from--;
741 c = FETCH_CHAR (from);
742 code = SYNTAX (c);
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)
e5d4f4dc
RS
747 {
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 */
751 code = Sendcomment;
752 comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from - 1));
753 from--;
754 }
755
8489eb67
RS
756 if (SYNTAX_PREFIX (c))
757 continue;
758
759#ifdef SWITCH_ENUM_BUG
760 switch ((int) (quoted ? Sword : code))
761#else
762 switch (quoted ? Sword : code)
763#endif
764 {
765 case Sword:
766 case Ssymbol:
767 if (depth || !sexpflag) break;
768 /* This word counts as a sexp; count object finished after passing it. */
769 while (from > stop)
770 {
771 quoted = char_quoted (from - 1);
772 if (quoted)
773 from--;
e5d4f4dc
RS
774 if (! (quoted || SYNTAX (FETCH_CHAR (from - 1)) == Sword
775 || SYNTAX (FETCH_CHAR (from - 1)) == Ssymbol
776 || SYNTAX (FETCH_CHAR (from - 1)) == Squote))
8489eb67
RS
777 goto done2;
778 from--;
779 }
780 goto done2;
781
782 case Smath:
783 if (!sexpflag)
784 break;
785 if (from != stop && c == FETCH_CHAR (from - 1))
786 from--;
787 if (mathexit)
788 {
789 mathexit = 0;
790 goto open2;
791 }
792 mathexit = 1;
793
794 case Sclose:
795 if (!++depth) goto done2;
796 break;
797
798 case Sopen:
799 open2:
800 if (!--depth) goto done2;
801 if (depth < min_depth)
802 error ("Containing expression ends prematurely");
803 break;
804
805 case Sendcomment:
806 if (!parse_sexp_ignore_comments)
807 break;
37bef230
RS
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. */
811 {
812 if (from != stop) from--;
813 while (1)
814 {
815 if (SYNTAX (c = FETCH_CHAR (from)) == Scomment
816 && SYNTAX_COMMENT_STYLE (c) == comstyle)
817 break;
818 if (from == stop) goto done;
819 from--;
820 if (SYNTAX_COMSTART_SECOND (c)
821 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from))
822 && SYNTAX_COMMENT_STYLE (c) == comstyle
823 && !char_quoted (from))
824 break;
825 }
826 break;
827 }
828
8489eb67
RS
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.
834
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. */
838 {
8489eb67 839 int parity = 0;
e5d4f4dc
RS
840 char my_stringend = 0;
841 int string_lossage = 0;
842 int comment_end = from;
37bef230
RS
843 int comstart_pos = 0;
844 int comstart_parity = 0;
8489eb67
RS
845
846 /* At beginning of range to scan, we're outside of strings;
847 that determines quote parity to the comment-end. */
848 while (from != stop)
849 {
850 /* Move back and examine a character. */
851 from--;
852
853 c = FETCH_CHAR (from);
854 code = SYNTAX (c);
855
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)))
e5d4f4dc
RS
860 {
861 code = Sendcomment;
862 from--;
863 }
864
8489eb67 865 else if (from > stop && SYNTAX_COMSTART_SECOND (c)
e5d4f4dc
RS
866 && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
867 && comstyle == SYNTAX_COMMENT_STYLE (c))
868 {
869 code = Scomment;
870 from--;
871 }
8489eb67
RS
872
873 /* Ignore escaped characters. */
874 if (char_quoted (from))
875 continue;
876
37bef230 877 /* Track parity of quotes. */
8489eb67 878 if (code == Sstring)
e5d4f4dc
RS
879 {
880 parity ^= 1;
881 if (my_stringend == 0)
882 my_stringend = c;
37bef230 883 /* If we have two kinds of string delimiters.
e5d4f4dc
RS
884 There's no way to grok this scanning backwards. */
885 else if (my_stringend != c)
886 string_lossage = 1;
887 }
8489eb67
RS
888
889 /* Record comment-starters according to that
890 quote-parity to the comment-end. */
891 if (code == Scomment)
37bef230
RS
892 {
893 comstart_parity = parity;
894 comstart_pos = from;
895 }
8489eb67 896
37bef230
RS
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). */
e5d4f4dc
RS
900 if (code == Sendcomment
901 && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle)
8489eb67 902 break;
37bef230
RS
903
904 /* Assume a defun-start point is outside of strings. */
905 if (code == Sopen
906 && (from == stop || FETCH_CHAR (from - 1) == '\n'))
907 break;
8489eb67 908 }
37bef230
RS
909
910 if (comstart_pos == 0)
911 from = comment_end;
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)
918 from = comstart_pos;
919 else
e5d4f4dc
RS
920 {
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;
37bef230
RS
927 scan_sexps_forward (&state, find_defun_start (comment_end),
928 comment_end - 1, -10000, 0, Qnil);
e5d4f4dc
RS
929 if (state.incomment)
930 from = state.comstart;
931 else
932 /* We can't grok this as a comment; scan it normally. */
933 from = comment_end;
934 }
8489eb67
RS
935 }
936 break;
937
938 case Sstring:
939 stringterm = FETCH_CHAR (from);
940 while (1)
941 {
942 if (from == stop) goto lose;
943 if (!char_quoted (from - 1)
944 && stringterm == FETCH_CHAR (from - 1))
945 break;
946 from--;
947 }
948 from--;
949 if (!depth && sexpflag) goto done2;
950 break;
951 }
952 }
953
954 /* Reached start of buffer. Error if within object, return nil if between */
955 if (depth) goto lose;
956
957 immediate_quit = 0;
958 return Qnil;
959
960 done2:
961 count++;
962 }
963
964
965 immediate_quit = 0;
966 XFASTINT (val) = from;
967 return val;
968
969 lose:
970 error ("Unbalanced parentheses");
971 /* NOTREACHED */
972}
973
974char_quoted (pos)
975 register int pos;
976{
977 register enum syntaxcode code;
978 register int beg = BEGV;
979 register int quoted = 0;
980
981 while (pos > beg
982 && ((code = SYNTAX (FETCH_CHAR (pos - 1))) == Scharquote
983 || code == Sescape))
984 pos--, quoted = !quoted;
985 return quoted;
986}
987
988DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
989 "Scan from character number FROM by COUNT lists.\n\
990Returns the character number of the position thus found.\n\
991\n\
992If DEPTH is nonzero, paren depth begins counting from that value,\n\
993only places where the depth in parentheses becomes zero\n\
994are candidates for stopping; COUNT such places are counted.\n\
995Thus, a positive value for DEPTH means go out levels.\n\
996\n\
997Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
998\n\
999If the beginning or end of (the accessible part of) the buffer is reached\n\
1000and the depth is wrong, an error is signaled.\n\
1001If the depth is right but the count is not used up, nil is returned.")
1002 (from, count, depth)
1003 Lisp_Object from, count, depth;
1004{
1005 CHECK_NUMBER (from, 0);
1006 CHECK_NUMBER (count, 1);
1007 CHECK_NUMBER (depth, 2);
1008
1009 return scan_lists (XINT (from), XINT (count), XINT (depth), 0);
1010}
1011
1012DEFUN ("scan-sexps", Fscan_sexps, Sscan_sexps, 2, 2, 0,
1013 "Scan from character number FROM by COUNT balanced expressions.\n\
1014If COUNT is negative, scan backwards.\n\
1015Returns the character number of the position thus found.\n\
1016\n\
1017Comments are ignored if `parse-sexp-ignore-comments' is non-nil.\n\
1018\n\
1019If the beginning or end of (the accessible part of) the buffer is reached\n\
1020in the middle of a parenthetical grouping, an error is signaled.\n\
1021If the beginning or end is reached between groupings\n\
1022but before count is used up, nil is returned.")
1023 (from, count)
1024 Lisp_Object from, count;
1025{
1026 CHECK_NUMBER (from, 0);
1027 CHECK_NUMBER (count, 1);
1028
1029 return scan_lists (XINT (from), XINT (count), 0, 1);
1030}
1031
1032DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
1033 0, 0, 0,
1034 "Move point backward over any number of chars with prefix syntax.\n\
1035This includes chars with \"quote\" or \"prefix\" syntax (' or p).")
1036 ()
1037{
1038 int beg = BEGV;
1039 int pos = point;
1040
1041 while (pos > beg && !char_quoted (pos - 1)
1042 && (SYNTAX (FETCH_CHAR (pos - 1)) == Squote
1043 || SYNTAX_PREFIX (FETCH_CHAR (pos - 1))))
1044 pos--;
1045
1046 SET_PT (pos);
1047
1048 return Qnil;
1049}
1050\f
8489eb67 1051/* Parse forward from FROM to END,
e5d4f4dc
RS
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. */
8489eb67 1055
e5d4f4dc
RS
1056scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate)
1057 struct lisp_parse_state *stateptr;
8489eb67
RS
1058 register int from;
1059 int end, targetdepth, stopbefore;
1060 Lisp_Object oldstate;
1061{
1062 struct lisp_parse_state state;
1063
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;
1069 char prev;
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 */
1075 Lisp_Object tem;
1076
1077 immediate_quit = 1;
1078 QUIT;
1079
265a9e55 1080 if (NILP (oldstate))
8489eb67
RS
1081 {
1082 depth = 0;
1083 state.instring = -1;
1084 state.incomment = 0;
e5d4f4dc 1085 state.comstyle = 0; /* comment style a by default */
8489eb67
RS
1086 }
1087 else
1088 {
1089 tem = Fcar (oldstate);
265a9e55 1090 if (!NILP (tem))
8489eb67
RS
1091 depth = XINT (tem);
1092 else
1093 depth = 0;
1094
1095 oldstate = Fcdr (oldstate);
1096 oldstate = Fcdr (oldstate);
1097 oldstate = Fcdr (oldstate);
1098 tem = Fcar (oldstate);
265a9e55 1099 state.instring = !NILP (tem) ? XINT (tem) : -1;
8489eb67
RS
1100
1101 oldstate = Fcdr (oldstate);
1102 tem = Fcar (oldstate);
265a9e55 1103 state.incomment = !NILP (tem);
8489eb67
RS
1104
1105 oldstate = Fcdr (oldstate);
1106 tem = Fcar (oldstate);
265a9e55 1107 start_quoted = !NILP (tem);
e5d4f4dc
RS
1108
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);
8489eb67
RS
1116 }
1117 state.quoted = 0;
1118 mindepth = depth;
1119
1120 curlevel->prev = -1;
1121 curlevel->last = -1;
1122
1123 /* Enter the loop at a place appropriate for initial state. */
1124
1125 if (state.incomment) goto startincomment;
1126 if (state.instring >= 0)
1127 {
1128 if (start_quoted) goto startquotedinstring;
1129 goto startinstring;
1130 }
1131 if (start_quoted) goto startquoted;
1132
1133 while (from < end)
1134 {
e5d4f4dc 1135 code = SYNTAX (FETCH_CHAR (from));
8489eb67
RS
1136 from++;
1137 if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
e5d4f4dc
RS
1138 && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))
1139 {
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. */
1143 code = Scomment;
1144 state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
1145 from++;
1146 }
1147
8489eb67
RS
1148 if (SYNTAX_PREFIX (FETCH_CHAR (from - 1)))
1149 continue;
1150#ifdef SWITCH_ENUM_BUG
1151 switch ((int) code)
1152#else
1153 switch (code)
1154#endif
1155 {
1156 case Sescape:
1157 case Scharquote:
1158 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1159 curlevel->last = from - 1;
1160 startquoted:
1161 if (from == end) goto endquoted;
1162 from++;
1163 goto symstarted;
1164 /* treat following character as a word constituent */
1165 case Sword:
1166 case Ssymbol:
1167 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1168 curlevel->last = from - 1;
1169 symstarted:
1170 while (from < end)
1171 {
1172#ifdef SWITCH_ENUM_BUG
e5d4f4dc 1173 switch ((int) SYNTAX (FETCH_CHAR (from)))
8489eb67 1174#else
e5d4f4dc 1175 switch (SYNTAX (FETCH_CHAR (from)))
8489eb67
RS
1176#endif
1177 {
1178 case Scharquote:
1179 case Sescape:
1180 from++;
1181 if (from == end) goto endquoted;
1182 break;
1183 case Sword:
1184 case Ssymbol:
1185 case Squote:
1186 break;
1187 default:
1188 goto symdone;
1189 }
1190 from++;
1191 }
1192 symdone:
1193 curlevel->prev = curlevel->last;
1194 break;
1195
1196 case Scomment:
1197 state.incomment = 1;
e5d4f4dc 1198 state.comstart = from;
8489eb67
RS
1199 startincomment:
1200 while (1)
1201 {
1202 if (from == end) goto done;
e5d4f4dc
RS
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
1208 encountered. */
8489eb67
RS
1209 break;
1210 from++;
1211 if (from < end && SYNTAX_COMEND_FIRST (prev)
e5d4f4dc
RS
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. */
8489eb67
RS
1217 { from++; break; }
1218 }
1219 state.incomment = 0;
e5d4f4dc 1220 state.comstyle = 0; /* reset the comment style */
8489eb67
RS
1221 break;
1222
1223 case Sopen:
1224 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1225 depth++;
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;
1233 break;
1234
1235 case Sclose:
1236 depth--;
1237 if (depth < mindepth)
1238 mindepth = depth;
1239 if (curlevel != levelstart)
1240 curlevel--;
1241 curlevel->prev = curlevel->last;
1242 if (!++targetdepth) goto done;
1243 break;
1244
1245 case Sstring:
1246 if (stopbefore) goto stop; /* this arg means stop at sexp start */
1247 curlevel->last = from - 1;
1248 state.instring = FETCH_CHAR (from - 1);
1249 startinstring:
1250 while (1)
1251 {
1252 if (from >= end) goto done;
1253 if (FETCH_CHAR (from) == state.instring) break;
1254#ifdef SWITCH_ENUM_BUG
e5d4f4dc 1255 switch ((int) SYNTAX (FETCH_CHAR (from)))
8489eb67 1256#else
e5d4f4dc 1257 switch (SYNTAX (FETCH_CHAR (from)))
8489eb67
RS
1258#endif
1259 {
1260 case Scharquote:
1261 case Sescape:
1262 from++;
1263 startquotedinstring:
1264 if (from >= end) goto endquoted;
1265 }
1266 from++;
1267 }
1268 state.instring = -1;
1269 curlevel->prev = curlevel->last;
1270 from++;
1271 break;
1272
1273 case Smath:
1274 break;
1275 }
1276 }
1277 goto done;
1278
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. */
1282
1283 endquoted:
1284 state.quoted = 1;
1285 done:
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;
1292 immediate_quit = 0;
1293
e5d4f4dc 1294 *stateptr = state;
8489eb67
RS
1295}
1296
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.
1300
a4275ad1 1301DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 5, 0,
8489eb67
RS
1302 "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
1303Parsing stops at TO or when certain criteria are met;\n\
1304 point is set to where parsing stops.\n\
1305If fifth arg STATE is omitted or nil,\n\
1306 parsing assumes that FROM is the beginning of a function.\n\
e5d4f4dc 1307Value is a list of eight elements describing final state of parsing:\n\
8489eb67
RS
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\
e5d4f4dc 1316 8. t if in a comment of style `b'.\n\
8489eb67
RS
1317If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
1318in parentheses becomes equal to TARGETDEPTH.\n\
1319Fourth arg STOPBEFORE non-nil means stop when come to\n\
1320 any character that starts a sexp.\n\
1321Fifth arg STATE is a seven-list like what this function returns.\n\
a4275ad1
JB
1322It is used to initialize the state of the parse. Its second and third
1323elements are ignored.")
1324 (from, to, targetdepth, stopbefore, state)
8489eb67
RS
1325*/
1326
1327DEFUN ("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;
1331{
1332 struct lisp_parse_state state;
1333 int target;
1334
265a9e55 1335 if (!NILP (targetdepth))
8489eb67
RS
1336 {
1337 CHECK_NUMBER (targetdepth, 3);
1338 target = XINT (targetdepth);
1339 }
1340 else
1341 target = -100000; /* We won't reach this depth */
1342
1343 validate_region (&from, &to);
e5d4f4dc
RS
1344 scan_sexps_forward (&state, XINT (from), XINT (to),
1345 target, !NILP (stopbefore), oldstate);
8489eb67
RS
1346
1347 SET_PT (state.location);
1348
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,
e5d4f4dc
RS
1355 Fcons (make_number (state.mindepth),
1356 Fcons (state.comstyle ? Qt : Qnil,
1357 Qnil))))))));
8489eb67
RS
1358}
1359\f
1360init_syntax_once ()
1361{
1362 register int i;
1363 register struct Lisp_Vector *v;
1364
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);
1370
1371 v = XVECTOR (Vstandard_syntax_table);
1372
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;
1381
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;
1390
1391 for (i = 0; i < 10; i++)
1392 XFASTINT (v->contents["_-+*/&|<>="[i]]) = (int) Ssymbol;
1393
1394 for (i = 0; i < 12; i++)
1395 XFASTINT (v->contents[".,;:?!#@~^'`"[i]]) = (int) Spunct;
1396}
1397
1398syms_of_syntax ()
1399{
1400 Qsyntax_table_p = intern ("syntax-table-p");
1401 staticpro (&Qsyntax_table_p);
1402
1403 DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments,
1404 "Non-nil means `forward-sexp', etc., should treat comments as whitespace.");
1405
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.");
1409
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);
1418
1419 defsubr (&Sforward_word);
1420
1421 defsubr (&Sscan_lists);
1422 defsubr (&Sscan_sexps);
1423 defsubr (&Sbackward_prefix_chars);
1424 defsubr (&Sparse_partial_sexp);
1425}