diff options
| author | Richard M. Stallman | 1997-04-15 04:53:58 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-04-15 04:53:58 +0000 |
| commit | 195d13612d320503ec7efe4fbf8acbaa114114db (patch) | |
| tree | bab72c741f8fcf365f781dbe30d4e7840b0fee98 /src/syntax.c | |
| parent | 8bb43c28a30734966e16c7968baafb469a0a3f18 (diff) | |
| download | emacs-195d13612d320503ec7efe4fbf8acbaa114114db.tar.gz emacs-195d13612d320503ec7efe4fbf8acbaa114114db.zip | |
(SYNTAX_ENTRY_VIA_PROPERTY): Set to take `syntax-table'
text property into account when doing SYNTAX (c).
(ST_COMMENT_STYLE, ST_STRING_STYLE): New codes to denote
delimiters for new types of strings and comments.
(Vparse_sexp_lookup_properties): New variable.
(struct lisp_parse_state): Comment updated.
(gl_state): New global variable.
(update_syntax_table): New function.
(char_quoted): Move earlier, update gl_state when needed.
(find_defun_start): Update gl_state when needed.
(back_comment): New function.
(Scomment_fence, Sstring_fence): New delimeter char classes
denoted by `!' and `|'.
(Fchar_syntax, Fmatching_paren): Update gl_state to whole-bufferstate.
(scan_words): update gl_state when needed.
(Fskip_chars_forward): Move from search.c.
(Fskip_chars_backward): Move from search.c.
(Fskip_syntax_forward): Move from search.c.
(Fskip_syntax_backward): Move from search.c.
(skip_chars): Move from search.c.
(Fforward_comment, scan_lists): Update gl_state when needed.
Handle Scomment_fence, Sstring_fence.
(Fbackward_prefix_chars) Update gl_state when needed.
(scan_sexps_forward): Update gl_state when needed.
Handle Scomment_fence, Sstring_fence. If comment_stop==-1, stop at start
or end of comment or string.
(Fparse-partial-sexp): Doc fix.
(syms_of_syntax): Move initialization of skip* from search.c.
Diffstat (limited to 'src/syntax.c')
| -rw-r--r-- | src/syntax.c | 884 |
1 files changed, 783 insertions, 101 deletions
diff --git a/src/syntax.c b/src/syntax.c index ee935e77911..3cf575b71eb 100644 --- a/src/syntax.c +++ b/src/syntax.c | |||
| @@ -25,7 +25,19 @@ Boston, MA 02111-1307, USA. */ | |||
| 25 | #include "commands.h" | 25 | #include "commands.h" |
| 26 | #include "buffer.h" | 26 | #include "buffer.h" |
| 27 | #include "charset.h" | 27 | #include "charset.h" |
| 28 | |||
| 29 | /* Make syntax table lookup grant data in gl_state. */ | ||
| 30 | #define SYNTAX_ENTRY_VIA_PROPERTY | ||
| 31 | |||
| 28 | #include "syntax.h" | 32 | #include "syntax.h" |
| 33 | #include "intervals.h" | ||
| 34 | |||
| 35 | /* We use these constants in place for comment-style and | ||
| 36 | string-ender-char to distinguish comments/strings started by | ||
| 37 | comment_fence and string_fence codes. */ | ||
| 38 | |||
| 39 | #define ST_COMMENT_STYLE (256 + 1) | ||
| 40 | #define ST_STRING_STYLE (256 + 2) | ||
| 29 | #include "category.h" | 41 | #include "category.h" |
| 30 | 42 | ||
| 31 | Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error; | 43 | Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error; |
| @@ -34,6 +46,7 @@ static void scan_sexps_forward (); | |||
| 34 | static int char_quoted (); | 46 | static int char_quoted (); |
| 35 | 47 | ||
| 36 | int words_include_escapes; | 48 | int words_include_escapes; |
| 49 | int parse_sexp_lookup_properties; | ||
| 37 | 50 | ||
| 38 | /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h, | 51 | /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h, |
| 39 | if not compiled with GCC. No need to mark it, since it is used | 52 | if not compiled with GCC. No need to mark it, since it is used |
| @@ -44,16 +57,16 @@ Lisp_Object syntax_temp; | |||
| 44 | 57 | ||
| 45 | struct lisp_parse_state | 58 | struct lisp_parse_state |
| 46 | { | 59 | { |
| 47 | int depth; /* Depth at end of parsing */ | 60 | int depth; /* Depth at end of parsing. */ |
| 48 | int instring; /* -1 if not within string, else desired terminator. */ | 61 | int instring; /* -1 if not within string, else desired terminator. */ |
| 49 | int incomment; /* Nonzero if within a comment at end of parsing */ | 62 | int incomment; /* Nonzero if within a comment at end of parsing. */ |
| 50 | int comstyle; /* comment style a=0, or b=1 */ | 63 | int comstyle; /* comment style a=0, or b=1, or ST_COMMENT_STYLE. */ |
| 51 | int quoted; /* Nonzero if just after an escape char at end of parsing */ | 64 | int quoted; /* Nonzero if just after an escape char at end of parsing */ |
| 52 | int thislevelstart; /* Char number of most recent start-of-expression at current level */ | 65 | int thislevelstart; /* Char number of most recent start-of-expression at current level */ |
| 53 | int prevlevelstart; /* Char number of start of containing expression */ | 66 | int prevlevelstart; /* Char number of start of containing expression */ |
| 54 | int location; /* Char number at which parsing stopped. */ | 67 | int location; /* Char number at which parsing stopped. */ |
| 55 | int mindepth; /* Minimum depth seen while scanning. */ | 68 | int mindepth; /* Minimum depth seen while scanning. */ |
| 56 | int comstart; /* Position just after last comment starter. */ | 69 | int comstr_start; /* Position just after last comment/string starter. */ |
| 57 | }; | 70 | }; |
| 58 | 71 | ||
| 59 | /* These variables are a cache for finding the start of a defun. | 72 | /* These variables are a cache for finding the start of a defun. |
| @@ -68,10 +81,205 @@ static int find_start_value; | |||
| 68 | static struct buffer *find_start_buffer; | 81 | static struct buffer *find_start_buffer; |
| 69 | static int find_start_begv; | 82 | static int find_start_begv; |
| 70 | static int find_start_modiff; | 83 | static int find_start_modiff; |
| 84 | |||
| 85 | |||
| 86 | struct gl_state_s gl_state; /* Global state of syntax parser. */ | ||
| 87 | |||
| 88 | INTERVAL interval_of (); | ||
| 89 | #define INTERVALS_AT_ONCE 10 /* 1 + max-number of intervals | ||
| 90 | to scan to property-change. */ | ||
| 91 | |||
| 92 | /* | ||
| 93 | Update gl_state to an appropriate interval which contains POS. The | ||
| 94 | sign of COUNT give the relative position of POS wrt the previously | ||
| 95 | valid interval. If INIT, only [be]_property fields of gl_state are | ||
| 96 | valid at start, the rest is filled basing on OBJECT. | ||
| 97 | |||
| 98 | `gl_state.*_i' are the intervals, and pos is further in the search | ||
| 99 | direction than the intervals - or in an interval. We update the | ||
| 100 | current syntax-table basing on the property of this interval, and | ||
| 101 | update the interval to start further than POS - or be | ||
| 102 | NULL_INTERVAL. We also update lim_property to be the next value of | ||
| 103 | pos to call this subroutine again - or be before/after the | ||
| 104 | start/end of OBJECT. */ | ||
| 105 | |||
| 106 | void | ||
| 107 | update_syntax_table (pos, count, init, object) | ||
| 108 | int pos, count, init; | ||
| 109 | Lisp_Object object; | ||
| 110 | { | ||
| 111 | Lisp_Object tmp_table; | ||
| 112 | int cnt = 0, doing_extra = 0, invalidate = 1; | ||
| 113 | INTERVAL i, oldi; | ||
| 114 | |||
| 115 | if (init) | ||
| 116 | { | ||
| 117 | gl_state.start = gl_state.b_property; | ||
| 118 | gl_state.stop = gl_state.e_property; | ||
| 119 | gl_state.forward_i = interval_of (pos, object); | ||
| 120 | i = gl_state.backward_i = gl_state.forward_i; | ||
| 121 | gl_state.left_ok = gl_state.right_ok = 1; | ||
| 122 | invalidate = 0; | ||
| 123 | if (NULL_INTERVAL_P (i)) | ||
| 124 | return; | ||
| 125 | gl_state.b_property = i->position - 1; | ||
| 126 | gl_state.e_property = INTERVAL_LAST_POS (i); | ||
| 127 | goto update; | ||
| 128 | } | ||
| 129 | oldi = i = count > 0 ? gl_state.forward_i : gl_state.backward_i; | ||
| 130 | |||
| 131 | /* We are guarantied to be called with pos either in i, of further off. */ | ||
| 132 | if (NULL_INTERVAL_P (i)) | ||
| 133 | error ("Error in syntax_table logic for to-the-end intervals"); | ||
| 134 | else if (pos < i->position) /* Move left. */ | ||
| 135 | { | ||
| 136 | if (count > 0) | ||
| 137 | error ("Error in syntax_table logic for intervals <-."); | ||
| 138 | /* Update the interval. */ | ||
| 139 | i = update_interval (i, pos); | ||
| 140 | if (oldi->position != INTERVAL_LAST_POS (i)) | ||
| 141 | { | ||
| 142 | invalidate = 0; | ||
| 143 | gl_state.right_ok = 1; /* Invalidate the other end. */ | ||
| 144 | gl_state.forward_i = i; | ||
| 145 | gl_state.e_property = INTERVAL_LAST_POS (i); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | else if (pos >= INTERVAL_LAST_POS (i)) /* Move right. */ | ||
| 149 | { | ||
| 150 | if (count < 0) | ||
| 151 | error ("Error in syntax_table logic for intervals ->."); | ||
| 152 | /* Update the interval. */ | ||
| 153 | i = update_interval (i, pos); | ||
| 154 | if (i->position != INTERVAL_LAST_POS (oldi)) | ||
| 155 | { | ||
| 156 | invalidate = 0; | ||
| 157 | gl_state.left_ok = 1; /* Invalidate the other end. */ | ||
| 158 | gl_state.backward_i = i; | ||
| 159 | gl_state.b_property = i->position - 1; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | else if (count > 0 ? gl_state.right_ok : gl_state.left_ok) | ||
| 163 | { | ||
| 164 | /* We do not need to recalculate tmp_table. */ | ||
| 165 | tmp_table = gl_state.old_prop; | ||
| 166 | } | ||
| 167 | |||
| 168 | update: | ||
| 169 | tmp_table = textget (i->plist, Qsyntax_table); | ||
| 170 | |||
| 171 | if (invalidate) | ||
| 172 | invalidate = !EQ (tmp_table, gl_state.old_prop); /* Need to invalidate? */ | ||
| 173 | |||
| 174 | if (invalidate) /* Did not get to adjacent interval. */ | ||
| 175 | { /* with the same table => */ | ||
| 176 | /* invalidate the old range. */ | ||
| 177 | if (count > 0) | ||
| 178 | { | ||
| 179 | gl_state.backward_i = i; | ||
| 180 | gl_state.left_ok = 1; /* Invalidate the other end. */ | ||
| 181 | gl_state.b_property = i->position - 1; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | { | ||
| 185 | gl_state.forward_i = i; | ||
| 186 | gl_state.right_ok = 1; /* Invalidate the other end. */ | ||
| 187 | gl_state.e_property = INTERVAL_LAST_POS (i); | ||
| 188 | } | ||
| 189 | } | ||
| 71 | 190 | ||
| 191 | gl_state.current_syntax_table = tmp_table; | ||
| 192 | gl_state.old_prop = tmp_table; | ||
| 193 | if (Fsyntax_table_p (tmp_table) == Qt) | ||
| 194 | { | ||
| 195 | gl_state.use_global = 0; | ||
| 196 | } | ||
| 197 | else if (CONSP (tmp_table)) | ||
| 198 | { | ||
| 199 | gl_state.use_global = 1; | ||
| 200 | gl_state.global_code = tmp_table; | ||
| 201 | } | ||
| 202 | else | ||
| 203 | { | ||
| 204 | gl_state.use_global = 0; | ||
| 205 | gl_state.current_syntax_table = current_buffer->syntax_table; | ||
| 206 | } | ||
| 207 | |||
| 208 | while (!NULL_INTERVAL_P (i)) | ||
| 209 | { | ||
| 210 | if (cnt && !EQ (tmp_table, textget (i->plist, Qsyntax_table))) | ||
| 211 | { | ||
| 212 | if (count > 0) | ||
| 213 | gl_state.right_ok = 0; | ||
| 214 | else | ||
| 215 | gl_state.left_ok = 0; | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | else if (cnt == INTERVALS_AT_ONCE) | ||
| 219 | { | ||
| 220 | if (count > 0) | ||
| 221 | gl_state.right_ok = 1; | ||
| 222 | else | ||
| 223 | gl_state.left_ok = 1; | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | cnt++; | ||
| 227 | i = count > 0 ? next_interval (i) : previous_interval (i); | ||
| 228 | } | ||
| 229 | if (NULL_INTERVAL_P (i)) | ||
| 230 | { /* This property goes to the end. */ | ||
| 231 | if (count > 0) | ||
| 232 | gl_state.e_property = gl_state.stop; | ||
| 233 | else | ||
| 234 | gl_state.b_property = gl_state.start; | ||
| 235 | } | ||
| 236 | else | ||
| 237 | { | ||
| 238 | if (count > 0) | ||
| 239 | { | ||
| 240 | gl_state.e_property = i->position; | ||
| 241 | gl_state.forward_i = i; | ||
| 242 | } | ||
| 243 | else | ||
| 244 | { | ||
| 245 | gl_state.b_property = i->position + LENGTH (i) - 1; | ||
| 246 | gl_state.backward_i = i; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | /* Returns TRUE if char at POS is quoted. | ||
| 252 | Global syntax-table data should be set up already to be good at pos | ||
| 253 | or after. On return global syntax data is good for lookup at POS. */ | ||
| 254 | |||
| 255 | static int | ||
| 256 | char_quoted (pos) | ||
| 257 | register int pos; | ||
| 258 | { | ||
| 259 | register enum syntaxcode code; | ||
| 260 | register int beg = BEGV; | ||
| 261 | register int quoted = 0; | ||
| 262 | int temp_pos = pos; | ||
| 263 | |||
| 264 | DEC_POS (temp_pos); | ||
| 265 | while (temp_pos >= beg | ||
| 266 | && ( UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos), 1) | ||
| 267 | && ((code = SYNTAX (FETCH_CHAR (temp_pos))) == Scharquote | ||
| 268 | || code == Sescape)) | ||
| 269 | { | ||
| 270 | temp_pos--, quoted = !quoted; | ||
| 271 | } | ||
| 272 | UPDATE_SYNTAX_TABLE (pos); | ||
| 273 | return quoted; | ||
| 274 | } | ||
| 275 | |||
| 72 | /* Find a defun-start that is the last one before POS (or nearly the last). | 276 | /* Find a defun-start that is the last one before POS (or nearly the last). |
| 73 | We record what we find, so that another call in the same area | 277 | We record what we find, so that another call in the same area |
| 74 | can return the same value right away. */ | 278 | can return the same value right away. |
| 279 | |||
| 280 | There is no promise at which position the global syntax data is | ||
| 281 | valid on return from the subroutine, so the caller should explicitly | ||
| 282 | update the global data. */ | ||
| 75 | 283 | ||
| 76 | static int | 284 | static int |
| 77 | find_defun_start (pos) | 285 | find_defun_start (pos) |
| @@ -94,11 +302,23 @@ find_defun_start (pos) | |||
| 94 | /* Back up to start of line. */ | 302 | /* Back up to start of line. */ |
| 95 | tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1); | 303 | tem = scan_buffer ('\n', pos, BEGV, -1, &shortage, 1); |
| 96 | 304 | ||
| 305 | /* We optimize syntax-table lookup for rare updates. Thus we accept | ||
| 306 | only those `^\s(' which are good in global _and_ text-property | ||
| 307 | syntax-tables. */ | ||
| 308 | gl_state.current_syntax_table = current_buffer->syntax_table; | ||
| 309 | gl_state.use_global = 0; | ||
| 97 | while (tem > BEGV) | 310 | while (tem > BEGV) |
| 98 | { | 311 | { |
| 99 | /* Open-paren at start of line means we found our defun-start. */ | 312 | /* Open-paren at start of line means we found our defun-start. */ |
| 100 | if (SYNTAX (FETCH_CHAR (tem)) == Sopen) | 313 | if (SYNTAX (FETCH_CHAR (tem)) == Sopen) |
| 101 | break; | 314 | { |
| 315 | SETUP_SYNTAX_TABLE (tem + 1, -1); /* Try again... */ | ||
| 316 | if (SYNTAX (FETCH_CHAR (tem)) == Sopen) | ||
| 317 | break; | ||
| 318 | /* Now fallback to the default value. */ | ||
| 319 | gl_state.current_syntax_table = current_buffer->syntax_table; | ||
| 320 | gl_state.use_global = 0; | ||
| 321 | } | ||
| 102 | /* Move to beg of previous line. */ | 322 | /* Move to beg of previous line. */ |
| 103 | tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1); | 323 | tem = scan_buffer ('\n', tem, BEGV, -2, &shortage, 1); |
| 104 | } | 324 | } |
| @@ -113,6 +333,158 @@ find_defun_start (pos) | |||
| 113 | return find_start_value; | 333 | return find_start_value; |
| 114 | } | 334 | } |
| 115 | 335 | ||
| 336 | /* Checks whether FROM is the end of comment. Does not try to | ||
| 337 | fallback more than to STOP. | ||
| 338 | Returns -1 if cannot find comment ending at from, otherwise start | ||
| 339 | of comment. Global syntax data remains valid for | ||
| 340 | backward search starting at the returned value (or at FROM, if | ||
| 341 | the search was not successful). */ | ||
| 342 | |||
| 343 | static int | ||
| 344 | back_comment (from, stop) | ||
| 345 | int from, stop; | ||
| 346 | { | ||
| 347 | /* Look back, counting the parity of string-quotes, | ||
| 348 | and recording the comment-starters seen. | ||
| 349 | When we reach a safe place, assume that's not in a string; | ||
| 350 | then step the main scan to the earliest comment-starter seen | ||
| 351 | an even number of string quotes away from the safe place. | ||
| 352 | |||
| 353 | OFROM[I] is position of the earliest comment-starter seen | ||
| 354 | which is I+2X quotes from the comment-end. | ||
| 355 | PARITY is current parity of quotes from the comment end. */ | ||
| 356 | int parity = 0; | ||
| 357 | int my_stringend = 0; | ||
| 358 | int string_lossage = 0; | ||
| 359 | int comment_end = from; | ||
| 360 | int comstart_pos = 0; | ||
| 361 | int comstart_parity = 0; | ||
| 362 | int scanstart = from - 1; | ||
| 363 | register enum syntaxcode code; | ||
| 364 | int c, comstyle = 0; | ||
| 365 | |||
| 366 | /* At beginning of range to scan, we're outside of strings; | ||
| 367 | that determines quote parity to the comment-end. */ | ||
| 368 | while (from != stop) | ||
| 369 | { | ||
| 370 | /* Move back and examine a character. */ | ||
| 371 | DEC_POS (from); | ||
| 372 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 373 | |||
| 374 | c = FETCH_CHAR (from); | ||
| 375 | code = SYNTAX (c); | ||
| 376 | |||
| 377 | /* If this char is the second of a 2-char comment sequence, | ||
| 378 | back up and give the pair the appropriate syntax. */ | ||
| 379 | if (from > stop && SYNTAX_COMEND_SECOND (c) | ||
| 380 | && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))) | ||
| 381 | { | ||
| 382 | code = Sendcomment; | ||
| 383 | DEC_POS (from); | ||
| 384 | /* This is apparently the best we can do: */ | ||
| 385 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 386 | c = FETCH_CHAR (from); | ||
| 387 | } | ||
| 388 | |||
| 389 | /* If this char starts a 2-char comment start sequence, | ||
| 390 | treat it like a 1-char comment starter. */ | ||
| 391 | if (from < scanstart && SYNTAX_COMSTART_FIRST (c) | ||
| 392 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from + 1)) | ||
| 393 | && comstyle == SYNTAX_COMMENT_STYLE (FETCH_CHAR (from + 1))) | ||
| 394 | code = Scomment; | ||
| 395 | |||
| 396 | /* Ignore escaped characters. */ | ||
| 397 | if (char_quoted (from)) | ||
| 398 | continue; | ||
| 399 | |||
| 400 | /* Track parity of quotes. */ | ||
| 401 | if (code == Sstring) | ||
| 402 | { | ||
| 403 | parity ^= 1; | ||
| 404 | if (my_stringend == 0) | ||
| 405 | my_stringend = c; | ||
| 406 | /* If we have two kinds of string delimiters. | ||
| 407 | There's no way to grok this scanning backwards. */ | ||
| 408 | else if (my_stringend != c) | ||
| 409 | string_lossage = 1; | ||
| 410 | } | ||
| 411 | |||
| 412 | if (code == Sstring_fence || code == Scomment_fence) | ||
| 413 | { | ||
| 414 | parity ^= 1; | ||
| 415 | if (my_stringend == 0) | ||
| 416 | my_stringend = | ||
| 417 | code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE; | ||
| 418 | /* If we have two kinds of string delimiters. | ||
| 419 | There's no way to grok this scanning backwards. */ | ||
| 420 | else if (my_stringend != (code == Sstring_fence | ||
| 421 | ? ST_STRING_STYLE : ST_COMMENT_STYLE)) | ||
| 422 | string_lossage = 1; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Record comment-starters according to that | ||
| 426 | quote-parity to the comment-end. */ | ||
| 427 | if (code == Scomment) | ||
| 428 | { | ||
| 429 | comstart_parity = parity; | ||
| 430 | comstart_pos = from; | ||
| 431 | } | ||
| 432 | |||
| 433 | /* If we find another earlier comment-ender, | ||
| 434 | any comment-starts earlier than that don't count | ||
| 435 | (because they go with the earlier comment-ender). */ | ||
| 436 | if (code == Sendcomment | ||
| 437 | && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle) | ||
| 438 | break; | ||
| 439 | |||
| 440 | /* Assume a defun-start point is outside of strings. */ | ||
| 441 | if (code == Sopen | ||
| 442 | && (from == stop || FETCH_CHAR (from - 1) == '\n')) | ||
| 443 | break; | ||
| 444 | } | ||
| 445 | |||
| 446 | if (comstart_pos == 0) | ||
| 447 | { | ||
| 448 | from = comment_end; | ||
| 449 | UPDATE_SYNTAX_TABLE_FORWARD (comment_end - 1); | ||
| 450 | } | ||
| 451 | /* If the earliest comment starter | ||
| 452 | is followed by uniform paired string quotes or none, | ||
| 453 | we know it can't be inside a string | ||
| 454 | since if it were then the comment ender would be inside one. | ||
| 455 | So it does start a comment. Skip back to it. */ | ||
| 456 | else if (comstart_parity == 0 && !string_lossage) | ||
| 457 | { | ||
| 458 | from = comstart_pos; | ||
| 459 | /* Globals are correct now. */ | ||
| 460 | } | ||
| 461 | else | ||
| 462 | { | ||
| 463 | /* We had two kinds of string delimiters mixed up | ||
| 464 | together. Decode this going forwards. | ||
| 465 | Scan fwd from the previous comment ender | ||
| 466 | to the one in question; this records where we | ||
| 467 | last passed a comment starter. */ | ||
| 468 | struct lisp_parse_state state; | ||
| 469 | scan_sexps_forward (&state, find_defun_start (comment_end), | ||
| 470 | comment_end - 1, -10000, 0, Qnil, 0); | ||
| 471 | if (state.incomment) | ||
| 472 | { | ||
| 473 | /* scan_sexps_forward changed the direction of search in | ||
| 474 | global variables, so we need to update it completely. */ | ||
| 475 | |||
| 476 | from = state.comstr_start; | ||
| 477 | } | ||
| 478 | else | ||
| 479 | { | ||
| 480 | from = comment_end; | ||
| 481 | } | ||
| 482 | UPDATE_SYNTAX_TABLE_FORWARD (from - 1); | ||
| 483 | } | ||
| 484 | |||
| 485 | return from; | ||
| 486 | } | ||
| 487 | |||
| 116 | DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0, | 488 | DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0, |
| 117 | "Return t if OBJECT is a syntax table.\n\ | 489 | "Return t if OBJECT is a syntax table.\n\ |
| 118 | Currently, any char-table counts as a syntax table.") | 490 | Currently, any char-table counts as a syntax table.") |
| @@ -194,14 +566,14 @@ One argument, a syntax table.") | |||
| 194 | 566 | ||
| 195 | /* Convert a letter which signifies a syntax code | 567 | /* Convert a letter which signifies a syntax code |
| 196 | into the code it signifies. | 568 | into the code it signifies. |
| 197 | This is used by modify-syntax-entry, and other things. */ | 569 | This is used by modify-syntax-entry, and other things. */ |
| 198 | 570 | ||
| 199 | unsigned char syntax_spec_code[0400] = | 571 | unsigned char syntax_spec_code[0400] = |
| 200 | { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | 572 | { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
| 201 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | 573 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
| 202 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | 574 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
| 203 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | 575 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
| 204 | (char) Swhitespace, 0377, (char) Sstring, 0377, | 576 | (char) Swhitespace, (char) Scomment_fence, (char) Sstring, 0377, |
| 205 | (char) Smath, 0377, 0377, (char) Squote, | 577 | (char) Smath, 0377, 0377, (char) Squote, |
| 206 | (char) Sopen, (char) Sclose, 0377, 0377, | 578 | (char) Sopen, (char) Sclose, 0377, 0377, |
| 207 | 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote, | 579 | 0377, (char) Swhitespace, (char) Spunct, (char) Scharquote, |
| @@ -215,14 +587,15 @@ unsigned char syntax_spec_code[0400] = | |||
| 215 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */ | 587 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, /* `, a, ... */ |
| 216 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, | 588 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377, |
| 217 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, | 589 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword, |
| 218 | 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377 | 590 | 0377, 0377, 0377, 0377, (char) Sstring_fence, 0377, 0377, 0377 |
| 219 | }; | 591 | }; |
| 220 | 592 | ||
| 221 | /* Indexed by syntax code, give the letter that describes it. */ | 593 | /* Indexed by syntax code, give the letter that describes it. */ |
| 222 | 594 | ||
| 223 | char syntax_code_spec[14] = | 595 | char syntax_code_spec[16] = |
| 224 | { | 596 | { |
| 225 | ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@' | 597 | ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>', '@', |
| 598 | '!', '|' | ||
| 226 | }; | 599 | }; |
| 227 | 600 | ||
| 228 | /* Indexed by syntax code, give the object (cons of syntax code and | 601 | /* Indexed by syntax code, give the object (cons of syntax code and |
| @@ -266,6 +639,9 @@ are listed in the documentation of `modify-syntax-entry'.") | |||
| 266 | Lisp_Object character; | 639 | Lisp_Object character; |
| 267 | { | 640 | { |
| 268 | int char_int; | 641 | int char_int; |
| 642 | gl_state.current_syntax_table = current_buffer->syntax_table; | ||
| 643 | |||
| 644 | gl_state.use_global = 0; | ||
| 269 | CHECK_NUMBER (character, 0); | 645 | CHECK_NUMBER (character, 0); |
| 270 | char_int = XINT (character); | 646 | char_int = XINT (character); |
| 271 | return make_number (syntax_code_spec[(int) SYNTAX (char_int)]); | 647 | return make_number (syntax_code_spec[(int) SYNTAX (char_int)]); |
| @@ -277,6 +653,8 @@ DEFUN ("matching-paren", Fmatching_paren, Smatching_paren, 1, 1, 0, | |||
| 277 | Lisp_Object character; | 653 | Lisp_Object character; |
| 278 | { | 654 | { |
| 279 | int char_int, code; | 655 | int char_int, code; |
| 656 | gl_state.current_syntax_table = current_buffer->syntax_table; | ||
| 657 | gl_state.use_global = 0; | ||
| 280 | CHECK_NUMBER (character, 0); | 658 | CHECK_NUMBER (character, 0); |
| 281 | char_int = XINT (character); | 659 | char_int = XINT (character); |
| 282 | code = SYNTAX (char_int); | 660 | code = SYNTAX (char_int); |
| @@ -313,7 +691,7 @@ Defined flags are the characters 1, 2, 3, 4, b, and p.\n\ | |||
| 313 | 3 means CHAR is the start of a two-char comment end sequence.\n\ | 691 | 3 means CHAR is the start of a two-char comment end sequence.\n\ |
| 314 | 4 means CHAR is the second character of such a sequence.\n\ | 692 | 4 means CHAR is the second character of such a sequence.\n\ |
| 315 | \n\ | 693 | \n\ |
| 316 | There can be up to two orthogonal comment sequences. This is to support\n\ | 694 | There can be up to two orthogonal comment sequences. This is to support\n\ |
| 317 | language modes such as C++. By default, all comment sequences are of style\n\ | 695 | language modes such as C++. By default, all comment sequences are of style\n\ |
| 318 | a, but you can set the comment sequence style to b (on the second character\n\ | 696 | a, but you can set the comment sequence style to b (on the second character\n\ |
| 319 | of a comment-start, or the first character of a comment-end sequence) using\n\ | 697 | of a comment-start, or the first character of a comment-end sequence) using\n\ |
| @@ -579,6 +957,8 @@ The descriptions are inserted in a buffer, which is then displayed.") | |||
| 579 | return Qnil; | 957 | return Qnil; |
| 580 | } | 958 | } |
| 581 | 959 | ||
| 960 | int parse_sexp_ignore_comments; | ||
| 961 | |||
| 582 | /* Return the position across COUNT words from FROM. | 962 | /* Return the position across COUNT words from FROM. |
| 583 | If that many words cannot be found before the end of the buffer, return 0. | 963 | If that many words cannot be found before the end of the buffer, return 0. |
| 584 | COUNT negative means scan backward and stop at word beginning. */ | 964 | COUNT negative means scan backward and stop at word beginning. */ |
| @@ -595,6 +975,8 @@ scan_words (from, count) | |||
| 595 | immediate_quit = 1; | 975 | immediate_quit = 1; |
| 596 | QUIT; | 976 | QUIT; |
| 597 | 977 | ||
| 978 | SETUP_SYNTAX_TABLE (from, count); | ||
| 979 | |||
| 598 | while (count > 0) | 980 | while (count > 0) |
| 599 | { | 981 | { |
| 600 | while (1) | 982 | while (1) |
| @@ -604,6 +986,7 @@ scan_words (from, count) | |||
| 604 | immediate_quit = 0; | 986 | immediate_quit = 0; |
| 605 | return 0; | 987 | return 0; |
| 606 | } | 988 | } |
| 989 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 607 | ch0 = FETCH_CHAR (from); | 990 | ch0 = FETCH_CHAR (from); |
| 608 | code = SYNTAX (ch0); | 991 | code = SYNTAX (ch0); |
| 609 | INC_POS (from); | 992 | INC_POS (from); |
| @@ -618,6 +1001,7 @@ scan_words (from, count) | |||
| 618 | while (1) | 1001 | while (1) |
| 619 | { | 1002 | { |
| 620 | if (from == end) break; | 1003 | if (from == end) break; |
| 1004 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 621 | ch1 = FETCH_CHAR (from); | 1005 | ch1 = FETCH_CHAR (from); |
| 622 | code = SYNTAX (ch1); | 1006 | code = SYNTAX (ch1); |
| 623 | if (!(words_include_escapes | 1007 | if (!(words_include_escapes |
| @@ -639,6 +1023,7 @@ scan_words (from, count) | |||
| 639 | return 0; | 1023 | return 0; |
| 640 | } | 1024 | } |
| 641 | DEC_POS (from); | 1025 | DEC_POS (from); |
| 1026 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 642 | ch1 = FETCH_CHAR (from); | 1027 | ch1 = FETCH_CHAR (from); |
| 643 | code = SYNTAX (ch1); | 1028 | code = SYNTAX (ch1); |
| 644 | if (words_include_escapes | 1029 | if (words_include_escapes |
| @@ -654,6 +1039,7 @@ scan_words (from, count) | |||
| 654 | if (from == beg) break; | 1039 | if (from == beg) break; |
| 655 | temp_pos = from; | 1040 | temp_pos = from; |
| 656 | DEC_POS (temp_pos); | 1041 | DEC_POS (temp_pos); |
| 1042 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 657 | ch0 = FETCH_CHAR (temp_pos); | 1043 | ch0 = FETCH_CHAR (temp_pos); |
| 658 | code = SYNTAX (ch0); | 1044 | code = SYNTAX (ch0); |
| 659 | if (!(words_include_escapes | 1045 | if (!(words_include_escapes |
| @@ -691,6 +1077,176 @@ and nil is returned.") | |||
| 691 | return Qt; | 1077 | return Qt; |
| 692 | } | 1078 | } |
| 693 | 1079 | ||
| 1080 | Lisp_Object skip_chars (); | ||
| 1081 | |||
| 1082 | DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0, | ||
| 1083 | "Move point forward, stopping before a char not in STRING, or at pos LIM.\n\ | ||
| 1084 | STRING is like the inside of a `[...]' in a regular expression\n\ | ||
| 1085 | except that `]' is never special and `\\' quotes `^', `-' or `\\'.\n\ | ||
| 1086 | Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\ | ||
| 1087 | With arg \"^a-zA-Z\", skips nonletters stopping before first letter.\n\ | ||
| 1088 | Returns the distance traveled, either zero or positive.") | ||
| 1089 | (string, lim) | ||
| 1090 | Lisp_Object string, lim; | ||
| 1091 | { | ||
| 1092 | return skip_chars (1, 0, string, lim); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0, | ||
| 1096 | "Move point backward, stopping after a char not in STRING, or at pos LIM.\n\ | ||
| 1097 | See `skip-chars-forward' for details.\n\ | ||
| 1098 | Returns the distance traveled, either zero or negative.") | ||
| 1099 | (string, lim) | ||
| 1100 | Lisp_Object string, lim; | ||
| 1101 | { | ||
| 1102 | return skip_chars (0, 0, string, lim); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0, | ||
| 1106 | "Move point forward across chars in specified syntax classes.\n\ | ||
| 1107 | SYNTAX is a string of syntax code characters.\n\ | ||
| 1108 | Stop before a char whose syntax is not in SYNTAX, or at position LIM.\n\ | ||
| 1109 | If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\ | ||
| 1110 | This function returns the distance traveled, either zero or positive.") | ||
| 1111 | (syntax, lim) | ||
| 1112 | Lisp_Object syntax, lim; | ||
| 1113 | { | ||
| 1114 | return skip_chars (1, 1, syntax, lim); | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0, | ||
| 1118 | "Move point backward across chars in specified syntax classes.\n\ | ||
| 1119 | SYNTAX is a string of syntax code characters.\n\ | ||
| 1120 | Stop on reaching a char whose syntax is not in SYNTAX, or at position LIM.\n\ | ||
| 1121 | If SYNTAX starts with ^, skip characters whose syntax is NOT in SYNTAX.\n\ | ||
| 1122 | This function returns the distance traveled, either zero or negative.") | ||
| 1123 | (syntax, lim) | ||
| 1124 | Lisp_Object syntax, lim; | ||
| 1125 | { | ||
| 1126 | return skip_chars (0, 1, syntax, lim); | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | Lisp_Object | ||
| 1130 | skip_chars (forwardp, syntaxp, string, lim) | ||
| 1131 | int forwardp, syntaxp; | ||
| 1132 | Lisp_Object string, lim; | ||
| 1133 | { | ||
| 1134 | register unsigned char *p, *pend; | ||
| 1135 | register unsigned int c; | ||
| 1136 | unsigned char fastmap[0400]; | ||
| 1137 | int negate = 0; | ||
| 1138 | register int i; | ||
| 1139 | |||
| 1140 | CHECK_STRING (string, 0); | ||
| 1141 | |||
| 1142 | if (NILP (lim)) | ||
| 1143 | XSETINT (lim, forwardp ? ZV : BEGV); | ||
| 1144 | else | ||
| 1145 | CHECK_NUMBER_COERCE_MARKER (lim, 1); | ||
| 1146 | |||
| 1147 | /* In any case, don't allow scan outside bounds of buffer. */ | ||
| 1148 | /* jla turned this off, for no known reason. | ||
| 1149 | bfox turned the ZV part on, and rms turned the | ||
| 1150 | BEGV part back on. */ | ||
| 1151 | if (XINT (lim) > ZV) | ||
| 1152 | XSETFASTINT (lim, ZV); | ||
| 1153 | if (XINT (lim) < BEGV) | ||
| 1154 | XSETFASTINT (lim, BEGV); | ||
| 1155 | |||
| 1156 | p = XSTRING (string)->data; | ||
| 1157 | pend = p + XSTRING (string)->size; | ||
| 1158 | bzero (fastmap, sizeof fastmap); | ||
| 1159 | |||
| 1160 | if (p != pend && *p == '^') | ||
| 1161 | { | ||
| 1162 | negate = 1; p++; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | /* Find the characters specified and set their elements of fastmap. | ||
| 1166 | If syntaxp, each character counts as itself. | ||
| 1167 | Otherwise, handle backslashes and ranges specially. */ | ||
| 1168 | |||
| 1169 | while (p != pend) | ||
| 1170 | { | ||
| 1171 | c = *p++; | ||
| 1172 | if (syntaxp) | ||
| 1173 | fastmap[syntax_spec_code[c]] = 1; | ||
| 1174 | else | ||
| 1175 | { | ||
| 1176 | if (c == '\\') | ||
| 1177 | { | ||
| 1178 | if (p == pend) break; | ||
| 1179 | c = *p++; | ||
| 1180 | } | ||
| 1181 | if (p != pend && *p == '-') | ||
| 1182 | { | ||
| 1183 | p++; | ||
| 1184 | if (p == pend) break; | ||
| 1185 | while (c <= *p) | ||
| 1186 | { | ||
| 1187 | fastmap[c] = 1; | ||
| 1188 | c++; | ||
| 1189 | } | ||
| 1190 | p++; | ||
| 1191 | } | ||
| 1192 | else | ||
| 1193 | fastmap[c] = 1; | ||
| 1194 | } | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | /* If ^ was the first character, complement the fastmap. */ | ||
| 1198 | |||
| 1199 | if (negate) | ||
| 1200 | for (i = 0; i < sizeof fastmap; i++) | ||
| 1201 | fastmap[i] ^= 1; | ||
| 1202 | |||
| 1203 | { | ||
| 1204 | int start_point = PT; | ||
| 1205 | int pos = PT; | ||
| 1206 | |||
| 1207 | immediate_quit = 1; | ||
| 1208 | if (syntaxp) | ||
| 1209 | { | ||
| 1210 | SETUP_SYNTAX_TABLE (pos, forwardp ? 1 : -1); | ||
| 1211 | if (forwardp) | ||
| 1212 | { | ||
| 1213 | while (pos < XINT (lim) | ||
| 1214 | && fastmap[(int) SYNTAX (FETCH_CHAR (pos))]) | ||
| 1215 | { | ||
| 1216 | pos++; | ||
| 1217 | UPDATE_SYNTAX_TABLE_FORWARD (pos); | ||
| 1218 | } | ||
| 1219 | } | ||
| 1220 | else | ||
| 1221 | { | ||
| 1222 | while (pos > XINT (lim) | ||
| 1223 | && fastmap[(int) SYNTAX (FETCH_CHAR (pos - 1))]) | ||
| 1224 | { | ||
| 1225 | pos--; | ||
| 1226 | UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1); | ||
| 1227 | } | ||
| 1228 | } | ||
| 1229 | } | ||
| 1230 | else | ||
| 1231 | { | ||
| 1232 | if (forwardp) | ||
| 1233 | { | ||
| 1234 | while (pos < XINT (lim) && fastmap[FETCH_CHAR (pos)]) | ||
| 1235 | pos++; | ||
| 1236 | } | ||
| 1237 | else | ||
| 1238 | { | ||
| 1239 | while (pos > XINT (lim) && fastmap[FETCH_CHAR (pos - 1)]) | ||
| 1240 | pos--; | ||
| 1241 | } | ||
| 1242 | } | ||
| 1243 | SET_PT (pos); | ||
| 1244 | immediate_quit = 0; | ||
| 1245 | |||
| 1246 | return make_number (PT - start_point); | ||
| 1247 | } | ||
| 1248 | } | ||
| 1249 | |||
| 694 | DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, | 1250 | DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0, |
| 695 | "Move forward across up to N comments. If N is negative, move backward.\n\ | 1251 | "Move forward across up to N comments. If N is negative, move backward.\n\ |
| 696 | Stop scanning if we find something other than a comment or whitespace.\n\ | 1252 | Stop scanning if we find something other than a comment or whitespace.\n\ |
| @@ -711,15 +1267,16 @@ between them, return t; otherwise return nil.") | |||
| 711 | 1267 | ||
| 712 | CHECK_NUMBER (count, 0); | 1268 | CHECK_NUMBER (count, 0); |
| 713 | count1 = XINT (count); | 1269 | count1 = XINT (count); |
| 1270 | stop = count1 > 0 ? ZV : BEGV; | ||
| 714 | 1271 | ||
| 715 | immediate_quit = 1; | 1272 | immediate_quit = 1; |
| 716 | QUIT; | 1273 | QUIT; |
| 717 | 1274 | ||
| 718 | from = PT; | 1275 | from = PT; |
| 719 | 1276 | ||
| 1277 | SETUP_SYNTAX_TABLE (from, count1); | ||
| 720 | while (count1 > 0) | 1278 | while (count1 > 0) |
| 721 | { | 1279 | { |
| 722 | stop = ZV; | ||
| 723 | do | 1280 | do |
| 724 | { | 1281 | { |
| 725 | if (from == stop) | 1282 | if (from == stop) |
| @@ -728,6 +1285,7 @@ between them, return t; otherwise return nil.") | |||
| 728 | immediate_quit = 0; | 1285 | immediate_quit = 0; |
| 729 | return Qnil; | 1286 | return Qnil; |
| 730 | } | 1287 | } |
| 1288 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 731 | c = FETCH_CHAR (from); | 1289 | c = FETCH_CHAR (from); |
| 732 | code = SYNTAX (c); | 1290 | code = SYNTAX (c); |
| 733 | INC_POS (from); | 1291 | INC_POS (from); |
| @@ -747,7 +1305,7 @@ between them, return t; otherwise return nil.") | |||
| 747 | } | 1305 | } |
| 748 | } | 1306 | } |
| 749 | while (code == Swhitespace || code == Sendcomment); | 1307 | while (code == Swhitespace || code == Sendcomment); |
| 750 | if (code != Scomment) | 1308 | if (code != Scomment && code != Scomment_fence) |
| 751 | { | 1309 | { |
| 752 | immediate_quit = 0; | 1310 | immediate_quit = 0; |
| 753 | DEC_POS (from); | 1311 | DEC_POS (from); |
| @@ -763,6 +1321,7 @@ between them, return t; otherwise return nil.") | |||
| 763 | SET_PT (from); | 1321 | SET_PT (from); |
| 764 | return Qnil; | 1322 | return Qnil; |
| 765 | } | 1323 | } |
| 1324 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 766 | c = FETCH_CHAR (from); | 1325 | c = FETCH_CHAR (from); |
| 767 | INC_POS (from); | 1326 | INC_POS (from); |
| 768 | if (SYNTAX (c) == Sendcomment | 1327 | if (SYNTAX (c) == Sendcomment |
| @@ -771,6 +1330,12 @@ between them, return t; otherwise return nil.") | |||
| 771 | as the comment sequence which began this comment | 1330 | as the comment sequence which began this comment |
| 772 | section */ | 1331 | section */ |
| 773 | break; | 1332 | break; |
| 1333 | if (SYNTAX (c) == Scomment_fence | ||
| 1334 | && comstyle == ST_COMMENT_STYLE) | ||
| 1335 | /* we have encountered a comment end of the same style | ||
| 1336 | as the comment sequence which began this comment | ||
| 1337 | section. */ | ||
| 1338 | break; | ||
| 774 | if (from < stop && SYNTAX_COMEND_FIRST (c) | 1339 | if (from < stop && SYNTAX_COMEND_FIRST (c) |
| 775 | && (c1 = FETCH_CHAR (from), | 1340 | && (c1 = FETCH_CHAR (from), |
| 776 | SYNTAX_COMEND_SECOND (c1)) | 1341 | SYNTAX_COMEND_SECOND (c1)) |
| @@ -786,7 +1351,6 @@ between them, return t; otherwise return nil.") | |||
| 786 | 1351 | ||
| 787 | while (count1 < 0) | 1352 | while (count1 < 0) |
| 788 | { | 1353 | { |
| 789 | stop = BEGV; | ||
| 790 | while (from > stop) | 1354 | while (from > stop) |
| 791 | { | 1355 | { |
| 792 | int quoted; | 1356 | int quoted; |
| @@ -794,7 +1358,11 @@ between them, return t; otherwise return nil.") | |||
| 794 | DEC_POS (from); | 1358 | DEC_POS (from); |
| 795 | quoted = char_quoted (from); | 1359 | quoted = char_quoted (from); |
| 796 | if (quoted) | 1360 | if (quoted) |
| 797 | DEC_POS (from); | 1361 | { |
| 1362 | DEC_POS (from); | ||
| 1363 | goto leave; /* ????? XXXXX */ | ||
| 1364 | } | ||
| 1365 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 798 | c = FETCH_CHAR (from); | 1366 | c = FETCH_CHAR (from); |
| 799 | code = SYNTAX (c); | 1367 | code = SYNTAX (c); |
| 800 | comstyle = 0; | 1368 | comstyle = 0; |
| @@ -815,7 +1383,28 @@ between them, return t; otherwise return nil.") | |||
| 815 | from = temp_pos; | 1383 | from = temp_pos; |
| 816 | } | 1384 | } |
| 817 | 1385 | ||
| 818 | if (code == Sendcomment && !quoted) | 1386 | if (code == Scomment_fence) |
| 1387 | { | ||
| 1388 | /* Skip until first preceding unquoted comment_fence. */ | ||
| 1389 | int found = 0, ini = from; | ||
| 1390 | |||
| 1391 | while (--from != stop) | ||
| 1392 | { | ||
| 1393 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 1394 | c = FETCH_CHAR (from); | ||
| 1395 | if (SYNTAX (c) == Scomment_fence && !char_quoted (from)) | ||
| 1396 | { | ||
| 1397 | found = 1; | ||
| 1398 | break; | ||
| 1399 | } | ||
| 1400 | } | ||
| 1401 | if (found == 0) | ||
| 1402 | { | ||
| 1403 | from = ini; /* Set point to ini + 1. */ | ||
| 1404 | goto leave; | ||
| 1405 | } | ||
| 1406 | } | ||
| 1407 | else if (code == Sendcomment) | ||
| 819 | { | 1408 | { |
| 820 | #if 0 | 1409 | #if 0 |
| 821 | if (code != SYNTAX (c)) | 1410 | if (code != SYNTAX (c)) |
| @@ -846,7 +1435,9 @@ between them, return t; otherwise return nil.") | |||
| 846 | break; | 1435 | break; |
| 847 | } | 1436 | } |
| 848 | #endif /* 0 */ | 1437 | #endif /* 0 */ |
| 849 | 1438 | found = back_comment (from, stop); | |
| 1439 | if (found != -1) from = found; | ||
| 1440 | #if 0 | ||
| 850 | /* Look back, counting the parity of string-quotes, | 1441 | /* Look back, counting the parity of string-quotes, |
| 851 | and recording the comment-starters seen. | 1442 | and recording the comment-starters seen. |
| 852 | When we reach a safe place, assume that's not in a string; | 1443 | When we reach a safe place, assume that's not in a string; |
| @@ -873,6 +1464,7 @@ between them, return t; otherwise return nil.") | |||
| 873 | /* Move back and examine a character. */ | 1464 | /* Move back and examine a character. */ |
| 874 | DEC_POS (from); | 1465 | DEC_POS (from); |
| 875 | 1466 | ||
| 1467 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 876 | c = FETCH_CHAR (from); | 1468 | c = FETCH_CHAR (from); |
| 877 | code = SYNTAX (c); | 1469 | code = SYNTAX (c); |
| 878 | 1470 | ||
| @@ -956,17 +1548,19 @@ between them, return t; otherwise return nil.") | |||
| 956 | scan_sexps_forward (&state, find_defun_start (comment_end), | 1548 | scan_sexps_forward (&state, find_defun_start (comment_end), |
| 957 | comment_end - 1, -10000, 0, Qnil, 0); | 1549 | comment_end - 1, -10000, 0, Qnil, 0); |
| 958 | if (state.incomment) | 1550 | if (state.incomment) |
| 959 | from = state.comstart; | 1551 | from = state.comstr_start; |
| 960 | else | 1552 | else |
| 961 | /* We can't grok this as a comment; scan it normally. */ | 1553 | /* We can't grok this as a comment; scan it normally. */ |
| 962 | from = comment_end; | 1554 | from = comment_end; |
| 963 | } | 1555 | } |
| 964 | } | 1556 | } |
| 1557 | #endif /* 0 */ | ||
| 965 | /* We have skipped one comment. */ | 1558 | /* We have skipped one comment. */ |
| 966 | break; | 1559 | break; |
| 967 | } | 1560 | } |
| 968 | else if ((code != Swhitespace && code != Scomment) || quoted) | 1561 | else if (code != Swhitespace && code != Scomment) |
| 969 | { | 1562 | { |
| 1563 | leave: | ||
| 970 | immediate_quit = 0; | 1564 | immediate_quit = 0; |
| 971 | INC_POS (from); | 1565 | INC_POS (from); |
| 972 | SET_PT (from); | 1566 | SET_PT (from); |
| @@ -982,46 +1576,47 @@ between them, return t; otherwise return nil.") | |||
| 982 | return Qt; | 1576 | return Qt; |
| 983 | } | 1577 | } |
| 984 | 1578 | ||
| 985 | int parse_sexp_ignore_comments; | ||
| 986 | |||
| 987 | Lisp_Object | 1579 | Lisp_Object |
| 988 | scan_lists (from, count, depth, sexpflag) | 1580 | scan_lists (from, count, depth, sexpflag) |
| 989 | register int from; | 1581 | register int from; |
| 990 | int count, depth, sexpflag; | 1582 | int count, depth, sexpflag; |
| 991 | { | 1583 | { |
| 992 | Lisp_Object val; | 1584 | Lisp_Object val; |
| 993 | register int stop; | 1585 | register int stop = count > 0 ? ZV : BEGV; |
| 994 | register int c, c1; | 1586 | register int c, c1; |
| 995 | int stringterm; | 1587 | int stringterm; |
| 996 | int quoted; | 1588 | int quoted; |
| 997 | int mathexit = 0; | 1589 | int mathexit = 0; |
| 998 | register enum syntaxcode code, temp_code; | 1590 | register enum syntaxcode code, temp_code; |
| 999 | int min_depth = depth; /* Err out if depth gets less than this. */ | 1591 | int min_depth = depth; /* Err out if depth gets less than this. */ |
| 1000 | int comstyle = 0; /* style of comment encountered */ | 1592 | int comstyle = 0; /* style of comment encountered */ |
| 1001 | int temp_pos; | 1593 | int temp_pos; |
| 1002 | int last_good = from; | 1594 | int last_good = from; |
| 1595 | int found; | ||
| 1003 | 1596 | ||
| 1004 | if (depth > 0) min_depth = 0; | 1597 | if (depth > 0) min_depth = 0; |
| 1005 | 1598 | ||
| 1006 | immediate_quit = 1; | 1599 | immediate_quit = 1; |
| 1007 | QUIT; | 1600 | QUIT; |
| 1008 | 1601 | ||
| 1602 | SETUP_SYNTAX_TABLE (from, count); | ||
| 1009 | while (count > 0) | 1603 | while (count > 0) |
| 1010 | { | 1604 | { |
| 1011 | stop = ZV; | ||
| 1012 | while (from < stop) | 1605 | while (from < stop) |
| 1013 | { | 1606 | { |
| 1607 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1014 | c = FETCH_CHAR (from); | 1608 | c = FETCH_CHAR (from); |
| 1015 | code = SYNTAX (c); | 1609 | code = SYNTAX (c); |
| 1016 | if (depth == min_depth) | 1610 | if (depth == min_depth) |
| 1017 | last_good = from; | 1611 | last_good = from; |
| 1018 | INC_POS (from); | 1612 | INC_POS (from); |
| 1613 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1019 | if (from < stop && SYNTAX_COMSTART_FIRST (c) | 1614 | if (from < stop && SYNTAX_COMSTART_FIRST (c) |
| 1020 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)) | 1615 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)) |
| 1021 | && parse_sexp_ignore_comments) | 1616 | && parse_sexp_ignore_comments) |
| 1022 | { | 1617 | { |
| 1023 | /* we have encountered a comment start sequence and we | 1618 | /* we have encountered a comment start sequence and we |
| 1024 | are ignoring all text inside comments. we must record | 1619 | are ignoring all text inside comments. We must record |
| 1025 | the comment style this sequence begins so that later, | 1620 | the comment style this sequence begins so that later, |
| 1026 | only a comment end of the same style actually ends | 1621 | only a comment end of the same style actually ends |
| 1027 | the comment section */ | 1622 | the comment section */ |
| @@ -1030,6 +1625,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1030 | INC_POS (from); | 1625 | INC_POS (from); |
| 1031 | } | 1626 | } |
| 1032 | 1627 | ||
| 1628 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1033 | if (SYNTAX_PREFIX (c)) | 1629 | if (SYNTAX_PREFIX (c)) |
| 1034 | continue; | 1630 | continue; |
| 1035 | 1631 | ||
| @@ -1043,9 +1639,10 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1043 | case Sword: | 1639 | case Sword: |
| 1044 | case Ssymbol: | 1640 | case Ssymbol: |
| 1045 | if (depth || !sexpflag) break; | 1641 | if (depth || !sexpflag) break; |
| 1046 | /* This word counts as a sexp; return at end of it. */ | 1642 | /* This word counts as a sexp; return at end of it. */ |
| 1047 | while (from < stop) | 1643 | while (from < stop) |
| 1048 | { | 1644 | { |
| 1645 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1049 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) | 1646 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) |
| 1050 | { | 1647 | { |
| 1051 | case Scharquote: | 1648 | case Scharquote: |
| @@ -1065,6 +1662,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1065 | goto done; | 1662 | goto done; |
| 1066 | 1663 | ||
| 1067 | case Scomment: | 1664 | case Scomment: |
| 1665 | case Scomment_fence: | ||
| 1068 | if (!parse_sexp_ignore_comments) break; | 1666 | if (!parse_sexp_ignore_comments) break; |
| 1069 | while (1) | 1667 | while (1) |
| 1070 | { | 1668 | { |
| @@ -1074,9 +1672,12 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1074 | goto done; | 1672 | goto done; |
| 1075 | goto lose; | 1673 | goto lose; |
| 1076 | } | 1674 | } |
| 1675 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1077 | c = FETCH_CHAR (from); | 1676 | c = FETCH_CHAR (from); |
| 1078 | if (SYNTAX (c) == Sendcomment | 1677 | if (code == Scomment |
| 1079 | && SYNTAX_COMMENT_STYLE (c) == comstyle) | 1678 | ? (SYNTAX (c) == Sendcomment |
| 1679 | && SYNTAX_COMMENT_STYLE (c) == comstyle) | ||
| 1680 | : (SYNTAX (c) == Scomment_fence)) | ||
| 1080 | /* we have encountered a comment end of the same style | 1681 | /* we have encountered a comment end of the same style |
| 1081 | as the comment sequence which began this comment | 1682 | as the comment sequence which began this comment |
| 1082 | section */ | 1683 | section */ |
| @@ -1084,7 +1685,8 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1084 | INC_POS (from); | 1685 | INC_POS (from); |
| 1085 | if (from < stop && SYNTAX_COMEND_FIRST (c) | 1686 | if (from < stop && SYNTAX_COMEND_FIRST (c) |
| 1086 | && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) | 1687 | && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)) |
| 1087 | && SYNTAX_COMMENT_STYLE (c) == comstyle) | 1688 | && SYNTAX_COMMENT_STYLE (c) == comstyle |
| 1689 | && code == Scomment) | ||
| 1088 | /* we have encountered a comment end of the same style | 1690 | /* we have encountered a comment end of the same style |
| 1089 | as the comment sequence which began this comment | 1691 | as the comment sequence which began this comment |
| 1090 | section */ | 1692 | section */ |
| @@ -1119,13 +1721,18 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1119 | break; | 1721 | break; |
| 1120 | 1722 | ||
| 1121 | case Sstring: | 1723 | case Sstring: |
| 1724 | case Sstring_fence: | ||
| 1122 | temp_pos = from; | 1725 | temp_pos = from; |
| 1123 | DEC_POS (temp_pos); | 1726 | DEC_POS (temp_pos); |
| 1124 | stringterm = FETCH_CHAR (temp_pos); | 1727 | stringterm = FETCH_CHAR (temp_pos); |
| 1125 | while (1) | 1728 | while (1) |
| 1126 | { | 1729 | { |
| 1127 | if (from >= stop) goto lose; | 1730 | if (from >= stop) goto lose; |
| 1128 | if (FETCH_CHAR (from) == stringterm) break; | 1731 | UPDATE_SYNTAX_TABLE_FORWARD (from); |
| 1732 | if (code == Sstring | ||
| 1733 | ? (FETCH_CHAR (from) == stringterm) | ||
| 1734 | : SYNTAX (FETCH_CHAR (from)) == Sstring_fence) | ||
| 1735 | break; | ||
| 1129 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) | 1736 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) |
| 1130 | { | 1737 | { |
| 1131 | case Scharquote: | 1738 | case Scharquote: |
| @@ -1153,12 +1760,15 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1153 | 1760 | ||
| 1154 | while (count < 0) | 1761 | while (count < 0) |
| 1155 | { | 1762 | { |
| 1156 | stop = BEGV; | ||
| 1157 | while (from > stop) | 1763 | while (from > stop) |
| 1158 | { | 1764 | { |
| 1159 | DEC_POS (from); | 1765 | DEC_POS (from); |
| 1766 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 1160 | if (quoted = char_quoted (from)) | 1767 | if (quoted = char_quoted (from)) |
| 1161 | DEC_POS (from); | 1768 | { |
| 1769 | DEC_POS (from); | ||
| 1770 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 1771 | } | ||
| 1162 | c = FETCH_CHAR (from); | 1772 | c = FETCH_CHAR (from); |
| 1163 | code = SYNTAX (c); | 1773 | code = SYNTAX (c); |
| 1164 | if (depth == min_depth) | 1774 | if (depth == min_depth) |
| @@ -1189,16 +1799,19 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1189 | case Sword: | 1799 | case Sword: |
| 1190 | case Ssymbol: | 1800 | case Ssymbol: |
| 1191 | if (depth || !sexpflag) break; | 1801 | if (depth || !sexpflag) break; |
| 1192 | /* This word counts as a sexp; count object finished after passing it. */ | 1802 | /* This word counts as a sexp; count object finished |
| 1803 | after passing it. */ | ||
| 1193 | while (from > stop) | 1804 | while (from > stop) |
| 1194 | { | 1805 | { |
| 1195 | temp_pos = from; | 1806 | temp_pos = from; |
| 1196 | DEC_POS (temp_pos); | 1807 | DEC_POS (temp_pos); |
| 1808 | UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos); | ||
| 1197 | quoted = char_quoted (temp_pos); | 1809 | quoted = char_quoted (temp_pos); |
| 1198 | if (quoted) | 1810 | if (quoted) |
| 1199 | { | 1811 | { |
| 1200 | from = temp_pos; | 1812 | from = temp_pos; |
| 1201 | DEC_POS (temp_pos); | 1813 | DEC_POS (temp_pos); |
| 1814 | UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos); | ||
| 1202 | } | 1815 | } |
| 1203 | c1 = FETCH_CHAR (temp_pos); | 1816 | c1 = FETCH_CHAR (temp_pos); |
| 1204 | temp_code = SYNTAX (c1); | 1817 | temp_code = SYNTAX (c1); |
| @@ -1215,6 +1828,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1215 | break; | 1828 | break; |
| 1216 | temp_pos = from; | 1829 | temp_pos = from; |
| 1217 | DEC_POS (temp_pos); | 1830 | DEC_POS (temp_pos); |
| 1831 | UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos); | ||
| 1218 | if (from != stop && c == FETCH_CHAR (temp_pos)) | 1832 | if (from != stop && c == FETCH_CHAR (temp_pos)) |
| 1219 | from = temp_pos; | 1833 | from = temp_pos; |
| 1220 | if (mathexit) | 1834 | if (mathexit) |
| @@ -1268,7 +1882,9 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1268 | break; | 1882 | break; |
| 1269 | } | 1883 | } |
| 1270 | #endif /* 0 */ | 1884 | #endif /* 0 */ |
| 1271 | 1885 | found = back_comment (from, stop); | |
| 1886 | if (found != -1) from = found; | ||
| 1887 | #if 0 | ||
| 1272 | /* Look back, counting the parity of string-quotes, | 1888 | /* Look back, counting the parity of string-quotes, |
| 1273 | and recording the comment-starters seen. | 1889 | and recording the comment-starters seen. |
| 1274 | When we reach a safe place, assume that's not in a string; | 1890 | When we reach a safe place, assume that's not in a string; |
| @@ -1379,14 +1995,29 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1379 | scan_sexps_forward (&state, find_defun_start (comment_end), | 1995 | scan_sexps_forward (&state, find_defun_start (comment_end), |
| 1380 | comment_end - 1, -10000, 0, Qnil, 0); | 1996 | comment_end - 1, -10000, 0, Qnil, 0); |
| 1381 | if (state.incomment) | 1997 | if (state.incomment) |
| 1382 | from = state.comstart; | 1998 | from = state.comstr_start; |
| 1383 | else | 1999 | else |
| 1384 | /* We can't grok this as a comment; scan it normally. */ | 2000 | /* We can't grok this as a comment; scan it normally. */ |
| 1385 | from = comment_end; | 2001 | from = comment_end; |
| 1386 | } | 2002 | } |
| 1387 | } | 2003 | } |
| 2004 | #endif /* 0 */ | ||
| 1388 | break; | 2005 | break; |
| 1389 | 2006 | ||
| 2007 | case Scomment_fence: | ||
| 2008 | case Sstring_fence: | ||
| 2009 | while (1) | ||
| 2010 | { | ||
| 2011 | DEC_POS (from); | ||
| 2012 | if (from == stop) goto lose; | ||
| 2013 | UPDATE_SYNTAX_TABLE_BACKWARD (from); | ||
| 2014 | if (!char_quoted (from) | ||
| 2015 | && SYNTAX (FETCH_CHAR (from)) == code) | ||
| 2016 | break; | ||
| 2017 | } | ||
| 2018 | if (code == Sstring_fence && !depth && sexpflag) goto done2; | ||
| 2019 | break; | ||
| 2020 | |||
| 1390 | case Sstring: | 2021 | case Sstring: |
| 1391 | stringterm = FETCH_CHAR (from); | 2022 | stringterm = FETCH_CHAR (from); |
| 1392 | while (1) | 2023 | while (1) |
| @@ -1394,6 +2025,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1394 | if (from == stop) goto lose; | 2025 | if (from == stop) goto lose; |
| 1395 | temp_pos = from; | 2026 | temp_pos = from; |
| 1396 | DEC_POS (temp_pos); | 2027 | DEC_POS (temp_pos); |
| 2028 | UPDATE_SYNTAX_TABLE_BACKWARD (temp_pos); | ||
| 1397 | if (!char_quoted (temp_pos) | 2029 | if (!char_quoted (temp_pos) |
| 1398 | && stringterm == FETCH_CHAR (temp_pos)) | 2030 | && stringterm == FETCH_CHAR (temp_pos)) |
| 1399 | break; | 2031 | break; |
| @@ -1429,27 +2061,6 @@ scan_lists (from, count, depth, sexpflag) | |||
| 1429 | /* NOTREACHED */ | 2061 | /* NOTREACHED */ |
| 1430 | } | 2062 | } |
| 1431 | 2063 | ||
| 1432 | static int | ||
| 1433 | char_quoted (pos) | ||
| 1434 | register int pos; | ||
| 1435 | { | ||
| 1436 | register enum syntaxcode code; | ||
| 1437 | register int beg = BEGV; | ||
| 1438 | register int quoted = 0; | ||
| 1439 | int temp_pos = pos; | ||
| 1440 | |||
| 1441 | DEC_POS (temp_pos); | ||
| 1442 | while (pos > beg | ||
| 1443 | && ((code = SYNTAX (FETCH_CHAR (temp_pos))) == Scharquote | ||
| 1444 | || code == Sescape)) | ||
| 1445 | { | ||
| 1446 | pos = temp_pos; | ||
| 1447 | quoted = !quoted; | ||
| 1448 | DEC_POS (temp_pos); | ||
| 1449 | } | ||
| 1450 | return quoted; | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0, | 2064 | DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0, |
| 1454 | "Scan from character number FROM by COUNT lists.\n\ | 2065 | "Scan from character number FROM by COUNT lists.\n\ |
| 1455 | Returns the character number of the position thus found.\n\ | 2066 | Returns the character number of the position thus found.\n\ |
| @@ -1505,9 +2116,14 @@ This includes chars with \"quote\" or \"prefix\" syntax (' or p).") | |||
| 1505 | int c; | 2116 | int c; |
| 1506 | int temp_pos = pos; | 2117 | int temp_pos = pos; |
| 1507 | 2118 | ||
| 2119 | if (pos > beg) | ||
| 2120 | { | ||
| 2121 | SETUP_SYNTAX_TABLE (pos, -1); | ||
| 2122 | } | ||
| 1508 | DEC_POS (temp_pos); | 2123 | DEC_POS (temp_pos); |
| 1509 | 2124 | ||
| 1510 | while (pos > beg && !char_quoted (temp_pos) | 2125 | while (pos > beg && !char_quoted (temp_pos) |
| 2126 | /* Previous statement updates syntax table. */ | ||
| 1511 | && ((c = FETCH_CHAR (temp_pos), SYNTAX (c) == Squote) | 2127 | && ((c = FETCH_CHAR (temp_pos), SYNTAX (c) == Squote) |
| 1512 | || SYNTAX_PREFIX (c))) | 2128 | || SYNTAX_PREFIX (c))) |
| 1513 | { | 2129 | { |
| @@ -1550,6 +2166,8 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1550 | int start_quoted = 0; /* Nonzero means starting after a char quote */ | 2166 | int start_quoted = 0; /* Nonzero means starting after a char quote */ |
| 1551 | Lisp_Object tem; | 2167 | Lisp_Object tem; |
| 1552 | int prev_from; /* Keep one character before FROM. */ | 2168 | int prev_from; /* Keep one character before FROM. */ |
| 2169 | int boundary_stop = commentstop == -1; | ||
| 2170 | int nofence; | ||
| 1553 | 2171 | ||
| 1554 | prev_from = from; | 2172 | prev_from = from; |
| 1555 | DEC_POS (prev_from); | 2173 | DEC_POS (prev_from); |
| @@ -1560,12 +2178,15 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1560 | immediate_quit = 1; | 2178 | immediate_quit = 1; |
| 1561 | QUIT; | 2179 | QUIT; |
| 1562 | 2180 | ||
| 2181 | SETUP_SYNTAX_TABLE (from, 1); | ||
| 2182 | |||
| 1563 | if (NILP (oldstate)) | 2183 | if (NILP (oldstate)) |
| 1564 | { | 2184 | { |
| 1565 | depth = 0; | 2185 | depth = 0; |
| 1566 | state.instring = -1; | 2186 | state.instring = -1; |
| 1567 | state.incomment = 0; | 2187 | state.incomment = 0; |
| 1568 | state.comstyle = 0; /* comment style a by default */ | 2188 | state.comstyle = 0; /* comment style a by default. */ |
| 2189 | state.comstr_start = -1; /* no comment/string seen. */ | ||
| 1569 | } | 2190 | } |
| 1570 | else | 2191 | else |
| 1571 | { | 2192 | { |
| @@ -1579,7 +2200,10 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1579 | oldstate = Fcdr (oldstate); | 2200 | oldstate = Fcdr (oldstate); |
| 1580 | oldstate = Fcdr (oldstate); | 2201 | oldstate = Fcdr (oldstate); |
| 1581 | tem = Fcar (oldstate); | 2202 | tem = Fcar (oldstate); |
| 1582 | state.instring = !NILP (tem) ? XINT (tem) : -1; | 2203 | /* Check whether we are inside string_fence-style string: */ |
| 2204 | state.instring = ( !NILP (tem) | ||
| 2205 | ? ( INTEGERP (tem) ? XINT (tem) : ST_STRING_STYLE) | ||
| 2206 | : -1); | ||
| 1583 | 2207 | ||
| 1584 | oldstate = Fcdr (oldstate); | 2208 | oldstate = Fcdr (oldstate); |
| 1585 | tem = Fcar (oldstate); | 2209 | tem = Fcar (oldstate); |
| @@ -1590,11 +2214,16 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1590 | start_quoted = !NILP (tem); | 2214 | start_quoted = !NILP (tem); |
| 1591 | 2215 | ||
| 1592 | /* if the eight element of the list is nil, we are in comment | 2216 | /* if the eight element of the list is nil, we are in comment |
| 1593 | style a. if it is non-nil, we are in comment style b */ | 2217 | style a. If it is non-nil, we are in comment style b */ |
| 2218 | oldstate = Fcdr (oldstate); | ||
| 1594 | oldstate = Fcdr (oldstate); | 2219 | oldstate = Fcdr (oldstate); |
| 2220 | tem = Fcar (oldstate); | ||
| 2221 | state.comstyle = NILP (tem) ? 0 : ( EQ (tem, Qsyntax_table) | ||
| 2222 | ? ST_COMMENT_STYLE : 1 ); | ||
| 2223 | |||
| 1595 | oldstate = Fcdr (oldstate); | 2224 | oldstate = Fcdr (oldstate); |
| 1596 | tem = Fcar (oldstate); | 2225 | tem = Fcar (oldstate); |
| 1597 | state.comstyle = !NILP (tem); | 2226 | state.comstr_start = NILP (tem) ? -1 : XINT (tem) ; |
| 1598 | } | 2227 | } |
| 1599 | state.quoted = 0; | 2228 | state.quoted = 0; |
| 1600 | mindepth = depth; | 2229 | mindepth = depth; |
| @@ -1602,11 +2231,12 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1602 | curlevel->prev = -1; | 2231 | curlevel->prev = -1; |
| 1603 | curlevel->last = -1; | 2232 | curlevel->last = -1; |
| 1604 | 2233 | ||
| 1605 | /* Enter the loop at a place appropriate for initial state. */ | 2234 | /* Enter the loop at a place appropriate for initial state. */ |
| 1606 | 2235 | ||
| 1607 | if (state.incomment) goto startincomment; | 2236 | if (state.incomment) goto startincomment; |
| 1608 | if (state.instring >= 0) | 2237 | if (state.instring >= 0) |
| 1609 | { | 2238 | { |
| 2239 | nofence = state.instring != ST_STRING_STYLE; | ||
| 1610 | if (start_quoted) goto startquotedinstring; | 2240 | if (start_quoted) goto startquotedinstring; |
| 1611 | goto startinstring; | 2241 | goto startinstring; |
| 1612 | } | 2242 | } |
| @@ -1614,21 +2244,25 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1614 | 2244 | ||
| 1615 | while (from < end) | 2245 | while (from < end) |
| 1616 | { | 2246 | { |
| 2247 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1617 | code = SYNTAX (FETCH_CHAR (from)); | 2248 | code = SYNTAX (FETCH_CHAR (from)); |
| 1618 | INC_FROM; | 2249 | INC_FROM; |
| 1619 | if (code == Scomment) | 2250 | if (code == Scomment) |
| 1620 | state.comstart = prev_from; | 2251 | state.comstr_start = prev_from; |
| 1621 | 2252 | ||
| 1622 | else if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (prev_from)) | 2253 | else if (code == Scomment_fence |
| 1623 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))) | 2254 | || (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (prev_from)) |
| 2255 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))) | ||
| 1624 | { | 2256 | { |
| 1625 | /* Record the comment style we have entered so that only | 2257 | /* Record the comment style we have entered so that only |
| 1626 | the comment-end sequence of the same style actually | 2258 | the comment-end sequence of the same style actually |
| 1627 | terminates the comment section. */ | 2259 | terminates the comment section. */ |
| 2260 | state.comstyle = ( code == Scomment_fence | ||
| 2261 | ? ST_COMMENT_STYLE | ||
| 2262 | : SYNTAX_COMMENT_STYLE (FETCH_CHAR (from))); | ||
| 2263 | state.comstr_start = prev_from; | ||
| 2264 | if (code != Scomment_fence) INC_FROM; | ||
| 1628 | code = Scomment; | 2265 | code = Scomment; |
| 1629 | state.comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)); | ||
| 1630 | state.comstart = prev_from; | ||
| 1631 | INC_FROM; | ||
| 1632 | } | 2266 | } |
| 1633 | 2267 | ||
| 1634 | if (SYNTAX_PREFIX (FETCH_CHAR (prev_from))) | 2268 | if (SYNTAX_PREFIX (FETCH_CHAR (prev_from))) |
| @@ -1651,6 +2285,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1651 | symstarted: | 2285 | symstarted: |
| 1652 | while (from < end) | 2286 | while (from < end) |
| 1653 | { | 2287 | { |
| 2288 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1654 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) | 2289 | switch (SWITCH_ENUM_CAST (SYNTAX (FETCH_CHAR (from)))) |
| 1655 | { | 2290 | { |
| 1656 | case Scharquote: | 2291 | case Scharquote: |
| @@ -1672,7 +2307,7 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1672 | break; | 2307 | break; |
| 1673 | 2308 | ||
| 1674 | startincomment: | 2309 | startincomment: |
| 1675 | if (commentstop) | 2310 | if (commentstop == 1) |
| 1676 | goto done; | 2311 | goto done; |
| 1677 | if (from != BEGV) | 2312 | if (from != BEGV) |
| 1678 | { | 2313 | { |
| @@ -1682,14 +2317,17 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1682 | goto startincomment_1; | 2317 | goto startincomment_1; |
| 1683 | } | 2318 | } |
| 1684 | /* At beginning of buffer, enter the loop the ordinary way. */ | 2319 | /* At beginning of buffer, enter the loop the ordinary way. */ |
| 2320 | state.incomment = 1; | ||
| 2321 | goto commentloop; | ||
| 1685 | 2322 | ||
| 1686 | case Scomment: | 2323 | case Scomment: |
| 1687 | state.incomment = 1; | 2324 | state.incomment = 1; |
| 1688 | if (commentstop) | 2325 | if (commentstop || boundary_stop) goto done; |
| 1689 | goto done; | 2326 | commentloop: |
| 1690 | while (1) | 2327 | while (1) |
| 1691 | { | 2328 | { |
| 1692 | if (from == end) goto done; | 2329 | if (from == end) goto done; |
| 2330 | UPDATE_SYNTAX_TABLE_FORWARD (from); | ||
| 1693 | prev = FETCH_CHAR (from); | 2331 | prev = FETCH_CHAR (from); |
| 1694 | if (SYNTAX (prev) == Sendcomment | 2332 | if (SYNTAX (prev) == Sendcomment |
| 1695 | && SYNTAX_COMMENT_STYLE (prev) == state.comstyle) | 2333 | && SYNTAX_COMMENT_STYLE (prev) == state.comstyle) |
| @@ -1697,6 +2335,9 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1697 | of the same style as the start sequence has been | 2335 | of the same style as the start sequence has been |
| 1698 | encountered. */ | 2336 | encountered. */ |
| 1699 | break; | 2337 | break; |
| 2338 | if (state.comstyle == ST_COMMENT_STYLE | ||
| 2339 | && SYNTAX (prev) == Scomment_fence) | ||
| 2340 | break; | ||
| 1700 | INC_FROM; | 2341 | INC_FROM; |
| 1701 | startincomment_1: | 2342 | startincomment_1: |
| 1702 | if (from < end && SYNTAX_COMEND_FIRST (prev) | 2343 | if (from < end && SYNTAX_COMEND_FIRST (prev) |
| @@ -1705,10 +2346,12 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1705 | /* Only terminate the comment section if the end-comment | 2346 | /* Only terminate the comment section if the end-comment |
| 1706 | sequence of the same style as the start sequence has | 2347 | sequence of the same style as the start sequence has |
| 1707 | been encountered. */ | 2348 | been encountered. */ |
| 1708 | { INC_FROM; break; } | 2349 | { break; } |
| 1709 | } | 2350 | } |
| 2351 | INC_FROM; | ||
| 1710 | state.incomment = 0; | 2352 | state.incomment = 0; |
| 1711 | state.comstyle = 0; /* reset the comment style */ | 2353 | state.comstyle = 0; /* reset the comment style */ |
| 2354 | if (boundary_stop) goto done; | ||
| 1712 | break; | 2355 | break; |
| 1713 | 2356 | ||
| 1714 | case Sopen: | 2357 | case Sopen: |
| @@ -1734,30 +2377,45 @@ scan_sexps_forward (stateptr, from, end, targetdepth, | |||
| 1734 | break; | 2377 | break; |
| 1735 | 2378 | ||
| 1736 | case Sstring: | 2379 | case Sstring: |
| 2380 | case Sstring_fence: | ||
| 2381 | state.comstr_start = from - 1; | ||
| 1737 | if (stopbefore) goto stop; /* this arg means stop at sexp start */ | 2382 | if (stopbefore) goto stop; /* this arg means stop at sexp start */ |
| 1738 | curlevel->last = prev_from; | 2383 | curlevel->last = prev_from; |
| 1739 | state.instring = FETCH_CHAR (prev_from); | 2384 | state.instring = (code == Sstring |
| 2385 | ? (FETCH_CHAR (prev_from)) | ||
| 2386 | : ST_STRING_STYLE); | ||
| 2387 | if (boundary_stop) goto done; | ||
| 1740 | startinstring: | 2388 | startinstring: |
| 1741 | while (1) | 2389 | { |
| 1742 | { | 2390 | nofence = state.instring != ST_STRING_STYLE; |
| 1743 | int c; | 2391 | |
| 1744 | 2392 | while (1) | |
| 1745 | if (from >= end) goto done; | 2393 | { |
| 1746 | c = FETCH_CHAR (from); | 2394 | int c; |
| 1747 | if (c == state.instring) break; | 2395 | |
| 1748 | switch (SWITCH_ENUM_CAST (SYNTAX (c))) | 2396 | if (from >= end) goto done; |
| 1749 | { | 2397 | c = FETCH_CHAR (from); |
| 1750 | case Scharquote: | 2398 | if (nofence && c == state.instring) break; |
| 1751 | case Sescape: | 2399 | UPDATE_SYNTAX_TABLE_FORWARD (from); |
| 1752 | INC_FROM; | 2400 | switch (SWITCH_ENUM_CAST (SYNTAX (c))) |
| 1753 | startquotedinstring: | 2401 | { |
| 1754 | if (from >= end) goto endquoted; | 2402 | case Sstring_fence: |
| 1755 | } | 2403 | if (!nofence) goto string_end; |
| 1756 | INC_FROM; | 2404 | break; |
| 1757 | } | 2405 | case Scharquote: |
| 2406 | case Sescape: | ||
| 2407 | INC_FROM; | ||
| 2408 | startquotedinstring: | ||
| 2409 | if (from >= end) goto endquoted; | ||
| 2410 | } | ||
| 2411 | INC_FROM; | ||
| 2412 | } | ||
| 2413 | } | ||
| 2414 | string_end: | ||
| 1758 | state.instring = -1; | 2415 | state.instring = -1; |
| 1759 | curlevel->prev = curlevel->last; | 2416 | curlevel->prev = curlevel->last; |
| 1760 | INC_FROM; | 2417 | INC_FROM; |
| 2418 | if (boundary_stop) goto done; | ||
| 1761 | break; | 2419 | break; |
| 1762 | 2420 | ||
| 1763 | case Smath: | 2421 | case Smath: |
| @@ -1794,16 +2452,20 @@ Parsing stops at TO or when certain criteria are met;\n\ | |||
| 1794 | point is set to where parsing stops.\n\ | 2452 | point is set to where parsing stops.\n\ |
| 1795 | If fifth arg STATE is omitted or nil,\n\ | 2453 | If fifth arg STATE is omitted or nil,\n\ |
| 1796 | parsing assumes that FROM is the beginning of a function.\n\ | 2454 | parsing assumes that FROM is the beginning of a function.\n\ |
| 1797 | Value is a list of eight elements describing final state of parsing:\n\ | 2455 | Value is a list of nine elements describing final state of parsing:\n\ |
| 1798 | 0. depth in parens.\n\ | 2456 | 0. depth in parens.\n\ |
| 1799 | 1. character address of start of innermost containing list; nil if none.\n\ | 2457 | 1. character address of start of innermost containing list; nil if none.\n\ |
| 1800 | 2. character address of start of last complete sexp terminated.\n\ | 2458 | 2. character address of start of last complete sexp terminated.\n\ |
| 1801 | 3. non-nil if inside a string.\n\ | 2459 | 3. non-nil if inside a string.\n\ |
| 1802 | (it is the character that will terminate the string.)\n\ | 2460 | (it is the character that will terminate the string,\n\ |
| 2461 | or t if the string should be terminated by an explicit\n\ | ||
| 2462 | `syntax-table' property.)\n\ | ||
| 1803 | 4. t if inside a comment.\n\ | 2463 | 4. t if inside a comment.\n\ |
| 1804 | 5. t if following a quote character.\n\ | 2464 | 5. t if following a quote character.\n\ |
| 1805 | 6. the minimum paren-depth encountered during this scan.\n\ | 2465 | 6. the minimum paren-depth encountered during this scan.\n\ |
| 1806 | 7. t if in a comment of style `b'.\n\ | 2466 | 7. t if in a comment of style `b'; `syntax-table' if given by an explicit\n\ |
| 2467 | `syntax-table' property.\n\ | ||
| 2468 | 8. character address of start of last comment or string; nil if none.\n\ | ||
| 1807 | If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\ | 2469 | If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\ |
| 1808 | in parentheses becomes equal to TARGETDEPTH.\n\ | 2470 | in parentheses becomes equal to TARGETDEPTH.\n\ |
| 1809 | Fourth arg STOPBEFORE non-nil means stop when come to\n\ | 2471 | Fourth arg STOPBEFORE non-nil means stop when come to\n\ |
| @@ -1811,7 +2473,9 @@ Fourth arg STOPBEFORE non-nil means stop when come to\n\ | |||
| 1811 | Fifth arg STATE is an eight-list like what this function returns.\n\ | 2473 | Fifth arg STATE is an eight-list like what this function returns.\n\ |
| 1812 | It is used to initialize the state of the parse. Its second and third | 2474 | It is used to initialize the state of the parse. Its second and third |
| 1813 | elements are ignored. | 2475 | elements are ignored. |
| 1814 | Sixth args COMMENTSTOP non-nil means stop at the start of a comment.") | 2476 | Sixth arg COMMENTSTOP non-nil means stop at the start of a comment. If\n\ |
| 2477 | it is `syntax-table', stop after the start of a comment or a string, or\n\ | ||
| 2478 | after end of a comment or a string.") | ||
| 1815 | (from, to, targetdepth, stopbefore, state, commentstop) | 2479 | (from, to, targetdepth, stopbefore, state, commentstop) |
| 1816 | */ | 2480 | */ |
| 1817 | 2481 | ||
| @@ -1834,19 +2498,25 @@ DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 6, 0, | |||
| 1834 | validate_region (&from, &to); | 2498 | validate_region (&from, &to); |
| 1835 | scan_sexps_forward (&state, XINT (from), XINT (to), | 2499 | scan_sexps_forward (&state, XINT (from), XINT (to), |
| 1836 | target, !NILP (stopbefore), oldstate, | 2500 | target, !NILP (stopbefore), oldstate, |
| 1837 | !NILP (commentstop)); | 2501 | (NILP (commentstop) |
| 2502 | ? 0 : (EQ (commentstop, Qsyntax_table) ? -1 : 1))); | ||
| 1838 | 2503 | ||
| 1839 | SET_PT (state.location); | 2504 | SET_PT (state.location); |
| 1840 | 2505 | ||
| 1841 | return Fcons (make_number (state.depth), | 2506 | return Fcons (make_number (state.depth), |
| 1842 | Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart), | 2507 | Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart), |
| 1843 | Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart), | 2508 | Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart), |
| 1844 | Fcons (state.instring >= 0 ? make_number (state.instring) : Qnil, | 2509 | Fcons (state.instring >= 0 |
| 2510 | ? (state.instring == ST_STRING_STYLE | ||
| 2511 | ? Qt : make_number (state.instring)) : Qnil, | ||
| 1845 | Fcons (state.incomment ? Qt : Qnil, | 2512 | Fcons (state.incomment ? Qt : Qnil, |
| 1846 | Fcons (state.quoted ? Qt : Qnil, | 2513 | Fcons (state.quoted ? Qt : Qnil, |
| 1847 | Fcons (make_number (state.mindepth), | 2514 | Fcons (make_number (state.mindepth), |
| 1848 | Fcons (state.comstyle ? Qt : Qnil, | 2515 | Fcons (state.comstyle |
| 1849 | Qnil)))))))); | 2516 | ? (state.comstyle == ST_COMMENT_STYLE |
| 2517 | ? Qsyntax_table : Qt) : Qnil, | ||
| 2518 | Fcons (state.comstr_start != -1 ? make_number (state.comstr_start) : Qnil, | ||
| 2519 | Qnil))))))))); | ||
| 1850 | } | 2520 | } |
| 1851 | 2521 | ||
| 1852 | init_syntax_once () | 2522 | init_syntax_once () |
| @@ -1937,6 +2607,13 @@ syms_of_syntax () | |||
| 1937 | DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments, | 2607 | DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments, |
| 1938 | "Non-nil means `forward-sexp', etc., should treat comments as whitespace."); | 2608 | "Non-nil means `forward-sexp', etc., should treat comments as whitespace."); |
| 1939 | 2609 | ||
| 2610 | DEFVAR_BOOL ("parse-sexp-lookup-properties", &parse_sexp_lookup_properties, | ||
| 2611 | "Non-nil means `forward-sexp', etc., grant `syntax-table' property.\n\ | ||
| 2612 | The value of this property should be either a syntax table, or a cons\n\ | ||
| 2613 | of the form (SYNTAXCODE . MATCHCHAR), SYNTAXCODE being the numeric\n\ | ||
| 2614 | syntax code, MATCHCHAR being nil or the character to match (which is\n\ | ||
| 2615 | relevant only for open/close type."); | ||
| 2616 | |||
| 1940 | words_include_escapes = 0; | 2617 | words_include_escapes = 0; |
| 1941 | DEFVAR_BOOL ("words-include-escapes", &words_include_escapes, | 2618 | DEFVAR_BOOL ("words-include-escapes", &words_include_escapes, |
| 1942 | "Non-nil means `forward-word', etc., should treat escape chars part of words."); | 2619 | "Non-nil means `forward-word', etc., should treat escape chars part of words."); |
| @@ -1953,6 +2630,11 @@ syms_of_syntax () | |||
| 1953 | 2630 | ||
| 1954 | defsubr (&Sforward_word); | 2631 | defsubr (&Sforward_word); |
| 1955 | 2632 | ||
| 2633 | defsubr (&Sskip_chars_forward); | ||
| 2634 | defsubr (&Sskip_chars_backward); | ||
| 2635 | defsubr (&Sskip_syntax_forward); | ||
| 2636 | defsubr (&Sskip_syntax_backward); | ||
| 2637 | |||
| 1956 | defsubr (&Sforward_comment); | 2638 | defsubr (&Sforward_comment); |
| 1957 | defsubr (&Sscan_lists); | 2639 | defsubr (&Sscan_lists); |
| 1958 | defsubr (&Sscan_sexps); | 2640 | defsubr (&Sscan_sexps); |