/* Default error handlers for CPP Library.
   Copyright (C) 1986-2021 Free Software Foundation, Inc.
   Written by Per Bothner, 1994.
   Based on CCCP program by Paul Rubin, June 1986
   Adapted to ANSI C, Richard Stallman, Jan 1987

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.

 In other words, you are welcome to use, share and improve this program.
 You are forbidden to forbid anyone else to use, share and improve
 what you give them.   Help stamp out software-hoarding!  */

#include "config.h"
#include "system.h"
#include "cpplib.h"
#include "internal.h"

/* Print a diagnostic at the given location.  */

ATTRIBUTE_FPTR_PRINTF(5,0)
static bool
cpp_diagnostic_at (cpp_reader * pfile, enum cpp_diagnostic_level level,
		   enum cpp_warning_reason reason, rich_location *richloc,
		   const char *msgid, va_list *ap)
{
  bool ret;

  if (!pfile->cb.diagnostic)
    abort ();
  ret = pfile->cb.diagnostic (pfile, level, reason, richloc, _(msgid), ap);

  return ret;
}

/* Print a diagnostic at the location of the previously lexed token.  */

ATTRIBUTE_FPTR_PRINTF(4,0)
static bool
cpp_diagnostic (cpp_reader * pfile, enum cpp_diagnostic_level level,
		enum cpp_warning_reason reason,
		const char *msgid, va_list *ap)
{
  location_t src_loc;

  if (CPP_OPTION (pfile, traditional))
    {
      if (pfile->state.in_directive)
	src_loc = pfile->directive_line;
      else
	src_loc = pfile->line_table->highest_line;
    }
  /* We don't want to refer to a token before the beginning of the
     current run -- that is invalid.  */
  else if (pfile->cur_token == pfile->cur_run->base)
    {
      src_loc = 0;
    }
  else
    {
      src_loc = pfile->cur_token[-1].src_loc;
    }
  rich_location richloc (pfile->line_table, src_loc);
  return cpp_diagnostic_at (pfile, level, reason, &richloc, msgid, ap);
}

/* Print a warning or error, depending on the value of LEVEL.  */

bool
cpp_error (cpp_reader * pfile, enum cpp_diagnostic_level level,
	   const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic (pfile, level, CPP_W_NONE, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a warning.  The warning reason may be given in REASON.  */

bool
cpp_warning (cpp_reader * pfile, enum cpp_warning_reason reason,
	     const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic (pfile, CPP_DL_WARNING, reason, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a pedantic warning.  The warning reason may be given in REASON.  */

bool
cpp_pedwarning (cpp_reader * pfile, enum cpp_warning_reason reason,
		const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic (pfile, CPP_DL_PEDWARN, reason, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a warning, including system headers.  The warning reason may be
   given in REASON.  */

bool
cpp_warning_syshdr (cpp_reader * pfile, enum cpp_warning_reason reason,
		    const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, reason, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a diagnostic at a specific location.  */

ATTRIBUTE_FPTR_PRINTF(6,0)
static bool
cpp_diagnostic_with_line (cpp_reader * pfile, enum cpp_diagnostic_level level,
			  enum cpp_warning_reason reason,
			  location_t src_loc, unsigned int column,
			  const char *msgid, va_list *ap)
{
  bool ret;
  
  if (!pfile->cb.diagnostic)
    abort ();
  rich_location richloc (pfile->line_table, src_loc);
  if (column)
    richloc.override_column (column);
  ret = pfile->cb.diagnostic (pfile, level, reason, &richloc, _(msgid), ap);

  return ret;
}

/* Print a warning or error, depending on the value of LEVEL.  */

bool
cpp_error_with_line (cpp_reader *pfile, enum cpp_diagnostic_level level,
		     location_t src_loc, unsigned int column,
		     const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic_with_line (pfile, level, CPP_W_NONE, src_loc,
                                  column, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a warning.  The warning reason may be given in REASON.  */

bool
cpp_warning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason,
		       location_t src_loc, unsigned int column,
		       const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING, reason, src_loc,
                                  column, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a pedantic warning.  The warning reason may be given in REASON.  */

bool
cpp_pedwarning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason,
			  location_t src_loc, unsigned int column,
			  const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic_with_line (pfile, CPP_DL_PEDWARN, reason, src_loc,
                                  column, msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a warning, including system headers.  The warning reason may be
   given in REASON.  */

bool
cpp_warning_with_line_syshdr (cpp_reader *pfile, enum cpp_warning_reason reason,
			      location_t src_loc, unsigned int column,
			      const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING_SYSHDR, reason, src_loc,
                                  column, msgid, &ap);

  va_end (ap);
  return ret;
}

/* As cpp_error, but use SRC_LOC as the location of the error, without
   a column override.  */

bool
cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level,
	      location_t src_loc, const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  rich_location richloc (pfile->line_table, src_loc);
  ret = cpp_diagnostic_at (pfile, level, CPP_W_NONE, &richloc,
			   msgid, &ap);

  va_end (ap);
  return ret;
}

/* As cpp_error, but use RICHLOC as the location of the error, without
   a column override.  */

bool
cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level,
	      rich_location *richloc, const char *msgid, ...)
{
  va_list ap;
  bool ret;

  va_start (ap, msgid);

  ret = cpp_diagnostic_at (pfile, level, CPP_W_NONE, richloc,
			   msgid, &ap);

  va_end (ap);
  return ret;
}

/* Print a warning or error, depending on the value of LEVEL.  Include
   information from errno.  */

bool
cpp_errno (cpp_reader *pfile, enum cpp_diagnostic_level level,
	   const char *msgid)
{
  return cpp_error (pfile, level, "%s: %s", _(msgid), xstrerror (errno));
}

/* Print a warning or error, depending on the value of LEVEL.  Include
   information from errno.  Unlike cpp_errno, the argument is a filename
   that is not localized, but "" is replaced with localized "stdout".  */

bool
cpp_errno_filename (cpp_reader *pfile, enum cpp_diagnostic_level level,
		    const char *filename,
		    location_t loc)
{
  if (filename[0] == '\0')
    filename = _("stdout");

  return cpp_error_at (pfile, level, loc, "%s: %s", filename,
		       xstrerror (errno));
}
