/* Writes out the preprocessed file, handling spacing and paste
   avoidance issues.  */
static void
scan_translation_unit (cpp_reader *pfile)
{
  bool avoid_paste = false;
  bool do_line_adjustments
    = cpp_get_options (parse_in)->lang != CLK_ASM
      && !flag_no_line_commands;
  bool in_pragma = false;

  print.source = NULL;
  for (;;)
    {
      source_location loc;
      const cpp_token *token = cpp_get_token_with_location (pfile, &loc);

      if (token->type == CPP_PADDING)
	{
	  avoid_paste = true;
	  if (print.source == NULL
	      || (!(print.source->flags & PREV_WHITE)
		  && token->val.source == NULL))
	    print.source = token->val.source;
	  continue;
	}

      if (token->type == CPP_EOF)
	break;

      /* Subtle logic to output a space if and only if necessary.  */
      if (avoid_paste)
	{
	  const struct line_map *map
	    = linemap_lookup (line_table, loc);
	  int src_line = SOURCE_LINE (map, loc);

	  if (print.source == NULL)
	    print.source = token;

	  if (src_line != print.src_line
	      && do_line_adjustments
	      && !in_pragma)
	    {
	      do_line_change (pfile, token, loc, false);
	      putc (' ', print.outf);
	    }
	  else if (print.source->flags & PREV_WHITE
		   || (print.prev
		       && cpp_avoid_paste (pfile, print.prev, token))
		   || (print.prev == NULL && token->type == CPP_HASH))
	    putc (' ', print.outf);
	}
      else if (token->flags & PREV_WHITE)
	{
	  const struct line_map *map
	    = linemap_lookup (line_table, loc);
	  int src_line = SOURCE_LINE (map, loc);

	  if (src_line != print.src_line
	      && do_line_adjustments
	      && !in_pragma)
	    do_line_change (pfile, token, loc, false);
	  putc (' ', print.outf);
	}

      avoid_paste = false;
      print.source = NULL;
      print.prev = token;
      if (token->type == CPP_PRAGMA)
	{
	  const char *space;
	  const char *name;

	  maybe_print_line (token->src_loc);
	  fputs ("#pragma ", print.outf);
	  c_pp_lookup_pragma (token->val.pragma, &space, &name);
	  if (space)
	    fprintf (print.outf, "%s %s", space, name);
	  else
	    fprintf (print.outf, "%s", name);
	  print.printed = 1;
	  in_pragma = true;
	}
      else if (token->type == CPP_PRAGMA_EOL)
	{
	  maybe_print_line (token->src_loc);
	  in_pragma = false;
	}
      else
	cpp_output_token (token, print.outf);

      if (token->type == CPP_COMMENT)
	account_for_newlines (token->val.str.text, token->val.str.len);
    }
}
예제 #2
0
파일: c-ppoutput.c 프로젝트: ChaosJohn/gcc
/* Writes out the preprocessed file, handling spacing and paste
   avoidance issues.  */
static void
scan_translation_unit (cpp_reader *pfile)
{
  bool avoid_paste = false;
  bool do_line_adjustments
    = cpp_get_options (parse_in)->lang != CLK_ASM
      && !flag_no_line_commands;
  bool in_pragma = false;

  print.source = NULL;
  for (;;)
    {
      source_location loc;
      const cpp_token *token = cpp_get_token_with_location (pfile, &loc);

      if (token->type == CPP_PADDING)
	{
	  avoid_paste = true;
	  if (print.source == NULL
	      || (!(print.source->flags & PREV_WHITE)
		  && token->val.source == NULL))
	    print.source = token->val.source;
	  continue;
	}

      if (token->type == CPP_EOF)
	break;

      /* Subtle logic to output a space if and only if necessary.  */
      if (avoid_paste)
	{
	  int src_line = LOCATION_LINE (loc);

	  if (print.source == NULL)
	    print.source = token;

	  if (src_line != print.src_line
	      && do_line_adjustments
	      && !in_pragma)
	    {
	      do_line_change (pfile, token, loc, false);
	      putc (' ', print.outf);
	    }
	  else if (print.source->flags & PREV_WHITE
		   || (print.prev
		       && cpp_avoid_paste (pfile, print.prev, token))
		   || (print.prev == NULL && token->type == CPP_HASH))
	    putc (' ', print.outf);
	}
      else if (token->flags & PREV_WHITE)
	{
	  int src_line = LOCATION_LINE (loc);

	  if (src_line != print.src_line
	      && do_line_adjustments
	      && !in_pragma)
	    do_line_change (pfile, token, loc, false);
	  putc (' ', print.outf);
	}

      avoid_paste = false;
      print.source = NULL;
      print.prev = token;
      if (token->type == CPP_PRAGMA)
	{
	  const char *space;
	  const char *name;

	  maybe_print_line (token->src_loc);
	  fputs ("#pragma ", print.outf);
	  c_pp_lookup_pragma (token->val.pragma, &space, &name);
	  if (space)
	    fprintf (print.outf, "%s %s", space, name);
	  else
	    fprintf (print.outf, "%s", name);
	  print.printed = 1;
	  in_pragma = true;
	}
      else if (token->type == CPP_PRAGMA_EOL)
	{
	  maybe_print_line (token->src_loc);
	  in_pragma = false;
	}
      else
	{
	  if (cpp_get_options (parse_in)->debug)
	      linemap_dump_location (line_table, token->src_loc,
				     print.outf);
	  cpp_output_token (token, print.outf);
	}

      /* CPP_COMMENT tokens and raw-string literal tokens can
	 have embedded new-line characters.  Rather than enumerating
	 all the possible token types just check if token uses
	 val.str union member.  */
      if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
	account_for_newlines (token->val.str.text, token->val.str.len);
    }
}