#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_type.h"
#include "dbx_fiel.h"
#include "dbx_matc.h"

#ifdef XDEBUG

#define MAX_FIELDS 1000
static dbx_field field_table[MAX_FIELDS];
static unsigned used_fields = 0;

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

dbx_field *dbx_new_field YPARAMS0
{
  dbx_field *p;
  assert(used_fields < MAX_FIELDS);
  p = &field_table[used_fields];
  memset (p,0,sizeof(dbx_field));
  used_fields++;
  return p;
}

static void dump_fields YPARAMS0
{
  int i;
  dbx_field *p;
  char *str, a[200];
  
  emit_stdout("dbx_field\tonce\ttype\tlevel\toffset\n\n");
  for (i = 0;i < used_fields;i++)
  {
    p = &field_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_field *dbx_new_field YPARAMS0
{
  dbx_field *p;
  p = (dbx_field *)malloc(sizeof(dbx_field));
  assertp(p);
  memset (p,0,sizeof(dbx_field));
  return p;
}

#endif



char *field_name YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  assert(pf->name != NULL);
  return(pf->name);
}

int once_field YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  return(pf->once != NULL);
}



dbx_type *dbx_field_type YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  assertp(pf->field_dual);
  return(pf->field_dual);
}

unsigned field_level YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  return(pf->level);
}

dbx_field *next_field YPARAMS2(dbx_field *,  pf) /* _of_class */
{
  assertp(pf);
  return(pf->next);
}

dbx_field *prev_field YPARAMS2(dbx_field *,  pf) /* _of_class */
{
  assertp(pf);
  return(pf->prev);
}

dbx_class *field_class YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  assertp(pf->dual);
  return type_class(pf->dual);
}
  
VOID *field_data YPARAMS2(dbx_field *,  pf)
{
  assertp(pf);
  assertp(pf->once);
  return (pf->once);
}

/* obtain the address of a data item in an object */
/* is is necessary to distinguate between once fields */
/* and not once fields;for the former the address is unique */
/* and is stored in the data field of the dbx_field structure */
/* in this case the offset is not significant */
/* for the latter the address is computed with the (base) address */
/* of the object and the offset,and data is not significant */

VOID *get_fdata YPARAMS4(dbx_field *,  pf,
                        obj_ptr ,     po)
{
  assertp(pf);
  assertp(po);
  if (once_field(pf))
    return (pf->once);
  else
    return ((char *)po+pf->offset);
}			

dbx_field *find_next_field YPARAMS4(dbx_field *,  pf,
                                   char *,      pattern)
{
  dbx_field *pfie = NULL;
  while (pf)
  {
    if (dbx_match(field_name(pf),pattern))
    {
      pfie = pf;
      pf = NULL;
    }
    else
    {
      pf = next_field(pf);
    }
  }
  return pfie;
}

dbx_field *find_prev_field YPARAMS4(dbx_field *,  pf,
                                   char *,      pattern)
{
  dbx_field *pfie = NULL;
  while (pf)
  {
    if (dbx_match(field_name(pf),pattern))
    {
      pfie = pf;
      pf = NULL;
    }
    else
    {
      pf = prev_field(pf);
    }
  }
  return pfie;
}


