/* Error reporting facilities.

   Copyright (C) 1986-2025 Free Software Foundation, Inc.

   This file is part of GDB.

   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 of the License, 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.  If not, see <http://www.gnu.org/licenses/>.  */

#include "errors.h"
#if defined (USE_WIN32API) || defined(__CYGWIN__)
#include <windows.h>
#endif /* USE_WIN32API */

/* See gdbsupport/errors.h.  */

void
warning (const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  vwarning (fmt, ap);
  va_end (ap);
}

/* See gdbsupport/errors.h.  */

void
error (const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  verror (fmt, ap);
  va_end (ap);
}

/* See gdbsupport/errors.h.  */

void
internal_error_loc (const char *file, int line, const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  internal_verror (file, line, fmt, ap);
  va_end (ap);
}

/* See gdbsupport/errors.h.  */

void
internal_warning_loc (const char *file, int line, const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);
  internal_vwarning (file, line, fmt, ap);
  va_end (ap);
}

/* See errors.h.  */

std::string
perror_string (const char *prefix, int errnum)
{
  const char *err;

  if (errnum != 0)
    err = safe_strerror (errnum);
  else
    err = safe_strerror (errno);
  return std::string (prefix) + ": " + err;
}

/* See errors.h.  */

void
perror_with_name (const char *string, int errnum)
{
  std::string combined = perror_string (string, errnum);

  error (_("%s."), combined.c_str ());
}

#if defined (USE_WIN32API) || defined(__CYGWIN__)

/* See errors.h.  */

const char *
strwinerror (ULONGEST error)
{
  static char buf[1024];
  TCHAR *msgbuf;
  DWORD lasterr = GetLastError ();
  DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
			       | FORMAT_MESSAGE_ALLOCATE_BUFFER,
			       NULL,
			       error,
			       0, /* Default language */
			       (LPTSTR) &msgbuf,
			       0,
			       NULL);
  if (chars != 0)
    {
      /* If there is an \r\n appended, zap it.  */
      if (chars >= 2
	  && msgbuf[chars - 2] == '\r'
	  && msgbuf[chars - 1] == '\n')
	{
	  chars -= 2;
	  msgbuf[chars] = 0;
	}

      if (chars > ARRAY_SIZE (buf) - 1)
	{
	  chars = ARRAY_SIZE (buf) - 1;
	  msgbuf [chars] = 0;
	}

#ifdef UNICODE
      wcstombs (buf, msgbuf, chars + 1);
#else
      strncpy (buf, msgbuf, chars + 1);
#endif
      LocalFree (msgbuf);
    }
  else
    sprintf (buf, "unknown win32 error (%u)", (unsigned) error);

  SetLastError (lasterr);
  return buf;
}

/* See errors.h.  */

void
throw_winerror_with_name (const char *string, ULONGEST err)
{
  error (_("%s (error %u): %s"), string, (unsigned) err, strwinerror (err));
}

#endif /* USE_WIN32API */
