#include <sys/types.h>
#include "tc-i386.h"
#include <a.out.h>

/* variable to access to the symbol table */
extern size_t nsymbols;			/* number of symbols */
extern struct nlist *symbols;		/* symbol table */
extern char *string_table;		/* string table */
extern unsigned long string_table_size;	/* size of the string table */
extern struct exec header;		/* header structure */
extern unsigned char *text_seg;		/* raw text segment */
extern unsigned int text_len;		/* len of the text segment */
extern unsigned int treloc_len;
extern struct relocation_info *treloc_table;
extern u_char *text_bm;
extern u_int text_decoded;
extern int dis_res;
extern u_int func_align;

#define CHAR_BIT 8
#define NBR_CHAR (1 << CHAR_BIT)

struct discrib
{
 union
 {
  template const *onebyte;
  template const *group[8];
  template const *fgroup[72];	/* special case for Fpinst. 72 is 64 + 8 */
  template **grp;
 } info;
 enum TType { TUnknown, Prefix, OneByte, TwoByte, Extend, FPint, TGroup} type;
};

extern struct discrib instr[NBR_CHAR];
extern struct discrib extend_instr[NBR_CHAR];

void init_instr_table();
int load_symbol_table(char *prog_path);
void first_process();

struct TSym 
{ 
  unsigned int addr; 
  int gcc; 
  int sym;
};
extern struct TSym *text_sym;
extern unsigned int nbr_text_sym;

struct Soffset
{
  u_int old_offset;
  u_int new_offset;
  u_int len;
};
void new_offset(u_int old_off, u_int new_off, u_int len);

struct relocation_info* search_reloc(u_int offset);

void init_sym_gen();
void init_text_bm();
void show_text_bm();
void save_text_bm();
void restore_text_bm();

#define TBM_UNKNOWN 0x00
#define TBM_LIT     0x01
#define TBM_INSTR   0x04
#define TBM_ENTRY   0x05
#define TBM_ENDING  0x06
#define TBM_NOOP    0x07
#define TBM_RELOC   0x20
#define TBM_SYM     0x40
#define TBM_ALIGN   0x80

#define T_ERROR  0
#define T_CONDBR 1
#define T_CALL   2
#define T_JUMP   3
#define T_NOBR   4
#define T_RET    5

struct dis_info
{
  u_int length;
  u_int offset;
  u_int type;
  u_int address;	/* valid if T_JMP, T_CALL, or T_CONDBR */
};

void disassemble(struct dis_info *info);

extern int verbose;