#define IAMTHEBASTARD
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
/* 3rd-party add-ins */
#ifndef NO_LIBOPCODES
	#include <dis-asm.h>
	#include <bfd.h>
#endif
#include <typhoon.h>
#include <seer.h>
/* bastard includes */
#include <api.h>
#include <bdb.h>
#include <db.h>
#include <dislib.h>
#include <macro.h>

/* bastard definitions */
#undef  FALSE
#define FALSE 0
#undef  TRUE
#define TRUE 1


/* bastard environment :  flags */
/*      Current state of target */
#define DB_LOADED	   	0x00000001			/* .bdb loaded */
#define TGT_MAPPED		0x00000002			/* target bin image mmap'ed */
#define DB_MOD		   	0x00000004			/* .bdb has been modified */
#define TGT MOD 	   	0x00000008			/* target bin image modified */
/*      Current state of disassembly */
#define PASS_1				0x00000010			/* main disassembly pass */
#define PASS_2				0x00000020			/* subsequent passes */
#define CODE_INT			0x00000040			/* intermediate code rep is done */
#define CODE_FIN			0x00000080			/* final code rep is done */
/*      User convenience */
#define PAGINATE			0x00000100
/*      User inconvenience ;) */
#define QUIET				0x00001000	/* print std msgs to STDOUT */
#define ANNOY_USER		0x00002000	/* bug user with save prompts, etc */
/*      Safety stuff */
#define DISABLE_EXEC		0x00010000	/* do not allow shell escapes */
#define DEBUG_LIB			0x00020000  /* use SeeR debugging */

/* global variables */
struct DISASM_ENV {
		char	home[128]; /* bastard dir info */
		char	p1[16];	/* main prompt */
		char	p2[16];  /* multiline prompt */
		char	p3[16];	/* 'other' prompt */
		char	p4[16];	/* help system prompt */
		char *ttyFmt;  /* asmsprintf format string for printing to screen */
		char *asmFmt;  /* asmsprintf format string for printing to .asm file */
		char *lprFmt;  /* asmsprintf format string for printing to printer */
		int 	flags;
} disasm_env;

struct DISASM_TGT {   /* target information */
		int 	FD;					// fd to .bdb image of target
		caddr_t	image;			// memory mapped image of target
		size_t	size;				// size of target
		long	entry;				// entrypoint
		char 	cpu[32];				// CPU type [./arch/lib*.so]
		char	format[32];			// file format [./formats/*.sc]
		char	*header;				// string containing formatted file header
		char	name[64];			// name of target
		char	path[PATH_MAX];	// location of target
		char	dbname[PATH_MAX];	// path+name of .bdb for target
} target;


struct DISASM_ENG {   /* disassembler information */
		bool init;					// must set to '0' when a file is unloaded
		char path[PATH_MAX];		// path to disassembler library
		char name[PATH_MAX];		// name of disassembler lib [lib(target.cpu).so]
		void * lib;					// handle to loaded library
		/* ------------------ Library Functions -------------------- */
		disinit disasm_init;		// ptr to init routine
		disfunc disasm_addr;		// ptr to disassembly routine
		getcode get_prologue;   // WARNING From here down are considered	
		getcode get_epilogue;   //         "optional" and no errors are 
		getsz   get_endian;     //         reported  if they fail to load.
		getsz   get_addrsize;   //         ALWAYS check these pointers vs NULL
		getsz   get_byte;			//         before invoking!!!
		getsz   get_word;
		getsz   get_dword;
		getreg  get_SP;
		getreg  get_IP;
} disasm_eng;


#ifndef NO_LIBOPCODES
/* for use with libopcodes */
extern int print_insn_i386_intel      PARAMS ((bfd_vma, disassemble_info*));
disassembler_ftype disassemble_fn;
disassemble_info target_info;
#endif

struct code *curr_inst;

/* Vars which are global for cleanup purposes */
char *cmd; 
FILE *oldIN, *oldOUT, *oldERR;


/* note: later, to support multiple targets, the target info may become a
 * linked list of target structures */

/* bastard/interpreter prototypes */
int TranslateCmd( char* cmd) ;
void ReadPrefs( char* filename);
int main (int argc, char* argv[]);


/* Error numbers:
 * 70 -- file format errors
 * 90 -- file/IO errors
 * 100 -- SeerC errors
 * 200 + db_status  -- Typhoon Errors
 * 300 -- Section errors
 * 400
 * 500
 * 600 -- Disassembler errors
 */

/* default settings */
static char defaultFmt[] = "%n%:%^%a %8b\t%m\t%d%, %s%;%c %x";
