#include ".\print_tree.h"
#include "globals.h"

print_tree::print_tree(void)
{
	_printed.clear();
}

print_tree::~print_tree(void)
{
}
void print_tree::do_it(x86_insn_t *ins)
{
	char line[4096];
	x86_format_insn(ins, line, 4096, intel_syntax);
	printf("[%X] %s\n",ins->addr,line);
}
void print_tree::do_it2(instruction *ins)
{
	
}

void print_tree::init()
{
	_printed.clear();
}


void print_tree::print(long offset)
{
	print(offset,0);
}

void print_tree::print(long offset,instruction *ins_o)
{
    x86_insn_t * insn;
	instruction *ins,*ins_old;
	ins_old=ins_o;
	
	ins=globals::instance()._map[offset];
	if(!ins)
		return;

	insn=ins->insn();
	if(!insn)
		return;

	
	if(rejected(ins,ins_old))
			return;

	_printed[offset]=1;
	this->do_it(insn);
	this->do_it2(ins);

	for(;;)
	{
		if(!ins->next && !ins->next_flow)
			break;
		ins_old = ins;
		
		//Un call ou un jcc
		if ( ins->next_flow && ins->next ) 
		{
			print(ins->next,ins_old);
			//ins_old=0;
			ins=globals::instance()._map[ins->next_flow];
		}
		else
		{
			// Normal
			if(ins->next)
				ins=globals::instance()._map[ins->next];
			else
				if(ins->next_flow) //Jmp par exemple.
					ins=globals::instance()._map[ins->next_flow];
		}
		if(!ins)
			break;

		
		insn=ins->insn();
		if(rejected(ins,ins_old))
			break;
		
		_printed[insn->offset]=1;
		this->do_it(insn);
		this->do_it2(ins);
	}
}

bool print_tree::rejected(instruction *ins,instruction *ins2)
{
	x86_insn_t * insn;
	insn=ins->insn();
	if(_printed[insn->offset])
	{
			return true;
	}
	return false;
}