You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include "buffer.h"
#include "charset.h"
#include "keymap.h"
+#include "regex.h"
/* Make syntax table lookup grant data in gl_state. */
#define SYNTAX_ENTRY_VIA_PROPERTY
static int find_defun_start P_ ((int, int));
static int back_comment P_ ((int, int, int, int, int, int *, int *));
static int char_quoted P_ ((int, int));
-static Lisp_Object skip_chars P_ ((int, int, Lisp_Object, Lisp_Object));
+static Lisp_Object skip_chars P_ ((int, int, Lisp_Object, Lisp_Object, int));
static Lisp_Object scan_lists P_ ((int, int, int, int));
static void scan_sexps_forward P_ ((struct lisp_parse_state *,
int, int, int, int,
int, Lisp_Object, int));
+static int in_classes P_ ((int, Lisp_Object));
\f
struct gl_state_s gl_state; /* Global state of syntax parser. */
DEC_BOTH (charpos, bytepos);
- while (bytepos >= beg)
+ while (charpos >= beg)
{
+ int c;
+
UPDATE_SYNTAX_TABLE_BACKWARD (charpos);
- code = SYNTAX (FETCH_CHAR (bytepos));
+ c = FETCH_CHAR (bytepos);
+ code = SYNTAX (c);
if (! (code == Scharquote || code == Sescape))
break;
gl_state.use_global = 0;
while (PT > BEGV)
{
+ int c;
+
/* Open-paren at start of line means we may have found our
defun-start. */
- if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
+ c = FETCH_CHAR (PT_BYTE);
+ if (SYNTAX (c) == Sopen)
{
SETUP_SYNTAX_TABLE (PT + 1, -1); /* Try again... */
- if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
+ c = FETCH_CHAR (PT_BYTE);
+ if (SYNTAX (c) == Sopen)
break;
/* Now fallback to the default value. */
gl_state.current_syntax_table = current_buffer->syntax_table;
{
from = comstart_pos;
from_byte = comstart_byte;
- /* Globals are correct now. */
+ UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
}
else
{
p = SDATA (string);
code = (enum syntaxcode) syntax_spec_code[*p++];
if (((int) code & 0377) == 0377)
- error ("invalid syntax description letter: %c", p[-1]);
+ error ("Invalid syntax description letter: %c", p[-1]);
if (code == Sinherit)
return Qnil;
(arg)
Lisp_Object arg;
{
+ Lisp_Object tmp;
int orig_val, val;
if (NILP (arg))
val = XINT (arg) > 0 ? ZV : BEGV;
/* Avoid jumping out of an input field. */
- val = XFASTINT (Fconstrain_to_field (make_number (val), make_number (PT),
- Qt, Qnil, Qnil));
+ tmp = Fconstrain_to_field (make_number (val), make_number (PT),
+ Qt, Qnil, Qnil);
+ val = XFASTINT (tmp);
SET_PT (val);
return val == orig_val ? Qt : Qnil;
(but not as the end of a range; quoting is never needed there).
Thus, with arg "a-zA-Z", this skips letters stopping before first nonletter.
With arg "^a-zA-Z", skips nonletters stopping before first letter.
-Returns the distance traveled, either zero or positive.
-Note that char classes, e.g. `[:alpha:]', are not currently supported;
-they will be treated as literals. */)
+Char classes, e.g. `[:alpha:]', are supported.
+
+Returns the distance traveled, either zero or positive. */)
(string, lim)
Lisp_Object string, lim;
{
- return skip_chars (1, 0, string, lim);
+ return skip_chars (1, 0, string, lim, 1);
}
DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,
(string, lim)
Lisp_Object string, lim;
{
- return skip_chars (0, 0, string, lim);
+ return skip_chars (0, 0, string, lim, 1);
}
DEFUN ("skip-syntax-forward", Fskip_syntax_forward, Sskip_syntax_forward, 1, 2, 0,
(syntax, lim)
Lisp_Object syntax, lim;
{
- return skip_chars (1, 1, syntax, lim);
+ return skip_chars (1, 1, syntax, lim, 0);
}
DEFUN ("skip-syntax-backward", Fskip_syntax_backward, Sskip_syntax_backward, 1, 2, 0,
(syntax, lim)
Lisp_Object syntax, lim;
{
- return skip_chars (0, 1, syntax, lim);
+ return skip_chars (0, 1, syntax, lim, 0);
}
static Lisp_Object
-skip_chars (forwardp, syntaxp, string, lim)
+skip_chars (forwardp, syntaxp, string, lim, handle_iso_classes)
int forwardp, syntaxp;
Lisp_Object string, lim;
+ int handle_iso_classes;
{
register unsigned int c;
unsigned char fastmap[0400];
int size_byte;
const unsigned char *str;
int len;
+ Lisp_Object iso_classes;
CHECK_STRING (string);
char_ranges = (int *) alloca (SCHARS (string) * (sizeof (int)) * 2);
string_multibyte = STRING_MULTIBYTE (string);
str = SDATA (string);
size_byte = SBYTES (string);
+ iso_classes = Qnil;
/* Adjust the multibyteness of the string to that of the buffer. */
if (multibyte != string_multibyte)
fastmap[syntax_spec_code[c & 0377]] = 1;
else
{
+ if (handle_iso_classes && c == '['
+ && i_byte < size_byte
+ && STRING_CHAR (str + i_byte, size_byte - i_byte) == ':')
+ {
+ const unsigned char *class_beg = str + i_byte + 1;
+ const unsigned char *class_end = class_beg;
+ const unsigned char *class_limit = str + size_byte - 2;
+ /* Leave room for the null. */
+ unsigned char class_name[CHAR_CLASS_MAX_LENGTH + 1];
+ re_wctype_t cc;
+
+ if (class_limit - class_beg > CHAR_CLASS_MAX_LENGTH)
+ class_limit = class_beg + CHAR_CLASS_MAX_LENGTH;
+
+ while (class_end < class_limit
+ && *class_end >= 'a' && *class_end <= 'z')
+ class_end++;
+
+ if (class_end == class_beg
+ || *class_end != ':' || class_end[1] != ']')
+ goto not_a_class_name;
+
+ bcopy (class_beg, class_name, class_end - class_beg);
+ class_name[class_end - class_beg] = 0;
+
+ cc = re_wctype (class_name);
+ if (cc == 0)
+ error ("Invalid ISO C character class");
+
+ iso_classes = Fcons (make_number (cc), iso_classes);
+
+ i_byte = class_end + 2 - str;
+ continue;
+ }
+
+ not_a_class_name:
if (c == '\\')
{
if (i_byte == size_byte)
stop = endp;
}
c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, nbytes);
+
+ if (! NILP (iso_classes) && in_classes (c, iso_classes))
+ {
+ if (negate)
+ break;
+ else
+ goto fwd_ok;
+ }
+
if (SINGLE_BYTE_CHAR_P (c))
{
if (!fastmap[c])
if (!(negate ^ (i < n_char_ranges)))
break;
}
+ fwd_ok:
p += nbytes, pos++, pos_byte += nbytes;
}
else
p = GAP_END_ADDR;
stop = endp;
}
+
+ if (!NILP (iso_classes) && in_classes (*p, iso_classes))
+ {
+ if (negate)
+ break;
+ else
+ goto fwd_unibyte_ok;
+ }
+
if (!fastmap[*p])
break;
+ fwd_unibyte_ok:
p++, pos++;
}
}
p = prev_p - 1, c = *p, nbytes = 1;
else
c = STRING_CHAR (p, MAX_MULTIBYTE_LENGTH);
+
+ if (! NILP (iso_classes) && in_classes (c, iso_classes))
+ {
+ if (negate)
+ break;
+ else
+ goto back_ok;
+ }
+
if (SINGLE_BYTE_CHAR_P (c))
{
if (!fastmap[c])
if (!(negate ^ (i < n_char_ranges)))
break;
}
+ back_ok:
pos--, pos_byte -= nbytes;
}
else
p = GPT_ADDR;
stop = endp;
}
+
+ if (! NILP (iso_classes) && in_classes (p[-1], iso_classes))
+ {
+ if (negate)
+ break;
+ else
+ goto back_unibyte_ok;
+ }
+
if (!fastmap[p[-1]])
break;
+ back_unibyte_ok:
p--, pos--;
}
}
return make_number (PT - start_point);
}
}
+
+/* Return 1 if character C belongs to one of the ISO classes
+ in the list ISO_CLASSES. Each class is represented by an
+ integer which is its type according to re_wctype. */
+
+static int
+in_classes (c, iso_classes)
+ int c;
+ Lisp_Object iso_classes;
+{
+ int fits_class = 0;
+
+ while (! NILP (iso_classes))
+ {
+ Lisp_Object elt;
+ elt = XCAR (iso_classes);
+ iso_classes = XCDR (iso_classes);
+
+ if (re_iswctype (c, XFASTINT (elt)))
+ fits_class = 1;
+ }
+
+ return fits_class;
+}
\f
/* Jump over a comment, assuming we are at the beginning of one.
FROM is the current position.
INC_BOTH (from, from_byte);
UPDATE_SYNTAX_TABLE_FORWARD (from);
if (from < stop && comstart_first
- && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from_byte))
+ && (c = FETCH_CHAR (from_byte), SYNTAX_COMSTART_SECOND (c))
&& parse_sexp_ignore_comments)
{
/* we have encountered a comment start sequence and we
Fcons (build_string ("Unbalanced parentheses"),
Fcons (make_number (last_good),
Fcons (make_number (from), Qnil))));
-
+ abort ();
/* NOTREACHED */
}
#define INC_FROM \
do { prev_from = from; \
prev_from_byte = from_byte; \
- prev_from_syntax \
- = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte)); \
+ temp = FETCH_CHAR (prev_from_byte); \
+ prev_from_syntax = SYNTAX_WITH_FLAGS (temp); \
INC_BOTH (from, from_byte); \
if (from < end) \
UPDATE_SYNTAX_TABLE_FORWARD (from); \
curlevel->last = -1;
SETUP_SYNTAX_TABLE (prev_from, 1);
- prev_from_syntax = SYNTAX_WITH_FLAGS (FETCH_CHAR (prev_from_byte));
+ temp = FETCH_CHAR (prev_from_byte);
+ prev_from_syntax = SYNTAX_WITH_FLAGS (temp);
UPDATE_SYNTAX_TABLE_FORWARD (from);
/* Enter the loop at a place appropriate for initial state. */
INC_FROM;
code = prev_from_syntax & 0xff;
- if (code == Scomment)
+ if (from < end
+ && SYNTAX_FLAGS_COMSTART_FIRST (prev_from_syntax)
+ && (c1 = FETCH_CHAR (from_byte),
+ SYNTAX_COMSTART_SECOND (c1)))
+ /* Duplicate code to avoid a complex if-expression
+ which causes trouble for the SGI compiler. */
{
- state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax);
- state.incomment = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax) ?
- 1 : -1);
+ /* Record the comment style we have entered so that only
+ the comment-end sequence of the same style actually
+ terminates the comment section. */
+ state.comstyle = SYNTAX_COMMENT_STYLE (c1);
+ comnested = SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax);
+ comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+ state.incomment = comnested ? 1 : -1;
state.comstr_start = prev_from;
+ INC_FROM;
+ code = Scomment;
}
else if (code == Scomment_fence)
{
state.comstr_start = prev_from;
code = Scomment;
}
- else if (from < end)
- if (SYNTAX_FLAGS_COMSTART_FIRST (prev_from_syntax))
- if (c1 = FETCH_CHAR (from_byte),
- SYNTAX_COMSTART_SECOND (c1))
- /* Duplicate code to avoid a complex if-expression
- which causes trouble for the SGI compiler. */
- {
- /* Record the comment style we have entered so that only
- the comment-end sequence of the same style actually
- terminates the comment section. */
- state.comstyle = SYNTAX_COMMENT_STYLE (c1);
- comnested = SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax);
- comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
- state.incomment = comnested ? 1 : -1;
- state.comstr_start = prev_from;
- INC_FROM;
- code = Scomment;
- }
+ else if (code == Scomment)
+ {
+ state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax);
+ state.incomment = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax) ?
+ 1 : -1);
+ state.comstr_start = prev_from;
+ }
if (SYNTAX_FLAGS_PREFIX (prev_from_syntax))
continue;
while (from < end)
{
/* Some compilers can't handle this inside the switch. */
- temp = SYNTAX (FETCH_CHAR (from_byte));
+ temp = FETCH_CHAR (from_byte);
+ temp = SYNTAX (temp);
switch (temp)
{
case Scharquote:
staticpro (&Vsyntax_code_object);
+ staticpro (&gl_state.object);
+ staticpro (&gl_state.global_code);
+ staticpro (&gl_state.current_syntax_table);
+ staticpro (&gl_state.old_prop);
+
+ /* Defined in regex.c */
+ staticpro (&re_match_object);
+
Qscan_error = intern ("scan-error");
staticpro (&Qscan_error);
Fput (Qscan_error, Qerror_conditions,