//						XREF.CPP

#include <windows.h>

#include "xref.h"
#include "disasm.h"
#include "textout.h"
#include "dasm.h"

xref::xref(void)
{ listtop=new struct xreflist;
  listtop->where=0;
  listtop->ref_by=0;
  listtop->reftype=XREF_NULL;
  listtop->decoded=TRUE;
  listtop->next=new struct xreflist;
  listtop->next->where=0xffffffff;
  listtop->next->ref_by=0xffffffff;
  listtop->next->reftype=XREF_NULL;
  listtop->next->decoded=TRUE;
  listtop->next->next=NULL;
  lastxref=listtop;
  addedxref=FALSE;
  printref=listtop;
}

xref::~xref(void)
{ struct xreflist *xr2;
  while(listtop!=NULL)
  { xr2=listtop->next;
	 delete listtop;
    listtop=xr2;
  }
}

void xref::addxref(unsigned long where,unsigned long ref_by,unsigned char reftype)
{ struct xreflist *addit,*prev;
  if(!where)return;
  addit=listtop;
  while((where>addit->where)||((where==addit->where)&&(ref_by>addit->ref_by)))
  { prev=addit;
	 addit=addit->next;
  }
  if((where==addit->where)&&(ref_by==addit->ref_by))return;
  prev->next=new struct xreflist;
  prev->next->next=addit;
  addit=prev->next;
  addedxref=TRUE;
  addit->where=where;
  addit->ref_by=ref_by;
  addit->reftype=reftype;
  addit->decoded=FALSE;
  if(prev->where==addit->where)addit->decoded=prev->decoded;
  if(addit->where==addit->next->where)addit->decoded=addit->next->decoded;
  lastxref=addit;
}

void xref::printxref(unsigned long where)
{ struct xreflist *listptr;
  int numprinted;
  BOOL startpt;
  startpt=FALSE;
  listptr=printref;
  numprinted=0;
  while(listptr->where<where)listptr=listptr->next;
  while(listptr->where==where)
  { if(listptr->reftype==XREF_START)
	 { startpt=TRUE;
	 }
	 else if(listptr->reftype!=XREF_EXPORT)
	 { if(!numprinted)
		{ PrintBuff(";");
		  LastPrintBuffEpos(60);
		  LastPrintBuff("XREF:");
		}
		if(disassemble.mode32)LastPrintBuff("%lx ",listptr->ref_by);
		else LastPrintBuff("seg%03lx:%lx ",listptr->ref_by>>16,listptr->ref_by&0xffff);
		numprinted++;
		if(numprinted==5)numprinted=0;
	 }
	 listptr=listptr->next;
  }
  printref=listptr;
  if(startpt)
  { if(disassemble.mode32)PrintBuff("%lx start:",where);
	 else PrintBuff("seg%03lx:%lx start:",where>>16,where&0xffff);
  }
}

unsigned long xref::nextcode(void)
{ struct xreflist *listptr,*nxtptr;
  if(!addedxref)return 0;
  listptr=lastxref;
  while(listptr!=NULL)
  { if((!listptr->decoded)&&(listptr->reftype!=XREF_DATA))
	 { listptr->decoded=TRUE;
		nxtptr=listptr->next;
		while(nxtptr!=NULL)
		{ if(nxtptr->where==listptr->where)nxtptr->decoded=TRUE;
		  if(nxtptr->where>listptr->where)break;
		  nxtptr=nxtptr->next;
		}
		lastxref=listptr;
		return listptr->where;
	 }
	 listptr=listptr->next;
  }
  listptr=listtop;
  while(listptr!=NULL)
  { if((!listptr->decoded)&&(listptr->reftype!=XREF_DATA))
	 { listptr->decoded=TRUE;
		nxtptr=listptr->next;
		while(nxtptr!=NULL)
		{ if(nxtptr->where==listptr->where)nxtptr->decoded=TRUE;
		  if(nxtptr->where>listptr->where)break;
		  nxtptr=nxtptr->next;
		}
		lastxref=listptr;
		return listptr->where;
	 }
	 listptr=listptr->next;
  }
  addedxref=FALSE;
  return 0;
}

void xref::reset(void)
{ struct xreflist *listptr;
  listptr=listtop->next;
  while(listptr->reftype!=XREF_NULL)
  { listptr->decoded=FALSE;
	 listptr=listptr->next;
  }
}

unsigned long xref::getref(unsigned long addr)
{ struct xreflist *listptr;
  listptr=lastxref;
  while(listptr!=NULL)
  { if((!listptr->decoded)&&(listptr->where==addr)&&(listptr->ref_by))
	 { listptr->decoded=TRUE;
		lastxref=listptr;
		return listptr->ref_by;
	 }
	 listptr=listptr->next;
  }
  listptr=listtop;
  while(listptr!=NULL)
  { if((!listptr->decoded)&&(listptr->where==addr)&&(listptr->ref_by))
	 { listptr->decoded=TRUE;
		lastxref=listptr;
		return listptr->ref_by;
	 }
	 listptr=listptr->next;
  }
  return 0;
}
