+typedef signed char s8;
+typedef uint16_t u16;
+typedef int16_t s16;
+typedef uint32_t u32;
+typedef int32_t s32;
+typedef uint64_t u64;
+typedef int64_t s64;
+
+
+#define MAX_STRING_LEN 100
+#define MAX_INSTRUCTION_LEN 40
+
+typedef struct _instruction {
+ int offsetInFile;
+ int offsetInCode;
+
+ u8 bytes[MAX_INSTRUCTION_LEN];
+ int bytePos;
+
+ char string[MAX_STRING_LEN];
+ int stringPos;
+
+ int isJump;
+ int jumpAddress;
+
+ int isCall;
+ int callAddress;
+
+ int isCallTarget;
+ int isJumpTarget;
+
+ int callLabel;
+ int jumpLabel;
+
+ struct _instruction *next;
+} instruction;
+
+typedef struct _statistics {
+ int maxInstructionLen;
+} statistics;
+
+static instruction* instruction_new(int offsetInFile, int offsetInCode) {
+ instruction *inst = malloc(sizeof(instruction));
+ assert(inst != NULL);
+
+ memset(inst, 0, sizeof(instruction));
+
+ inst->offsetInFile = offsetInFile;
+ inst->offsetInCode = offsetInCode;
+
+ return inst;
+}
+
+static void instruction_print(instruction *inst, const char *c) {
+ int len = strlen(c);
+ assert((inst->stringPos+len) < MAX_STRING_LEN);
+ for (int i=0; i<len; i++)
+ inst->string[inst->stringPos++] = c[i];
+}
+
+static void instruction_push_byte(instruction *inst, u8 byte) {
+ assert((inst->bytePos+1) < MAX_INSTRUCTION_LEN);
+ inst->bytes[inst->bytePos++] = byte;
+}
+
+static instruction *first_instruction;
+static instruction *current_instruction;
+static int current_call_label=0;
+static int current_jump_label=0;
+static statistics stat;
+static int entry_point;
+
+
+/*
+ * BEGIN - interface functions
+ */
+static void i_begin(int offsetInFile, int offsetInCode) {
+ if (first_instruction == NULL) {
+ first_instruction = current_instruction = instruction_new(offsetInFile, offsetInCode);
+ } else {
+ assert(current_instruction->next == 0);
+ current_instruction->next = instruction_new(offsetInFile, offsetInCode);
+ current_instruction = current_instruction->next;
+ }
+}
+
+static void i_print(const char *fmt, ...) {
+ assert(current_instruction != NULL);
+
+ va_list args;
+ char str[MAX_STRING_LEN];
+
+ memset(str, 0, MAX_STRING_LEN);
+
+ va_start(args, fmt);
+ vsprintf(str, fmt, args);
+ instruction_print(current_instruction, str);
+ va_end(args);
+}
+
+static u8 i_push(u8 byte) {
+ assert(current_instruction != NULL);
+ instruction_push_byte(current_instruction, byte);
+ return byte;
+}
+
+static void i_set_relative_call(int relAddr) {
+ current_instruction->isCall=1;
+ current_instruction->callAddress = current_instruction->offsetInCode + current_instruction->bytePos + relAddr;
+ /*i_print("[call to 0x%08x] ", current_instruction->callAddress);*/
+}
+
+static void i_set_relative_jmp(int relAddr) {
+ current_instruction->isJump=1;
+ // FIXME: is this correct ?
+ current_instruction->jumpAddress = current_instruction->offsetInCode + current_instruction->bytePos + relAddr;
+ /*current_instruction->jumpAddress = current_instruction->offsetInCode + relAddr;*/
+ /*i_print("[jump to 0x%08x] ", current_instruction->jumpAddress);*/
+}
+
+static int i_get_jump_label(int absoluteCodeOffset) {
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->offsetInCode == absoluteCodeOffset && i->isJumpTarget)
+ return i->jumpLabel;
+ i = i->next;
+ }
+ return -1;
+}
+static int i_get_call_label(int absoluteCodeOffset) {
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->offsetInCode == absoluteCodeOffset && i->isCallTarget)
+ return i->callLabel;
+ i = i->next;
+ }
+ return -1;
+}
+
+static void i_dump() {
+ int k;
+
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->offsetInCode == entry_point)
+ printf("\n\nENTRY_POINT:\n");
+ if (i->isCallTarget)
+ printf("\n\nfunction%d:\n", i->callLabel);
+ if (i->isJumpTarget)
+ printf("label%d: \n", i->jumpLabel);
+
+ printf("\t0x%08x:", i->offsetInCode);
+ for (k=0; k<stat.maxInstructionLen; k++) {
+ if (k<i->bytePos)
+ printf(" %02x", i->bytes[k]);
+ else
+ printf(" ");
+ }
+ if (i->isCall)
+ printf(" %s [call function%d]\n", i->string, i_get_call_label(i->callAddress));
+ else if (i->isJump)
+ printf(" %s [jump label%d]\n", i->string, i_get_jump_label(i->jumpAddress));
+ else
+ printf(" %s\n", i->string);
+ i = i->next;
+ }
+}
+
+static void i_mark_jump_target(int absoluteCodeOffset) {
+ // search in list for address and set isJumpTarget = true
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->offsetInCode == absoluteCodeOffset) {
+ i->isJumpTarget++;
+ return;
+ }
+ i = i->next;
+ }
+ assert(0);
+}
+static void i_mark_call_target(int absoluteCodeOffset) {
+ // search in list for address and set isCallTarget = true
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->offsetInCode == absoluteCodeOffset) {
+ i->isCallTarget++;
+ return;
+ }
+ i = i->next;
+ }
+ assert(0);
+}
+
+static void i_mark_jump_targets() {
+ // search the whole list for jumps and call
+ // i_mark_jump_target() for every of them
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->isJump)
+ i_mark_jump_target(i->jumpAddress);
+ i = i->next;
+ }
+}
+
+static void i_mark_call_targets() {
+ // search the whole list for calls and call
+ // i_mark_call_target() for every of them
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->isCall)
+ i_mark_call_target(i->callAddress);
+ i = i->next;
+ }
+}
+
+static void i_enumerate_jump_targets() {
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->isJumpTarget)
+ i->jumpLabel = current_jump_label++;
+ i = i->next;
+ }
+}
+
+static void i_enumerate_call_targets() {
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->isCallTarget)
+ i->callLabel = current_call_label++;
+ i = i->next;
+ }
+}
+
+static void i_make_statistics() {
+ instruction *i = first_instruction;
+ while (i != NULL) {
+ if (i->bytePos > stat.maxInstructionLen) {
+ stat.maxInstructionLen = i->bytePos;
+ }
+ i = i->next;
+ }
+}
+
+static void i_end() {
+ i_mark_jump_targets();
+ i_mark_call_targets();
+
+ i_enumerate_jump_targets();
+ i_enumerate_call_targets();
+
+ i_make_statistics();
+}
+
+static void i_cleanup() {
+ instruction *current_inst = first_instruction;
+ instruction *next;
+
+ first_instruction = NULL;
+ while (current_inst != NULL) {
+ next = current_inst->next;
+ free(current_inst);
+ current_inst = next;
+ }
+}
+
+/*
+ * END - interface functions
+ */