/* Copyright (C) 2021 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;
}

