/* Control warning output in GNU Make.
Copyright (C) 2023-2025 Free Software Foundation, Inc.
This file is part of GNU Make.

GNU Make 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.

GNU Make 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 <https://www.gnu.org/licenses/>.  */

#include "makeint.h"

#include "warning.h"

#include "variable.h"

/* Current action for each warning.  */
enum warning_action warnings[wt_max];

/* The default behavior of warnings.  */
static struct warning_data warn_default;

/* Warning settings from the .WARNING variable.  */
static struct warning_data warn_variable;

/* Warning settings from the command line.  */
static struct warning_data warn_flag;

static const char *w_action_map[w_error+1] = {NULL, "ignore", "warn", "error"};
static const char *w_name_map[wt_max] = {
                                          "circular-dep",
                                          "invalid-ref",
                                          "invalid-var",
                                          "undefined-var"
                                        };

#define encode_warn_action(_b,_s) \
    variable_buffer_output (_b, w_action_map[_s], strlen (w_action_map[_s]))
#define encode_warn_name(_b,_t)   \
    variable_buffer_output (_b, w_name_map[_t], strlen (w_name_map[_t]))

static void set_warnings ()
{
  /* Called whenever any warnings could change; resets the current actions.  */
  for (enum warning_type wt = 0; wt < wt_max; ++wt)
    warnings[wt] =
        warn_flag.actions[wt]     != w_unset ? warn_flag.actions[wt]
      : warn_flag.global          != w_unset ? warn_flag.global
      : warn_variable.actions[wt] != w_unset ? warn_variable.actions[wt]
      : warn_variable.global      != w_unset ? warn_variable.global
      : warn_default.actions[wt];
}

void
warn_init ()
{
  memset (&warn_default, '\0', sizeof (warn_default));
  memset (&warn_variable, '\0', sizeof (warn_variable));
  memset (&warn_flag, '\0', sizeof (warn_flag));

  /* All warnings must have a default.  */
  warn_default.global = w_warn;
  warn_default.actions[wt_circular_dep] = w_warn;
  warn_default.actions[wt_invalid_ref] = w_warn;
  warn_default.actions[wt_invalid_var] = w_warn;
  warn_default.actions[wt_undefined_var] = w_ignore;

  set_warnings ();
}

static void
init_data (struct warning_data *data)
{
  data->global = w_unset;
  for (enum warning_type wt = 0; wt < wt_max; ++wt)
    data->actions[wt] = w_unset;
}

static enum warning_action
decode_warn_action (const char *action, size_t length)
{
  for (enum warning_action st = w_ignore; st <= w_error; ++st)
    {
      size_t len = strlen (w_action_map[st]);
      if (length == len && strncasecmp (action, w_action_map[st], length) == 0)
        return st;
    }

  return w_unset;
}

static enum warning_type
decode_warn_name (const char *name, size_t length)
{
  for (enum warning_type wt = 0; wt < wt_max; ++wt)
    {
      size_t len = strlen (w_name_map[wt]);
      if (length == len && strncasecmp (name, w_name_map[wt], length) == 0)
        return wt;
    }

  return wt_max;
}

void
decode_warn_actions (const char *value, const floc *flocp)
{
  struct warning_data *data = &warn_flag;

  NEXT_TOKEN (value);

  if (flocp)
    {
      data = &warn_variable;
      /* When a variable is set to empty, reset everything.  */
      if (*value == '\0')
        init_data (data);
    }

  while (*value != '\0')
    {
      enum warning_action action;

      /* Find the end of the next warning definition.  */
      const char *ep = value;
      while (! STOP_SET (*ep, MAP_BLANK|MAP_COMMA|MAP_NUL))
        ++ep;

      /* If the value is just an action set it globally.  */
      action = decode_warn_action (value, ep - value);
      if (action != w_unset)
        data->global = action;
      else
        {
          enum warning_type type;
          const char *cp = memchr (value, ':', ep - value);
          int wl, al;

          if (!cp)
            cp = ep;
          wl = (int)(cp - value);
          type = decode_warn_name (value, wl);
          if (cp == ep)
            action = w_warn;
          else
            {
              /* There's a warning action: decode it.  */
              ++cp;
              al = (int)(ep - cp);
              action = decode_warn_action (cp, al);
            }

          if (type == wt_max)
            {
              if (!flocp)
                ONS (fatal, NILF, _("unknown warning '%.*s'"), wl, value);
              ONS (error, flocp,
                   _("unknown warning '%.*s': ignored"), wl, value);
            }
          else if (action == w_unset)
            {
              if (!flocp)
                ONS (fatal, NILF,
                     _("unknown warning action '%.*s'"), al, cp);
              ONS (error, flocp,
                   _("unknown warning action '%.*s': ignored"), al, cp);
            }
          else
            data->actions[type] = action;
        }

      value = ep;
      while (STOP_SET (*value, MAP_BLANK|MAP_COMMA))
        ++value;
    }

  set_warnings ();
}

char *
encode_warn_flag (char *fp)
{
  enum warning_type wt;
  char sp = '=';

  /* See if any warning options are set.  */
  for (wt = 0; wt < wt_max; ++wt)
    if (warn_flag.actions[wt] != w_unset)
      break;
  if (wt == wt_max && warn_flag.global == w_unset)
    return fp;

  /* Something is set so construct a --warn option.  */
  fp = variable_buffer_output (fp, STRING_SIZE_TUPLE (" --warn"));

  /* If only a global action set to warn, we're done.  */
  if (wt == wt_max && warn_flag.global == w_warn)
    return fp;

  /* If a global action is set, add it.  */
  if (warn_flag.global > w_unset)
    {
      fp = variable_buffer_output (fp, &sp, 1);
      sp = ',';
      fp = encode_warn_action (fp, warn_flag.global);
    }

  /* Add any specific actions.  */
  if (wt != wt_max)
    for (wt = 0; wt < wt_max; ++wt)
      {
        enum warning_action act = warn_flag.actions[wt];
        if (act > w_unset)
          {
            fp = variable_buffer_output (fp, &sp, 1);
            sp = ',';
            fp = encode_warn_name (fp, wt);
            if (act != w_warn)
              fp = encode_warn_action (variable_buffer_output (fp, ":", 1), act);
          }
      }

  return fp;
}

void
warn_get_vardata (struct warning_data *data)
{
  memcpy (data, &warn_variable, sizeof (warn_variable));
}

void
warn_set_vardata (const struct warning_data *data)
{
  memcpy (&warn_variable, data, sizeof (warn_variable));
  set_warnings ();
}
