X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e5d4f4dc541c0177c62baf13cd75e9c7c83da502..e9e7f5f226df28ed883dc96324094437ea04563e:/src/syntax.c diff --git a/src/syntax.c b/src/syntax.c index aa40547ba5..b6f2da23fc 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -1,5 +1,5 @@ /* GNU Emacs routines to deal with syntax tables; also word and list parsing. - Copyright (C) 1985, 1987, 1992 Free Software Foundation, Inc. + Copyright (C) 1985, 1987, 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -18,7 +18,7 @@ along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include #include #include "lisp.h" #include "commands.h" @@ -27,6 +27,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ Lisp_Object Qsyntax_table_p; +static void scan_sexps_forward (); +static int char_quoted (); + int words_include_escapes; /* This is the internal form of the parse state used in parse-partial-sexp. */ @@ -45,13 +48,70 @@ struct lisp_parse_state int comstart; /* Position just after last comment starter. */ }; +/* These variables are a cache for finding the start of a defun. + find_start_pos is the place for which the defun start was found. + find_start_value is the defun start position found for it. + find_start_buffer is the buffer it was found in. + find_start_begv is the BEGV value when it was found. + find_start_modiff is the value of MODIFF when it was found. */ + +static int find_start_pos; +static int find_start_value; +static struct buffer *find_start_buffer; +static int find_start_begv; +static int find_start_modiff; + +/* Find a defun-start that is the last one before POS (or nearly the last). + We record what we find, so that another call in the same area + can return the same value right away. */ + +static int +find_defun_start (pos) + int pos; +{ + int tem; + int shortage; + + /* Use previous finding, if it's valid and applies to this inquiry. */ + if (current_buffer == find_start_buffer + /* Reuse the defun-start even if POS is a little farther on. + POS might be in the next defun, but that's ok. + Our value may not be the best possible, but will still be usable. */ + && pos <= find_start_pos + 1000 + && pos >= find_start_value + && BEGV == find_start_begv + && MODIFF == find_start_modiff) + return find_start_value; + + /* Back up to start of line. */ + tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1); + + while (tem > BEGV) + { + /* Open-paren at start of line means we found our defun-start. */ + if (SYNTAX (FETCH_CHAR (tem)) == Sopen) + break; + /* Move to beg of previous line. */ + tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1); + } + + /* Record what we found, for the next try. */ + find_start_value = tem; + find_start_buffer = current_buffer; + find_start_modiff = MODIFF; + find_start_begv = BEGV; + find_start_pos = pos; + + return find_start_value; +} + DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0, "Return t if ARG is a syntax table.\n\ Any vector of 256 elements will do.") (obj) Lisp_Object obj; { - if (XTYPE (obj) == Lisp_Vector && XVECTOR (obj)->size == 0400) + if (VECTORP (obj) && XVECTOR (obj)->size == 0400) return Qt; return Qnil; } @@ -63,7 +123,7 @@ check_syntax_table (obj) register Lisp_Object tem; while (tem = Fsyntax_table_p (obj), NILP (tem)) - obj = wrong_type_argument (Qsyntax_table_p, obj, 0); + obj = wrong_type_argument (Qsyntax_table_p, obj); return obj; } @@ -92,8 +152,8 @@ It is a copy of the TABLE, which defaults to the standard syntax table.") Lisp_Object table; { Lisp_Object size, val; - XFASTINT (size) = 0400; - XFASTINT (val) = 0; + XSETFASTINT (size, 0400); + XSETFASTINT (val, 0); val = Fmake_vector (size, val); if (!NILP (table)) table = check_syntax_table (table); @@ -116,7 +176,8 @@ One argument, a syntax table.") table = check_syntax_table (table); current_buffer->syntax_table = table; /* Indicate that this buffer now has a specified syntax table. */ - current_buffer->local_var_flags |= buffer_local_flags.syntax_table; + current_buffer->local_var_flags + |= XFASTINT (buffer_local_flags.syntax_table); return table; } @@ -136,7 +197,7 @@ unsigned char syntax_spec_code[0400] = 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Scomment, 0377, (char) Sendcomment, 0377, - 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A, ... */ + (char) Sinherit, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* @, A ... */ 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, 0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol, @@ -148,9 +209,9 @@ unsigned char syntax_spec_code[0400] = /* Indexed by syntax code, give the letter that describes it. */ -char syntax_code_spec[13] = +char syntax_code_spec[14] = { - ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>' + ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@' }; DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0, @@ -162,14 +223,27 @@ are listed in the documentation of `modify-syntax-entry'.") Lisp_Object ch; { CHECK_NUMBER (ch, 0); - return make_number (syntax_code_spec[(int) SYNTAX (0xFF & XINT (ch))]); + return make_number (syntax_code_spec[(int) SYNTAX (XINT (ch))]); +} + +DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0, + "Return the matching parenthesis of CHAR, or nil if none.") + (ch) + Lisp_Object ch; +{ + int code; + CHECK_NUMBER (ch, 0); + code = SYNTAX (XINT (ch)); + if (code == Sopen || code == Sclose) + return make_number (SYNTAX_MATCH (XINT (ch))); + return Qnil; } /* This comment supplies the doc string for modify-syntax-entry, for make-docfile to see. We cannot put this in the real DEFUN due to limits in the Unix cpp. -DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0, +DEFUN ("modify-syntax-entry", foo, bar, 2, 3, 0, "Set syntax for character CHAR according to string S.\n\ The syntax is changed only for table TABLE, which defaults to\n\ the current buffer's syntax table.\n\ @@ -179,8 +253,9 @@ The first character of S should be one of the following:\n\ ( open-parenthesis. ) close-parenthesis.\n\ \" string quote. \\ escape.\n\ $ paired delimiter. ' expression quote or prefix operator.\n\ - < comment starter. > comment ender.\n\ - / character-quote.\n\ + < comment starter. > comment ender.\n\ + / character-quote. @ inherit from `standard-syntax-table'.\n\ +\n\ Only single-character comment start and end sequences are represented thus.\n\ Two-character sequences are represented as described below.\n\ The second character of S is the matching parenthesis,\n\ @@ -194,15 +269,15 @@ Defined flags are the characters 1, 2, 3, 4, b, and p.\n\ \n\ There can be up to two orthogonal comment sequences. This is to support\n\ language modes such as C++. By default, all comment sequences are of style\n\ -a, but you can set the comment sequence style to b (on the second character of a\n\ -comment-start, or the first character of a comment-end sequence) by using\n\ +a, but you can set the comment sequence style to b (on the second character\n\ +of a comment-start, or the first character of a comment-end sequence) using\n\ this flag:\n\ b means C is part of comment sequence b.\n\ \n\ p means C is a prefix character for `backward-prefix-chars';\n\ such characters are treated as whitespace when they occur\n\ between expressions.") - + (char, s, table) */ DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3, @@ -216,7 +291,7 @@ DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3, { register unsigned char *p, match; register enum syntaxcode code; - Lisp_Object val; + int val; CHECK_NUMBER (c, 0); CHECK_STRING (newentry, 1); @@ -234,42 +309,43 @@ DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3, if (match) p++; if (match == ' ') match = 0; - XFASTINT (val) = (match << 8) + (int) code; + val = (match << 8) + (int) code; while (*p) switch (*p++) { case '1': - XFASTINT (val) |= 1 << 16; + val |= 1 << 16; break; case '2': - XFASTINT (val) |= 1 << 17; + val |= 1 << 17; break; case '3': - XFASTINT (val) |= 1 << 18; + val |= 1 << 18; break; case '4': - XFASTINT (val) |= 1 << 19; + val |= 1 << 19; break; case 'p': - XFASTINT (val) |= 1 << 20; + val |= 1 << 20; break; case 'b': - XFASTINT (val) |= 1 << 21; + val |= 1 << 21; break; } - XVECTOR (syntax_table)->contents[0xFF & XINT (c)] = val; + XSETFASTINT (XVECTOR (syntax_table)->contents[0xFF & XINT (c)], val); return Qnil; } /* Dump syntax table to buffer in human-readable format */ +static void describe_syntax (value) Lisp_Object value; { @@ -279,7 +355,7 @@ describe_syntax (value) Findent_to (make_number (16), make_number (1)); - if (XTYPE (value) != Lisp_Int) + if (!INTEGERP (value)) { insert_string ("invalid"); return; @@ -325,11 +401,7 @@ describe_syntax (value) insert_string ("\twhich means: "); -#ifdef SWITCH_ENUM_BUG - switch ((int) code) -#else - switch (code) -#endif + switch (SWITCH_ENUM_CAST (code)) { case Swhitespace: insert_string ("whitespace"); break; @@ -357,6 +429,8 @@ describe_syntax (value) insert_string ("comment"); break; case Sendcomment: insert_string ("endcomment"); break; + case Sinherit: + insert_string ("inherit"); break; default: insert_string ("invalid"); return; @@ -365,9 +439,7 @@ describe_syntax (value) if (match) { insert_string (", matches "); - - str[0] = match, str[1] = 0; - insert (str, 1); + insert_char (match); } if (start1) @@ -388,13 +460,14 @@ describe_syntax (value) insert_string ("\n"); } -Lisp_Object +static Lisp_Object describe_syntax_1 (vector) Lisp_Object vector; { struct buffer *old = current_buffer; set_buffer_internal (XBUFFER (Vstandard_output)); - describe_vector (vector, Qnil, describe_syntax, 0, Qnil, Qnil); + describe_vector (vector, Qnil, describe_syntax, 0, Qnil); + call0 (intern ("help-mode")); set_buffer_internal (old); return Qnil; } @@ -508,6 +581,280 @@ and nil is returned.") return Qt; } +DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, + "Move forward across up to N comments. If N is negative, move backward.\n\ +Stop scanning if we find something other than a comment or whitespace.\n\ +Set point to where scanning stops.\n\ +If N comments are found as expected, with nothing except whitespace\n\ +between them, return t; otherwise return nil.") + (count) + Lisp_Object count; +{ + register int from; + register int stop; + register int c; + register enum syntaxcode code; + int comstyle = 0; /* style of comment encountered */ + int found; + int count1; + + CHECK_NUMBER (count, 0); + count1 = XINT (count); + + immediate_quit = 1; + QUIT; + + from = PT; + + while (count1 > 0) + { + stop = ZV; + do + { + if (from == stop) + { + SET_PT (from); + immediate_quit = 0; + return Qnil; + } + c = FETCH_CHAR (from); + code = SYNTAX (c); + from++; + comstyle = 0; + if (from < stop && SYNTAX_COMSTART_FIRST (c) + && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) + { + /* We have encountered a comment start sequence and we + are ignoring all text inside comments. We must record + the comment style this sequence begins so that later, + only a comment end of the same style actually ends + the comment section. */ + code = Scomment; + comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)); + from++; + } + } + while (code == Swhitespace || code == Sendcomment); + if (code != Scomment) + { + immediate_quit = 0; + SET_PT (from - 1); + return Qnil; + } + /* We're at the start of a comment. */ + while (1) + { + if (from == stop) + { + immediate_quit = 0; + SET_PT (from); + return Qnil; + } + c = FETCH_CHAR (from); + from++; + if (SYNTAX (c) == Sendcomment + && SYNTAX_COMMENT_STYLE (c) == comstyle) + /* we have encountered a comment end of the same style + as the comment sequence which began this comment + section */ + break; + if (from < stop && SYNTAX_COMEND_FIRST (c) + && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) + && SYNTAX_COMMENT_STYLE (c) == comstyle) + /* we have encountered a comment end of the same style + as the comment sequence which began this comment + section */ + { from++; break; } + } + /* We have skipped one comment. */ + count1--; + } + + while (count1 < 0) + { + stop = BEGV; + while (from > stop) + { + int quoted; + + from--; + quoted = char_quoted (from); + if (quoted) + from--; + c = FETCH_CHAR (from); + code = SYNTAX (c); + comstyle = 0; + if (code == Sendcomment) + comstyle = SYNTAX_COMMENT_STYLE (c); + if (from > stop && SYNTAX_COMEND_SECOND (c) + && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)) + && !char_quoted (from - 1)) + { + /* We must record the comment style encountered so that + later, we can match only the proper comment begin + sequence of the same style. */ + code = Sendcomment; + comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from - 1)); + from--; + } + + if (code == Sendcomment && !quoted) + { +#if 0 + if (code != SYNTAX (c)) + /* For a two-char comment ender, we can assume + it does end a comment. So scan back in a simple way. */ + { + if (from != stop) from--; + while (1) + { + if (SYNTAX (c = FETCH_CHAR (from)) == Scomment + && SYNTAX_COMMENT_STYLE (c) == comstyle) + break; + if (from == stop) + { + immediate_quit = 0; + SET_PT (from); + return Qnil; + } + from--; + if (SYNTAX_COMSTART_SECOND (c) + && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from)) + && SYNTAX_COMMENT_STYLE (c) == comstyle + && !char_quoted (from)) + break; + } + break; + } +#endif /* 0 */ + + /* Look back, counting the parity of string-quotes, + and recording the comment-starters seen. + When we reach a safe place, assume that's not in a string; + then step the main scan to the earliest comment-starter seen + an even number of string quotes away from the safe place. + + OFROM[I] is position of the earliest comment-starter seen + which is I+2X quotes from the comment-end. + PARITY is current parity of quotes from the comment end. */ + { + int parity = 0; + char my_stringend = 0; + int string_lossage = 0; + int comment_end = from; + int comstart_pos = 0; + int comstart_parity = 0; + int scanstart = from - 1; + + /* At beginning of range to scan, we're outside of strings; + that determines quote parity to the comment-end. */ + while (from != stop) + { + /* Move back and examine a character. */ + from--; + + c = FETCH_CHAR (from); + code = SYNTAX (c); + + /* If this char is the second of a 2-char comment sequence, + back up and give the pair the appropriate syntax. */ + if (from > stop && SYNTAX_COMEND_SECOND (c) + && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))) + { + code = Sendcomment; + from--; + c = FETCH_CHAR (from); + } + + /* If this char starts a 2-char comment start sequence, + treat it like a 1-char comment starter. */ + if (from < scanstart && SYNTAX_COMSTART_FIRST (c) + && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1)) + && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1))) + code = Scomment; + + /* Ignore escaped characters. */ + if (char_quoted (from)) + continue; + + /* Track parity of quotes. */ + if (code == Sstring) + { + parity ^= 1; + if (my_stringend == 0) + my_stringend = c; + /* If we have two kinds of string delimiters. + There's no way to grok this scanning backwards. */ + else if (my_stringend != c) + string_lossage = 1; + } + + /* Record comment-starters according to that + quote-parity to the comment-end. */ + if (code == Scomment) + { + comstart_parity = parity; + comstart_pos = from; + } + + /* If we find another earlier comment-ender, + any comment-starts earlier than that don't count + (because they go with the earlier comment-ender). */ + if (code == Sendcomment + && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle) + break; + + /* Assume a defun-start point is outside of strings. */ + if (code == Sopen + && (from == stop || FETCH_CHAR (from - 1) == '\n')) + break; + } + + if (comstart_pos == 0) + from = comment_end; + /* If the earliest comment starter + is followed by uniform paired string quotes or none, + we know it can't be inside a string + since if it were then the comment ender would be inside one. + So it does start a comment. Skip back to it. */ + else if (comstart_parity == 0 && !string_lossage) + from = comstart_pos; + else + { + /* We had two kinds of string delimiters mixed up + together. Decode this going forwards. + Scan fwd from the previous comment ender + to the one in question; this records where we + last passed a comment starter. */ + struct lisp_parse_state state; + scan_sexps_forward (&state, find_defun_start (comment_end), + comment_end - 1, -10000, 0, Qnil, 0); + if (state.incomment) + from = state.comstart; + else + /* We can't grok this as a comment; scan it normally. */ + from = comment_end; + } + } + /* We have skipped one comment. */ + break; + } + else if ((code != Swhitespace && code != Scomment) || quoted) + { + immediate_quit = 0; + SET_PT (from + 1); + return Qnil; + } + } + + count1++; + } + + SET_PT (from); + immediate_quit = 0; + return Qt; +} + int parse_sexp_ignore_comments; Lisp_Object @@ -555,11 +902,7 @@ scan_lists (from, count, depth, sexpflag) if (SYNTAX_PREFIX (c)) continue; -#ifdef SWITCH_ENUM_BUG - switch ((int) code) -#else - switch (code) -#endif + switch (SWITCH_ENUM_CAST (code)) { case Sescape: case Scharquote: @@ -572,11 +915,7 @@ scan_lists (from, count, depth, sexpflag) /* This word counts as a sexp; return at end of it. */ while (from < stop) { -#ifdef SWITCH_ENUM_BUG - switch ((int) SYNTAX (FETCH_CHAR (from))) -#else - switch (SYNTAX (FETCH_CHAR (from))) -#endif + switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) { case Scharquote: case Sescape: @@ -598,7 +937,12 @@ scan_lists (from, count, depth, sexpflag) if (!parse_sexp_ignore_comments) break; while (1) { - if (from == stop) goto done; + if (from == stop) + { + if (depth == 0) + goto done; + goto lose; + } c = FETCH_CHAR (from); if (SYNTAX (c) == Sendcomment && SYNTAX_COMMENT_STYLE (c) == comstyle) @@ -646,11 +990,7 @@ scan_lists (from, count, depth, sexpflag) { if (from >= stop) goto lose; if (FETCH_CHAR (from) == stringterm) break; -#ifdef SWITCH_ENUM_BUG - switch ((int) SYNTAX (FETCH_CHAR (from))) -#else - switch (SYNTAX (FETCH_CHAR (from))) -#endif + switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) { case Scharquote: case Sescape: @@ -685,6 +1025,9 @@ scan_lists (from, count, depth, sexpflag) from--; c = FETCH_CHAR (from); code = SYNTAX (c); + comstyle = 0; + if (code == Sendcomment) + comstyle = SYNTAX_COMMENT_STYLE (c); if (from > stop && SYNTAX_COMEND_SECOND (c) && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)) && !char_quoted (from - 1) @@ -701,11 +1044,7 @@ scan_lists (from, count, depth, sexpflag) if (SYNTAX_PREFIX (c)) continue; -#ifdef SWITCH_ENUM_BUG - switch ((int) (quoted ? Sword : code)) -#else - switch (quoted ? Sword : code) -#endif + switch (SWITCH_ENUM_CAST (quoted ? Sword : code)) { case Sword: case Ssymbol: @@ -750,6 +1089,34 @@ scan_lists (from, count, depth, sexpflag) case Sendcomment: if (!parse_sexp_ignore_comments) break; +#if 0 + if (code != SYNTAX (c)) + /* For a two-char comment ender, we can assume + it does end a comment. So scan back in a simple way. */ + { + if (from != stop) from--; + while (1) + { + if (SYNTAX (c = FETCH_CHAR (from)) == Scomment + && SYNTAX_COMMENT_STYLE (c) == comstyle) + break; + if (from == stop) + { + if (depth == 0) + goto done2; + goto lose; + } + from--; + if (SYNTAX_COMSTART_SECOND (c) + && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from)) + && SYNTAX_COMMENT_STYLE (c) == comstyle + && !char_quoted (from)) + break; + } + break; + } +#endif /* 0 */ + /* Look back, counting the parity of string-quotes, and recording the comment-starters seen. When we reach a safe place, assume that's not in a string; @@ -760,13 +1127,13 @@ scan_lists (from, count, depth, sexpflag) which is I+2X quotes from the comment-end. PARITY is current parity of quotes from the comment end. */ { - int ofrom[2]; int parity = 0; char my_stringend = 0; int string_lossage = 0; int comment_end = from; - - ofrom[0] = ofrom[1] = from; + int comstart_pos = 0; + int comstart_parity = 0; + int scanstart = from - 1; /* At beginning of range to scan, we're outside of strings; that determines quote parity to the comment-end. */ @@ -785,27 +1152,27 @@ scan_lists (from, count, depth, sexpflag) { code = Sendcomment; from--; + c = FETCH_CHAR (from); } - else if (from > stop && SYNTAX_COMSTART_SECOND (c) - && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1)) - && comstyle == SYNTAX_COMMENT_STYLE (c)) - { - code = Scomment; - from--; - } + /* If this char starts a 2-char comment start sequence, + treat it like a 1-char comment starter. */ + if (from < scanstart && SYNTAX_COMSTART_FIRST (c) + && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1)) + && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1))) + code = Scomment; /* Ignore escaped characters. */ if (char_quoted (from)) continue; - /* Track parity of quotes between here and comment-end. */ + /* Track parity of quotes. */ if (code == Sstring) { parity ^= 1; if (my_stringend == 0) my_stringend = c; - /* We have two kinds of string delimiters. + /* If we have two kinds of string delimiters. There's no way to grok this scanning backwards. */ else if (my_stringend != c) string_lossage = 1; @@ -814,18 +1181,34 @@ scan_lists (from, count, depth, sexpflag) /* Record comment-starters according to that quote-parity to the comment-end. */ if (code == Scomment) - ofrom[parity] = from; + { + comstart_parity = parity; + comstart_pos = from; + } - /* If we come to another comment-end, - assume it's not inside a string. - That determines the quote parity to the comment-end. - Note that the comment style this character ends must - match the style that we have begun */ + /* If we find another earlier comment-ender, + any comment-starts earlier than that don't count + (because they go with the earlier comment-ender). */ if (code == Sendcomment && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle) break; + + /* Assume a defun-start point is outside of strings. */ + if (code == Sopen + && (from == stop || FETCH_CHAR (from - 1) == '\n')) + break; } - if (string_lossage) + + if (comstart_pos == 0) + from = comment_end; + /* If the earliest comment starter + is followed by uniform paired string quotes or none, + we know it can't be inside a string + since if it were then the comment ender would be inside one. + So it does start a comment. Skip back to it. */ + else if (comstart_parity == 0 && !string_lossage) + from = comstart_pos; + else { /* We had two kinds of string delimiters mixed up together. Decode this going forwards. @@ -833,16 +1216,14 @@ scan_lists (from, count, depth, sexpflag) to the one in question; this records where we last passed a comment starter. */ struct lisp_parse_state state; - scan_sexps_forward (&state, from + 1, comment_end - 1, - -10000, 0, Qnil); + scan_sexps_forward (&state, find_defun_start (comment_end), + comment_end - 1, -10000, 0, Qnil, 0); if (state.incomment) from = state.comstart; else /* We can't grok this as a comment; scan it normally. */ from = comment_end; } - else - from = ofrom[parity]; } break; @@ -874,7 +1255,7 @@ scan_lists (from, count, depth, sexpflag) immediate_quit = 0; - XFASTINT (val) = from; + XSETFASTINT (val, from); return val; lose: @@ -882,6 +1263,7 @@ scan_lists (from, count, depth, sexpflag) /* NOTREACHED */ } +static int char_quoted (pos) register int pos; { @@ -962,13 +1344,17 @@ This includes chars with \"quote\" or \"prefix\" syntax (' or p).") /* Parse forward from FROM to END, assuming that FROM has state OLDSTATE (nil means FROM is start of function), and return a description of the state of the parse at END. - If STOPBEFORE is nonzero, stop at the start of an atom. */ + If STOPBEFORE is nonzero, stop at the start of an atom. + If COMMENTSTOP is nonzero, stop at the start of a comment. */ -scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) +static void +scan_sexps_forward (stateptr, from, end, targetdepth, + stopbefore, oldstate, commentstop) struct lisp_parse_state *stateptr; register int from; int end, targetdepth, stopbefore; Lisp_Object oldstate; + int commentstop; { struct lisp_parse_state state; @@ -1021,7 +1407,6 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) style a. if it is non-nil, we are in comment style b */ oldstate = Fcdr (oldstate); oldstate = Fcdr (oldstate); - oldstate = Fcdr (oldstate); tem = Fcar (oldstate); state.comstyle = !NILP (tem); } @@ -1045,24 +1430,24 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) { code = SYNTAX (FETCH_CHAR (from)); from++; - if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1)) - && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) + if (code == Scomment) + state.comstart = from-1; + + else if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1)) + && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) { /* Record the comment style we have entered so that only the comment-end sequence of the same style actually terminates the comment section. */ code = Scomment; state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)); + state.comstart = from-1; from++; } if (SYNTAX_PREFIX (FETCH_CHAR (from - 1))) continue; -#ifdef SWITCH_ENUM_BUG - switch ((int) code) -#else - switch (code) -#endif + switch (SWITCH_ENUM_CAST (code)) { case Sescape: case Scharquote: @@ -1080,11 +1465,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) symstarted: while (from < end) { -#ifdef SWITCH_ENUM_BUG - switch ((int) SYNTAX (FETCH_CHAR (from))) -#else - switch (SYNTAX (FETCH_CHAR (from))) -#endif + switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) { case Scharquote: case Sescape: @@ -1104,10 +1485,22 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) curlevel->prev = curlevel->last; break; + startincomment: + if (commentstop) + goto done; + if (from != BEGV) + { + /* Enter the loop in the middle so that we find + a 2-char comment ender if we start in the middle of it. */ + prev = FETCH_CHAR (from - 1); + goto startincomment_1; + } + /* At beginning of buffer, enter the loop the ordinary way. */ + case Scomment: state.incomment = 1; - state.comstart = from; - startincomment: + if (commentstop) + goto done; while (1) { if (from == end) goto done; @@ -1119,6 +1512,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) encountered. */ break; from++; + startincomment_1: if (from < end && SYNTAX_COMEND_FIRST (prev) && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) && SYNTAX_COMMENT_STYLE (prev) == state.comstyle) @@ -1162,11 +1556,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) { if (from >= end) goto done; if (FETCH_CHAR (from) == state.instring) break; -#ifdef SWITCH_ENUM_BUG - switch ((int) SYNTAX (FETCH_CHAR (from))) -#else - switch (SYNTAX (FETCH_CHAR (from))) -#endif + switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) { case Scharquote: case Sescape: @@ -1209,36 +1599,37 @@ scan_sexps_forward (stateptr, from, end, targetdepth, stopbefore, oldstate) for make-docfile to see. We cannot put this in the real DEFUN due to limits in the Unix cpp. -DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 5, 0, +DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 2, 6, 0, "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\ Parsing stops at TO or when certain criteria are met;\n\ point is set to where parsing stops.\n\ If fifth arg STATE is omitted or nil,\n\ parsing assumes that FROM is the beginning of a function.\n\ Value is a list of eight elements describing final state of parsing:\n\ - 1. depth in parens.\n\ - 2. character address of start of innermost containing list; nil if none.\n\ - 3. character address of start of last complete sexp terminated.\n\ - 4. non-nil if inside a string.\n\ + 0. depth in parens.\n\ + 1. character address of start of innermost containing list; nil if none.\n\ + 2. character address of start of last complete sexp terminated.\n\ + 3. non-nil if inside a string.\n\ (it is the character that will terminate the string.)\n\ - 5. t if inside a comment.\n\ - 6. t if following a quote character.\n\ - 7. the minimum paren-depth encountered during this scan.\n\ - 8. t if in a comment of style `b'.\n\ + 4. t if inside a comment.\n\ + 5. t if following a quote character.\n\ + 6. the minimum paren-depth encountered during this scan.\n\ + 7. t if in a comment of style `b'.\n\ If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\ in parentheses becomes equal to TARGETDEPTH.\n\ Fourth arg STOPBEFORE non-nil means stop when come to\n\ any character that starts a sexp.\n\ -Fifth arg STATE is a seven-list like what this function returns.\n\ +Fifth arg STATE is an eight-list like what this function returns.\n\ It is used to initialize the state of the parse. Its second and third -elements are ignored.") - (from, to, targetdepth, stopbefore, state) +elements are ignored. +Sixth args COMMENTSTOP non-nil means stop at the start of a comment.") + (from, to, targetdepth, stopbefore, state, commentstop) */ -DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 5, 0, +DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0, 0 /* See immediately above */) - (from, to, targetdepth, stopbefore, oldstate) - Lisp_Object from, to, targetdepth, stopbefore, oldstate; + (from, to, targetdepth, stopbefore, oldstate, commentstop) + Lisp_Object from, to, targetdepth, stopbefore, oldstate, commentstop; { struct lisp_parse_state state; int target; @@ -1253,7 +1644,8 @@ DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 5, 0, validate_region (&from, &to); scan_sexps_forward (&state, XINT (from), XINT (to), - target, !NILP (stopbefore), oldstate); + target, !NILP (stopbefore), oldstate, + !NILP (commentstop)); SET_PT (state.location); @@ -1282,28 +1674,28 @@ init_syntax_once () v = XVECTOR (Vstandard_syntax_table); for (i = 'a'; i <= 'z'; i++) - XFASTINT (v->contents[i]) = (int) Sword; + XSETFASTINT (v->contents[i], (int) Sword); for (i = 'A'; i <= 'Z'; i++) - XFASTINT (v->contents[i]) = (int) Sword; + XSETFASTINT (v->contents[i], (int) Sword); for (i = '0'; i <= '9'; i++) - XFASTINT (v->contents[i]) = (int) Sword; - XFASTINT (v->contents['$']) = (int) Sword; - XFASTINT (v->contents['%']) = (int) Sword; - - XFASTINT (v->contents['(']) = (int) Sopen + (')' << 8); - XFASTINT (v->contents[')']) = (int) Sclose + ('(' << 8); - XFASTINT (v->contents['[']) = (int) Sopen + (']' << 8); - XFASTINT (v->contents[']']) = (int) Sclose + ('[' << 8); - XFASTINT (v->contents['{']) = (int) Sopen + ('}' << 8); - XFASTINT (v->contents['}']) = (int) Sclose + ('{' << 8); - XFASTINT (v->contents['"']) = (int) Sstring; - XFASTINT (v->contents['\\']) = (int) Sescape; + XSETFASTINT (v->contents[i], (int) Sword); + XSETFASTINT (v->contents['$'], (int) Sword); + XSETFASTINT (v->contents['%'], (int) Sword); + + XSETFASTINT (v->contents['('], (int) Sopen + (')' << 8)); + XSETFASTINT (v->contents[')'], (int) Sclose + ('(' << 8)); + XSETFASTINT (v->contents['['], (int) Sopen + (']' << 8)); + XSETFASTINT (v->contents[']'], (int) Sclose + ('[' << 8)); + XSETFASTINT (v->contents['{'], (int) Sopen + ('}' << 8)); + XSETFASTINT (v->contents['}'], (int) Sclose + ('{' << 8)); + XSETFASTINT (v->contents['"'], (int) Sstring); + XSETFASTINT (v->contents['\\'], (int) Sescape); for (i = 0; i < 10; i++) - XFASTINT (v->contents["_-+*/&|<>="[i]]) = (int) Ssymbol; + XSETFASTINT (v->contents["_-+*/&|<>="[i]], (int) Ssymbol); for (i = 0; i < 12; i++) - XFASTINT (v->contents[".,;:?!#@~^'`"[i]]) = (int) Spunct; + XSETFASTINT (v->contents[".,;:?!#@~^'`"[i]], (int) Spunct); } syms_of_syntax () @@ -1324,11 +1716,13 @@ syms_of_syntax () defsubr (&Scopy_syntax_table); defsubr (&Sset_syntax_table); defsubr (&Schar_syntax); + defsubr (&Smatching_paren); defsubr (&Smodify_syntax_entry); defsubr (&Sdescribe_syntax); defsubr (&Sforward_word); + defsubr (&Sforward_comment); defsubr (&Sscan_lists); defsubr (&Sscan_sexps); defsubr (&Sbackward_prefix_chars);