#ifndef BASTARD_EXTENSION_H
#define BASTARD_EXTENSION_H
#include <dirent.h>
#include <bdb.h>

/* EXTENSION FLAGS */

/* methods */
#define EXT_METHOD_MASK 0xF000
#define EXT_BC          0x1000
#define EXT_SO          0x2000
/* status */
#define EXT_STATUS_MASK 0x0F00
#define EXT_OPEN        0x0100
#define EXT_INIT        0x0200
#define EXT_CLEANUP     0x0300
#define EXT_CLOSED      0x0400
/* types */
#define EXT_TYPE_MASK   0x00FF
#define EXT_PLUGIN      0x0001
#define EXT_ENGINE      0x0002
#define EXT_ARCH        0x0003
#define EXT_ASM         0x0004 
#define EXT_FORMAT      0x0005
#define EXT_LANG        0x0006



typedef void (*ext_init_fn)(void *);
typedef void (*ext_clean_fn)(void);
struct EXTENSION {
   char *filename;      /* name of extension file [full path] */
   int flags;           /* uhh..... */
   void *lib;           /* pointer to library */
   ext_init_fn fn_init;       /* init function for extension */
   ext_clean_fn fn_cleanup;    /* cleanup function for extension */
}; /* these are linked to from standard extensions : hll, engine, etc */

typedef int (*plugin_fn)(void *);
struct EXT__PLUGIN {
   struct EXTENSION ext;
   int options;
   plugin_fn fn_main;
} *ext_plugin;

typedef int (*engine_fn)(void *);
struct EXT__ENGINE {
   struct EXTENSION ext;
   int options;
   engine_fn fn_main;
} *ext_engine;

/* predef 's for use with dynamic loading */
typedef int (*disfunc_fn)(unsigned char *, unsigned char, struct code *, long);
typedef int (*getcode_fn)(struct code **);
typedef int (*geneffect_fn)(char *, struct code_effect *e);
typedef int (*genint_fn)(int);
struct EXT__ARCH {   /* disassembler information */
   struct EXTENSION ext;
   //char name[PATH_MAX];      // name of disassembler lib [lib(target.cpu).so]
   int options;             // module-specific options
   /* ------------------  CPU Information  -------------------- */
   int cpu_hi, cpu_lo;      // CPU high and low version numbers
   char endian;             // 0 = BIG, 1 = LITTLE
   char sz_addr;            // Default Size of Address in Bytes
   char sz_oper;            // Default Size of Operand in Bytes
   char sz_inst;            // Default Size of Instruction in Bytes
   char sz_byte;            // Size of Machine Byte in Bits
   char sz_word;            // Size of Machine Word in Bytes
   char sz_dword;           // Size of Machine DoubleWord in Bytes
   int SP;                  // RegID of Stack Pointer
   int IP;                  // RegID of Instruction Pointer
   int reg_gen;             // start of General regs in table
   int reg_seg, reg_fp;     // start of seg, FPU regs in table
   int reg_in, reg_out;     // start of procedure IN, OUT regs in table
   /* ------------------ Register Tables ---------------------- */
   //char **StringRegs;   //  Registers used for strings
   //int StringRegsLen;   // # of entries in StringRegs table
   struct REGTBL_ENTRY *reg_table;
   int sz_regtable;
   unsigned char *reg_storage;
   /* ------------------ Library Functions -------------------- */
   disfunc_fn   fn_disasm_addr;      // ptr to disassembly routine
   getcode_fn   fn_get_prologue;   // WARNING From here down are considered   
   getcode_fn   fn_get_epilogue;   //         "optional"  
   geneffect_fn fn_gen_effect;
   genint_fn    fn_gen_int;
} *ext_arch;


typedef int (*sprintaddrexp_fn)(char *, int, char *, char *, char *, char *, int);
typedef int (*sprintcode_fn)(long, char *, int, int);
typedef int (*sprintsec_fn)(char *, int, char *);
typedef int (*sprintfunc_fn)(char *, int, int);
typedef int (*sprintstruct_fn)(char *, int, long);
typedef int (*genasmfile_fn)(char *);
struct EXT__ASM {             /* target assembler */
   struct EXTENSION ext;
   /* settings */
   char *comment;          /* comment character/string */
   char *reg_pre;          /* register prefix string */
   char *imm_pre;          /* immediate value prefix string */
   char *local_pre;        /* local label value prefix string */
   /* format strings */
   char *asm_ttyColor;         /* assume 80 col, use coor escape seq's */
   char *asm_ttyMono;          /* assume 80 col, no escape seq's */
   char *asm_file;             /* no line length */
   char *asm_lpr;              /* no line length */
   char *data_ttyColor;        /* assume 80 col, use coor escape seq's */
   char *data_ttyMono;         /* assume 80 col, no escape seq's */
   char *data_file;            /* no line length */
   char *data_lpr;             /* no line length */
   /* function pointers */
   sprintcode_fn      fn_sprint_code;  /* fix reg, addr, mnems */
   sprintaddrexp_fn   fn_sprint_addrexp;  /* sprint the address expression */
   sprintfunc_fn      fn_sprint_func_s;
   sprintfunc_fn      fn_sprint_func_e;
   sprintstruct_fn    fn_sprint_struct;
   sprintsec_fn       fn_sprint_sec_s;      /* declare section */
   sprintsec_fn       fn_sprint_sec_e;      /* declare section */
   genasmfile_fn      fn_gen_file;
} *ext_asm;

typedef int (*datatype_fn)(int);
typedef int (*findstr_fn)(char *, int, int *, char*, int, int);
typedef int (*makestr_fn)(char *, char *, int, int);
typedef int (*sprint_fn)(char *, int, int);
typedef int (*genfinal_fn)(int);
typedef int (*genhllfile_fn)(char *);

struct EXT__LANG {            /* target HighLevelLanguage */
   struct EXTENSION ext;
   /* default data types  -- these map to IDs in ths DB */
   int u1, s1;          /* unsigned/signed 1-byte */
   int u2, s2;          /* unsigned/signed 2-byte */
   int u4, s4;          /* unsigned/signed 4-byte */
   int u8, s8;          /* unsigned/signed 8-byte */
   /* function pointers */
   void *fn_parsehdr;   /* process header for constants, fn protos, etc */
   findstr_fn fn_findstr;
   datatype_fn fn_datatype;
   makestr_fn fn_makestr;
   sprint_fn fn_sprint_proto;
   sprint_fn fn_sprint_func;
   genfinal_fn fn_gen_final;
   genhllfile_fn fn_gen_file;
} *ext_lang;

typedef int (*readhdr_fn)(void);
struct EXT__FORMAT {
   struct EXTENSION ext;
   readhdr_fn fn_read_header;
} *ext_format;



/* EXTENSION ROUTINES */
void InitExtensions();
void CleanupExtensions();
int LoadExtension( int type, char * filename, void *param);
int GetExtensionFlags( int type );
int UnloadExtension( int type );



/* EXTENSION .bc WRAPPERS */
/* these enable functions in .bc scripts to be called in place of .so libs */
int plugin_main_stub(void *plugin_arg) ;
int engine_main_stub(void *engine_arg) ;
int read_header_stub(void);
void arch_init_stub(void *param);
void arch_cleanup_stub(void);
int disasm_addr_stub(unsigned char *c, unsigned char n, struct code *inst, long rva);
int get_prologue_stub(struct code **table);
int get_epilogue_stub(struct code **table);
int gen_effect_stub(char *mnemonic, struct code_effect *e);
int gen_int_stub(int func_id);
void asm_init_stub(void *param);
void asm_cleanup_stub(void);
int sprint_code_stub(long rva, char *buf, int len, int output);
int sprint_func_start_stub( char *str, int len, int func_id);
int sprint_func_end_stub( char *str, int len, int func_id);
int sprint_struct_stub(char *str, int len, long rva);
int sprint_section_start_stub(char *str, int len, char *name);
int sprint_section_end_stub(char *str, int len, char *name);
int gen_asmfile_stub( char *path );
int sprint_addrexp_stub(char *str, int len, char *scale, char *index, 
                        char *base, char *disp, int sign);
void lang_init_stub(void *param);
void lang_cleanup_stub(void);
int findstr_stub(char *buf, char *text, int text_len, int type);
int datatype_stub(int mach_word);
int findstr_stub(char *buf, char *text, int text_len, int type);
int makestr_stub(char *buf, int len, int *pos, char *text, int text_len,int type);
int sprint_proto_stub(char *buf, int len, int func_id);
int sprint_func_stub(char *buf, int len, int func_id);
int gen_final_stub(int func_id);
int gen_hllfile_stub( char *path);

/* Safe wrappers for EXTENSION fn's -- these check for NULL fn pointers */
int ext_plugin_main(void *param);
int ext_engine_main(void *param);
int ext_disasm_addr(char *buf, char tbl, struct code *c, long rva);
int ext_get_prologue(struct code **table);
int ext_get_epilogue(struct code **table);
int ext_gen_effect(char *mnemonic, struct code_effect *e);
int ext_gen_int(int func_id);
int ext_add_data_types(int mach_word);
int ext_findstr(char *buf, int len, int *pos, char *text, int text_len, int type) ;
int ext_makestr(char *buf, char *text, int text_len, int type);
int ext_sprint_hll_proto(char *buf, int len, int func_id);
int ext_sprint_hll_func(char *buf, int len, int func_id);
int ext_gen_final(int func_id);
int ext_gen_hll_file(char *path);
int ext_read_header(void);
int ext_sprint_code(long rva, char *line, int len, int output);
int ext_sprint_addrexp(char *str, int len, char *scale, char *index,
                             char *base, char *disp, int sign);
int ext_sprint_asm_func_start(char *str, int len, int func_id);
int ext_sprint_asm_func_end(char *str, int len, int func_id);
int ext_sprint_asm_struct(char *str, int len, long rva);
int ext_sprint_sec_end(char *str, int len, char *name);
int ext_sprint_sec_start(char *str, int len, char *name);
int ext_gen_asm_file(char *path);
   

#endif
