/* Copyright (C) 2021-2024 Free Software Foundation, Inc.
   Contributed by Oracle.

   This file is part of GNU Binutils.

   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; if not, write to the Free Software
   Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

#include "config.h"
#include <strings.h>
#include "DerivedMetrics.h"
#include "util.h"

enum opType
{
  opNULL,
  opPrimitive,
  opDivide
};

class definition
{
public:
  definition();
  ~definition();
  char *name;
  char *def;
  opType op;
  definition *arg1;
  definition *arg2;
  int index;
};

definition::definition ()
{
  name = def = NULL;
  arg1 = arg2 = NULL;
}

definition::~definition ()
{
  free (name);
  free (def);
}

DerivedMetrics::DerivedMetrics ()
{
  items = new Vector<definition*>;
}

DerivedMetrics::~DerivedMetrics ()
{
  Destroy (items);
}

definition *
DerivedMetrics::add_definition (char *_name, char *_username, char *_def)
{
  definition *p;

  // if the name doesn't matter, maybe there is a duplicate we can use
  if (_name == NULL)
    {
      int i;
      Vec_loop (definition*, items, i, p)
      {
	if (strcmp (p->def, _def) == 0)
	  return p;
      }
    }

  p = new definition;
  p->name = dbe_strdup (_name);
  p->def = dbe_strdup (_def);

  // parse the definition
  if (strchr (_def, '/') == NULL)
    {
      // it's a primitive metric
      p->op = opPrimitive;
      p->arg1 = p->arg2 = NULL;

    }
  else
    {
      // it's some operation on arguments
      p->op = opDivide;
      char *op_ptr = strchr (p->def, '/');
      *op_ptr = 0;
      p->arg1 = add_definition (NULL, NULL, p->def);
      *op_ptr = '/';
      p->arg2 = add_definition (NULL, NULL, op_ptr + 1);
    }
  p->index = items->size ();
  items->append (p);
  return p;
}

int *
DerivedMetrics::construct_map (Vector<Metric*> *mitems, BaseMetric::SubType st, char *expr_spec)
{
  if (items == NULL)
    return NULL;
  int ndm = items->size ();
  if (ndm == 0)
    return NULL;
  int nmetrics = mitems->size ();

  // allocate arrays for the mapping between derived metrics and requested values
  int *map = (int *) xmalloc (ndm * sizeof (int));

  // map derived metrics to requested metrics    // EUGENE explain this more clearly
  //   0  means not mapped
  //  >0  means primitive metric maps to map-1
  //  <0  means  derived  metric maps to 1-map
  int ndm_requested = 0;
  for (int idm = 0; idm < ndm; idm++)
    {
      definition *defdm = items->fetch (idm);
      map[idm] = 0;

      // figure out what name to use for this derived metric
      char *dname;
      if (defdm->op == opPrimitive)
	dname = defdm->def;
      else
	{
	  dname = defdm->name;
	  if (dname == NULL) break;
	}

      // look for this name among metrics
      int im;
      for (im = 0; im < nmetrics; im++)
	{
	  Metric *m = mitems->fetch (im);
	  if (strcmp (dname, m->get_cmd ()) == 0 && m->get_subtype () == st)
	    // apparent match, but let's check comparison mode
	    if (dbe_strcmp (expr_spec, m->get_expr_spec ()) == 0)
	      break;
	}

      // encode the mapping
      if (im >= nmetrics)
	map[idm] = 0; // does not map to requested metrics
      else if (defdm->op == opPrimitive)
	map[idm] = +1 + im; // encode as a positive index
      else
	{
	  map[idm] = -1 - im; // encode as a negative index
	  ndm_requested++;
	}
    }
  if (ndm_requested == 0)
    {
      free (map);
      map = NULL;
    }
  return map;
}

void
DerivedMetrics::fill_dependencies (definition *def, int *vec)
{
  switch (def->op)
    {
    case opPrimitive:
      vec[def->index] = 1;
      break;
    case opDivide:
      fill_dependencies (def->arg1, vec);
      fill_dependencies (def->arg2, vec);
      break;
    default:
      break;
    }
}

Vector<definition*> *
DerivedMetrics::get_dependencies (definition *def)
{
  int n = items->size ();

  // zero out a vector representing definitions
  int *vec = (int *) xmalloc (n * sizeof (int));
  for (int i = 0; i < n; i++)
    vec[i] = 0;
  fill_dependencies (def, vec);

  // construct the dependency vector
  Vector<definition*> *dependencies = new Vector<definition*>;
  for (int i = 0; i < n; i++)
    if (vec[i] == 1)
      dependencies->append (items->fetch (i));
  free (vec);
  return dependencies;
}

void
DerivedMetrics::dump (FILE *dis_file, int verbosity)
{
  int i;
  definition *item;

  // deal with the possibility that names might be NULL
  const char *UNNAMED = "(unnamed)";
#define NAME(x) ( (x) ? (x) : UNNAMED)

  Vec_loop (definition*, items, i, item)
  {
    // at low verbosity, skip over some items
    if (verbosity == 0)
      {
	if (item->name == NULL)
	  continue;
	if (strcmp (item->name, item->def) && item->op == opPrimitive)
	  continue;
      }

    // dump the definition
    switch (item->op)
      {
      case opPrimitive:
	fprintf (dis_file, "%s [%s] is a primitive metric\n", NAME (item->name),
		 item->def);
	break;
      case opDivide:
	fprintf (dis_file, "%s [%s] = %s [%s] / %s [%s]\n", NAME (item->name),
		 item->def, NAME (item->arg1->name), item->arg1->def,
		 NAME (item->arg2->name), item->arg2->def);
	break;
      default:
	fprintf (dis_file, "%s [%s] has an unrecognized op %d\n",
		 NAME (item->name), item->def, item->op);
	break;
      }
  }
}

double
DerivedMetrics::eval_one_item (definition *def, int *map, double *values)
{
  switch (def->op)
    {
    case opNULL:
      fprintf (stderr, GTXT ("cannot eval NULL expression\n"));
      return 0.;
    case opPrimitive:
      {
	int ival = map[def->index];
	if (ival <= 0) return 0.;
	ival--;
	return values[ival];
      }
    case opDivide:
      {
	double x1 = eval_one_item (def->arg1, map, values);
	double x2 = eval_one_item (def->arg2, map, values);
	if (x2 == 0) return 0.;
	return (x1 / x2);
      }
    default:
      fprintf (stderr, GTXT ("unknown expression\n"));
      return 0.;
    }
}

int
DerivedMetrics::eval (int *map, double *values)
{
  for (int i = 0, n = items->size (); i < n; i++)
    {
      if (map[i] < 0)
	{
	  int ival = -1 - map[i];
	  values[ival] = eval_one_item (items->fetch (i), map, values);
	}
    }
  return 0;
}

