#include <stdio.h>
#include <stdlib.h>
#include <string.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_brea.h"
#include "dbx_list.h"

dbx_list *break_list = NULL; /* visible outside */

dbx_breakpoint *current_breakpoint YPARAMS0
{
  if (current_elem(break_list))
    return(elem_info(current_elem(break_list)));
  else
    return NULL;
}

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

void dispose_breakpoint YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  free(pb->string);
  free(pb);
}
  
dbx_method *breakpoint_method YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (pb->method);
}

dbx_class *breakpoint_class YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (method_class(breakpoint_method(pb)));
}

dbx_module *breakpoint_module YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (class_module(breakpoint_class(pb)));
}
  
unsigned breakpoint_line YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (pb->line);
}

unsigned breakpoint_counter YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (pb->counter);
}

unsigned breakpoint_step YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (pb->step);
}

int breakpoint_action YPARAMS2(dbx_breakpoint *,  pb)
{
  return (pb->action);
}

char *breakpoint_string YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  return (pb->string);
}

void inc_counter YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  (pb->counter)++;
}

void reset_counter YPARAMS2(dbx_breakpoint *,  pb)
{
  assertp(pb);
  pb->counter = 0;
}

int breakpoint_evaluate YPARAMS2(dbx_breakpoint *, pb)
{
  assertp(pb);
  return ((pb->counter % pb->step) == 0);
}

dbx_elem *find_belem YPARAMS4(dbx_method *,  pm,
                             unsigned,  line)
{
   dbx_elem *pe;
   dbx_elem *pele = NULL;
   dbx_breakpoint *pb;
   pe = first_elem(break_list);
   while (pe)
   {
     pb = elem_info(pe);
     if ((breakpoint_method(pb) == pm)&&(breakpoint_line(pb) == line))
     {
       pele = pe;
       pe = NULL;
     }
     else
        pe = next_elem(pe);
   }
   return pele;
}

void add_breakpoint YPARAMS10(dbx_method *,  pm,
                             unsigned,  line,
                   			     unsigned,  step,
			                       int,       action,
			                       char *,    string)
{
  dbx_breakpoint *pb;
  pb = new_breakpoint();
  pb->method = pm;
  pb->line = line;
  pb->action = action;
  pb->counter = 0;
  pb->step = step;
  pb->string = string;
  insert(break_list,last_elem(break_list),NULL,pb);
  inc_bp_count(pm); /* don't forget to update the count or else it won't work */
}

void sub_breakpoint YPARAMS4(dbx_method *,  pm,
                            unsigned,  line)			    			    
{
  dbx_breakpoint *pb;
  dbx_elem *pe;
  pe = find_belem(pm,line);
  pb = suppress(break_list,pe);
  dispose_breakpoint(pb);
  dec_bp_count(pm); /* don't forget to update the count or else it won't work */
}
  
void sub2_breakpoint YPARAMS2(unsigned,  number)
{
  dbx_breakpoint *pb;
  dbx_elem *pe;
  pe = nth_elem(break_list,number);
  pb = suppress(break_list,pe);
  dec_bp_count(breakpoint_method(pb));
  dispose_breakpoint(pb);
}				

dbx_breakpoint *find_breakpoint YPARAMS4(dbx_method *,  pm,
                                        unsigned,  line)
{
  dbx_elem *pe;
  pe = find_belem(pm,line);
  if (pe)
    return elem_info(pe);
  else
    return NULL;
}

dbx_breakpoint *find2_breakpoint YPARAMS2(unsigned,  n)
{
  dbx_elem *pe;
  pe = nth_elem(break_list,n);
  if (pe)
    return elem_info(pe);
  else
    return NULL;
}

int search_breakpoint YPARAMS4(dbx_module *,  pm,
                              unsigned,  line)
{
  dbx_elem *pe;
  dbx_breakpoint *pb;
  pe = first_elem(break_list);
  while (pe)
  {
    pb = elem_info(pe);
    if ((breakpoint_module(pb)==pm)&&(breakpoint_line(pb)==line))
      return 1;
    pe = next_elem(pe);
  }
  return 0;
}  
			      								
void init_dbx_brea YPARAMS0
{
  break_list = new_list();
}

void term_dbx_brea YPARAMS0
{
}
