]> code.delx.au - gnu-emacs/blobdiff - src/syntax.c
Typo in comment.
[gnu-emacs] / src / syntax.c
index 6065d5fec7c778eedb0df7eec7630fae26f2abe5..fa34c2433c159534c71326c8413503c5133b1f14 100644 (file)
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA.  */
 #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
@@ -97,11 +98,12 @@ static int find_start_modiff;
 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.  */
@@ -290,7 +292,7 @@ char_quoted (charpos, bytepos)
 
   DEC_BOTH (charpos, bytepos);
 
-  while (bytepos >= beg)
+  while (charpos >= beg)
     {
       int c;
 
@@ -671,7 +673,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
     {
       from = comstart_pos;
       from_byte = comstart_byte;
-      /* Globals are correct now.  */
+      UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
     }
   else
     {
@@ -1293,6 +1295,7 @@ and the function returns nil.  Field boundaries are not noticed if
      (arg)
      Lisp_Object arg;
 {
+  Lisp_Object tmp;
   int orig_val, val;
 
   if (NILP (arg))
@@ -1305,8 +1308,9 @@ and the function returns nil.  Field boundaries are not noticed if
     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;
@@ -1321,13 +1325,13 @@ except that `]' is never special and `\\' quotes `^', `-' or `\\'
  (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,
@@ -1337,7 +1341,7 @@ Returns the distance traveled, either zero or negative.  */)
      (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,
@@ -1349,7 +1353,7 @@ This function returns the distance traveled, either zero or positive.  */)
      (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,
@@ -1361,13 +1365,14 @@ This function returns the distance traveled, either zero or negative.  */)
      (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];
@@ -1383,12 +1388,14 @@ skip_chars (forwardp, syntaxp, string, lim)
   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)
@@ -1444,6 +1451,42 @@ skip_chars (forwardp, syntaxp, string, lim)
        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)
@@ -1637,6 +1680,15 @@ skip_chars (forwardp, syntaxp, string, lim)
                      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])
@@ -1659,6 +1711,7 @@ skip_chars (forwardp, syntaxp, string, lim)
                      if (!(negate ^ (i < n_char_ranges)))
                        break;
                    }
+               fwd_ok:
                  p += nbytes, pos++, pos_byte += nbytes;
                }
            else
@@ -1671,8 +1724,18 @@ skip_chars (forwardp, syntaxp, string, lim)
                      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++;
                }
          }
@@ -1698,6 +1761,15 @@ skip_chars (forwardp, syntaxp, string, lim)
                    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])
@@ -1712,6 +1784,7 @@ skip_chars (forwardp, syntaxp, string, lim)
                      if (!(negate ^ (i < n_char_ranges)))
                        break;
                    }
+               back_ok:
                  pos--, pos_byte -= nbytes;
                }
            else
@@ -1724,8 +1797,18 @@ skip_chars (forwardp, syntaxp, string, lim)
                      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--;
                }
          }
@@ -1748,6 +1831,30 @@ skip_chars (forwardp, syntaxp, string, lim)
     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.
@@ -2694,12 +2801,23 @@ do { prev_from = from;                          \
       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)
        {
@@ -2711,24 +2829,13 @@ do { prev_from = from;                          \
          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;