#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <yafl_usr.h>
#include <yafl_rnt.h>
#include "dbx_rnt.h"
#include "dbx_modu.h"
#include "dbx_type.h"
#include "dbx_clas.h"
#include "dbx_meth.h"
#include "dbx_type.h"
#include "dbx_call.h"
#include "dbx_loca.h"
#include "dbx_matc.h"

#ifdef XDEBUG

#define MAX_METHODS 1000
static dbx_method method_table[MAX_METHODS];
static unsigned used_methods = 0;

static char yesstr[] = "YES";
static char nostr[] = "NO";

dbx_method *new_method YPARAMS0
{
  dbx_method *p;
  assert(used_methods < MAX_METHODS);
  p = &method_table[used_methods];
  memset (p,0,sizeof(dbx_method));
  used_methods++;
  return p;
}

static void dump_methods YPARAMS0
{
  int i;
  dbx_method *p; 
  char a[200];
  
  sprintf(a, "dbx_method\tline\n\n");
  emit_stdout(a);
  for (i = 0;i < used_methods;i++)
  {
    p = &method_table[i];
    sprintf(a, "%s\t%u\n",p->name,p->line);
    emit_stdout(a);
  }
  emit_nl();
}


#else

dbx_method *new_method YPARAMS0
{
  dbx_method *p;
  p = (dbx_method *)malloc(sizeof(dbx_method));
  assertp(p);
  memset (p,0,sizeof(dbx_method));
  return p;
}

#endif



char *method_name YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  if (pm->name)
    return (pm->name);
  else
    return("<undefined>");
}

dbx_method *enclosing_method YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return (pm->method);
}

unsigned method_beginline YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return (pm->beginline);
}

unsigned method_endline YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return (pm->endline);
}

dbx_method *next_method YPARAMS2(dbx_method *,  pm) /* _of_class */
{
  assertp(pm);
  return (pm->next);
}

dbx_method *prev_method YPARAMS2(dbx_method *,  pm) /* of_class */
{
  assertp(pm);
  return (pm->prev);
}

dbx_class *method_class YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  assert(pm->class != NULL);
  return (pm->class);
}

struct dbx_local *first_local YPARAMS2(dbx_method *,  pm) /* of_method */
{
  assertp(pm);
  return (pm->first_local);
}

struct dbx_local *last_local YPARAMS2(dbx_method *,  pm) /* of_method */
{
  assertp(pm);
  return (pm->last_local);
}

dbx_method *find_next_method YPARAMS4(dbx_method *,  pm,
                                     char *,       pattern)
{
  dbx_method *pmet = NULL;
  while (pm)
  {
    if (dbx_match(method_name(pm),pattern))
    {
      pmet = pm;
      pm = NULL;
    }
    else
    {
      pm = next_method(pm);
    }
  }
  return pmet;
}

dbx_method *find_prev_method YPARAMS4(dbx_method *,  pm,
                                     char *,       pattern)
{
  dbx_method *pmet = NULL;
  while (pm)
  {
    if (dbx_match(method_name(pm),pattern))
    {
      pmet = pm;
      pm = NULL;
    }
    else
    {
      pm = prev_method(pm);
    }
  }
  return pmet;
}

/* the count of the number of breakpoints in each debugged method */
/* is used to optimize the process of checking if a breakpoint has */
/* been hit */
/* it must be updated by the set and clear breakpoint commands */

void inc_bp_count YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  (pm->bp_count)++;
}

void dec_bp_count YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  assert(pm->bp_count>0);
  (pm->bp_count)--;
}


/* replace by macro for more speed */

unsigned bp_count YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return(pm->bp_count);
}

struct dbx_local *local_in_methods YPARAMS4(dbx_method *,  pm,
                                    char *,        name)
{
  dbx_local *pl;
  while (pm)
  {
    pl = find_next_local(first_local(pm),name);
    if (pl)
      return (pl);
    pm = enclosing_method(pm);
  }
  return NULL;
}


dbx_method *first_innermethod YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return(pm->first_inner);
}

dbx_method *last_innermethod YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return(pm->last_inner);
}

dbx_method *next_innermethod YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return(pm->next_inner);
}

dbx_method *prev_innermethod YPARAMS2(dbx_method *,  pm)
{
  assertp(pm);
  return(pm->prev_inner);
}

