diff options
Diffstat (limited to 'src/syntax.c')
| -rw-r--r-- | src/syntax.c | 155 |
1 files changed, 137 insertions, 18 deletions
diff --git a/src/syntax.c b/src/syntax.c index 4b26d04cd30..62612620f03 100644 --- a/src/syntax.c +++ b/src/syntax.c | |||
| @@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 26 | #include "buffer.h" | 26 | #include "buffer.h" |
| 27 | #include "charset.h" | 27 | #include "charset.h" |
| 28 | #include "keymap.h" | 28 | #include "keymap.h" |
| 29 | #include "regex.h" | ||
| 29 | 30 | ||
| 30 | /* Make syntax table lookup grant data in gl_state. */ | 31 | /* Make syntax table lookup grant data in gl_state. */ |
| 31 | #define SYNTAX_ENTRY_VIA_PROPERTY | 32 | #define SYNTAX_ENTRY_VIA_PROPERTY |
| @@ -97,11 +98,12 @@ static int find_start_modiff; | |||
| 97 | static int find_defun_start P_ ((int, int)); | 98 | static int find_defun_start P_ ((int, int)); |
| 98 | static int back_comment P_ ((int, int, int, int, int, int *, int *)); | 99 | static int back_comment P_ ((int, int, int, int, int, int *, int *)); |
| 99 | static int char_quoted P_ ((int, int)); | 100 | static int char_quoted P_ ((int, int)); |
| 100 | static Lisp_Object skip_chars P_ ((int, int, Lisp_Object, Lisp_Object)); | 101 | static Lisp_Object skip_chars P_ ((int, int, Lisp_Object, Lisp_Object, int)); |
| 101 | static Lisp_Object scan_lists P_ ((int, int, int, int)); | 102 | static Lisp_Object scan_lists P_ ((int, int, int, int)); |
| 102 | static void scan_sexps_forward P_ ((struct lisp_parse_state *, | 103 | static void scan_sexps_forward P_ ((struct lisp_parse_state *, |
| 103 | int, int, int, int, | 104 | int, int, int, int, |
| 104 | int, Lisp_Object, int)); | 105 | int, Lisp_Object, int)); |
| 106 | static int in_classes P_ ((int, Lisp_Object)); | ||
| 105 | 107 | ||
| 106 | 108 | ||
| 107 | struct gl_state_s gl_state; /* Global state of syntax parser. */ | 109 | struct gl_state_s gl_state; /* Global state of syntax parser. */ |
| @@ -292,8 +294,11 @@ char_quoted (charpos, bytepos) | |||
| 292 | 294 | ||
| 293 | while (bytepos >= beg) | 295 | while (bytepos >= beg) |
| 294 | { | 296 | { |
| 297 | int c; | ||
| 298 | |||
| 295 | UPDATE_SYNTAX_TABLE_BACKWARD (charpos); | 299 | UPDATE_SYNTAX_TABLE_BACKWARD (charpos); |
| 296 | code = SYNTAX (FETCH_CHAR (bytepos)); | 300 | c = FETCH_CHAR (bytepos); |
| 301 | code = SYNTAX (c); | ||
| 297 | if (! (code == Scharquote || code == Sescape)) | 302 | if (! (code == Scharquote || code == Sescape)) |
| 298 | break; | 303 | break; |
| 299 | 304 | ||
| @@ -380,12 +385,16 @@ find_defun_start (pos, pos_byte) | |||
| 380 | gl_state.use_global = 0; | 385 | gl_state.use_global = 0; |
| 381 | while (PT > BEGV) | 386 | while (PT > BEGV) |
| 382 | { | 387 | { |
| 388 | int c; | ||
| 389 | |||
| 383 | /* Open-paren at start of line means we may have found our | 390 | /* Open-paren at start of line means we may have found our |
| 384 | defun-start. */ | 391 | defun-start. */ |
| 385 | if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen) | 392 | c = FETCH_CHAR (PT_BYTE); |
| 393 | if (SYNTAX (c) == Sopen) | ||
| 386 | { | 394 | { |
| 387 | SETUP_SYNTAX_TABLE (PT + 1, -1); /* Try again... */ | 395 | SETUP_SYNTAX_TABLE (PT + 1, -1); /* Try again... */ |
| 388 | if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen) | 396 | c = FETCH_CHAR (PT_BYTE); |
| 397 | if (SYNTAX (c) == Sopen) | ||
| 389 | break; | 398 | break; |
| 390 | /* Now fallback to the default value. */ | 399 | /* Now fallback to the default value. */ |
| 391 | gl_state.current_syntax_table = current_buffer->syntax_table; | 400 | gl_state.current_syntax_table = current_buffer->syntax_table; |
| @@ -1314,13 +1323,13 @@ except that `]' is never special and `\\' quotes `^', `-' or `\\' | |||
| 1314 | (but not as the end of a range; quoting is never needed there). | 1323 | (but not as the end of a range; quoting is never needed there). |
| 1315 | Thus, with arg "a-zA-Z", this skips letters stopping before first nonletter. | 1324 | Thus, with arg "a-zA-Z", this skips letters stopping before first nonletter. |
| 1316 | With arg "^a-zA-Z", skips nonletters stopping before first letter. | 1325 | With arg "^a-zA-Z", skips nonletters stopping before first letter. |
| 1317 | Returns the distance traveled, either zero or positive. | 1326 | Char classes, e.g. `[:alpha:]', are supported. |
| 1318 | Note that char classes, e.g. `[:alpha:]', are not currently supported; | 1327 | |
| 1319 | they will be treated as literals. */) | 1328 | Returns the distance traveled, either zero or positive. */) |
| 1320 | (string, lim) | 1329 | (string, lim) |
| 1321 | Lisp_Object string, lim; | 1330 | Lisp_Object string, lim; |
| 1322 | { | 1331 | { |
| 1323 | return skip_chars (1, 0, string, lim); | 1332 | return skip_chars (1, 0, string, lim, 1); |
| 1324 | } | 1333 | } |
| 1325 | 1334 | ||
| 1326 | DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0, | 1335 | DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0, |
| @@ -1330,7 +1339,7 @@ Returns the distance traveled, either zero or negative. */) | |||
| 1330 | (string, lim) | 1339 | (string, lim) |
| 1331 | Lisp_Object string, lim; | 1340 | Lisp_Object string, lim; |
| 1332 | { | 1341 | { |
| 1333 | return skip_chars (0, 0, string, lim); | 1342 | return skip_chars (0, 0, string, lim, 1); |
| 1334 | } | 1343 | } |
| 1335 | 1344 | ||
| 1336 | DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0, | 1345 | DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0, |
| @@ -1342,7 +1351,7 @@ This function returns the distance traveled, either zero or positive. */) | |||
| 1342 | (syntax, lim) | 1351 | (syntax, lim) |
| 1343 | Lisp_Object syntax, lim; | 1352 | Lisp_Object syntax, lim; |
| 1344 | { | 1353 | { |
| 1345 | return skip_chars (1, 1, syntax, lim); | 1354 | return skip_chars (1, 1, syntax, lim, 0); |
| 1346 | } | 1355 | } |
| 1347 | 1356 | ||
| 1348 | DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0, | 1357 | DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0, |
| @@ -1354,13 +1363,14 @@ This function returns the distance traveled, either zero or negative. */) | |||
| 1354 | (syntax, lim) | 1363 | (syntax, lim) |
| 1355 | Lisp_Object syntax, lim; | 1364 | Lisp_Object syntax, lim; |
| 1356 | { | 1365 | { |
| 1357 | return skip_chars (0, 1, syntax, lim); | 1366 | return skip_chars (0, 1, syntax, lim, 0); |
| 1358 | } | 1367 | } |
| 1359 | 1368 | ||
| 1360 | static Lisp_Object | 1369 | static Lisp_Object |
| 1361 | skip_chars (forwardp, syntaxp, string, lim) | 1370 | skip_chars (forwardp, syntaxp, string, lim, handle_iso_classes) |
| 1362 | int forwardp, syntaxp; | 1371 | int forwardp, syntaxp; |
| 1363 | Lisp_Object string, lim; | 1372 | Lisp_Object string, lim; |
| 1373 | int handle_iso_classes; | ||
| 1364 | { | 1374 | { |
| 1365 | register unsigned int c; | 1375 | register unsigned int c; |
| 1366 | unsigned char fastmap[0400]; | 1376 | unsigned char fastmap[0400]; |
| @@ -1376,12 +1386,14 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1376 | int size_byte; | 1386 | int size_byte; |
| 1377 | const unsigned char *str; | 1387 | const unsigned char *str; |
| 1378 | int len; | 1388 | int len; |
| 1389 | Lisp_Object iso_classes; | ||
| 1379 | 1390 | ||
| 1380 | CHECK_STRING (string); | 1391 | CHECK_STRING (string); |
| 1381 | char_ranges = (int *) alloca (SCHARS (string) * (sizeof (int)) * 2); | 1392 | char_ranges = (int *) alloca (SCHARS (string) * (sizeof (int)) * 2); |
| 1382 | string_multibyte = STRING_MULTIBYTE (string); | 1393 | string_multibyte = STRING_MULTIBYTE (string); |
| 1383 | str = SDATA (string); | 1394 | str = SDATA (string); |
| 1384 | size_byte = SBYTES (string); | 1395 | size_byte = SBYTES (string); |
| 1396 | iso_classes = Qnil; | ||
| 1385 | 1397 | ||
| 1386 | /* Adjust the multibyteness of the string to that of the buffer. */ | 1398 | /* Adjust the multibyteness of the string to that of the buffer. */ |
| 1387 | if (multibyte != string_multibyte) | 1399 | if (multibyte != string_multibyte) |
| @@ -1437,6 +1449,45 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1437 | fastmap[syntax_spec_code[c & 0377]] = 1; | 1449 | fastmap[syntax_spec_code[c & 0377]] = 1; |
| 1438 | else | 1450 | else |
| 1439 | { | 1451 | { |
| 1452 | if (handle_iso_classes && c == '[' | ||
| 1453 | && i_byte < size_byte | ||
| 1454 | && STRING_CHAR (str + i_byte, size_byte - i_byte) == ':') | ||
| 1455 | { | ||
| 1456 | const unsigned char *class_beg = str + i_byte + 1; | ||
| 1457 | const unsigned char *class_end = class_beg; | ||
| 1458 | const unsigned char *class_limit = str + size_byte; | ||
| 1459 | /* Leave room for the null. */ | ||
| 1460 | unsigned char class_name[CHAR_CLASS_MAX_LENGTH + 1]; | ||
| 1461 | re_wctype_t cc; | ||
| 1462 | |||
| 1463 | if (class_limit - class_beg > CHAR_CLASS_MAX_LENGTH) | ||
| 1464 | class_limit = class_beg + CHAR_CLASS_MAX_LENGTH; | ||
| 1465 | |||
| 1466 | while (class_end != class_limit | ||
| 1467 | && ! (*class_end >= 0200 | ||
| 1468 | || *class_end <= 040 | ||
| 1469 | || (*class_end == ':' | ||
| 1470 | && class_end[1] == ']'))) | ||
| 1471 | class_end++; | ||
| 1472 | |||
| 1473 | if (class_end == class_limit | ||
| 1474 | || *class_end >= 0200 | ||
| 1475 | || *class_end <= 040) | ||
| 1476 | error ("Invalid ISO C character class"); | ||
| 1477 | |||
| 1478 | bcopy (class_beg, class_name, class_end - class_beg); | ||
| 1479 | class_name[class_end - class_beg] = 0; | ||
| 1480 | |||
| 1481 | cc = re_wctype (class_name); | ||
| 1482 | if (cc == 0) | ||
| 1483 | error ("Invalid ISO C character class"); | ||
| 1484 | |||
| 1485 | iso_classes = Fcons (make_number (cc), iso_classes); | ||
| 1486 | |||
| 1487 | i_byte = class_end + 2 - str; | ||
| 1488 | continue; | ||
| 1489 | } | ||
| 1490 | |||
| 1440 | if (c == '\\') | 1491 | if (c == '\\') |
| 1441 | { | 1492 | { |
| 1442 | if (i_byte == size_byte) | 1493 | if (i_byte == size_byte) |
| @@ -1630,6 +1681,15 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1630 | stop = endp; | 1681 | stop = endp; |
| 1631 | } | 1682 | } |
| 1632 | c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, nbytes); | 1683 | c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, nbytes); |
| 1684 | |||
| 1685 | if (! NILP (iso_classes) && in_classes (c, iso_classes)) | ||
| 1686 | { | ||
| 1687 | if (negate) | ||
| 1688 | break; | ||
| 1689 | else | ||
| 1690 | goto fwd_ok; | ||
| 1691 | } | ||
| 1692 | |||
| 1633 | if (SINGLE_BYTE_CHAR_P (c)) | 1693 | if (SINGLE_BYTE_CHAR_P (c)) |
| 1634 | { | 1694 | { |
| 1635 | if (!fastmap[c]) | 1695 | if (!fastmap[c]) |
| @@ -1652,6 +1712,7 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1652 | if (!(negate ^ (i < n_char_ranges))) | 1712 | if (!(negate ^ (i < n_char_ranges))) |
| 1653 | break; | 1713 | break; |
| 1654 | } | 1714 | } |
| 1715 | fwd_ok: | ||
| 1655 | p += nbytes, pos++, pos_byte += nbytes; | 1716 | p += nbytes, pos++, pos_byte += nbytes; |
| 1656 | } | 1717 | } |
| 1657 | else | 1718 | else |
| @@ -1664,8 +1725,19 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1664 | p = GAP_END_ADDR; | 1725 | p = GAP_END_ADDR; |
| 1665 | stop = endp; | 1726 | stop = endp; |
| 1666 | } | 1727 | } |
| 1728 | |||
| 1729 | if (!NILP (iso_classes) && in_classes (*p, iso_classes)) | ||
| 1730 | { | ||
| 1731 | if (negate) | ||
| 1732 | break; | ||
| 1733 | else | ||
| 1734 | goto fwd_ok; | ||
| 1735 | } | ||
| 1736 | |||
| 1667 | if (!fastmap[*p]) | 1737 | if (!fastmap[*p]) |
| 1668 | break; | 1738 | break; |
| 1739 | |||
| 1740 | fwd_unibyte_ok: | ||
| 1669 | p++, pos++; | 1741 | p++, pos++; |
| 1670 | } | 1742 | } |
| 1671 | } | 1743 | } |
| @@ -1691,6 +1763,15 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1691 | p = prev_p - 1, c = *p, nbytes = 1; | 1763 | p = prev_p - 1, c = *p, nbytes = 1; |
| 1692 | else | 1764 | else |
| 1693 | c = STRING_CHAR (p, MAX_MULTIBYTE_LENGTH); | 1765 | c = STRING_CHAR (p, MAX_MULTIBYTE_LENGTH); |
| 1766 | |||
| 1767 | if (! NILP (iso_classes) && in_classes (c, iso_classes)) | ||
| 1768 | { | ||
| 1769 | if (negate) | ||
| 1770 | break; | ||
| 1771 | else | ||
| 1772 | goto back_ok; | ||
| 1773 | } | ||
| 1774 | |||
| 1694 | if (SINGLE_BYTE_CHAR_P (c)) | 1775 | if (SINGLE_BYTE_CHAR_P (c)) |
| 1695 | { | 1776 | { |
| 1696 | if (!fastmap[c]) | 1777 | if (!fastmap[c]) |
| @@ -1705,6 +1786,7 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1705 | if (!(negate ^ (i < n_char_ranges))) | 1786 | if (!(negate ^ (i < n_char_ranges))) |
| 1706 | break; | 1787 | break; |
| 1707 | } | 1788 | } |
| 1789 | back_ok: | ||
| 1708 | pos--, pos_byte -= nbytes; | 1790 | pos--, pos_byte -= nbytes; |
| 1709 | } | 1791 | } |
| 1710 | else | 1792 | else |
| @@ -1717,8 +1799,19 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1717 | p = GPT_ADDR; | 1799 | p = GPT_ADDR; |
| 1718 | stop = endp; | 1800 | stop = endp; |
| 1719 | } | 1801 | } |
| 1802 | |||
| 1803 | if (! NILP (iso_classes) && in_classes (p[-1], iso_classes)) | ||
| 1804 | { | ||
| 1805 | if (negate) | ||
| 1806 | break; | ||
| 1807 | else | ||
| 1808 | goto fwd_ok; | ||
| 1809 | } | ||
| 1810 | |||
| 1720 | if (!fastmap[p[-1]]) | 1811 | if (!fastmap[p[-1]]) |
| 1721 | break; | 1812 | break; |
| 1813 | |||
| 1814 | back_unibyte_ok: | ||
| 1722 | p--, pos--; | 1815 | p--, pos--; |
| 1723 | } | 1816 | } |
| 1724 | } | 1817 | } |
| @@ -1741,6 +1834,30 @@ skip_chars (forwardp, syntaxp, string, lim) | |||
| 1741 | return make_number (PT - start_point); | 1834 | return make_number (PT - start_point); |
| 1742 | } | 1835 | } |
| 1743 | } | 1836 | } |
| 1837 | |||
| 1838 | /* Return 1 if character C belongs to one of the ISO classes | ||
| 1839 | in the list ISO_CLASSES. Each class is represented by an | ||
| 1840 | integer which is its type according to re_wctype. */ | ||
| 1841 | |||
| 1842 | static int | ||
| 1843 | in_classes (c, iso_classes) | ||
| 1844 | int c; | ||
| 1845 | Lisp_Object iso_classes; | ||
| 1846 | { | ||
| 1847 | int fits_class = 0; | ||
| 1848 | |||
| 1849 | while (! NILP (iso_classes)) | ||
| 1850 | { | ||
| 1851 | Lisp_Object elt; | ||
| 1852 | elt = XCAR (iso_classes); | ||
| 1853 | iso_classes = XCDR (iso_classes); | ||
| 1854 | |||
| 1855 | if (re_iswctype (c, XFASTINT (elt))) | ||
| 1856 | fits_class = 1; | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | return fits_class; | ||
| 1860 | } | ||
| 1744 | 1861 | ||
| 1745 | /* Jump over a comment, assuming we are at the beginning of one. | 1862 | /* Jump over a comment, assuming we are at the beginning of one. |
| 1746 | FROM is the current position. | 1863 | FROM is the current position. |
| @@ -2124,7 +2241,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 2124 | INC_BOTH (from, from_byte); | 2241 | INC_BOTH (from, from_byte); |
| 2125 | UPDATE_SYNTAX_TABLE_FORWARD (from); | 2242 | UPDATE_SYNTAX_TABLE_FORWARD (from); |
| 2126 | if (from < stop && comstart_first | 2243 | if (from < stop && comstart_first |
| 2127 | && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from_byte)) | 2244 | && (c = FETCH_CHAR (from_byte), SYNTAX_COMSTART_SECOND (c)) |
| 2128 | && parse_sexp_ignore_comments) | 2245 | && parse_sexp_ignore_comments) |
| 2129 | { | 2246 | { |
| 2130 | /* we have encountered a comment start sequence and we | 2247 | /* we have encountered a comment start sequence and we |
| @@ -2449,7 +2566,7 @@ scan_lists (from, count, depth, sexpflag) | |||
| 2449 | Fcons (build_string ("Unbalanced parentheses"), | 2566 | Fcons (build_string ("Unbalanced parentheses"), |
| 2450 | Fcons (make_number (last_good), | 2567 | Fcons (make_number (last_good), |
| 2451 | Fcons (make_number (from), Qnil)))); | 2568 | Fcons (make_number (from), Qnil)))); |
| 2452 | 2569 | abort (); | |
| 2453 | /* NOTREACHED */ | 2570 | /* NOTREACHED */ |
| 2454 | } | 2571 | } |
| 2455 | 2572 | ||
| @@ -2588,8 +2705,8 @@ scan_sexps_forward (stateptr, from, from_byte, end, targetdepth, | |||
| 2588 | #define INC_FROM \ | 2705 | #define INC_FROM \ |
| 2589 | do { prev_from = from; \ | 2706 | do { prev_from = from; \ |
| 2590 | prev_from_byte = from_byte; \ | 2707 | prev_from_byte = from_byte; \ |
| 2591 | prev_from_syntax \ | 2708 | temp = FETCH_CHAR (prev_from_byte); \ |
| 2592 | = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte)); \ | 2709 | prev_from_syntax = SYNTAX_WITH_FLAGS (temp); \ |
| 2593 | INC_BOTH (from, from_byte); \ | 2710 | INC_BOTH (from, from_byte); \ |
| 2594 | if (from < end) \ | 2711 | if (from < end) \ |
| 2595 | UPDATE_SYNTAX_TABLE_FORWARD (from); \ | 2712 | UPDATE_SYNTAX_TABLE_FORWARD (from); \ |
| @@ -2664,7 +2781,8 @@ do { prev_from = from; \ | |||
| 2664 | curlevel->last = -1; | 2781 | curlevel->last = -1; |
| 2665 | 2782 | ||
| 2666 | SETUP_SYNTAX_TABLE (prev_from, 1); | 2783 | SETUP_SYNTAX_TABLE (prev_from, 1); |
| 2667 | prev_from_syntax = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte)); | 2784 | temp = FETCH_CHAR (prev_from_byte); |
| 2785 | prev_from_syntax = SYNTAX_WITH_FLAGS (temp); | ||
| 2668 | UPDATE_SYNTAX_TABLE_FORWARD (from); | 2786 | UPDATE_SYNTAX_TABLE_FORWARD (from); |
| 2669 | 2787 | ||
| 2670 | /* Enter the loop at a place appropriate for initial state. */ | 2788 | /* Enter the loop at a place appropriate for initial state. */ |
| @@ -2743,7 +2861,8 @@ do { prev_from = from; \ | |||
| 2743 | while (from < end) | 2861 | while (from < end) |
| 2744 | { | 2862 | { |
| 2745 | /* Some compilers can't handle this inside the switch. */ | 2863 | /* Some compilers can't handle this inside the switch. */ |
| 2746 | temp = SYNTAX (FETCH_CHAR (from_byte)); | 2864 | temp = FETCH_CHAR (from_byte); |
| 2865 | temp = SYNTAX (temp); | ||
| 2747 | switch (temp) | 2866 | switch (temp) |
| 2748 | { | 2867 | { |
| 2749 | case Scharquote: | 2868 | case Scharquote: |