Function: forward-comment

forward-comment is a function defined in syntax.c.

Signature

(forward-comment COUNT)

Documentation

Move forward across up to COUNT comments. If COUNT is negative, move backward.

Stop scanning if we find something other than a comment or whitespace. Set point to where scanning stops. If COUNT comments are found as expected, with nothing except whitespace between them, return t; otherwise return nil.

Probably introduced at or before Emacs version 27.1.

Aliases

vhdl-forward-comment

Source Code

// Defined in /usr/src/emacs/src/syntax.c
// Skipping highlighting due to helpful-max-highlight.
{
  ptrdiff_t from, from_byte, stop;
  int c, c1;
  enum syntaxcode code;
  int comstyle = 0;	    /* style of comment encountered */
  bool comnested = 0;	    /* whether the comment is nestable or not */
  bool found;
  EMACS_INT count1;
  ptrdiff_t out_charpos, out_bytepos;
  EMACS_INT dummy;
  int dummy2;
  unsigned short int quit_count = 0;

  CHECK_FIXNUM (count);
  count1 = XFIXNUM (count);
  stop = count1 > 0 ? ZV : BEGV;

  from = PT;
  from_byte = PT_BYTE;

  SETUP_SYNTAX_TABLE (from, clip_to_bounds (PTRDIFF_MIN, count1, PTRDIFF_MAX));
  while (count1 > 0)
    {
      do
	{
	  bool comstart_first;
	  int syntax, other_syntax;

	  if (from == stop)
	    {
	      SET_PT_BOTH (from, from_byte);
	      return Qnil;
	    }
	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
	  syntax = SYNTAX_WITH_FLAGS (c);
	  code = SYNTAX (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),
		  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
		 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_FLAGS_COMMENT_STYLE (other_syntax, syntax);
	      comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
	      inc_both (&from, &from_byte);
	      UPDATE_SYNTAX_TABLE_FORWARD (from);
	    }
	  rarely_quit (++quit_count);
	}
      while (code == Swhitespace || (code == Sendcomment && c == '\n'));

      if (code == Scomment_fence)
	comstyle = ST_COMMENT_STYLE;
      else if (code != Scomment)
	{
	  dec_both (&from, &from_byte);
	  SET_PT_BOTH (from, from_byte);
	  return Qnil;
	}
      /* We're at the start of a comment.  */
      found = forw_comment (from, from_byte, stop, comnested, comstyle, 0,
			    &out_charpos, &out_bytepos, &dummy, &dummy2);
      from = out_charpos; from_byte = out_bytepos;
      if (!found)
	{
	  SET_PT_BOTH (from, from_byte);
	  return Qnil;
	}
      inc_both (&from, &from_byte);
      UPDATE_SYNTAX_TABLE_FORWARD (from);
      /* We have skipped one comment.  */
      count1--;
    }

  while (count1 < 0)
    {
      while (true)
	{
	  if (from <= stop)
	    {
	      SET_PT_BOTH (BEGV, BEGV_BYTE);
	      return Qnil;
	    }

	  dec_both (&from, &from_byte);
	  /* char_quoted does UPDATE_SYNTAX_TABLE_BACKWARD (from).  */
	  bool quoted = char_quoted (from, from_byte);
	  c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
	  int syntax = SYNTAX_WITH_FLAGS (c);
	  code = SYNTAX (c);
	  comstyle = 0;
	  comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
	  if (code == Sendcomment)
	    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.  */
	      dec_both (&from, &from_byte);
	      code = Sendcomment;
	      /* Calling char_quoted, above, set up global syntax position
		 at the new value of FROM.  */
	      c1 = FETCH_CHAR_AS_MULTIBYTE (from_byte);
	      other_syntax = SYNTAX_WITH_FLAGS (c1);
	      comstyle = SYNTAX_FLAGS_COMMENT_STYLE (other_syntax, syntax);
	      comnested |= SYNTAX_FLAGS_COMMENT_NESTED (other_syntax);
	    }

	  if (code == Scomment_fence)
	    {
	      /* Skip until first preceding unquoted comment_fence.  */
	      bool fence_found = 0;
	      ptrdiff_t ini = from, ini_byte = from_byte;

	      if (from > stop)
		{
		  while (1)
		    {
		      dec_both (&from, &from_byte);
		      UPDATE_SYNTAX_TABLE_BACKWARD (from);
		      c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
		      if (SYNTAX (c) == Scomment_fence
			  && !char_quoted (from, from_byte))
			{
			  fence_found = 1;
			  break;
			}
		      else if (from == stop)
			break;
		      rarely_quit (++quit_count);
		    }
		}
	      if (fence_found == 0)
		{
		  from = ini;		/* Set point to ini + 1.  */
		  from_byte = ini_byte;
		  goto leave;
		}
              else
		/* We have skipped one comment.  */
		break;
	    }
	  else if (code == Sendcomment)
	    {
              found = (!quoted || !comment_end_can_be_escaped)
                && back_comment (from, from_byte, stop, comnested, comstyle,
                                 &out_charpos, &out_bytepos);
	      if (!found)
		{
		  if (c == '\n')
		    /* This end-of-line is not an end-of-comment.
		       Treat it like a whitespace.
		       CC-mode (and maybe others) relies on this behavior.  */
		    ;
		  else
		    {
		      /* Failure: we should go back to the end of this
			 not-quite-endcomment.  */
		      if (SYNTAX (c) != code)
			/* It was a two-char Sendcomment.  */
			inc_both (&from, &from_byte);
		      goto leave;
		    }
		}
	      else
		{
		  /* We have skipped one comment.  */
		  from = out_charpos, from_byte = out_bytepos;
		  break;
		}
	    }
	  else if (code != Swhitespace || quoted)
	    {
	    leave:
	      inc_both (&from, &from_byte);
	      SET_PT_BOTH (from, from_byte);
	      return Qnil;
	    }

	  rarely_quit (++quit_count);
	}

      count1++;
    }

  SET_PT_BOTH (from, from_byte);
  return Qt;
}