Esempio n. 1
0
/* Process the notes created by add_line_note as far as the current
   location.  */
void
_cpp_process_line_notes (cpp_reader *pfile, int in_comment)
{
  cpp_buffer *buffer = pfile->buffer;

  for (;;)
    {
      _cpp_line_note *note = &buffer->notes[buffer->cur_note];
      unsigned int col;

      if (note->pos > buffer->cur)
	break;

      buffer->cur_note++;
      col = CPP_BUF_COLUMN (buffer, note->pos + 1);

      if (note->type == '\\' || note->type == ' ')
	{
	  if (note->type == ' ' && !in_comment)
	    cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
				 "backslash and newline separated by space");

	  if (buffer->next_line > buffer->rlimit)
	    {
	      cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line, col,
				   "backslash-newline at end of file");
	      /* Prevent "no newline at end of file" warning.  */
	      buffer->next_line = buffer->rlimit;
	    }

	  buffer->line_base = note->pos;
	  CPP_INCREMENT_LINE (pfile, 0);
	}
      else if (_cpp_trigraph_map[note->type])
	{
	  if (CPP_OPTION (pfile, warn_trigraphs)
	      && (!in_comment || warn_in_comment (pfile, note)))
	    {
	      if (CPP_OPTION (pfile, trigraphs))
		cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
				     "trigraph ??%c converted to %c",
				     note->type,
				     (int) _cpp_trigraph_map[note->type]);
	      else
		{
		  cpp_error_with_line 
		    (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
		     "trigraph ??%c ignored, use -trigraphs to enable",
		     note->type);
		}
	    }
	}
      else
	abort ();
    }
}
Esempio n. 2
0
/* Skip a C-style block comment.  We find the end of the comment by
   seeing if an asterisk is before every '/' we encounter.  Returns
   nonzero if comment terminated by EOF, zero otherwise.

   Buffer->cur points to the initial asterisk of the comment.  */
bool
_cpp_skip_block_comment (cpp_reader *pfile)
{
  cpp_buffer *buffer = pfile->buffer;
  const uchar *cur = buffer->cur;
  uchar c;

  cur++;
  if (*cur == '/')
    cur++;

  for (;;)
    {
      /* People like decorating comments with '*', so check for '/'
	 instead for efficiency.  */
      c = *cur++;

      if (c == '/')
	{
	  if (cur[-2] == '*')
	    break;

	  /* Warn about potential nested comments, but not if the '/'
	     comes immediately before the true comment delimiter.
	     Don't bother to get it right across escaped newlines.  */
	  if (CPP_OPTION (pfile, warn_comments)
	      && cur[0] == '*' && cur[1] != '/')
	    {
	      buffer->cur = cur;
	      cpp_error_with_line (pfile, CPP_DL_WARNING,
				   pfile->line_table->highest_line, CPP_BUF_COL (buffer),
				   "\"/*\" within comment");
	    }
	}
      else if (c == '\n')
	{
	  unsigned int cols;
	  buffer->cur = cur - 1;
	  _cpp_process_line_notes (pfile, true);
	  if (buffer->next_line >= buffer->rlimit)
	    return true;
	  _cpp_clean_line (pfile);

	  cols = buffer->next_line - buffer->line_base;
	  CPP_INCREMENT_LINE (pfile, cols);

	  cur = buffer->cur;
	}
    }

  buffer->cur = cur;
  _cpp_process_line_notes (pfile, true);
  return false;
}
Esempio n. 3
0
/* Writes out the preprocessed file, handling spacing and paste
   avoidance issues.  */
void
_cpp_preprocess_dir_only (cpp_reader *pfile,
			  const struct _cpp_dir_only_callbacks *cb)
{
  struct cpp_buffer *buffer;
  const unsigned char *cur, *base, *next_line, *rlimit;
  cppchar_t c, last_c;
  unsigned flags;
  linenum_type lines;
  int col;
  source_location loc;

 restart:
  /* Buffer initialization ala _cpp_clean_line(). */
  buffer = pfile->buffer;
  buffer->cur_note = buffer->notes_used = 0;
  buffer->cur = buffer->line_base = buffer->next_line;
  buffer->need_line = false;

  /* This isn't really needed.  It prevents a compiler warning, though. */
  loc = pfile->line_table->highest_line;

  /* Scan initialization. */
  next_line = cur = base = buffer->cur;
  rlimit = buffer->rlimit;
  flags = DO_BOL;
  lines = 0;
  col = 1;

  for (last_c = '\n', c = *cur; cur < rlimit; last_c = c, c = *++cur, ++col)
    {
      /* Skip over escaped newlines. */
      if (__builtin_expect (c == '\\', false))
	{
	  const unsigned char *tmp = cur + 1;

	  while (is_nvspace (*tmp) && tmp < rlimit)
	    tmp++;
	  if (*tmp == '\r')
	    tmp++;
	  if (*tmp == '\n' && tmp < rlimit)
	    {
	      CPP_INCREMENT_LINE (pfile, 0);
	      lines++;
	      col = 0;
	      cur = tmp;
	      c = last_c;
	      continue;
	    }
	}

      if (__builtin_expect (last_c == '#', false) && !(flags & DO_SPECIAL))
	{
	  if (c != '#' && (flags & DO_BOL))
	  {
	    struct line_maps *line_table;

	    if (!pfile->state.skipping && next_line != base)
	      cb->print_lines (lines, base, next_line - base);

	    /* Prep things for directive handling. */
	    buffer->next_line = cur;
	    buffer->need_line = true;
	    _cpp_get_fresh_line (pfile);

	    /* Ensure proper column numbering for generated error messages. */
	    buffer->line_base -= col - 1;

	    _cpp_handle_directive (pfile, 0 /* ignore indented */);

	    /* Sanitize the line settings.  Duplicate #include's can mess
	       things up. */
	    line_table = pfile->line_table;
	    line_table->highest_location = line_table->highest_line;

	    /* The if block prevents us from outputing line information when
	       the file ends with a directive and no newline.  Note that we
	       must use pfile->buffer, not buffer. */
	    if (pfile->buffer->next_line < pfile->buffer->rlimit)
	      cb->maybe_print_line (pfile->line_table->highest_line);

	    goto restart;
	  }

	  flags &= ~DO_BOL;
	  pfile->mi_valid = false;
	}
      else if (__builtin_expect (last_c == '/', false) \
	       && !(flags & DO_SPECIAL) && c != '*' && c != '/')
	{
	  /* If a previous slash is not starting a block comment, clear the
	     DO_BOL flag.  */
	  flags &= ~DO_BOL;
	  pfile->mi_valid = false;
	}

      switch (c)
	{
	case '/':
	  if ((flags & DO_BLOCK_COMMENT) && last_c == '*')
	    {
	      flags &= ~DO_BLOCK_COMMENT;
	      c = 0;
	    }
	  else if (!(flags & DO_SPECIAL) && last_c == '/')
	    flags |= DO_LINE_COMMENT;
	  else if (!(flags & DO_SPECIAL))
	    /* Mark the position for possible error reporting. */
	    loc = linemap_position_for_column (pfile->line_table, col);

	  break;

	case '*':
	  if (!(flags & DO_SPECIAL))
	    {
	      if (last_c == '/')
		flags |= DO_BLOCK_COMMENT;
	      else
		{
		  flags &= ~DO_BOL;
		  pfile->mi_valid = false;
		}
	    }

	  break;

	case '\'':
	case '"':
	  {
	    unsigned state = (c == '"') ? DO_STRING : DO_CHAR;

	    if (!(flags & DO_SPECIAL))
	      {
		flags |= state;
		flags &= ~DO_BOL;
		pfile->mi_valid = false;
	      }
	    else if ((flags & state) && last_c != '\\')
	      flags &= ~state;

	    break;
	  }

	case '\\':
	  {
	    if ((flags & (DO_STRING | DO_CHAR)) && last_c == '\\')
	      c = 0;

	    if (!(flags & DO_SPECIAL))
	      {
		flags &= ~DO_BOL;
		pfile->mi_valid = false;
	      }

	    break;
	  }

	case '\n':
	  CPP_INCREMENT_LINE (pfile, 0);
	  lines++;
	  col = 0;
	  flags &= ~DO_LINE_SPECIAL;
	  if (!(flags & DO_SPECIAL))
	    flags |= DO_BOL;
	  break;

	case '#':
	  next_line = cur;
	  /* Don't update DO_BOL yet. */
	  break;

	case ' ': case '\t': case '\f': case '\v': case '\0':
	  break;

	default:
	  if (!(flags & DO_SPECIAL))
	    {
	      flags &= ~DO_BOL;
	      pfile->mi_valid = false;
	    }
	  break;
	}
    }

  if (flags & DO_BLOCK_COMMENT)
    cpp_error_with_line (pfile, CPP_DL_ERROR, loc, 0, "unterminated comment");

  if (!pfile->state.skipping && cur != base)
    {
      /* If the file was not newline terminated, add rlimit, which is
         guaranteed to point to a newline, to the end of our range.  */
      if (cur[-1] != '\n')
	{
	  cur++;
	  CPP_INCREMENT_LINE (pfile, 0);
	  lines++;
	}

      cb->print_lines (lines, base, cur - base);
    }

  _cpp_pop_buffer (pfile);
  if (pfile->buffer)
    goto restart;
}