Subject: Re: bug#6834: octave-mode block comments need highlighting

From: Stefan Monnier <[email-masked]>
Date: Thu, 12 Aug 2010 16:46:32 +0200

>> In octave mode, block comments (separated by "%{" and "%}") should be
>> highlighted in the same font as regular line comments.
> The patch below should morally fix it, but as the comment explains, it
> won't work until we fix the underlying C code.

Actually, the patch had a bug and the underlying problem in the C-level
code didn't exist (it used to exist, but I already fixed it a few years
ago, apparently), but another limitation in the semantics of
syntax-tables was the culprit.
I installed the patch below on the trunk, which adds a new comment
style "c", and should also fix your problem.

        Stefan

=== modified file 'etc/NEWS'
--- etc/NEWS	2010-08-11 18:28:10 +0000
+++ etc/NEWS	2010-08-12 13:49:42 +0000
@@ -424,6 +424,7 @@
 
 * Lisp changes in Emacs 24.1
 
+** Syntax tables support a new "comment style c" additionally to style b.
 ** frame-local variables cannot be let-bound any more.
 ** prog-mode is a new major-mode meant to be the parent of programming mode.
 ** define-minor-mode accepts a new keyword :variable.

=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog	2010-08-12 12:46:24 +0000
+++ lisp/ChangeLog	2010-08-12 14:06:12 +0000
@@ -1,5 +1,11 @@
 2010-08-12  Stefan Monnier  <[email-masked]>
 
+	* progmodes/octave-mod.el (octave-mode-syntax-table): Use the new "c"
+	comment style (bug#6834).
+	* progmodes/scheme.el (scheme-mode-syntax-table):
+	* emacs-lisp/lisp-mode.el (lisp-mode-syntax-table): Remove spurious
+	"b" flag in "' 14b" syntax.
+
 	* progmodes/octave-mod.el (octave-mode-map): Remove special bindings
 	for (un)commenting the region and performing completion.
 	(octave-mode-menu): Use standard commands for help and completion.

=== modified file 'lisp/emacs-lisp/lisp-mode.el'
--- lisp/emacs-lisp/lisp-mode.el	2010-05-14 16:41:01 +0000
+++ lisp/emacs-lisp/lisp-mode.el	2010-08-12 12:10:52 +0000
@@ -85,7 +85,7 @@
   (let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
     (modify-syntax-entry ?\[ "_   " table)
     (modify-syntax-entry ?\] "_   " table)
-    (modify-syntax-entry ?# "' 14b" table)
+    (modify-syntax-entry ?# "' 14" table)
     (modify-syntax-entry ?| "\" 23bn" table)
     table)
   "Syntax table used in `lisp-mode'.")

=== modified file 'lisp/progmodes/octave-mod.el'
--- lisp/progmodes/octave-mod.el	2010-08-12 12:46:24 +0000
+++ lisp/progmodes/octave-mod.el	2010-08-12 13:51:38 +0000
@@ -294,17 +294,16 @@
     (modify-syntax-entry ?\" "\"" table)
     (modify-syntax-entry ?. "w"   table)
     (modify-syntax-entry ?_ "w"   table)
-    ;; FIXME: The "b" flag only applies to the second letter of the comstart
+    ;; The "b" flag only applies to the second letter of the comstart
     ;; and the first letter of the comend, i.e. the "4b" below is ineffective.
     ;; If we try to put `b' on the single-line comments, we get a similar
     ;; problem where the % and # chars appear as first chars of the 2-char
     ;; comend, so the multi-line ender is also turned into style-b.
-    ;; Really, we can't make it work without extending the syntax-tables, or
-    ;; via font-lock-syntactic-keywords.
+    ;; So we need the new "c" comment style.
     (modify-syntax-entry ?\% "< 13"  table)
     (modify-syntax-entry ?\# "< 13"  table)
-    (modify-syntax-entry ?\{ "(} 2b"  table)
-    (modify-syntax-entry ?\} "){ 4b"  table)
+    (modify-syntax-entry ?\{ "(} 2c"  table)
+    (modify-syntax-entry ?\} "){ 4c"  table)
     (modify-syntax-entry ?\n ">"  table)
     table)
   "Syntax table in use in `octave-mode' buffers.")

=== modified file 'lisp/progmodes/scheme.el'
--- lisp/progmodes/scheme.el	2010-01-13 08:35:10 +0000
+++ lisp/progmodes/scheme.el	2010-08-12 12:12:55 +0000
@@ -107,7 +107,7 @@
     ;; Special characters
     (modify-syntax-entry ?, "'   " st)
     (modify-syntax-entry ?@ "'   " st)
-    (modify-syntax-entry ?# "' 14b" st)
+    (modify-syntax-entry ?# "' 14" st)
     (modify-syntax-entry ?\\ "\\   " st)
     st))
 

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2010-08-11 18:47:34 +0000
+++ src/ChangeLog	2010-08-12 14:04:21 +0000
@@ -1,3 +1,22 @@
+2010-08-12  Stefan Monnier  <[email-masked]>
+
+	Introduce a new comment style "c" flag.
+	* syntax.c (SYNTAX_FLAGS_COMMENT_STYLEB)
+	(SYNTAX_FLAGS_COMMENT_STYLEC): New macros.
+	(SYNTAX_FLAGS_COMMENT_STYLE): Use them, add an argument.
+	(syntax_prefix_flag_p): New function.
+	(Fstring_to_syntax): Understand new "c" flag.
+	(Finternal_describe_syntax_value): Recognize new flag; use the
+	SYNTAX_FLAGS_* macros.
+	(scan_sexps_forward, Fparse_partial_sexp): Change representation of
+	comment style to accomodate the new styles.
+	(back_comment, forw_comment, Fforward_comment, scan_lists)
+	(scan_sexps_forward): Update code to obey the new comment style flag.
+
+	* syntax.h: Move SYNTAX_FLAGS_FOO() macros to syntax.c.
+
+	* casefiddle.c (casify_region): Use the new syntax_prefix_flag_p.
+
 2010-08-11  Jan Djärv  <[email-masked]>
 
 	* xfns.c (x_defined_color): If USE_GTK, call xg_check_special_colors

=== modified file 'src/casefiddle.c'
--- src/casefiddle.c	2010-07-08 21:25:08 +0000
+++ src/casefiddle.c	2010-08-12 12:35:56 +0000
@@ -243,7 +243,8 @@
 	       && (!inword || flag != CASE_CAPITALIZE_UP))
 	c = UPCASE1 (c);
       if ((int) flag >= (int) CASE_CAPITALIZE)
-	inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c)));
+	inword = ((SYNTAX (c) == Sword)
+		  && (inword || !syntax_prefix_flag_p (c)));
       if (c != c2)
 	{
 	  last = start;

=== modified file 'src/syntax.c'
--- src/syntax.c	2010-07-12 17:47:17 +0000
+++ src/syntax.c	2010-08-12 14:02:14 +0000
@@ -34,6 +34,60 @@
 
 #include "syntax.h"
 #include "intervals.h"
+#include "category.h"
+
+/* Then there are seven single-bit flags that have the following meanings:
+  1. This character is the first of a two-character comment-start sequence.
+  2. This character is the second of a two-character comment-start sequence.
+  3. This character is the first of a two-character comment-end sequence.
+  4. This character is the second of a two-character comment-end sequence.
+  5. This character is a prefix, for backward-prefix-chars.
+  6. The char is part of a delimiter for comments of style "b".
+  7. This character is part of a nestable comment sequence.
+  8. The char is part of a delimiter for comments of style "c".
+  Note that any two-character sequence whose first character has flag 1
+  and whose second character has flag 2 will be interpreted as a comment start.
+
+  bit 6 and 8 are used to discriminate between different comment styles.
+  Languages such as C++ allow two orthogonal syntax start/end pairs
+  and bit 6 is used to determine whether a comment-end or Scommentend
+  ends style a or b.  Comment markers can start style a, b, c, or bc.
+  Style a is always the default.
+  For 2-char comment markers, the style b flag is only looked up on the second
+  char of the comment marker and on the first char of the comment ender.
+  For style c (like to for the nested flag), the flag can be placed on any
+  one of the chars.
+  */
+
+/* These macros extract specific flags from an integer
+   that holds the syntax code and the flags.  */
+
+#define SYNTAX_FLAGS_COMSTART_FIRST(flags) (((flags) >> 16) & 1)
+
+#define SYNTAX_FLAGS_COMSTART_SECOND(flags) (((flags) >> 17) & 1)
+
+#define SYNTAX_FLAGS_COMEND_FIRST(flags) (((flags) >> 18) & 1)
+
+#define SYNTAX_FLAGS_COMEND_SECOND(flags) (((flags) >> 19) & 1)
+
+#define SYNTAX_FLAGS_PREFIX(flags) (((flags) >> 20) & 1)
+
+#define SYNTAX_FLAGS_COMMENT_STYLEB(flags) (((flags) >> 21) & 1)
+#define SYNTAX_FLAGS_COMMENT_STYLEC(flags) (((flags) >> 22) & 2)
+/* FLAGS should be the flags of the main char of the comment marker, e.g.
+   the second for comstart and the first for comend.  */
+#define SYNTAX_FLAGS_COMMENT_STYLE(flags, other_flags) \
+  (SYNTAX_FLAGS_COMMENT_STYLEB (flags) \
+   | SYNTAX_FLAGS_COMMENT_STYLEC (flags) \
+   | SYNTAX_FLAGS_COMMENT_STYLEC (other_flags))
+
+#define SYNTAX_FLAGS_COMMENT_NESTED(flags) (((flags) >> 22) & 1)
+
+/* These macros extract a particular flag for a given character.  */
+
+#define SYNTAX_COMEND_FIRST(c) \
+  (SYNTAX_FLAGS_COMEND_FIRST (SYNTAX_WITH_FLAGS (c)))
+#define SYNTAX_PREFIX(c) (SYNTAX_FLAGS_PREFIX (SYNTAX_WITH_FLAGS (c)))
 
 /* We use these constants in place for comment-style and
    string-ender-char to distinguish  comments/strings started by
@@ -41,7 +95,6 @@
 
 #define ST_COMMENT_STYLE (256 + 1)
 #define ST_STRING_STYLE (256 + 2)
-#include "category.h"
 
 Lisp_Object Qsyntax_table_p, Qsyntax_table, Qscan_error;
 
@@ -106,6 +159,11 @@
                                 int, Lisp_Object, int);
 static int in_classes (int, Lisp_Object);
 
+/* Whether the syntax of the character C has the prefix flag set.  */
+int syntax_prefix_flag_p (int c)
+{
+  return SYNTAX_PREFIX (c);
+}
 
 struct gl_state_s gl_state;		/* Global state of syntax parser.  */
 
@@ -514,7 +572,8 @@
       /* Check for 2-char comment markers.  */
       com2start = (SYNTAX_FLAGS_COMSTART_FIRST (syntax)
 		   && SYNTAX_FLAGS_COMSTART_SECOND (prev_syntax)
-		   && comstyle == SYNTAX_FLAGS_COMMENT_STYLE (prev_syntax)
+		   && (comstyle
+		       == SYNTAX_FLAGS_COMMENT_STYLE (prev_syntax, syntax))
 		   && (SYNTAX_FLAGS_COMMENT_NESTED (prev_syntax)
 		       || SYNTAX_FLAGS_COMMENT_NESTED (syntax)) == comnested);
       com2end = (SYNTAX_FLAGS_COMEND_FIRST (syntax)
@@ -543,7 +602,8 @@
 	       && SYNTAX_FLAGS_COMEND_FIRST (next_syntax))
 	      || ((com2end || comnested)
 		  && SYNTAX_FLAGS_COMSTART_SECOND (syntax)
-		  && comstyle == SYNTAX_FLAGS_COMMENT_STYLE (syntax)
+		  && (comstyle
+		      == SYNTAX_FLAGS_COMMENT_STYLE (syntax, prev_syntax))
 		  && SYNTAX_FLAGS_COMSTART_FIRST (next_syntax)))
 	    goto lossage;
 	  /* UPDATE_SYNTAX_TABLE_FORWARD (next + 1); */
@@ -563,7 +623,7 @@
 	code = Scomment;
       /* Ignore comment starters of a different style.  */
       else if (code == Scomment
-	       && (comstyle != SYNTAX_FLAGS_COMMENT_STYLE (syntax)
+	       && (comstyle != SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0)
 		   || SYNTAX_FLAGS_COMMENT_NESTED (syntax) != comnested))
 	continue;
 
@@ -613,7 +673,7 @@
 	  break;
 
 	case Sendcomment:
-	  if (SYNTAX_FLAGS_COMMENT_STYLE (syntax) == comstyle
+	  if (SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == comstyle
 	      && ((com2end && SYNTAX_FLAGS_COMMENT_NESTED (prev_syntax))
 		  || SYNTAX_FLAGS_COMMENT_NESTED (syntax)) == comnested)
 	    /* This is the same style of comment ender as ours. */
@@ -930,6 +990,10 @@
       case 'n':
 	val |= 1 << 22;
 	break;
+
+      case 'c':
+	val |= 1 << 23;
+	break;
       }
 
   if (val < XVECTOR (Vsyntax_code_object)->size && NILP (match))
@@ -969,12 +1033,13 @@
  3 means CHAR is the start of a two-char comment end sequence.
  4 means CHAR is the second character of such a sequence.
 
-There can be up to two orthogonal comment sequences.  This is to support
+There can be several orthogonal comment sequences.  This is to support
 language modes such as C++.  By default, all comment sequences are of style
 a, but you can set the comment sequence style to b (on the second character
-of a comment-start, or the first character of a comment-end sequence) using
-this flag:
+of a comment-start, and the first character of a comment-end sequence) and/or
+c (on any of its chars) using this flag:
  b means CHAR is part of comment sequence b.
+ c means CHAR is part of comment sequence c.
  n means CHAR is part of a nestable comment sequence.
 
  p means CHAR is a prefix character for `backward-prefix-chars';
@@ -1017,7 +1082,9 @@
   (Lisp_Object syntax)
 {
   register enum syntaxcode code;
-  char desc, start1, start2, end1, end2, prefix, comstyle, comnested;
+  int syntax_code;
+  char desc, start1, start2, end1, end2, prefix,
+    comstyleb, comstylec, comnested;
   char str[2];
   Lisp_Object first, match_lisp, value = syntax;
 
@@ -1048,14 +1115,16 @@
       return syntax;
     }
 
-  code = (enum syntaxcode) (XINT (first) & 0377);
-  start1 = (XINT (first) >> 16) & 1;
-  start2 = (XINT (first) >> 17) & 1;
-  end1 = (XINT (first) >> 18) & 1;
-  end2 = (XINT (first) >> 19) & 1;
-  prefix = (XINT (first) >> 20) & 1;
-  comstyle = (XINT (first) >> 21) & 1;
-  comnested = (XINT (first) >> 22) & 1;
+  syntax_code = XINT (first);
+  code = (enum syntaxcode) (syntax_code & 0377);
+  start1 = SYNTAX_FLAGS_COMSTART_FIRST (syntax_code);
+  start2 = SYNTAX_FLAGS_COMSTART_SECOND (syntax_code);;
+  end1 = SYNTAX_FLAGS_COMEND_FIRST (syntax_code);
+  end2 = SYNTAX_FLAGS_COMEND_SECOND (syntax_code);
+  prefix = SYNTAX_FLAGS_PREFIX (syntax_code);
+  comstyleb = SYNTAX_FLAGS_COMMENT_STYLEB (syntax_code);
+  comstylec = SYNTAX_FLAGS_COMMENT_STYLEC (syntax_code);
+  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax_code);
 
   if ((int) code < 0 || (int) code >= (int) Smax)
     {
@@ -1084,8 +1153,10 @@
 
   if (prefix)
     insert ("p", 1);
-  if (comstyle)
+  if (comstyleb)
     insert ("b", 1);
+  if (comstylec)
+    insert ("c", 1);
   if (comnested)
     insert ("n", 1);
 
@@ -1145,8 +1216,10 @@
     insert_string (",\n\t  is the first character of a comment-end sequence");
   if (end2)
     insert_string (",\n\t  is the second character of a comment-end sequence");
-  if (comstyle)
+  if (comstyleb)
     insert_string (" (comment style b)");
+  if (comstylec)
+    insert_string (" (comment style c)");
   if (comnested)
     insert_string (" (nestable)");
 
@@ -2060,7 +2133,7 @@
    FROM_BYTE is the bytepos corresponding to FROM.
    Do not move past STOP (a charpos).
    The comment over which we have to jump is of style STYLE
-     (either SYNTAX_COMMENT_STYLE(foo) or ST_COMMENT_STYLE).
+     (either SYNTAX_FLAGS_COMMENT_STYLE(foo) or ST_COMMENT_STYLE).
    NESTING should be positive to indicate the nesting at the beginning
      for nested comments and should be zero or negative else.
      ST_COMMENT_STYLE cannot be nested.
@@ -2087,7 +2160,7 @@
 {
   register int c, c1;
   register enum syntaxcode code;
-  register int syntax;
+  register int syntax, other_syntax;
 
   if (nesting <= 0) nesting = -1;
 
@@ -2109,7 +2182,7 @@
       syntax = SYNTAX_WITH_FLAGS (c);
       code = syntax & 0xff;
       if (code == Sendcomment
-	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax) == style
+	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style
 	  && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ?
 	      (nesting > 0 && --nesting == 0) : nesting < 0))
 	/* we have encountered a comment end of the same style
@@ -2125,7 +2198,7 @@
       if (nesting > 0
 	  && code == Scomment
 	  && SYNTAX_FLAGS_COMMENT_NESTED (syntax)
-	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax) == style)
+	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0) == style)
 	/* we have encountered a nested comment of the same style
 	   as the comment sequence which began this comment section */
 	nesting++;
@@ -2134,11 +2207,13 @@
 
     forw_incomment:
       if (from < stop && SYNTAX_FLAGS_COMEND_FIRST (syntax)
-	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax) == style
 	  && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
-	      SYNTAX_COMEND_SECOND (c1))
+	      other_syntax = SYNTAX_WITH_FLAGS (c1),
+	      SYNTAX_FLAGS_COMEND_SECOND (other_syntax))
+	  && SYNTAX_FLAGS_COMMENT_STYLE (syntax, other_syntax) == style
 	  && ((SYNTAX_FLAGS_COMMENT_NESTED (syntax) ||
-	       SYNTAX_COMMENT_NESTED (c1)) ? nesting > 0 : nesting < 0))
+	       SYNTAX_FLAGS_COMMENT_NESTED (other_syntax))
+	      ? nesting > 0 : nesting < 0))
 	{
 	  if (--nesting <= 0)
 	    /* we have encountered a comment end of the same style
@@ -2155,10 +2230,11 @@
 	  && from < stop
 	  && SYNTAX_FLAGS_COMSTART_FIRST (syntax)
 	  && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
-	      SYNTAX_COMMENT_STYLE (c1) == style
-	      && SYNTAX_COMSTART_SECOND (c1))
+	      other_syntax = SYNTAX_WITH_FLAGS (c1),
+	      SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax) == style
+	      && SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
 	  && (SYNTAX_FLAGS_COMMENT_NESTED (syntax) ||
-	      SYNTAX_COMMENT_NESTED (c1)))
+	      SYNTAX_FLAGS_COMMENT_NESTED (other_syntax)))
 	/* we have encountered a nested comment of the same style
 	   as the comment sequence which began this comment
 	   section */
@@ -2209,7 +2285,7 @@
     {
       do
 	{
-	  int comstart_first;
+	  int comstart_first, syntax, other_syntax;
 
 	  if (from == stop)
 	    {
@@ -2218,15 +2294,17 @@
 	      return Qnil;
 	    }
 	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+	  syntax = SYNTAX_WITH_FLAGS (c);
 	  code = SYNTAX (c);
-	  comstart_first = SYNTAX_COMSTART_FIRST (c);
-	  comnested = SYNTAX_COMMENT_NESTED (c);
-	  comstyle = SYNTAX_COMMENT_STYLE (c);
+	  comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
+	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
+	  comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
 	  INC_BOTH (from, from_byte);
 	  UPDATE_SYNTAX_TABLE_FORWARD (from);
 	  if (from < stop && comstart_first
 	      && (c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte),
-		  SYNTAX_COMSTART_SECOND (c1)))
+		  other_syntax = SYNTAX_WITH_FLAGS (c1),
+		  SYNTAX_FLAGS_COMSTART_SECOND (other_syntax)))
 	    {
 	      /* We have encountered a comment start sequence and we
 		 are ignoring all text inside comments.  We must record
@@ -2234,8 +2312,9 @@
 		 only a comment end of the same style actually ends
 		 the comment section.  */
 	      code = Scomment;
-	      comstyle = SYNTAX_COMMENT_STYLE (c1);
-	      comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+	      comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
+	      comnested
+		= comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
 	      INC_BOTH (from, from_byte);
 	      UPDATE_SYNTAX_TABLE_FORWARD (from);
 	    }
@@ -2271,7 +2350,7 @@
     {
       while (1)
 	{
-	  int quoted;
+	  int quoted, syntax;
 
 	  if (from <= stop)
 	    {
@@ -2284,15 +2363,17 @@
 	  /* char_quoted does UPDATE_SYNTAX_TABLE_BACKWARD (from).  */
 	  quoted = char_quoted (from, from_byte);
 	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+	  syntax = SYNTAX_WITH_FLAGS (c);
 	  code = SYNTAX (c);
 	  comstyle = 0;
-	  comnested = SYNTAX_COMMENT_NESTED (c);
+	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
 	  if (code == Sendcomment)
-	    comstyle = SYNTAX_COMMENT_STYLE (c);
-	  if (from > stop && SYNTAX_COMEND_SECOND (c)
+	    comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
+	  if (from > stop && SYNTAX_FLAGS_COMEND_SECOND (syntax)
 	      && prev_char_comend_first (from, from_byte)
 	      && !char_quoted (from - 1, dec_bytepos (from_byte)))
 	    {
+	      int other_syntax;
 	      /* We must record the comment style encountered so that
 		 later, we can match only the proper comment begin
 		 sequence of the same style.  */
@@ -2301,8 +2382,10 @@
 	      /* Calling char_quoted, above, set up global syntax position
 		 at the new value of FROM.  */
 	      c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-	      comstyle = SYNTAX_COMMENT_STYLE (c1);
-	      comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+	      other_syntax = SYNTAX_WITH_FLAGS (c1);
+	      comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
+	      comnested
+		= comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
 	    }
 
 	  if (code == Scomment_fence)
@@ -2349,7 +2432,7 @@
 		    {
 		      /* Failure: we should go back to the end of this
 			 not-quite-endcomment.  */
-		      if (SYNTAX(c) != code)
+		      if (SYNTAX (c) != code)
 			/* It was a two-char Sendcomment.  */
 			INC_BOTH (from, from_byte);
 		      goto leave;
@@ -2423,21 +2506,23 @@
     {
       while (from < stop)
 	{
-	  int comstart_first, prefix;
+	  int comstart_first, prefix, syntax, other_syntax;
 	  UPDATE_SYNTAX_TABLE_FORWARD (from);
 	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+	  syntax = SYNTAX_WITH_FLAGS (c);
 	  code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
-	  comstart_first = SYNTAX_COMSTART_FIRST (c);
-	  comnested = SYNTAX_COMMENT_NESTED (c);
-	  comstyle = SYNTAX_COMMENT_STYLE (c);
-	  prefix = SYNTAX_PREFIX (c);
+	  comstart_first = SYNTAX_FLAGS_COMSTART_FIRST (syntax);
+	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
+	  comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
+	  prefix = SYNTAX_FLAGS_PREFIX (syntax);
 	  if (depth == min_depth)
 	    last_good = from;
 	  INC_BOTH (from, from_byte);
 	  UPDATE_SYNTAX_TABLE_FORWARD (from);
 	  if (from < stop && comstart_first
 	      && (c = FETCH_CHAR_AS_MULTIBYTE (from_byte),
-		  SYNTAX_COMSTART_SECOND (c))
+		  other_syntax = SYNTAX_WITH_FLAGS (c),
+		  SYNTAX_FLAGS_COMSTART_SECOND (other_syntax))
 	      && parse_sexp_ignore_comments)
 	    {
 	      /* we have encountered a comment start sequence and we
@@ -2446,9 +2531,9 @@
 		 only a comment end of the same style actually ends
 		 the comment section */
 	      code = Scomment;
-	      c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-	      comstyle = SYNTAX_COMMENT_STYLE (c1);
-	      comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+	      comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
+	      comnested
+		= comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
 	      INC_BOTH (from, from_byte);
 	      UPDATE_SYNTAX_TABLE_FORWARD (from);
 	    }
@@ -2592,29 +2677,34 @@
     {
       while (from > stop)
 	{
+	  int syntax;
 	  DEC_BOTH (from, from_byte);
 	  UPDATE_SYNTAX_TABLE_BACKWARD (from);
 	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
+	  syntax= SYNTAX_WITH_FLAGS (c);
 	  code = SYNTAX_WITH_MULTIBYTE_CHECK (c);
 	  if (depth == min_depth)
 	    last_good = from;
 	  comstyle = 0;
-	  comnested = SYNTAX_COMMENT_NESTED (c);
+	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
 	  if (code == Sendcomment)
-	    comstyle = SYNTAX_COMMENT_STYLE (c);
-	  if (from > stop && SYNTAX_COMEND_SECOND (c)
+	    comstyle = SYNTAX_FLAGS_COMMENT_STYLE (syntax, 0);
+	  if (from > stop && SYNTAX_FLAGS_COMEND_SECOND (syntax)
 	      && prev_char_comend_first (from, from_byte)
 	      && parse_sexp_ignore_comments)
 	    {
 	      /* We must record the comment style encountered so that
 		 later, we can match only the proper comment begin
 		 sequence of the same style.  */
+	      int c1, other_syntax;
 	      DEC_BOTH (from, from_byte);
 	      UPDATE_SYNTAX_TABLE_BACKWARD (from);
 	      code = Sendcomment;
 	      c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
-	      comstyle = SYNTAX_COMMENT_STYLE (c1);
-	      comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+	      other_syntax = SYNTAX_WITH_FLAGS (c1);
+	      comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
+	      comnested
+		= comnested || SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
 	    }
 
 	  /* Quoting turns anything except a comment-ender
@@ -2625,7 +2715,7 @@
 	      DEC_BOTH (from, from_byte);
 	      code = Sword;
 	    }
-	  else if (SYNTAX_PREFIX (c))
+	  else if (SYNTAX_FLAGS_PREFIX (syntax))
 	    continue;
 
 	  switch (SWITCH_ENUM_CAST (code))
@@ -2949,8 +3039,11 @@
       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
+			   : INTEGERP (tem) ? XINT (tem) : 1));
 
       oldstate = Fcdr (oldstate);
       tem = Fcar (oldstate);
@@ -2995,22 +3088,25 @@
 
   while (from < end)
     {
+      int syntax;
       INC_FROM;
       code = prev_from_syntax & 0xff;
 
       if (from < end
 	  && SYNTAX_FLAGS_COMSTART_FIRST (prev_from_syntax)
 	  && (c1 = FETCH_CHAR (from_byte),
-	      SYNTAX_COMSTART_SECOND (c1)))
+	      syntax = SYNTAX_WITH_FLAGS (c1),
+	      SYNTAX_FLAGS_COMSTART_SECOND (syntax)))
 	/* 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);
+	  state.comstyle
+	    = SYNTAX_FLAGS_COMMENT_STYLE (syntax, prev_from_syntax);
 	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax);
-	  comnested = comnested || SYNTAX_COMMENT_NESTED (c1);
+	  comnested = comnested || SYNTAX_FLAGS_COMMENT_NESTED (syntax);
 	  state.incomment = comnested ? 1 : -1;
 	  state.comstr_start = prev_from;
 	  INC_FROM;
@@ -3028,7 +3124,7 @@
 	}
       else if (code == Scomment)
 	{
-	  state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax);
+	  state.comstyle = SYNTAX_FLAGS_COMMENT_STYLE (prev_from_syntax, 0);
 	  state.incomment = (SYNTAX_FLAGS_COMMENT_NESTED (prev_from_syntax) ?
 			     1 : -1);
 	  state.comstr_start = prev_from;
@@ -3221,8 +3317,7 @@
     else an integer (the current comment nesting).
  5. t if following a quote character.
  6. the minimum paren-depth encountered during this scan.
- 7. t if in a comment of style b; symbol `syntax-table' if the comment
-    should be terminated by a generic comment delimiter.
+ 7. style of comment, if any.
  8. character address of start of comment or string; nil if not in one.
  9. Intermediate data for continuation of parsing (subject to change).
 If third arg TARGETDEPTH is non-nil, parsing stops if the depth
@@ -3258,8 +3353,10 @@
   SET_PT (state.location);
 
   return Fcons (make_number (state.depth),
-	   Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart),
-	     Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart),
+	   Fcons (state.prevlevelstart < 0
+		  ? Qnil : make_number (state.prevlevelstart),
+	     Fcons (state.thislevelstart < 0
+		    ? Qnil : make_number (state.thislevelstart),
 	       Fcons (state.instring >= 0
 		      ? (state.instring == ST_STRING_STYLE
 			 ? Qt : make_number (state.instring)) : Qnil,
@@ -3270,8 +3367,9 @@
 		     Fcons (make_number (state.mindepth),
 		       Fcons ((state.comstyle
 			       ? (state.comstyle == ST_COMMENT_STYLE
-				  ? Qsyntax_table : Qt) :
-			       Qnil),
+				  ? Qsyntax_table
+				  : make_number (state.comstyle))
+			       : Qnil),
 			      Fcons (((state.incomment
 				       || (state.instring >= 0))
 				      ? make_number (state.comstr_start)

=== modified file 'src/syntax.h'
--- src/syntax.h	2010-07-02 09:26:33 +0000
+++ src/syntax.h	2010-08-12 12:36:28 +0000
@@ -128,56 +128,9 @@
     : Qnil))
 #endif
 
-/* Then there are seven single-bit flags that have the following meanings:
-  1. This character is the first of a two-character comment-start sequence.
-  2. This character is the second of a two-character comment-start sequence.
-  3. This character is the first of a two-character comment-end sequence.
-  4. This character is the second of a two-character comment-end sequence.
-  5. This character is a prefix, for backward-prefix-chars.
-  6. see below
-  7. This character is part of a nestable comment sequence.
-  Note that any two-character sequence whose first character has flag 1
-  and whose second character has flag 2 will be interpreted as a comment start.
 
-  bit 6 is used to discriminate between two different comment styles.
-  Languages such as C++ allow two orthogonal syntax start/end pairs
-  and bit 6 is used to determine whether a comment-end or Scommentend
-  ends style a or b.  Comment start sequences can start style a or b.
-  Style a is always the default.
-  */
-
-/* These macros extract a particular flag for a given character.  */
-
-#define SYNTAX_COMSTART_FIRST(c) ((SYNTAX_WITH_FLAGS (c) >> 16) & 1)
-
-#define SYNTAX_COMSTART_SECOND(c) ((SYNTAX_WITH_FLAGS (c) >> 17) & 1)
-
-#define SYNTAX_COMEND_FIRST(c) ((SYNTAX_WITH_FLAGS (c) >> 18) & 1)
-
-#define SYNTAX_COMEND_SECOND(c) ((SYNTAX_WITH_FLAGS (c) >> 19) & 1)
-
-#define SYNTAX_PREFIX(c) ((SYNTAX_WITH_FLAGS (c) >> 20) & 1)
-
-#define SYNTAX_COMMENT_STYLE(c) ((SYNTAX_WITH_FLAGS (c) >> 21) & 1)
-
-#define SYNTAX_COMMENT_NESTED(c) ((SYNTAX_WITH_FLAGS (c) >> 22) & 1)
-
-/* These macros extract specific flags from an integer
-   that holds the syntax code and the flags.  */
-
-#define SYNTAX_FLAGS_COMSTART_FIRST(flags) (((flags) >> 16) & 1)
-
-#define SYNTAX_FLAGS_COMSTART_SECOND(flags) (((flags) >> 17) & 1)
-
-#define SYNTAX_FLAGS_COMEND_FIRST(flags) (((flags) >> 18) & 1)
-
-#define SYNTAX_FLAGS_COMEND_SECOND(flags) (((flags) >> 19) & 1)
-
-#define SYNTAX_FLAGS_PREFIX(flags) (((flags) >> 20) & 1)
-
-#define SYNTAX_FLAGS_COMMENT_STYLE(flags) (((flags) >> 21) & 1)
-
-#define SYNTAX_FLAGS_COMMENT_NESTED(flags) (((flags) >> 22) & 1)
+/* Whether the syntax of the character C has the prefix flag set.  */
+extern int syntax_prefix_flag_p (int c);
 
 /* This array, indexed by a character, contains the syntax code which that
  character signifies (as a char).  For example,