/* The IGEN simulator generator for GDB, the GNU Debugger.

   Copyright 2002-2021 Free Software Foundation, Inc.

   Contributed by Andrew Cagney.

   This file is part of GDB.

   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 of the License, 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, see <http://www.gnu.org/licenses/>.  */



#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>

#include "misc.h"

#include <stdlib.h>
#include <string.h>

/* NB: Because warning and error can be interchanged, neither append a
   trailing '\n' */

void
error (const line_ref *line, char *msg, ...)
{
  va_list ap;
  if (line != NULL)
    fprintf (stderr, "%s:%d: ", line->file_name, line->line_nr);
  va_start (ap, msg);
  vfprintf (stderr, msg, ap);
  va_end (ap);
  exit (1);
}

void
warning (const line_ref *line, char *msg, ...)
{
  va_list ap;
  if (line != NULL)
    fprintf (stderr, "%s:%d: warning: ", line->file_name, line->line_nr);
  va_start (ap, msg);
  vfprintf (stderr, msg, ap);
  va_end (ap);
}

void
notify (const line_ref *line, char *msg, ...)
{
  va_list ap;
  if (line != NULL)
    fprintf (stdout, "%s %d: info: ", line->file_name, line->line_nr);
  va_start (ap, msg);
  vfprintf (stdout, msg, ap);
  va_end (ap);
}

void *
zalloc (long size)
{
  void *memory = malloc (size);
  if (memory == NULL)
    ERROR ("zalloc failed");
  memset (memory, 0, size);
  return memory;
}


unsigned long long
a2i (const char *a)
{
  int neg = 0;
  int base = 10;
  unsigned long long num = 0;
  int looping;

  while (isspace (*a))
    a++;

  if (strcmp (a, "true") == 0 || strcmp (a, "TRUE") == 0)
    return 1;

  if (strcmp (a, "false") == 0 || strcmp (a, "FALSE") == 0)
    return 0;

  if (*a == '-')
    {
      neg = 1;
      a++;
    }

  if (*a == '0')
    {
      if (a[1] == 'x' || a[1] == 'X')
	{
	  a += 2;
	  base = 16;
	}
      else if (a[1] == 'b' || a[1] == 'B')
	{
	  a += 2;
	  base = 2;
	}
      else
	base = 8;
    }

  looping = 1;
  while (looping)
    {
      int ch = *a++;

      switch (base)
	{
	default:
	  looping = 0;
	  break;

	case 2:
	  if (ch >= '0' && ch <= '1')
	    {
	      num = (num * 2) + (ch - '0');
	    }
	  else
	    {
	      looping = 0;
	    }
	  break;

	case 10:
	  if (ch >= '0' && ch <= '9')
	    {
	      num = (num * 10) + (ch - '0');
	    }
	  else
	    {
	      looping = 0;
	    }
	  break;

	case 8:
	  if (ch >= '0' && ch <= '7')
	    {
	      num = (num * 8) + (ch - '0');
	    }
	  else
	    {
	      looping = 0;
	    }
	  break;

	case 16:
	  if (ch >= '0' && ch <= '9')
	    {
	      num = (num * 16) + (ch - '0');
	    }
	  else if (ch >= 'a' && ch <= 'f')
	    {
	      num = (num * 16) + (ch - 'a' + 10);
	    }
	  else if (ch >= 'A' && ch <= 'F')
	    {
	      num = (num * 16) + (ch - 'A' + 10);
	    }
	  else
	    {
	      looping = 0;
	    }
	  break;
	}
    }

  if (neg)
    num = -num;

  return num;
}

unsigned
target_a2i (int ms_bit_nr, const char *a)
{
  if (ms_bit_nr)
    return (ms_bit_nr - a2i (a));
  else
    return a2i (a);
}

unsigned
i2target (int ms_bit_nr, unsigned bit)
{
  if (ms_bit_nr)
    return ms_bit_nr - bit;
  else
    return bit;
}


int
name2i (const char *names, const name_map * map)
{
  const name_map *curr;
  const char *name = names;
  while (*name != '\0')
    {
      /* find our name */
      char *end = strchr (name, ',');
      char *next;
      unsigned len;
      if (end == NULL)
	{
	  end = strchr (name, '\0');
	  next = end;
	}
      else
	{
	  next = end + 1;
	}
      len = end - name;
      /* look it up */
      curr = map;
      while (curr->name != NULL)
	{
	  if (strncmp (curr->name, name, len) == 0
	      && strlen (curr->name) == len)
	    return curr->i;
	  curr++;
	}
      name = next;
    }
  /* nothing found, possibly return a default */
  curr = map;
  while (curr->name != NULL)
    curr++;
  if (curr->i >= 0)
    return curr->i;
  else
    error (NULL, "%s contains no valid names", names);
  return 0;
}

const char *
i2name (const int i, const name_map * map)
{
  while (map->name != NULL)
    {
      if (map->i == i)
	return map->name;
      map++;
    }
  error (NULL, "map lookup failed for %d\n", i);
  return NULL;
}
