diff src/syntax.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents aa5ed11f473b
children d1247f3cc363
line wrap: on
line diff
--- a/src/syntax.c	Sat Dec 26 00:20:27 2009 -0600
+++ b/src/syntax.c	Sat Dec 26 21:18:49 2009 -0600
@@ -31,6 +31,12 @@
 #include "syntax.h"
 #include "extents.h"
 
+#ifdef NEW_GC
+# define UNUSED_IF_NEW_GC(decl) UNUSED (decl)
+#else
+# define UNUSED_IF_NEW_GC(decl) decl
+#endif
+
 #define ST_COMMENT_STYLE 0x101
 #define ST_STRING_STYLE  0x102
 
@@ -146,7 +152,6 @@
 
 DEFUN ("syntax-table-p", Fsyntax_table_p, 1, 1, 0, /*
 Return t if OBJECT is a syntax table.
-Any vector of 256 elements will do.
 */
        (object))
 {
@@ -238,7 +243,73 @@
   buf->local_var_flags |= XINT (buffer_local_flags.syntax_table);
   return syntax_table;
 }
+
+
 
+/*
+ * Syntax caching
+ */
+
+/* syntax_cache object implementation */
+
+static const struct memory_description syntax_cache_description_1 [] = {
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, object) },
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, buffer) },
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, syntax_table) },
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, mirror_table) },
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, start) },
+  { XD_LISP_OBJECT, offsetof (struct syntax_cache, end) },
+  { XD_END }
+};
+
+#ifdef NEW_GC
+DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("syntax-cache", syntax_cache,
+				      0, syntax_cache_description_1,
+				      Lisp_Syntax_Cache);
+#else /* not NEW_GC */
+
+const struct sized_memory_description syntax_cache_description = {
+  sizeof (struct syntax_cache),
+  syntax_cache_description_1
+};
+#endif /* not NEW_GC */
+
+/* static syntax cache utilities */
+
+static void
+syntax_cache_table_was_changed (struct buffer *buf)
+{
+  struct syntax_cache *cache = buf->syntax_cache;
+  if (cache->no_syntax_table_prop)
+    {
+      cache->syntax_table =
+	BUFFER_SYNTAX_TABLE (buf);
+      cache->mirror_table =
+	BUFFER_MIRROR_SYNTAX_TABLE (buf);
+    }
+}
+
+static void
+reset_buffer_syntax_cache_range (struct syntax_cache *cache,
+				 Lisp_Object buffer, int infinite)
+{
+  Fset_marker (cache->start, make_int (1), buffer);
+  Fset_marker (cache->end, make_int (1), buffer);
+  Fset_marker_insertion_type (cache->start, Qt);
+  Fset_marker_insertion_type (cache->end, Qnil);
+  /* #### Should we "cache->no_syntax_table_prop = 1;" here? */
+  /* #### Cf comment on INFINITE in init_syntax_cache. -- sjt */
+  if (infinite)
+    {
+      cache->prev_change = EMACS_INT_MIN;
+      cache->next_change = EMACS_INT_MAX;
+    }
+  else
+    {
+      cache->prev_change = -1;
+      cache->next_change = -1;
+    }
+}
 
 static void
 init_syntax_cache (struct syntax_cache *cache, Lisp_Object object,
@@ -254,6 +325,11 @@
     BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
   cache->start = Qnil;
   cache->end = Qnil;
+  /* #### I'm not sure what INFINITE is for, but it's apparently needed by
+     setup_syntax_cache().  It looks like it's supposed to guarantee that
+     the test for POS outside of cache-valid range will never succeed, so
+     that update_syntax_cache won't get called, but it's hard to be sure.
+     Cf reset_buffer_syntax_cache_range. -- sjt */
   if (infinite)
     {
       cache->prev_change = EMACS_INT_MIN;
@@ -266,15 +342,31 @@
     }
 }
 
-struct syntax_cache *
-setup_syntax_cache (struct syntax_cache *cache, Lisp_Object object,
-		    struct buffer *buffer, Charxpos from, int count)
+/* external syntax cache API */
+
+/* #### This function and associated logic still needs work, and especially
+   documentation. */
+struct syntax_cache *		/* return CACHE or the cache of OBJECT */
+setup_syntax_cache (struct syntax_cache *cache,	/* syntax cache, may be NULL
+						   if OBJECT is a buffer */
+		    Lisp_Object object,	 	/* the object (if any) cache
+						   is associated with */
+		    struct buffer *buffer,	/* the buffer to use as source
+						   of the syntax table */
+		    Charxpos from,		/* initial position of cache */
+		    int count)			/* direction? see code */
 {
+  /* If OBJECT is a buffer, use its cache.  Initialize cache.  Make it valid
+     for the whole buffer if the syntax-table property is not being respected.
+     Else if OBJECT is not a buffer, initialize the cache passed in CACHE.
+     If the syntax-table property is being respected, update the cache. */
   if (BUFFERP (object))
-    cache = XBUFFER (object)->syntax_cache;
-  if (!lookup_syntax_properties)
-    init_syntax_cache (cache, object, buffer, 1);
-  else if (!BUFFERP (object))
+    {
+      cache = XBUFFER (object)->syntax_cache;
+      if (!lookup_syntax_properties)
+	reset_buffer_syntax_cache_range (cache, object, 1);
+    }
+  else
     init_syntax_cache (cache, object, buffer, 0);
   if (lookup_syntax_properties)
     {
@@ -299,121 +391,6 @@
   return setup_syntax_cache (NULL, wrap_buffer (buffer), buffer, from, count);
 }
 
-static const struct memory_description syntax_cache_description_1 [] = {
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, object) },
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, buffer) },
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, syntax_table) },
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, mirror_table) },
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, start) },
-  { XD_LISP_OBJECT, offsetof (struct syntax_cache, end) },
-  { XD_END }
-};
-
-const struct sized_memory_description syntax_cache_description = {
-  sizeof (struct syntax_cache),
-  syntax_cache_description_1
-};
-
-void
-mark_buffer_syntax_cache (struct buffer *buf)
-{
-  struct syntax_cache *cache = buf->syntax_cache;
-  if (!cache) /* Vbuffer_defaults and such don't have caches */
-    return;
-  mark_object (cache->object);
-  if (cache->buffer)
-    mark_object (wrap_buffer (cache->buffer));
-  mark_object (cache->syntax_table);
-  mark_object (cache->mirror_table);
-  mark_object (cache->start);
-  mark_object (cache->end);
-}
-
-static void
-reset_buffer_cache_range (struct syntax_cache *cache, Lisp_Object buffer)
-{
-  Fset_marker (cache->start, make_int (1), buffer);
-  Fset_marker (cache->end, make_int (1), buffer);
-  Fset_marker_insertion_type (cache->start, Qt);
-  Fset_marker_insertion_type (cache->end, Qnil);
-  cache->prev_change = -1;
-  cache->next_change = -1;
-}
-
-void
-init_buffer_syntax_cache (struct buffer *buf)
-{
-  struct syntax_cache *cache;
-  buf->syntax_cache = xnew_and_zero (struct syntax_cache);
-  cache = buf->syntax_cache;
-  cache->object = wrap_buffer (buf);
-  cache->buffer = buf;
-  cache->no_syntax_table_prop = 1;
-  cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer);
-  cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
-  cache->start = Fmake_marker ();
-  cache->end = Fmake_marker ();
-  reset_buffer_cache_range (cache, cache->object);
-}
-
-void
-uninit_buffer_syntax_cache (struct buffer *buf)
-{
-  xfree (buf->syntax_cache, struct syntax_cache *);
-  buf->syntax_cache = 0;
-}
-
-
-static void
-syntax_cache_table_was_changed (struct buffer *buf)
-{
-  struct syntax_cache *cache = buf->syntax_cache;
-  if (cache->no_syntax_table_prop)
-    {
-      cache->syntax_table =
-	BUFFER_SYNTAX_TABLE (buf);
-      cache->mirror_table =
-	BUFFER_MIRROR_SYNTAX_TABLE (buf);
-    }
-}
-
-/* The syntax-table property on the range covered by EXTENT may be changing,
-   either because EXTENT has a syntax-table property and is being attached
-   or detached (this includes having its endpoints changed), or because
-   the value of EXTENT's syntax-table property is changing. */
-
-void
-signal_syntax_table_extent_changed (EXTENT extent)
-{
-  Lisp_Object buffer = Fextent_object (wrap_extent (extent));
-  if (BUFFERP (buffer))
-    {
-      struct syntax_cache *cache = XBUFFER (buffer)->syntax_cache;
-      Bytexpos start = extent_endpoint_byte (extent, 0);
-      Bytexpos end = extent_endpoint_byte (extent, 1);
-      Bytexpos start2 = byte_marker_position (cache->start);
-      Bytexpos end2 = byte_marker_position (cache->end);
-      /* If the extent is entirely before or entirely after the cache range,
-	 it doesn't overlap.  Otherwise, invalidate the range. */
-      if (!(end < start2 || start > end2))
-	reset_buffer_cache_range (cache, buffer);
-    }
-}
-
-/* Extents have been adjusted for insertion or deletion, so we need to
-   refetch the start and end position of the extent */
-void
-signal_syntax_table_extent_adjust (struct buffer *buf)
-{
-  struct syntax_cache *cache = buf->syntax_cache;
-  /* If the cache was invalid before, leave it that way.  We only want
-     to update the limits of validity when they were actually valid. */
-  if (cache->prev_change < 0)
-    return;
-  cache->prev_change = marker_position (cache->start);
-  cache->next_change = marker_position (cache->end);
-}
-
 /* 
    Update syntax_cache to an appropriate setting for position POS
 
@@ -481,7 +458,7 @@
 	 a zero-length `syntax-table' extent there (highly unlikely); if not,
 	 then we can safely make the end closed, so it will take in newly
 	 inserted text. (If such an extent is inserted, we will be informed
-	 through signal_syntax_table_extent_changed().) */
+	 through signal_syntax_cache_extent_changed().) */
       Fset_marker (cache->start, make_int (cache->prev_change), cache->object);
       Fset_marker_insertion_type
 	(cache->start,
@@ -523,6 +500,105 @@
 #endif /* NOT_WORTH_THE_EFFORT */
     }
 }
+
+/* buffer-specific APIs used in buffer.c
+   #### This is really unclean;
+   the syntax cache should just be a LISP object */
+
+void
+mark_buffer_syntax_cache (struct buffer *buf)
+{
+  struct syntax_cache *cache = buf->syntax_cache;
+  if (!cache) /* Vbuffer_defaults and such don't have caches */
+    return;
+  mark_object (cache->object);
+  if (cache->buffer)
+    mark_object (wrap_buffer (cache->buffer));
+  mark_object (cache->syntax_table);
+  mark_object (cache->mirror_table);
+  mark_object (cache->start);
+  mark_object (cache->end);
+}
+
+void
+init_buffer_syntax_cache (struct buffer *buf)
+{
+  struct syntax_cache *cache;
+#ifdef NEW_GC
+  buf->syntax_cache = alloc_lrecord_type (struct syntax_cache,
+					  &lrecord_syntax_cache);
+#else /* not NEW_GC */
+  buf->syntax_cache = xnew_and_zero (struct syntax_cache);
+#endif /* not NEW_GC */
+  cache = buf->syntax_cache;
+  cache->object = wrap_buffer (buf);
+  cache->buffer = buf;
+  cache->no_syntax_table_prop = 1;
+  cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer);
+  cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
+  cache->start = Fmake_marker ();
+  cache->end = Fmake_marker ();
+  reset_buffer_syntax_cache_range (cache, cache->object, 0);
+}
+
+/* finalize the syntax cache for BUF */
+
+void
+uninit_buffer_syntax_cache (struct buffer *UNUSED_IF_NEW_GC (buf))
+{
+#ifndef NEW_GC
+  xfree (buf->syntax_cache, struct syntax_cache *);
+  buf->syntax_cache = 0;
+#endif /* not NEW_GC */
+}
+
+/* extent-specific APIs used in extents.c and insdel.c */
+
+/* The syntax-table property on the range covered by EXTENT may be changing,
+   either because EXTENT has a syntax-table property and is being attached
+   or detached (this includes having its endpoints changed), or because
+   the value of EXTENT's syntax-table property is changing. */
+
+void
+signal_syntax_cache_extent_changed (EXTENT extent)
+{
+  Lisp_Object buffer = Fextent_object (wrap_extent (extent));
+  if (BUFFERP (buffer))
+    {
+      /* This was getting called with the buffer's start and end null, eg in
+	 cperl mode, which triggers an assert in byte_marker_position.  Cf
+	 thread rooted at <yxz7j7xzk97.fsf@gimli.holgi.priv> on xemacs-beta.
+	 <yxzfymklb6p.fsf@gimli.holgi.priv> has a recipe, but you also need
+	 to delete or type SPC to get the crash.
+	 #### Delete this comment when setup_syntax_cache is made sane. */
+      struct syntax_cache *cache = XBUFFER (buffer)->syntax_cache;
+      /* #### would this be slower or less accurate in character terms? */
+      Bytexpos start = extent_endpoint_byte (extent, 0);
+      Bytexpos end = extent_endpoint_byte (extent, 1);
+      Bytexpos start2 = byte_marker_position (cache->start);
+      Bytexpos end2 = byte_marker_position (cache->end);
+      /* If the extent is entirely before or entirely after the cache
+	 range, it doesn't overlap.  Otherwise, invalidate the range. */
+      if (!(end < start2 || start > end2))
+	reset_buffer_syntax_cache_range (cache, buffer, 0);
+    }
+}
+
+/* Extents have been adjusted for insertion or deletion, so we need to
+   refetch the start and end position of the extent */
+void
+signal_syntax_cache_extent_adjust (struct buffer *buf)
+{
+  struct syntax_cache *cache = buf->syntax_cache;
+  /* If the cache was invalid before, leave it that way.  We only want
+     to update the limits of validity when they were actually valid. */
+  if (cache->prev_change < 0)
+    return;
+  cache->prev_change = marker_position (cache->start);
+  cache->next_change = marker_position (cache->end);
+}
+
+
 
 /* Convert a letter which signifies a syntax code
    into the code it signifies.
@@ -595,7 +671,7 @@
 {
   *multi_p_out = 1;
   /* !!#### get this right */
-  return Spunct;
+  return Sword;
 }
 
 #endif
@@ -1991,7 +2067,6 @@
 	case Sopen:
 	  if (stopbefore) goto stop;  /* this arg means stop at sexp start */
 	  depth++;
-	  /* curlevel++->last ran into compiler bug on Apollo */
 	  curlevel->last = from - 1;
 	  if (++curlevel == endlevel)
 	    stack_overflow ("Nesting too deep for parser",
@@ -2278,8 +2353,8 @@
   if (!EQ (table, Vstandard_syntax_table) && !NILP (Vstandard_syntax_table))
     map_char_table (Vstandard_syntax_table, &range,
 		    copy_if_not_already_present, LISP_TO_VOID (mirrortab));
-  /* The resetting made the default be Qnil.  Put it back to Spunct. */
-  set_char_table_default (mirrortab, make_int (Spunct));
+  /* The resetting made the default be Qnil.  Put it back to Sword. */
+  set_char_table_default (mirrortab, make_int (Sword));
   XCHAR_TABLE (mirrortab)->dirty = 0;
 }
 
@@ -2313,6 +2388,9 @@
 void
 syms_of_syntax (void)
 {
+#ifdef NEW_GC
+  INIT_LISP_OBJECT (syntax_cache);
+#endif /* NEW_GC */
   DEFSYMBOL (Qsyntax_table_p);
   DEFSYMBOL (Qsyntax_table);
 
@@ -2373,7 +2451,7 @@
 }
 
 static void
-define_standard_syntax (const char *p, enum syntaxcode syn)
+define_standard_syntax (const UExtbyte *p, enum syntaxcode syn)
 {
   for (; *p; p++)
     Fput_char_table (make_char (*p), make_int (syn), Vstandard_syntax_table);
@@ -2383,10 +2461,19 @@
 complex_vars_of_syntax (void)
 {
   Ichar i;
-  const char *p;
-  /* Set this now, so first buffer creation can refer to it. */
-  /* Make it nil before calling copy-syntax-table
-     so that copy-syntax-table will know not to try to copy from garbage */
+  const UExtbyte *p; /* Latin-1, not internal format. */
+
+#define SET_RANGE_SYNTAX(start, end, syntax)				\
+  do {									\
+    for (i = start; i <= end; i++)					\
+      Fput_char_table(make_char(i), make_int(syntax),			\
+		      Vstandard_syntax_table);				\
+  } while (0)
+
+  /* Set this now, so first buffer creation can refer to it. 
+
+     Make it nil before calling copy-syntax-table so that copy-syntax-table
+     will know not to try to copy from garbage */
   Vstandard_syntax_table = Qnil;
   Vstandard_syntax_table = Fcopy_syntax_table (Qnil);
   staticpro (&Vstandard_syntax_table);
@@ -2398,25 +2485,26 @@
 							Smax);
   staticpro (&Vsyntax_designator_chars_string);
 
-  set_char_table_default (Vstandard_syntax_table, make_int (Spunct));
+  /* Default character syntax is word. */
+  set_char_table_default (Vstandard_syntax_table, make_int (Sword));
 
-  for (i = 0; i <= 32; i++)	/* Control 0 plus SPACE */
-    Fput_char_table (make_char (i), make_int (Swhitespace),
-		     Vstandard_syntax_table);
-  for (i = 127; i <= 159; i++)	/* DEL plus Control 1 */
-    Fput_char_table (make_char (i), make_int (Swhitespace),
-		     Vstandard_syntax_table);
+  /* Control 0; treat as punctuation */
+  SET_RANGE_SYNTAX(0, 32, Spunct);
+
+  /* The whitespace--overwriting some of the above changes.
 
-  define_standard_syntax ("abcdefghijklmnopqrstuvwxyz"
-			  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-			  "0123456789"
-			  "$%", Sword);
-  define_standard_syntax ("\"", Sstring);
-  define_standard_syntax ("\\", Sescape);
-  define_standard_syntax ("_-+*/&|<>=", Ssymbol);
-  define_standard_syntax (".,;:?!#@~^'`", Spunct);
+     String literals are const char *s, not const unsigned char *s. */
+  define_standard_syntax((const UExtbyte *)" \t\015\014\012", Swhitespace);
+
+  /* DEL plus Control 1 */
+  SET_RANGE_SYNTAX(127, 159, Spunct);
 
-  for (p = "()[]{}"; *p; p+=2)
+  define_standard_syntax ((const UExtbyte *)"\"", Sstring);
+  define_standard_syntax ((const UExtbyte *)"\\", Sescape);
+  define_standard_syntax ((const UExtbyte *)"_-+*/&|<>=", Ssymbol);
+  define_standard_syntax ((const UExtbyte *)".,;:?!#@~^'`", Spunct);
+
+  for (p = (const UExtbyte *)"()[]{}"; *p; p+=2)
     {
       Fput_char_table (make_char (p[0]),
 		       Fcons (make_int (Sopen), make_char (p[1])),
@@ -2425,4 +2513,18 @@
 		       Fcons (make_int (Sclose), make_char (p[0])),
 		       Vstandard_syntax_table);
     }
+
+  /* Latin 1 "symbols." This contrasts with the FSF, where they're word
+     constituents. */
+  SET_RANGE_SYNTAX(0240, 0277, Ssymbol); 
+
+  /* The guillemets. These are not parentheses, in contrast to what the old
+     code did. */
+  define_standard_syntax((const UExtbyte *)"\253\273", Spunct);
+
+  /* The inverted exclamation mark, and the multiplication and division
+     signs. */
+  define_standard_syntax((const UExtbyte *)"\241\327\367", Spunct);
+
+#undef SET_RANGE_SYNTAX  
 }