/* 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 *) malloc (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 *) malloc (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;
}

