(face-valid-attribute-values): Make sure directories we search for
[bpt/emacs.git] / src / syntax.c
index 9361ba0..189e50d 100644 (file)
@@ -469,12 +469,16 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
      PARITY is current parity of quotes from the comment end.  */
   int string_style = -1;       /* Presumed outside of any string. */
   int string_lossage = 0;
+  /* Not a real lossage: indicates that we have passed a matching comment
+     starter plus an non-matching comment-ender, meaning that any matching
+     comment-starter we might see later could be a false positive (hidden
+     inside another comment).
+     Test case:  { a (* b } c (* d *) */
+  int comment_lossage = 0;
   int comment_end = from;
   int comment_end_byte = from_byte;
   int comstart_pos = 0;
   int comstart_byte;
-  /* Value that PARITY had, when we reached the position
-     in COMSTART_POS.  */
   int scanstart = from - 1;
   /* Place where the containing defun starts,
      or 0 if we didn't come across it yet.  */
@@ -548,23 +552,24 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
          
        case Scomment:
          /* We've already checked that it is the relevant comstyle.  */
-         if (string_style != -1 || string_lossage)
+         if (string_style != -1 || comment_lossage || string_lossage)
            /* There are odd string quotes involved, so let's be careful.
               Test case in Pascal: " { " a { " } */
            goto lossage;
 
-         if (comnested && --nesting <= 0)
+         if (!comnested)
+           {
+             /* Record best comment-starter so far.  */
+             comstart_pos = from;
+             comstart_byte = from_byte;
+           }
+         else if (--nesting <= 0)
            /* nested comments have to be balanced, so we don't need to
               keep looking for earlier ones.  We use here the same (slightly
               incorrect) reasoning as below:  since it is followed by uniform
               paired string quotes, this comment-start has to be outside of
               strings, else the comment-end itself would be inside a string. */
            goto done;
-
-         /* Record comment-starters according to that
-            quote-parity to the comment-end.  */
-         comstart_pos = from;
-         comstart_byte = from_byte;
          break;
 
        case Sendcomment:
@@ -578,6 +583,15 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
                   this comment-ender rather than ours.  */
                from = stop;    /* Break out of the loop.  */
            }
+         else if (comstart_pos != 0 || c != '\n')
+           /* We're mixing comment styles here, so we'd better be careful.
+              The (comstart_pos != 0 || c != '\n') check is not quite correct
+              (we should just always set comment_lossage), but removing it
+              would imply that any multiline comment in C would go through
+              lossage, which seems overkill.
+              The failure should only happen in the rare cases such as
+                { (* } *)   */
+           comment_lossage = 1;
          break;
 
        case Sopen:
@@ -594,7 +608,7 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
          break;
 
        default:
-         continue;
+         break;
        }
     }
 
@@ -604,12 +618,9 @@ back_comment (from, from_byte, stop, comnested, comstyle, charpos_ptr, bytepos_p
       from_byte = comment_end_byte;
       UPDATE_SYNTAX_TABLE_FORWARD (comment_end - 1);
     }
-  /* If the earliest comment starter
-     is followed by uniform paired string quotes or none,
-     we know it can't be inside a string
-     since if it were then the comment ender would be inside one.
-     So it does start a comment.  Skip back to it.  */
-  else if (!comnested)
+  /* If comstart_pos is set and we get here (ie. didn't jump to `lossage'
+     or `done'), then we've found the beginning of the non-nested comment.  */
+  else if (1)  /* !comnested */
     {
       from = comstart_pos;
       from_byte = comstart_byte;
@@ -1370,7 +1381,7 @@ skip_chars (forwardp, syntaxp, string, lim)
       if (nbytes != size_byte)
        {
          str = (unsigned char *) alloca (nbytes);
-         copy_text (XSTRING (string)->data, str, nbytes,
+         copy_text (XSTRING (string)->data, str, size_byte,
                     string_multibyte, multibyte);
          size_byte = nbytes;
        }
@@ -1440,22 +1451,34 @@ skip_chars (forwardp, syntaxp, string, lim)
              if (SINGLE_BYTE_CHAR_P (c))
                {
                  if (! SINGLE_BYTE_CHAR_P (c2))
-                   error ("Invalid character range: %s",
-                          XSTRING (string)->data);
+                   {
+                     /* Handle a range such as \177-\377 in multibyte
+                        mode.  Split that into two ranges, the low
+                        one ending at 0237, and the high one starting
+                        at the smallest character in the charset of
+                        C2 and ending at C2.  */
+                     int charset = CHAR_CHARSET (c2);
+                     int c1 = MAKE_CHAR (charset, 0, 0);
+
+                     fastmap[c2_leading_code] = 1;
+                     char_ranges[n_char_ranges++] = c1;
+                     char_ranges[n_char_ranges++] = c2;
+                     c2 = 0237;
+                   }
                  while (c <= c2)
                    {
                      fastmap[c] = 1;
                      c++;
                    }
                }
-             else
+             else if (! SINGLE_BYTE_CHAR_P (c2))
                {
                  if (c_leading_code != c2_leading_code)
                    error ("Invalid character range: %s",
                           XSTRING (string)->data);
-                 fastmap[c_leading_code] = 1;
                  if (c <= c2)
                    {
+                     fastmap[c_leading_code] = 1;
                      char_ranges[n_char_ranges++] = c;
                      char_ranges[n_char_ranges++] = c2;
                    }
@@ -1463,9 +1486,11 @@ skip_chars (forwardp, syntaxp, string, lim)
            }
          else
            {
-             fastmap[c_leading_code] = 1;
-             if (!SINGLE_BYTE_CHAR_P (c))
+             if (SINGLE_BYTE_CHAR_P (c))
+               fastmap[c] = 1;
+             else
                {
+                 fastmap[c_leading_code] = 1;
                  char_ranges[n_char_ranges++] = c;
                  char_ranges[n_char_ranges++] = c;
                }
@@ -1562,26 +1587,24 @@ skip_chars (forwardp, syntaxp, string, lim)
            if (multibyte)
              while (pos < XINT (lim) && fastmap[(c = FETCH_BYTE (pos_byte))])
                {
-                 if (!BASE_LEADING_CODE_P (c))
-                   INC_BOTH (pos, pos_byte);
-                 else if (n_char_ranges)
+                 /* If we are looking at a multibyte character, we
+                    must look up the character in the table
+                    CHAR_RANGES.  If there's no data in the table,
+                    that character is not what we want to skip.  */
+                 if (BASE_LEADING_CODE_P (c)
+                     && (c = FETCH_MULTIBYTE_CHAR (pos_byte),
+                         ! SINGLE_BYTE_CHAR_P (c)))
                    {
-                     /* We much check CHAR_RANGES for a multibyte
-                        character.  */
-                     ch = FETCH_MULTIBYTE_CHAR (pos_byte);
+                     /* The following code do the right thing even if
+                        n_char_ranges is zero (i.e. no data in
+                        CHAR_RANGES).  */
                      for (i = 0; i < n_char_ranges; i += 2)
-                       if ((ch >= char_ranges[i] && ch <= char_ranges[i + 1]))
+                       if (c >= char_ranges[i] && c <= char_ranges[i + 1])
                          break;
                      if (!(negate ^ (i < n_char_ranges)))
                        break;
-
-                     INC_BOTH (pos, pos_byte);
-                   }
-                 else
-                   {
-                     if (!negate) break;
-                     INC_BOTH (pos, pos_byte);
                    }
+                 INC_BOTH (pos, pos_byte);
                }
            else
              while (pos < XINT (lim) && fastmap[FETCH_BYTE (pos)])
@@ -1592,41 +1615,25 @@ skip_chars (forwardp, syntaxp, string, lim)
            if (multibyte)
              while (pos > XINT (lim))
                {
-                 int savepos = pos_byte;
-                 DEC_BOTH (pos, pos_byte);
-                 if (fastmap[(c = FETCH_BYTE (pos_byte))])
-                   {
-                     if (!BASE_LEADING_CODE_P (c))
-                       ;
-                     else if (n_char_ranges)
-                       {
-                         /* We much check CHAR_RANGES for a multibyte
-                            character.  */
-                         ch = FETCH_MULTIBYTE_CHAR (pos_byte);
-                         for (i = 0; i < n_char_ranges; i += 2)
-                           if (ch >= char_ranges[i] && ch <= char_ranges[i + 1])
-                             break;
-                         if (!(negate ^ (i < n_char_ranges)))
-                           {
-                             pos++;
-                             pos_byte = savepos;
-                             break;
-                           }
-                       }
-                     else
-                       if (!negate)
-                         {
-                           pos++;
-                           pos_byte = savepos;
-                           break;
-                         }
-                   }
-                 else
+                 int prev_pos_byte = pos_byte;
+
+                 DEC_POS (prev_pos_byte);
+                 if (!fastmap[(c = FETCH_BYTE (prev_pos_byte))])
+                   break;
+
+                 /* See the comment in the previous similar code.  */
+                 if (BASE_LEADING_CODE_P (c)
+                     && (c = FETCH_MULTIBYTE_CHAR (prev_pos_byte),
+                         ! SINGLE_BYTE_CHAR_P (c)))
                    {
-                     pos++;
-                     pos_byte = savepos;
-                     break;
+                     for (i = 0; i < n_char_ranges; i += 2)
+                       if (c >= char_ranges[i] && c <= char_ranges[i + 1])
+                         break;
+                     if (!(negate ^ (i < n_char_ranges)))
+                       break;
                    }
+                 pos--;
+                 pos_byte = prev_pos_byte;
                }
            else
              while (pos > XINT (lim) && fastmap[FETCH_BYTE (pos - 1)])