/* Debug counter for debugging support
   Copyright (C) 2006-2020 Free Software Foundation, Inc.

This file is part of GCC.

GCC 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.

GCC 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.

See dbgcnt.def for usage information.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "diagnostic-core.h"
#include "dumpfile.h"
#include "selftest.h"
#include "intl.h"

#include "dbgcnt.h"

struct string2counter_map {
  const char *name;
  enum debug_counter counter;
};

#define DEBUG_COUNTER(a) { #a , a },

static struct string2counter_map map[debug_counter_number_of_counters] =
{
#include "dbgcnt.def"
};
#undef DEBUG_COUNTER

typedef std::pair<unsigned int, unsigned int> limit_tuple;

static vec<limit_tuple> limits[debug_counter_number_of_counters];

static unsigned int count[debug_counter_number_of_counters];

static void
print_limit_reach (const char *counter, int limit, bool upper_p)
{
  char buffer[128];
  sprintf (buffer, "***dbgcnt: %s limit %d reached for %s.***\n",
	   upper_p ? "upper" : "lower", limit, counter);
  fputs (buffer, stderr);
  if (dump_file)
    fputs (buffer, dump_file);
}

bool
dbg_cnt (enum debug_counter index)
{
  unsigned v = ++count[index];

  if (!limits[index].exists ())
    return true;
  else if (limits[index].is_empty ())
    return false;

  unsigned last = limits[index].length () - 1;
  unsigned int min = limits[index][last].first;
  unsigned int max = limits[index][last].second;

  if (v < min)
    return false;
  else if (v == min)
    {
      print_limit_reach (map[index].name, v, false);
      if (min == max)
	limits[index].pop ();
      return true;
    }
  else if (v < max)
    return true;
  else if (v == max)
    {
      print_limit_reach (map[index].name, v, true);
      limits[index].pop ();
      return true;
    }
  else
    return false;
}

/* Compare limit_tuple intervals by first item in descending order.  */

static int
cmp_tuples (const void *ptr1, const void *ptr2)
{
  const limit_tuple *p1 = (const limit_tuple *)ptr1;
  const limit_tuple *p2 = (const limit_tuple *)ptr2;

  if (p1->first < p2->first)
    return 1;
  else if (p1->first > p2->first)
    return -1;
  return 0;
}

static bool
dbg_cnt_set_limit_by_index (enum debug_counter index, const char *name,
			    unsigned int low, unsigned int high)
{
  if (!limits[index].exists ())
    limits[index].create (1);

  limits[index].safe_push (limit_tuple (low, high));
  limits[index].qsort (cmp_tuples);

  for (unsigned i = 0; i < limits[index].length () - 1; i++)
    {
      limit_tuple t1 = limits[index][i];
      limit_tuple t2 = limits[index][i + 1];
      if (t1.first <= t2.second)
	{
	  error ("Interval overlap of %<-fdbg-cnt=%s%>: [%u, %u] and "
		 "[%u, %u]\n", name, t2.first, t2.second, t1.first, t1.second);
	  return false;
	}
    }

  return true;
}

static bool
dbg_cnt_set_limit_by_name (const char *name, unsigned int low,
			   unsigned int high)
{
  if (high < low)
    {
      error ("%<-fdbg-cnt=%s:%d-%d%> has smaller upper limit than the lower",
	     name, low, high);
      return false;
    }

  int i;
  for (i = debug_counter_number_of_counters - 1; i >= 0; i--)
    if (strcmp (map[i].name, name) == 0)
      break;

  if (i < 0)
    {
      error ("cannot find a valid counter name %qs of %<-fdbg-cnt=%> option",
	     name);
      return false;
    }

  return dbg_cnt_set_limit_by_index ((enum debug_counter) i, name, low, high);
}

/* Process a single "low:high" pair.
   Returns NULL if there's no valid pair is found.
   Otherwise returns a pointer to the end of the pair. */

static bool
dbg_cnt_process_single_pair (char *name, char *str)
{
  char *value1 = strtok (str, "-");
  char *value2 = strtok (NULL, "-");

  unsigned int high, low;

  if (value1 == NULL)
    return false;

  if (value2 == NULL)
    {
      high = strtol (value1, NULL, 10);
      /* Let's allow 0:0.  */
      low = high == 0 ? 0 : 1;
    }
  else
    {
      low = strtol (value1, NULL, 10);
      high = strtol (value2, NULL, 10);
    }

  return dbg_cnt_set_limit_by_name (name, low, high);
}

void
dbg_cnt_process_opt (const char *arg)
{
  char *str = xstrdup (arg);
  unsigned int start = 0;

  auto_vec<char *> tokens;
  for (char *next = strtok (str, ","); next != NULL; next = strtok (NULL, ","))
    tokens.safe_push (next);

  unsigned i;
  for (i = 0; i < tokens.length (); i++)
    {
      auto_vec<char *> ranges;
      char *name = strtok (tokens[i], ":");
      for (char *part = strtok (NULL, ":"); part; part = strtok (NULL, ":"))
	ranges.safe_push (part);

      for (unsigned j = 0; j < ranges.length (); j++)
	{
	  if (!dbg_cnt_process_single_pair (name, ranges[j]))
	    break;
	}
      start += strlen (tokens[i]) + 1;
    }
}

/* Print name, limit and count of all counters.   */

void
dbg_cnt_list_all_counters (void)
{
  int i;
  printf ("  %-30s %s\n", G_("counter name"), G_("closed intervals"));
  printf ("-----------------------------------------------------------------\n");
  for (i = 0; i < debug_counter_number_of_counters; i++)
    {
      printf ("  %-30s ", map[i].name);
      if (limits[i].exists ())
	{
	  for (int j = limits[i].length () - 1; j >= 0; j--)
	    {
	      printf ("[%u, %u]", limits[i][j].first, limits[i][j].second);
	      if (j > 0)
		printf (", ");
	    }
	  putchar ('\n');
	}
      else
	printf ("unset\n");
    }
  printf ("\n");
}

#if CHECKING_P

namespace selftest {

/* Selftests.  */

static void
test_sorted_dbg_counters ()
{
  for (unsigned i = 0; i < debug_counter_number_of_counters - 1; i++)
    ASSERT_LT (strcmp (map[i].name, map[i + 1].name), 0);
}

void
dbgcnt_c_tests ()
{
  test_sorted_dbg_counters ();
}

} // namespace selftest

#endif /* #if CHECKING_P */
