]> code.delx.au - gnu-emacs/blobdiff - src/syntax.c
*** empty log message ***
[gnu-emacs] / src / syntax.c
index 98829863d424f92a4faa745d0f110228bcb8de50..c2711b90ef12bd706ffb172fce53bd5f0ec7f320 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
-   Copyright (C) 1985, 87, 93, 94, 95, 97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1985, 87, 93, 94, 95, 97, 1998, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA.  */
 #include "commands.h"
 #include "buffer.h"
 #include "charset.h"
-#include <assert.h>
 
 /* Make syntax table lookup grant data in gl_state.  */
 #define SYNTAX_ENTRY_VIA_PROPERTY
@@ -46,11 +45,20 @@ Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error;
 int words_include_escapes;
 int parse_sexp_lookup_properties;
 
+/* Nonzero means `scan-sexps' treat all multibyte characters as symbol.  */
+int multibyte_syntax_as_symbol;
+
 /* Used as a temporary in SYNTAX_ENTRY and other macros in syntax.h,
    if not compiled with GCC.  No need to mark it, since it is used
    only very temporarily.  */
 Lisp_Object syntax_temp;
 
+/* Non-zero means an open parenthesis in column 0 is always considered
+   to be the start of a defun.  Zero means an open parenthesis in
+   column 0 has no special meaning.  */
+
+int open_paren_in_column_0_is_defun_start;
+
 /* This is the internal form of the parse state used in parse-partial-sexp.  */
 
 struct lisp_parse_state
@@ -120,7 +128,7 @@ update_syntax_table (charpos, count, init, object)
      Lisp_Object object;
 {
   Lisp_Object tmp_table;
-  int cnt = 0, doing_extra = 0, invalidate = 1;
+  int cnt = 0, invalidate = 1;
   INTERVAL i, oldi;
 
   if (init)
@@ -138,14 +146,14 @@ update_syntax_table (charpos, count, init, object)
       while (!NULL_PARENT (i)) 
        {
          if (AM_RIGHT_CHILD (i))
-           i->parent->position = i->position
+           INTERVAL_PARENT (i)->position = i->position
              - LEFT_TOTAL_LENGTH (i) + TOTAL_LENGTH (i) /* right end */
-             - TOTAL_LENGTH (i->parent)
-             + LEFT_TOTAL_LENGTH (i->parent);
+             - TOTAL_LENGTH (INTERVAL_PARENT (i))
+             + LEFT_TOTAL_LENGTH (INTERVAL_PARENT (i));
          else
-           i->parent->position = i->position - LEFT_TOTAL_LENGTH (i)
+           INTERVAL_PARENT (i)->position = i->position - LEFT_TOTAL_LENGTH (i)
              + TOTAL_LENGTH (i);
-         i = i->parent;
+         i = INTERVAL_PARENT (i);
        }
       i = gl_state.forward_i;
       gl_state.b_property = i->position - 1 - gl_state.offset;
@@ -345,8 +353,6 @@ static int
 find_defun_start (pos, pos_byte)
      int pos, pos_byte;
 {
-  int tem;
-  int shortage;
   int opoint = PT, opoint_byte = PT_BYTE;
 
   /* Use previous finding, if it's valid and applies to this inquiry.  */
@@ -370,11 +376,13 @@ find_defun_start (pos, pos_byte)
   gl_state.use_global = 0;
   while (PT > BEGV)
     {
-      /* Open-paren at start of line means we found our defun-start.  */
+      /* Open-paren at start of line means we may have found our
+        defun-start.  */
       if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
        {
          SETUP_SYNTAX_TABLE (PT + 1, -1);      /* Try again... */
-         if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen)
+         if (SYNTAX (FETCH_CHAR (PT_BYTE)) == Sopen
+             && open_paren_in_column_0_is_defun_start)
            break;
          /* Now fallback to the default value.  */
          gl_state.current_syntax_table = current_buffer->syntax_table;
@@ -480,7 +488,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
      that determines quote parity to the comment-end.  */
   while (from != stop)
     {
-      int temp_byte, prev_comend_second;
+      int temp_byte;
 
       /* Move back and examine a character.  */
       DEC_BOTH (from, from_byte);
@@ -511,6 +519,9 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
            code = Scomment;
          UPDATE_SYNTAX_TABLE_BACKWARD (from);
        }
+      else if (code == Scomment && comstyle != SYNTAX_COMMENT_STYLE (c))
+       /* Ignore comment starters of a different style.  */
+       continue;
 
       /* Ignore escaped characters, except comment-enders.  */
       if (code != Sendcomment && char_quoted (from, from_byte))
@@ -542,8 +553,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
        }
 
       if (code == Scomment)
-       /* FIXME: we should also check that the comstyle is correct
-          if the Scomment is a single-char. */
+       /* We've already checked that it is the relevant comstyle.  */
        {
          if (comnested && --nesting <= 0 && parity == 0 && !string_lossage)
            /* nested comments have to be balanced, so we don't need to
@@ -565,10 +575,12 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
         (because they go with the earlier comment-ender).  */
       if (code == Sendcomment
          && SYNTAX_COMMENT_STYLE (FETCH_CHAR (from_byte)) == comstyle)
-       if (comnested)
-         nesting++;
-       else
-         break;
+       {
+         if (comnested)
+           nesting++;
+         else
+           break;
+       }
 
       /* Assume a defun-start point is outside of strings.  */
       if (code == Sopen
@@ -635,7 +647,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
   *charpos_ptr = from;
   *bytepos_ptr = from_byte;
 
-  return from;
+  return (from == comment_end) ? -1 : from;
 }
 \f
 DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
@@ -709,11 +721,12 @@ One argument, a syntax table.")
   (table)
      Lisp_Object table;
 {
+  int idx;
   check_syntax_table (table);
   current_buffer->syntax_table = table;
   /* Indicate that this buffer now has a specified syntax table.  */
-  current_buffer->local_var_flags
-    |= XFASTINT (buffer_local_flags.syntax_table);
+  idx = PER_BUFFER_VAR_IDX (syntax_table);
+  SET_PER_BUFFER_VALUE_P (current_buffer, idx, 1);
   return table;
 }
 \f
@@ -955,7 +968,7 @@ describe_syntax (value)
     Lisp_Object value;
 {
   register enum syntaxcode code;
-  char desc, match, start1, start2, end1, end2, prefix, comstyle;
+  char desc, start1, start2, end1, end2, prefix, comstyle;
   char str[2];
   Lisp_Object first, match_lisp;
 
@@ -1222,31 +1235,25 @@ scan_words (from, count)
 DEFUN ("forward-word", Fforward_word, Sforward_word, 1, 1, "p",
   "Move point forward ARG words (backward if ARG is negative).\n\
 Normally returns t.\n\
-If an edge of the buffer is reached, point is left there\n\
-and nil is returned.")
+If an edge of the buffer or a field boundary is reached, point is left there\n\
+and the function returns nil.  Field boundaries are not noticed if\n\
+`inhibit-field-text-motion' is non-nil.")
   (count)
      Lisp_Object count;
 {
-  int val, prompt_end;
+  int orig_val, val;
   CHECK_NUMBER (count, 0);
 
-  if (!(val = scan_words (PT, XINT (count))))
-    {
-      SET_PT (XINT (count) > 0 ? ZV : BEGV);
-      return Qnil;
-    }
+  val = orig_val = scan_words (PT, XINT (count));
+  if (! orig_val)
+    val = XINT (count) > 0 ? ZV : BEGV;
 
-  /* If in a mini-buffer and moving backwards, stop at the end of the
-     prompt.  This prevents accidentially moving into the read-only
-     prompt.  */
-  if (INTEGERP (current_buffer->prompt_end_charpos)
-      && (prompt_end = XINT (current_buffer->prompt_end_charpos),
-         ((PT > prompt_end && val < prompt_end)
-          || (PT < prompt_end && val > prompt_end))))
-    val = prompt_end;
-    
+  /* Avoid jumping out of an input field.  */
+  val = XFASTINT (Fconstrain_to_field (make_number (val), make_number (PT),
+                                      Qt, Qnil));
+  
   SET_PT (val);
-  return Qt;
+  return val == orig_val ? Qt : Qnil;
 }
 \f
 Lisp_Object skip_chars ();
@@ -1304,7 +1311,6 @@ skip_chars (forwardp, syntaxp, string, lim)
      int forwardp, syntaxp;
      Lisp_Object string, lim;
 {
-  register unsigned char *p, *pend;
   register unsigned int c;
   register int ch;
   unsigned char fastmap[0400];
@@ -1705,16 +1711,18 @@ forw_comment (from, from_byte, stop, nesting, style, prev_syntax,
          && SYNTAX_FLAGS_COMMENT_STYLE (syntax) == style
          && (c1 = FETCH_CHAR (from_byte),
              SYNTAX_COMEND_SECOND (c1)))
-       if (--nesting <= 0)
-         /* we have encountered a comment end of the same style
-            as the comment sequence which began this comment
-            section */
-         break;
-       else
-         {
-           INC_BOTH (from, from_byte);
-           UPDATE_SYNTAX_TABLE_FORWARD (from);
-         }
+       {
+         if (--nesting <= 0)
+           /* we have encountered a comment end of the same style
+              as the comment sequence which began this comment
+              section */
+           break;
+         else
+           {
+             INC_BOTH (from, from_byte);
+             UPDATE_SYNTAX_TABLE_FORWARD (from);
+           }
+       }
       if (nesting > 0
          && from < stop
          && SYNTAX_FLAGS_COMSTART_FIRST (syntax)
@@ -1801,6 +1809,8 @@ between them, return t; otherwise return nil.")
              INC_BOTH (from, from_byte);
              UPDATE_SYNTAX_TABLE_FORWARD (from);
            }
+         /* FIXME: here we ignore 2-char endcomments while we don't
+            when going backwards.  */
        }
       while (code == Swhitespace || code == Sendcomment);
 
@@ -1910,9 +1920,20 @@ between them, return t; otherwise return nil.")
            {
              found = back_comment (from, from_byte, stop, comnested, comstyle,
                                    &out_charpos, &out_bytepos);
-             if (found != -1)
+             if (found == -1)
+               {
+#if 0  /* cc-mode (and maybe others) relies on the bogus behavior.  */
+                 /* Failure: we should go back to the end of this
+                    not-quite-endcomment.  */
+                 if (SYNTAX(c) != code)
+                   /* It was a two-char Sendcomment.  */
+                   INC_BOTH (from, from_byte);
+                 goto leave;
+#endif
+               }
+             else
+               /* We have skipped one comment.  */
                from = out_charpos, from_byte = out_bytepos;
-             /* We have skipped one comment.  */
              break;
            }
          else if (code != Swhitespace && code != Scomment)
@@ -1933,6 +1954,13 @@ between them, return t; otherwise return nil.")
   return Qt;
 }
 \f
+/* Return syntax code of character C if C is a single byte character
+   or `multibyte_symbol_p' is zero.  Otherwise, retrun Ssymbol.  */
+
+#define SYNTAX_WITH_MULTIBYTE_CHECK(c)                 \
+  ((SINGLE_BYTE_CHAR_P (c) || !multibyte_symbol_p)     \
+   ? SYNTAX (c) : Ssymbol)
+
 static Lisp_Object
 scan_lists (from, count, depth, sexpflag)
      register int from;
@@ -1954,6 +1982,7 @@ scan_lists (from, count, depth, sexpflag)
   int from_byte;
   int out_bytepos, out_charpos;
   int temp, dummy;
+  int multibyte_symbol_p = sexpflag && multibyte_syntax_as_symbol;
 
   if (depth > 0) min_depth = 0;
 
@@ -1973,7 +2002,7 @@ scan_lists (from, count, depth, sexpflag)
          int comstart_first, prefix;
          UPDATE_SYNTAX_TABLE_FORWARD (from);
          c = FETCH_CHAR (from_byte);
-         code = SYNTAX (c);
+         code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
          comstart_first = SYNTAX_COMSTART_FIRST (c);
          comnested = SYNTAX_COMMENT_NESTED (c);
          prefix = SYNTAX_PREFIX (c);
@@ -2017,7 +2046,8 @@ scan_lists (from, count, depth, sexpflag)
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
 
                  /* Some compilers can't handle this inside the switch.  */
-                 temp = SYNTAX (FETCH_CHAR (from_byte));
+                 c = FETCH_CHAR (from_byte);
+                 temp = SYNTAX_WITH_MULTIBYTE_CHECK (c);
                  switch (temp)
                    {
                    case Scharquote:
@@ -2092,13 +2122,14 @@ scan_lists (from, count, depth, sexpflag)
                {
                  if (from >= stop) goto lose;
                  UPDATE_SYNTAX_TABLE_FORWARD (from);
+                 c = FETCH_CHAR (from_byte);
                  if (code == Sstring 
-                     ? (FETCH_CHAR (from_byte) == stringterm)
-                     : SYNTAX (FETCH_CHAR (from_byte)) == Sstring_fence) 
+                     ? c == stringterm
+                     : SYNTAX_WITH_MULTIBYTE_CHECK (c) == Sstring_fence)
                    break;
 
                  /* Some compilers can't handle this inside the switch.  */
-                 temp = SYNTAX (FETCH_CHAR (from_byte));
+                 temp = SYNTAX_WITH_MULTIBYTE_CHECK (c);
                  switch (temp)
                    {
                    case Scharquote:
@@ -2131,7 +2162,7 @@ scan_lists (from, count, depth, sexpflag)
          DEC_BOTH (from, from_byte);
          UPDATE_SYNTAX_TABLE_BACKWARD (from);
          c = FETCH_CHAR (from_byte);
-         code = SYNTAX (c);
+         code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
          if (depth == min_depth)
            last_good = from;
          comstyle = 0;
@@ -2179,7 +2210,7 @@ scan_lists (from, count, depth, sexpflag)
                    temp_pos--;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                  c1 = FETCH_CHAR (temp_pos);
-                 temp_code = SYNTAX (c1);
+                 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
                  /* Don't allow comment-end to be quoted.  */
                  if (temp_code == Sendcomment)
                    goto done2;
@@ -2191,7 +2222,7 @@ scan_lists (from, count, depth, sexpflag)
                      UPDATE_SYNTAX_TABLE_BACKWARD (from - 1);
                    }
                  c1 = FETCH_CHAR (temp_pos);
-                 temp_code = SYNTAX (c1);
+                 temp_code = SYNTAX_WITH_MULTIBYTE_CHECK (c1);
                  if (! (quoted || temp_code == Sword
                         || temp_code == Ssymbol
                         || temp_code == Squote))
@@ -2233,6 +2264,12 @@ scan_lists (from, count, depth, sexpflag)
                break;
              found = back_comment (from, from_byte, stop, comnested, comstyle,
                                    &out_charpos, &out_bytepos);
+             /* FIXME:  if found == -1, then it really wasn't a comment-end.
+                For single-char Sendcomment, we can't do much about it apart
+                from skipping the char.
+                For 2-char endcomments, we could try again, taking both
+                chars as separate entities, but it's a lot of trouble
+                for very little gain, so we don't bother either.  -sm */
              if (found != -1)
                from = out_charpos, from_byte = out_bytepos;
              break;
@@ -2245,7 +2282,8 @@ scan_lists (from, count, depth, sexpflag)
                  if (from == stop) goto lose;
                  UPDATE_SYNTAX_TABLE_BACKWARD (from);
                  if (!char_quoted (from, from_byte) 
-                     && SYNTAX (FETCH_CHAR (from_byte)) == code)
+                     && (c = FETCH_CHAR (from_byte),
+                         SYNTAX_WITH_MULTIBYTE_CHECK (c) == code))
                    break;
                }
              if (code == Sstring_fence && !depth && sexpflag) goto done2;
@@ -2462,14 +2500,14 @@ do { prev_from = from;                          \
       oldstate = Fcdr (oldstate);
       tem = Fcar (oldstate);
       /* Check whether we are inside string_fence-style string: */
-      state.instring = ( !NILP (tem) 
-                        ? ( INTEGERP (tem) ? XINT (tem) : ST_STRING_STYLE) 
-                        : -1);
+      state.instring = (!NILP (tem) 
+                       ? (INTEGERP (tem) ? XINT (tem) : ST_STRING_STYLE) 
+                       : -1);
 
       oldstate = Fcdr (oldstate);
       tem = Fcar (oldstate);
-      state.incomment = ( !NILP (tem)
-                        ? ( INTEGERP (tem) ? XINT (tem) : -1)
+      state.incomment = (!NILP (tem)
+                        ? (INTEGERP (tem) ? XINT (tem) : -1)
                         : 0);
 
       oldstate = Fcdr (oldstate);
@@ -2481,8 +2519,8 @@ do { prev_from = from;                            \
       oldstate = Fcdr (oldstate);
       oldstate = Fcdr (oldstate);
       tem = Fcar (oldstate);
-      state.comstyle = NILP (tem) ? 0 : ( EQ (tem, Qsyntax_table) 
-                                         ? ST_COMMENT_STYLE : 1 );
+      state.comstyle = NILP (tem) ? 0 : (EQ (tem, Qsyntax_table) 
+                                        ? ST_COMMENT_STYLE : 1);
 
       oldstate = Fcdr (oldstate);
       tem = Fcar (oldstate);
@@ -2618,7 +2656,8 @@ do { prev_from = from;                            \
          goto commentloop;
 
        case Scomment:
-         assert (state.incomment != 0); /* state.incomment = -1; */
+         if (! state.incomment)
+           abort ();
          if (commentstop || boundary_stop) goto done;
        commentloop:
          /* The (from == BEGV) test is to enter the loop in the middle so
@@ -2893,6 +2932,11 @@ init_syntax_once ()
       c = ".,;:?!#@~^'`"[i];
       SET_RAW_SYNTAX_ENTRY (Vstandard_syntax_table, c, temp);
     }
+
+  /* All multibyte characters have syntax `word' by default.  */
+  temp = XVECTOR (Vsyntax_code_object)->contents[(int) Sword];
+  for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
+    XCHAR_TABLE (Vstandard_syntax_table)->contents[i] = temp;
 }
 
 void
@@ -2924,6 +2968,15 @@ relevant only for open/close type.");
   DEFVAR_BOOL ("words-include-escapes", &words_include_escapes,
     "Non-nil means `forward-word', etc., should treat escape chars part of words.");
 
+  DEFVAR_BOOL ("multibyte-syntax-as-symbol", &multibyte_syntax_as_symbol,
+    "Non-nil means `scan-sexps' treats all multibyte characters as symbol.");
+  multibyte_syntax_as_symbol = 0;
+
+  DEFVAR_BOOL ("open-paren-in-column-0-is-defun-start",
+              &open_paren_in_column_0_is_defun_start,
+    "Non-nil means an open paren in column 0 denotes the start of a defun.");
+  open_paren_in_column_0_is_defun_start = 1;
+
   defsubr (&Ssyntax_table_p);
   defsubr (&Ssyntax_table);
   defsubr (&Sstandard_syntax_table);