#include <stdio.h>
#include <stdlib.h>
#include <assert.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_call.h"
#include "dbx_matc.h"
#include "dbx_stri.h"

#ifdef XDEBUG

#define MAX_LOCALS 4000
static dbx_local local_table[MAX_LOCALS];
static unsigned used_locals = 0;

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

dbx_local *new_local YPARAMS0
{
  dbx_local *p;
  assert(used_locals < MAX_LOCALS);
  p = &local_table[used_locals];
  memset (p,0,sizeof(dbx_local));
  used_locals++;
  return p;
}

static void dump_locals YPARAMS0
{
  int i;
  dbx_local *p;
  char *str, a[200];
  
  emit_stdout("dbx_local\tonce\ttype\tlevel\toffset\n\n");
  for (i = 0;i < used_locals;i++)
  {
    p = &local_table[i];
    if (p->once)
      str = yesstr;
    else
      str = nostr;
    sprintf(a, "%s\t%s\t%s\t%u\t%u\n",p->name,str,
                p->type->class_name,p->level,p->offset);
    emit_stdout(a);                
  }
  emit_nl();
}

#else

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

#endif




char *local_name YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  assertp(pl->name);
  return(pl->name);
}

int once_local YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  return(pl->once != NULL);
}

dbx_type *local_type YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  assertp(pl->type);
  return(pl->type);
}

unsigned local_level YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  return(pl->level);
}

dbx_local *next_local YPARAMS2(dbx_local *,  pl) /* _of_method */
{
  assertp(pl);
  return(pl->next);
}

dbx_local *prev_local YPARAMS2(dbx_local *,  pl) /* _of_method */
{
  assertp(pl);
  return(pl->prev);
}

dbx_method *local_method YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  assertp(pl->method);
  return(pl->method);
}

VOID *local_data YPARAMS2(dbx_local *,  pl)
{
  assertp(pl);
  assert(pl->once != NULL);
  return (pl->once);
}

/* obtain the adress of a local data item given a local */
/* and a call (instance of a method) */
/* it is necessary to differentiate between once and not once */
/* locals and between ordinary locals and this */
/* we don't have to use the call information to compute once */
/* locals adresses as such an address is unique and stored in */
/* the data field of the local */
/* for not once locals this field is not significant */
/* we still have to check if the local is THIS because in the */
/* current implementation it is not stored in the context data */
/* structure (which contains variables,parameters and the eventual */
/* RESULT); instead we store its address in the call,next to the */
/* address of the context */
/* for ordinary locals we compute the address by adding the corresponding */
/* offset to the address of the context data structure */

VOID *get_ldata YPARAMS4(dbx_local *,  pl,
                        dbx_call *,   pc)
{
  assertp(pl);
  assertp(pc);
  if (once_local(pl))
    return (pl->once);
  else
    if (streq(local_name(pl),"THIS"))
      return (pc->this);
    else
      return((char *)(pc->context)+pl->offset);
}			


dbx_local *find_next_local YPARAMS4(dbx_local *,  pl,
                                   char *,  pattern)
{
  dbx_local *ploc = NULL;
  while (pl)
  {
    if (dbx_match(local_name(pl),pattern))
    {
      ploc = pl;
      pl = NULL;
    }
    else
    {
      pl = next_local(pl);
    }
  }
  return ploc;
}

dbx_local *find_prev_local YPARAMS4(dbx_local *,  pl,
                                   char *,  pattern)
{
  dbx_local *ploc = NULL;
  while (pl)
  {
    if (dbx_match(local_name(pl),pattern))
    {
      ploc = pl;
      pl = NULL;
    }
    else
    {
      pl = prev_local(pl);
    }
  }
  return ploc;
}









                      
