changeset 1998:656f4297962e

(describe_syntax_1): Delete excess arg to describe_vector. (check_syntax_table): Delete excess arg to wrong_type_argument. (Fforward_comment): New function.
author Richard M. Stallman <rms@gnu.org>
date Tue, 02 Mar 1993 17:21:05 +0000
parents 4b2a76f0d640
children ced6a5b2519d
files src/syntax.c
diffstat 1 files changed, 260 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/syntax.c	Tue Mar 02 08:28:38 1993 +0000
+++ b/src/syntax.c	Tue Mar 02 17:21:05 1993 +0000
@@ -120,7 +120,7 @@
   register Lisp_Object tem;
   while (tem = Fsyntax_table_p (obj),
 	 NILP (tem))
-    obj = wrong_type_argument (Qsyntax_table_p, obj, 0);
+    obj = wrong_type_argument (Qsyntax_table_p, obj);
   return obj;
 }   
 
@@ -449,7 +449,7 @@
 {
   struct buffer *old = current_buffer;
   set_buffer_internal (XBUFFER (Vstandard_output));
-  describe_vector (vector, Qnil, describe_syntax, 0, Qnil, Qnil);
+  describe_vector (vector, Qnil, describe_syntax, 0, Qnil);
   set_buffer_internal (old);
   return Qnil;
 }
@@ -563,6 +563,263 @@
   return Qt;
 }
 
+DEFUN ("forward-comment", Fforward_comment, Sforward_comment, 1, 1, 0,
+  "Move forward across up to N comments.  If N is negative, move backward.\n\
+Set point to the far end of the last comment found.\n\
+Stop scanning if we find something other than a comment or whitespace.\n\
+If N comments are found as expected, with nothing except whitespace\n\
+between them, return t; otherwise return nil.")
+  (count)
+     int count;
+{
+  register int from;
+  register int stop;
+  register int c;
+  register enum syntaxcode code;
+  int comstyle = 0;	    /* style of comment encountered */
+
+  immediate_quit = 1;
+  QUIT;
+
+  from = PT;
+
+  while (count > 0)
+    {
+      stop = ZV;
+      while (from < stop)
+	{
+	  c = FETCH_CHAR (from);
+	  code = SYNTAX (c);
+	  from++;
+	  comstyle = 0;
+	  if (from < stop && SYNTAX_COMSTART_FIRST (c)
+	      && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))
+	    {
+	      /* we have encountered a comment start sequence and we 
+		 are ignoring all text inside comments. we must record
+		 the comment style this sequence begins so that later,
+		 only a comment end of the same style actually ends
+		 the comment section */
+	      code = Scomment;
+	      comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from));
+	      from++;
+	    }
+
+	  if (code == Scomment)
+	    {
+	      while (1)
+		{
+		  if (from == stop)
+		    {
+		      immediate_quit = 0;
+		      return Qnil;
+		    }
+		  c = FETCH_CHAR (from);
+		  if (SYNTAX (c) == Sendcomment
+		      && SYNTAX_COMMENT_STYLE (c) == comstyle)
+		    /* we have encountered a comment end of the same style
+		       as the comment sequence which began this comment
+		       section */
+		    break;
+		  from++;
+		  if (from < stop && SYNTAX_COMEND_FIRST (c)
+		      && SYNTAX_COMEND_SECOND (FETCH_CHAR (from))
+		      && SYNTAX_COMMENT_STYLE (c) == comstyle)
+		    /* we have encountered a comment end of the same style
+		       as the comment sequence which began this comment
+		       section */
+		    { from++; break; }
+		}
+	      /* We have skipped one comment.  */
+	      break;
+	    }
+	  else if (code != Swhitespace)
+	    {
+	      immediate_quit = 0;
+	      return Qnil;
+	    }
+	}
+
+      /* End of comment reached */
+      count--;
+    }
+
+  while (count < 0)
+    {
+      stop = BEGV;
+      while (from > stop)
+	{
+	  int quoted;
+
+	  from--;
+	  quoted = char_quoted (from);
+	  if (quoted)
+	    from--;
+	  c = FETCH_CHAR (from);
+	  code = SYNTAX (c);
+	  comstyle = 0;
+	  if (from > stop && SYNTAX_COMEND_SECOND (c)
+	      && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))
+	      && !char_quoted (from - 1))
+	    {
+	      /* we must record the comment style encountered so that
+		 later, we can match only the proper comment begin
+		 sequence of the same style */
+	      code = Sendcomment;
+	      comstyle = SYNTAX_COMMENT_STYLE (FETCH_CHAR (from - 1));
+	      from--;
+	    }
+
+	  if (code == Sendcomment && !quoted)
+	    {
+	      if (code != SYNTAX (c))
+		/* For a two-char comment ender, we can assume
+		   it does end a comment.  So scan back in a simple way.  */
+		{
+		  if (from != stop) from--;
+		  while (1)
+		    {
+		      if (SYNTAX (c = FETCH_CHAR (from)) == Scomment
+			  && SYNTAX_COMMENT_STYLE (c) == comstyle)
+			break;
+		      if (from == stop)
+			{
+			  immediate_quit = 0;
+			  return Qnil;
+			}
+		      from--;
+		      if (SYNTAX_COMSTART_SECOND (c)
+			  && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from))
+			  && SYNTAX_COMMENT_STYLE (c) == comstyle
+			  && !char_quoted (from))
+			break;
+		    }
+		  break;
+		}
+
+	      /* Look back, counting the parity of string-quotes,
+		 and recording the comment-starters seen.
+		 When we reach a safe place, assume that's not in a string;
+		 then step the main scan to the earliest comment-starter seen
+		 an even number of string quotes away from the safe place.
+
+		 OFROM[I] is position of the earliest comment-starter seen
+		 which is I+2X quotes from the comment-end.
+		 PARITY is current parity of quotes from the comment end.  */
+	      {
+		int parity = 0;
+		char my_stringend = 0;
+		int string_lossage = 0;
+		int comment_end = from;
+		int comstart_pos = 0;
+		int comstart_parity = 0;
+
+		/* At beginning of range to scan, we're outside of strings;
+		   that determines quote parity to the comment-end.  */
+		while (from != stop)
+		  {
+		    /* Move back and examine a character.  */
+		    from--;
+
+		    c = FETCH_CHAR (from);
+		    code = SYNTAX (c);
+
+		    /* If this char is the second of a 2-char comment sequence,
+		       back up and give the pair the appropriate syntax.  */
+		    if (from > stop && SYNTAX_COMEND_SECOND (c)
+			&& SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1)))
+		      {
+			code = Sendcomment;
+			from--;
+		      }
+			
+		    else if (from > stop && SYNTAX_COMSTART_SECOND (c)
+			     && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
+			     && comstyle == SYNTAX_COMMENT_STYLE (c))
+		      {
+			code = Scomment;
+			from--;
+		      }
+
+		    /* Ignore escaped characters.  */
+		    if (char_quoted (from))
+		      continue;
+
+		    /* Track parity of quotes.  */
+		    if (code == Sstring)
+		      {
+			parity ^= 1;
+			if (my_stringend == 0)
+			  my_stringend = c;
+			/* If we have two kinds of string delimiters.
+			   There's no way to grok this scanning backwards.  */
+			else if (my_stringend != c)
+			  string_lossage = 1;
+		      }
+
+		    /* Record comment-starters according to that
+		       quote-parity to the comment-end.  */
+		    if (code == Scomment)
+		      {
+			comstart_parity = parity;
+			comstart_pos = from;
+		      }
+
+		    /* If we find another earlier comment-ender,
+		       any comment-starts earier than that don't count
+		       (because they go with the earlier comment-ender).  */
+		    if (code == Sendcomment
+			&& SYNTAX_COMMENT_STYLE (FETCH_CHAR (from)) == comstyle)
+		      break;
+
+		    /* Assume a defun-start point is outside of strings.  */
+		    if (code == Sopen
+			&& (from == stop || FETCH_CHAR (from - 1) == '\n'))
+		      break;
+		  }
+
+		if (comstart_pos == 0)
+		  from = comment_end;
+		/* 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 (comstart_parity == 0 && !string_lossage)
+		  from = comstart_pos;
+		else
+		  {
+		    /* We had two kinds of string delimiters mixed up
+		       together.  Decode this going forwards.
+		       Scan fwd from the previous comment ender
+		       to the one in question; this records where we
+		       last passed a comment starter.  */
+		    struct lisp_parse_state state;
+		    scan_sexps_forward (&state, find_defun_start (comment_end),
+					comment_end - 1, -10000, 0, Qnil);
+		    if (state.incomment)
+		      from = state.comstart;
+		    else
+		      /* We can't grok this as a comment; scan it normally.  */
+		      from = comment_end;
+		  }
+	      }
+	    }
+	  else if (code != Swhitespace || quoted)
+	    {
+	      immediate_quit = 0;
+	      return Qnil;
+	    }
+	}
+
+      count++;
+    }
+
+  SET_PT (from);
+  immediate_quit = 0;
+  return Qt;
+}
+
 int parse_sexp_ignore_comments;
 
 Lisp_Object
@@ -1418,6 +1675,7 @@
 
   defsubr (&Sforward_word);
 
+  defsubr (&Sforward_comment);
   defsubr (&Sscan_lists);
   defsubr (&Sscan_sexps);
   defsubr (&Sbackward_prefix_chars);