Hi, XEmacs!
On Mon, Mar 18, 2013 at 10:22:55PM +0000, Alan Mackenzie wrote:
 On Sat, Mar 16, 2013 at 05:47:38PM +0000, Alan Mackenzie wrote:
 > 1. Using an up to date XEmacs and Packages, create the following
 > Objective C file, class-30.m: 
 >
#########################################################################
 > @interface Foo
 > (Bar)
 > <X, Y, Z>
 > @end 
 > @interface Foo (Bar)
 > <X, Y, Z>
 > @end
 > ######################################################################### 
 > 2. Kill the buffer and reload the file freshly. 
 > 3. M-: (scan-lists 1 1 -1).  This (correctly) returns 17, just
after the
 > "(" on L2. 
 > 4. Put point at BOL3 ("<X ,Y, Z>").  Narrow to
the first two lines with
 > M-<, C-x n n. 
 > 5. With point at BOL3, (point-max), do M-: (looking-at
c-opt-cpp-start). 
 > 6. M-: (scan-lists 1 1 -1).  This now (buggily) returns 2.
 > N.B. c-opt-cpp-start is "\\s *#\\s
*\\([a-zA-Z0-9]+\\)". 
 I've now diagnosed this problem.  The fault is in
update_syntax_cache
 (syntax.c) in the following statement: 
       tmp_table = get_char_property (pos, Qsyntax_table,
cache->object,
                                            EXTENT_AT_AFTER, 0); 
 When `cpos' is at (point-max) and the character just after
(point-max) has
 an extent with a syntax-table property, get_char_property returns that
 extent's property, even though that extent lies wholly in the inaccessible
 portion of the buffer.  In the above bug, tmp_table gets a cons (the
 internal representation of the "open paren" syntax). 
 Later on, CONSP (tmp_table) is detected, causing it to mark the
 syntax_cache as being at a syntax-table property.  Sadly, the region it
 marks as being thus propertised is the entire visible buffer portion. 
Here is a patch to fix this bug.  Actually, only the hunk in syntax.c is
strictly relevant to the bug.  The rest of the patch prevents Fextent_at
and friends from accessing buffer positions just outside the accessible
portion.
Please consider installing this patch, wholly or partially.  CC Mode will
not function properly without it.
diff -r ec3712ffd0e6 src/extents.c
--- a/src/extents.c	Fri Mar 15 13:52:53 2013 -0600
+++ b/src/extents.c	Sat Mar 30 18:22:45 2013 +0000
@@ -4339,17 +4339,18 @@
 {
   Bytexpos position;
   EXTENT before_extent;
-  enum extent_at_flag fl;
+  enum extent_at_flag fl = decode_extent_at_flag (at_flag);
+  unsigned int flags = (fl == EXTENT_AT_BEFORE) ? GB_NEED_CHAR_BEFORE :
+      (fl == EXTENT_AT_AFTER) ? GB_NEED_CHAR_AFTER : 0;
 
   object = decode_buffer_or_string (object);
-  position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
+  position = get_buffer_or_string_pos_byte (object, pos, flags | GB_NO_ERROR_IF_BAD);
   if (NILP (before))
     before_extent = 0;
   else
     before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
   if (before_extent && !EQ (object, extent_object (before_extent)))
     invalid_argument ("extent not in specified buffer or string", object);
-  fl = decode_extent_at_flag (at_flag);
 
   return extent_at (position, object, property, before_extent, fl, 0);
 }
@@ -4389,17 +4390,18 @@
 {
   Bytexpos position;
   EXTENT before_extent;
-  enum extent_at_flag fl;
+  enum extent_at_flag fl = decode_extent_at_flag (at_flag);
+  unsigned int flags = (fl == EXTENT_AT_BEFORE) ? GB_NEED_CHAR_BEFORE :
+      (fl == EXTENT_AT_AFTER) ? GB_NEED_CHAR_AFTER : 0;
 
   object = decode_buffer_or_string (object);
-  position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
+  position = get_buffer_or_string_pos_byte (object, pos, flags | GB_NO_ERROR_IF_BAD);
   if (NILP (before))
     before_extent = 0;
   else
     before_extent = decode_extent (before, DE_MUST_BE_ATTACHED);
   if (before_extent && !EQ (object, extent_object (before_extent)))
     invalid_argument ("extent not in specified buffer or string", object);
-  fl = decode_extent_at_flag (at_flag);
 
   return extent_at (position, object, property, before_extent, fl, 1);
 }
@@ -6278,9 +6280,12 @@
 {
   Bytexpos position;
   int invert = 0;
+  enum extent_at_flag fl = decode_extent_at_flag (at_flag);
+  unsigned int flags = (fl == EXTENT_AT_BEFORE) ? GB_NEED_CHAR_BEFORE :
+      (fl == EXTENT_AT_AFTER) ? GB_NEED_CHAR_AFTER : 0;
 
   object = decode_buffer_or_string (object);
-  position = get_buffer_or_string_pos_byte (object, pos, GB_NO_ERROR_IF_BAD);
+  position = get_buffer_or_string_pos_byte (object, pos, flags | GB_NO_ERROR_IF_BAD);
 
   /* We canonicalize the start/end-open/closed properties to the
      non-default version -- "adding" the default property really
@@ -6300,9 +6305,7 @@
 
   {
     Lisp_Object val =
-      get_char_property (position, prop, object,
-			 decode_extent_at_flag (at_flag),
-			 text_props_only);
+      get_char_property (position, prop, object, fl, text_props_only);
     if (invert)
       val = NILP (val) ? Qt : Qnil;
     return val;
diff -r ec3712ffd0e6 src/lisp.h
--- a/src/lisp.h	Fri Mar 15 13:52:53 2013 -0600
+++ b/src/lisp.h	Sat Mar 30 18:22:45 2013 +0000
@@ -5885,6 +5885,8 @@
 #define GB_COERCE_RANGE			(1 << 3)
 #define GB_NO_ERROR_IF_BAD		(1 << 4)
 #define GB_NEGATIVE_FROM_END		(1 << 5)
+#define GB_NEED_CHAR_BEFORE             (1 << 6)
+#define GB_NEED_CHAR_AFTER              (1 << 7)
 #define GB_HISTORICAL_STRING_BEHAVIOR	(GB_NEGATIVE_FROM_END | GB_ALLOW_NIL)
 
 Charbpos get_buffer_pos_char (struct buffer *b, Lisp_Object pos,
diff -r ec3712ffd0e6 src/syntax.c
--- a/src/syntax.c	Fri Mar 15 13:52:53 2013 -0600
+++ b/src/syntax.c	Sat Mar 30 18:22:45 2013 +0000
@@ -454,8 +454,12 @@
 
   pos = buffer_or_string_charxpos_to_bytexpos (cache->object, cpos);
 
-  tmp_table = get_char_property (pos, Qsyntax_table, cache->object,
-				 EXTENT_AT_AFTER, 0);
+  if (pos < buffer_or_string_accessible_end_byte (cache->object))
+      tmp_table = get_char_property (pos, Qsyntax_table, cache->object,
+                                     EXTENT_AT_AFTER, 0);
+  else
+      tmp_table = Qnil;
+
   lim = next_previous_single_property_change (pos, Qsyntax_table,
 					      cache->object, -1, 1, 0);
   if (lim < 0)
diff -r ec3712ffd0e6 src/text.c
--- a/src/text.c	Fri Mar 15 13:52:53 2013 -0600
+++ b/src/text.c	Sat Mar 30 18:22:45 2013 +0000
@@ -3626,6 +3626,11 @@
      of the range.  If the positions are reversed, an error is
      signalled.
 
+   GB_NEED_CHAR_BEFORE, GB_NEED_CHAR_AFTER
+
+     The character before or after POS must be in the accessible portion
+     of the buffer (BUF_BEGV to BUF_ZV).
+
    The following is a combination flag:
 
    GB_HISTORICAL_STRING_BEHAVIOR
@@ -3652,7 +3657,9 @@
   CHECK_FIXNUM_COERCE_MARKER (pos);
   ind = XFIXNUM (pos);
   min_allowed = flags & GB_ALLOW_PAST_ACCESSIBLE ? BUF_BEG (b) : BUF_BEGV (b);
+  if (flags & GB_NEED_CHAR_BEFORE) min_allowed += 1;
   max_allowed = flags & GB_ALLOW_PAST_ACCESSIBLE ? BUF_Z   (b) : BUF_ZV   (b);
+  if (flags & GB_NEED_CHAR_AFTER) max_allowed -= 1;
 
   if (ind < min_allowed || ind > max_allowed)
     {
@@ -3757,8 +3764,8 @@
 		       Charcount known_length)
 {
   Charcount ccpos;
-  Charcount min_allowed = 0;
-  Charcount max_allowed = known_length;
+  Charcount min_allowed = (flags & GB_NEED_CHAR_BEFORE) ? 1 : 0;
+  Charcount max_allowed = (flags & GB_NEED_CHAR_AFTER) ? known_length -1 :
known_length;
 
   /* Computation of KNOWN_LENGTH is potentially expensive so we pass
      it in. */
-- 
Alan Mackenzie (Nuremberg, Germany).
_______________________________________________
XEmacs-Beta mailing list
XEmacs-Beta(a)xemacs.org
http://lists.xemacs.org/mailman/listinfo/xemacs-beta