From ca87b3c5e9258053f839bd2e8040c9f51acfd5ce Mon Sep 17 00:00:00 2001 From: Joseph Kogut Date: Sun, 28 Aug 2016 20:31:12 -0700 Subject: [PATCH] Refactor with a consistent coding style This commit refactors the project using a single, consistent coding style, derived from the Linux Kernel Coding Style, available here: https://www.kernel.org/doc/Documentation/CodingStyle This includes, but is not limited to: * Removal of typedefs, especially for structs * Limiting lines to a reasonable length, 80 characters, mostly * K&R style braces * Removal of CamelCase --- include/tvm/tvm.h | 89 +++++++---- include/tvm/tvm_htab.h | 27 ++-- include/tvm/tvm_lexer.h | 12 +- include/tvm/tvm_memory.h | 31 ++-- include/tvm/tvm_parser.h | 9 +- include/tvm/tvm_preprocessor.h | 2 +- include/tvm/tvm_program.h | 25 ++- include/tvm/tvm_stack.h | 9 +- include/tvm/tvm_tokens.h | 24 +++ libtvm/tvm.c | 84 ++++++++-- libtvm/tvm_file.c | 30 ++-- libtvm/tvm_htab.c | 127 ++++++++------- libtvm/tvm_lexer.c | 57 +++---- libtvm/tvm_memory.c | 9 +- libtvm/tvm_parser.c | 281 +++++++++++++++++++++------------ libtvm/tvm_preprocessor.c | 222 +++++++++++++++----------- libtvm/tvm_program.c | 70 ++------ src/tvmi.c | 10 +- tdb/main.c | 6 +- tdb/tdb.c | 27 ++-- tdb/tdb.h | 6 +- tdb/tdb_breakpoint.h | 4 +- 22 files changed, 670 insertions(+), 491 deletions(-) create mode 100644 include/tvm/tvm_tokens.h diff --git a/include/tvm/tvm.h b/include/tvm/tvm.h index 9f69e76..adc6ce8 100644 --- a/include/tvm/tvm.h +++ b/include/tvm/tvm.h @@ -3,60 +3,83 @@ #include +#include "tvm_file.h" +#include "tvm_preprocessor.h" +#include "tvm_stack.h" + #include "tvm_memory.h" #include "tvm_program.h" -#include "tvm_stack.h" -#include "tvm_parser.h" +#include "tvm_tokens.h" -typedef struct tvm_s +struct tvm_ctx { + struct tvm_prog *prog; + struct tvm_mem *mem; +}; + +struct tvm_ctx *tvm_vm_create(); +void tvm_vm_destroy(struct tvm_ctx *vm); + +int tvm_vm_interpret(struct tvm_ctx *vm, char *filename); +void tvm_vm_run(struct tvm_ctx *vm); + +static inline void tvm_step(struct tvm_ctx *vm, int *instr_idx) { - tvm_program_t *pProgram; - tvm_memory_t *pMemory; -} tvm_t; + int *arg0 = vm->prog->args[*instr_idx][0], + *arg1 = vm->prog->args[*instr_idx][1]; -tvm_t *tvm_create(); -void tvm_destroy(tvm_t *vm); - -int tvm_interpret(tvm_t *vm, char *filename); -void tvm_run(tvm_t *vm); - -static inline void tvm_step(tvm_t *vm, int *instr_idx) -{ - int *arg0 = vm->pProgram->args[*instr_idx][0], *arg1 = vm->pProgram->args[*instr_idx][1]; - - switch(vm->pProgram->instr[*instr_idx]) - { + switch (vm->prog->instr[*instr_idx]) { /* nop */ case 0x0: break; /* int */ case 0x1: /* unimplemented */ break; /* mov */ case 0x2: *arg0 = *arg1; break; -/* push */ case 0x3: stack_push(vm->pMemory, arg0); break; -/* pop */ case 0x4: stack_pop(vm->pMemory, arg0); break; -/* pushf */ case 0x5: stack_push(vm->pMemory, &vm->pMemory->FLAGS); break; -/* popf */ case 0x6: stack_pop(vm->pMemory, arg0); break; +/* push */ case 0x3: tvm_stack_push(vm->mem, arg0); break; +/* pop */ case 0x4: tvm_stack_pop(vm->mem, arg0); break; +/* pushf */ case 0x5: tvm_stack_push(vm->mem, &vm->mem->FLAGS); break; +/* popf */ case 0x6: tvm_stack_pop(vm->mem, arg0); break; /* inc */ case 0x7: ++(*arg0); break; /* dec */ case 0x8: --(*arg0); break; /* add */ case 0x9: *arg0 += *arg1; break; /* sub */ case 0xA: *arg0 -= *arg1; break; /* mul */ case 0xB: *arg0 *= *arg1; break; /* div */ case 0xC: *arg0 /= *arg1; break; -/* mod */ case 0xD: vm->pMemory->remainder = *arg0 % *arg1; break; -/* rem */ case 0xE: *arg0 = vm->pMemory->remainder; break; +/* mod */ case 0xD: vm->mem->remainder = *arg0 % *arg1; break; +/* rem */ case 0xE: *arg0 = vm->mem->remainder; break; /* not */ case 0xF: *arg0 = ~(*arg0); break; /* xor */ case 0x10: *arg0 ^= *arg1; break; /* or */ case 0x11: *arg0 |= *arg1; break; /* and */ case 0x12: *arg0 &= *arg1; break; /* shl */ case 0x13: *arg0 <<= *arg1; break; /* shr */ case 0x14: *arg0 >>= *arg1; break; -/* cmp */ case 0x15: vm->pMemory->FLAGS = ((*arg0 == *arg1) | (*arg0 > *arg1) << 1); break; -/* call */ case 0x17: stack_push(vm->pMemory, instr_idx); +/* cmp */ case 0x15: vm->mem->FLAGS = + ((*arg0 == *arg1) | (*arg0 > *arg1) << 1); + break; +/* call */ case 0x17: tvm_stack_push(vm->mem, instr_idx); /* jmp */ case 0x16: *instr_idx = *arg0 - 1; break; -/* ret */ case 0x18: stack_pop(vm->pMemory, instr_idx); break; -/* je */ case 0x19: if(vm->pMemory->FLAGS & 0x1) *instr_idx = *arg0 - 1; break; -/* jne */ case 0x1A: if(!(vm->pMemory->FLAGS & 0x1)) *instr_idx = *arg0 - 1; break; -/* jg */ case 0x1B: if(vm->pMemory->FLAGS & 0x2) *instr_idx = *arg0 - 1; break; -/* jge */ case 0x1C: if(vm->pMemory->FLAGS & 0x3) *instr_idx = *arg0 - 1; break; -/* jl */ case 0x1D: if(!(vm->pMemory->FLAGS & 0x3)) *instr_idx = *arg0 - 1; break; -/* jle */ case 0x1E: if(!(vm->pMemory->FLAGS & 0x2)) *instr_idx = *arg0 - 1; break; +/* ret */ case 0x18: tvm_stack_pop(vm->mem, instr_idx); + break; +/* je */ case 0x19: + *instr_idx = (vm->mem->FLAGS & 0x1) + ? *arg0 - 1 : *instr_idx; + break; +/* jne */ case 0x1A: + *instr_idx = (!(vm->mem->FLAGS & 0x1)) + ? *arg0 - 1 : *instr_idx; + break; +/* jg */ case 0x1B: + *instr_idx = (vm->mem->FLAGS & 0x2) + ? *arg0 - 1 : *instr_idx; + break; +/* jge */ case 0x1C: + *instr_idx = (vm->mem->FLAGS & 0x3) + ? *arg0 - 1 : *instr_idx; + break; +/* jl */ case 0x1D: + *instr_idx = (!(vm->mem->FLAGS & 0x3)) + ? *arg0 - 1 : *instr_idx; + break; +/* jle */ case 0x1E: + *instr_idx = (!(vm->mem->FLAGS & 0x2)) + ? *arg0 - 1 : *instr_idx; + break; /* prn */ case 0x1F: printf("%i\n", *arg0); }; } diff --git a/include/tvm/tvm_htab.h b/include/tvm/tvm_htab.h index eb9c4be..9feb7a9 100644 --- a/include/tvm/tvm_htab.h +++ b/include/tvm/tvm_htab.h @@ -4,27 +4,26 @@ #define KEY_LENGTH 64 #define HTAB_SIZE 4096 -typedef struct tvm_htab_node_s -{ +struct tvm_htab_node { char *key; int value; void *valptr; - struct tvm_htab_node_s *next; -} tvm_htab_node_t; + struct tvm_htab_node *next; +}; -typedef struct tvm_htab_s -{ +struct tvm_htab_ctx { unsigned int num_nodes; unsigned int size; - tvm_htab_node_t **nodes; -} tvm_htab_t; + struct tvm_htab_node **nodes; +}; -tvm_htab_t* htab_create(); -void htab_destroy(tvm_htab_t *htab); +struct tvm_htab_ctx *tvm_htab_create(); +void tvm_htab_destroy(struct tvm_htab_ctx *htab); -int htab_add(tvm_htab_t *htab, const char *key, int value); -int htab_add_ref(tvm_htab_t *htab, const char *key, const void *valptr, int len); -int htab_find(tvm_htab_t *htab, const char *key); -char *htab_find_ref(tvm_htab_t *htab, const char *key); +int tvm_htab_add(struct tvm_htab_ctx *htab, const char *key, int value); +int tvm_htab_add_ref(struct tvm_htab_ctx *htab, + const char *key, const void *valptr, int len); +int tvm_htab_find(struct tvm_htab_ctx *htab, const char *key); +char *tvm_htab_find_ref(struct tvm_htab_ctx *htab, const char *key); #endif diff --git a/include/tvm/tvm_lexer.h b/include/tvm/tvm_lexer.h index 6724b5a..fce3785 100644 --- a/include/tvm/tvm_lexer.h +++ b/include/tvm/tvm_lexer.h @@ -6,16 +6,16 @@ #include "tvm_htab.h" -typedef struct tvm_lexer_s -{ +struct tvm_lexer_ctx { char **source_lines; char ***tokens; -} tvm_lexer_t; +}; -tvm_lexer_t *lexer_create(); -void lexer_destroy(tvm_lexer_t *l); +struct tvm_lexer_ctx *lexer_create(); +void tvm_lexer_destroy(struct tvm_lexer_ctx *l); /* Tokenize the character array "source" into lines and tokens */ -void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines); +void tvm_lex(struct tvm_lexer_ctx *lexer, + char *source, struct tvm_htab_ctx *defines); #endif diff --git a/include/tvm/tvm_memory.h b/include/tvm/tvm_memory.h index baff2d1..178c4ea 100644 --- a/include/tvm/tvm_memory.h +++ b/include/tvm/tvm_memory.h @@ -6,28 +6,25 @@ #define MIN_MEMORY_SIZE (64 * 1024 * 1024) /* 64 MB */ -typedef union -{ +union tvm_reg_u { int32_t i32; int32_t *i32_ptr; - union - { + union { int16_t h; int16_t l; } i16; -} tvm_register_t; +}; -typedef struct -{ +struct tvm_mem { /* - Similar to x86 FLAGS register - - 0x1 EQUAL - 0x2 GREATER - - */ + * Similar to x86 FLAGS register + * + * 0x1 EQUAL + * 0x2 GREATER + * + */ int FLAGS; int remainder; @@ -35,10 +32,10 @@ typedef struct void *mem_space; int mem_space_size; - tvm_register_t *registers; -} tvm_memory_t; + union tvm_reg_u *registers; +}; -tvm_memory_t *memory_create(size_t size); -void memory_destroy(tvm_memory_t *mem); +struct tvm_mem *tvm_mem_create(size_t size); +void tvm_mem_destroy(struct tvm_mem *mem); #endif diff --git a/include/tvm/tvm_parser.h b/include/tvm/tvm_parser.h index cba964c..9f46ae8 100644 --- a/include/tvm/tvm_parser.h +++ b/include/tvm/tvm_parser.h @@ -1,12 +1,13 @@ #ifndef TVM_PARSER_H_ #define TVM_PARSER_H_ -#include +#include "tvm.h" +#include "tvm_program.h" -int parse_labels(tvm_program_t *p, const char ***tokens); -int parse_instructions(tvm_program_t *pProgram, const char ***tokens, tvm_memory_t *pMemory); +int tvm_parse_labels(struct tvm_ctx *vm, const char ***tokens); +int tvm_parse_program(struct tvm_ctx *vm, const char ***tokens); -int *tvm_add_value(tvm_program_t *p, const int val); +int *tvm_add_value(struct tvm_ctx *vm, const int val); int tvm_parse_value(const char *str); #endif diff --git a/include/tvm/tvm_preprocessor.h b/include/tvm/tvm_preprocessor.h index 9832c62..34ae42d 100644 --- a/include/tvm/tvm_preprocessor.h +++ b/include/tvm/tvm_preprocessor.h @@ -3,6 +3,6 @@ #include "tvm_htab.h" -int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines); +int tvm_preprocess(char *src, int *src_len, struct tvm_htab_ctx *defines); #endif diff --git a/include/tvm/tvm_program.h b/include/tvm/tvm_program.h index 88a85c4..be8dd19 100644 --- a/include/tvm/tvm_program.h +++ b/include/tvm/tvm_program.h @@ -8,30 +8,23 @@ #include "tvm_htab.h" #include "tvm_memory.h" -typedef struct tvm_program_s -{ +struct tvm_prog { int start; - int num_instructions; - int *instr; - - int ***args; + int num_instr; + int *instr; + int ***args; int **values; int num_values; - tvm_htab_t *defines; - - tvm_htab_t *label_htab; - -} tvm_program_t; + struct tvm_htab_ctx *defines; + struct tvm_htab_ctx *label_htab; +}; /* Create and initialize an empty program object */ -tvm_program_t *program_create(); +struct tvm_prog *tvm_prog_create(); -/* Interpret a source file into bytecode, and store it in a program object */ -int program_interpret(tvm_program_t *p, char *filename, tvm_memory_t *pMemory); - -void program_destroy(tvm_program_t *p); +void tvm_prog_destroy(struct tvm_prog *p); #endif diff --git a/include/tvm/tvm_stack.h b/include/tvm/tvm_stack.h index ac8dc4e..97c3cfa 100644 --- a/include/tvm/tvm_stack.h +++ b/include/tvm/tvm_stack.h @@ -7,19 +7,20 @@ /* Initialize our stack by setting the base pointer and stack pointer */ -inline void stack_create(tvm_memory_t *mem, size_t size) +static inline void tvm_stack_create(struct tvm_mem *mem, size_t size) { - mem->registers[0x7].i32_ptr = ((int32_t *)mem->mem_space) + (size / sizeof(int32_t)); + mem->registers[0x7].i32_ptr = + ((int32_t *)mem->mem_space) + (size / sizeof(int32_t)); mem->registers[0x6].i32_ptr = mem->registers[0x7].i32_ptr; } -inline void stack_push(tvm_memory_t *mem, int *item) +static inline void tvm_stack_push(struct tvm_mem *mem, int *item) { mem->registers[0x6].i32_ptr -= 1; *mem->registers[0x6].i32_ptr = *item; } -inline void stack_pop(tvm_memory_t *mem, int *dest) +static inline void tvm_stack_pop(struct tvm_mem *mem, int *dest) { *dest = *mem->registers[0x6].i32_ptr; mem->registers[0x6].i32_ptr += 1; diff --git a/include/tvm/tvm_tokens.h b/include/tvm/tvm_tokens.h new file mode 100644 index 0000000..8642270 --- /dev/null +++ b/include/tvm/tvm_tokens.h @@ -0,0 +1,24 @@ +#ifndef _TVM_TOKENS_H_ +#define _TVM_TOKENS_H_ + +#define TOK_INCLUDE "%include" +#define TOK_DEFINE "%define" + +static const char *tvm_opcode_map[] = { + "nop", "int", "mov", + "push", "pop", "pushf", "popf", + "inc", "dec", "add", "sub", "mul", "div", "mod", "rem", + "not", "xor", "or", "and", "shl", "shr", + "cmp", "jmp", "call", "ret", + "je", "jne", "jg", "jge", "jl", "jle", + "prn", 0 +}; + +static const char *tvm_register_map[] = { + "eax", "ebx", "ecx", "edx", + "esi", "edi", "esp", "ebp", + "eip", + "r08", "r09", "r10", "r11", + "r12", "r13", "r14", "r15", 0}; + +#endif diff --git a/libtvm/tvm.c b/libtvm/tvm.c index 8a43be2..48edd08 100644 --- a/libtvm/tvm.c +++ b/libtvm/tvm.c @@ -1,36 +1,86 @@ #include -tvm_t *tvm_create(char *filename) +#include +#include + +struct tvm_ctx *tvm_vm_create(char *filename) { - tvm_t *vm = (tvm_t*)calloc(1, sizeof(tvm_t)); + struct tvm_ctx *vm = + (struct tvm_ctx *)calloc(1, sizeof(struct tvm_ctx)); - vm->pMemory = memory_create(MIN_MEMORY_SIZE); - vm->pProgram = program_create(); + vm->mem = tvm_mem_create(MIN_MEMORY_SIZE); + vm->prog = tvm_prog_create(); - stack_create(vm->pMemory, MIN_STACK_SIZE); + tvm_stack_create(vm->mem, MIN_STACK_SIZE); - if(!vm || !vm->pMemory || !vm->pProgram) return NULL; + if (!vm || !vm->mem || !vm->prog) + return NULL; return vm; } -int tvm_interpret(tvm_t *vm, char *filename) +int tvm_vm_interpret(struct tvm_ctx *vm, char *filename) { - if(program_interpret(vm->pProgram, filename, vm->pMemory) != 0) return 1; + FILE *filp = NULL; + int source_length = 0; + + /* Attempt to open the file. + * If the file cannot be opened, try once more. + */ + if (filename) { + for (int i = 0; i < 2; i++) { + if (!filp) + filp = tvm_fopen(filename, ".vm", "r"); + } + } + + if (!filp) { + printf("File was not found, or does not exist. Unable to interpret.\n"); + return 1; + } + + source_length = tvm_flength(filp); + char *source = calloc(source_length, sizeof(char)); + + tvm_fcopy(source, source_length, filp); + fclose(filp); + + int err = tvm_preprocess(source, &source_length, vm->prog->defines); + + /* The preprocessor encountered a problem. */ + if (err < 0) + return 1; + + struct tvm_lexer_ctx *lexer_ctx = lexer_create(); + + tvm_lex(lexer_ctx, source, vm->prog->defines); + free(source); + + if (tvm_parse_labels(vm, (const char ***)lexer_ctx->tokens) != 0) + return 1; + if (tvm_parse_program(vm, (const char ***)lexer_ctx->tokens) != 0) + return 1; + + tvm_lexer_destroy(lexer_ctx); return 0; } -void tvm_destroy(tvm_t *vm) +void tvm_vm_run(struct tvm_ctx *vm) { - if(vm && vm->pMemory) memory_destroy(vm->pMemory); - if(vm && vm->pProgram) program_destroy(vm->pProgram); - if(vm) free(vm); + int *instr_idx = &vm->mem->registers[0x8].i32; + *instr_idx = vm->prog->start; + + for (; vm->prog->instr[*instr_idx] != -0x1; ++(*instr_idx)) + tvm_step(vm, instr_idx); } -void tvm_run(tvm_t *vm) + +void tvm_vm_destroy(struct tvm_ctx *vm) { - int *instr_idx = &vm->pMemory->registers[0x8].i32; *instr_idx = vm->pProgram->start; - - for(;vm->pProgram->instr[*instr_idx] != -0x1; ++(*instr_idx)) tvm_step(vm, instr_idx); + if (vm && vm->mem) + tvm_mem_destroy(vm->mem); + if (vm && vm->prog) + tvm_prog_destroy(vm->prog); + if (vm) + free(vm); } - diff --git a/libtvm/tvm_file.c b/libtvm/tvm_file.c index be10954..0d4a40d 100644 --- a/libtvm/tvm_file.c +++ b/libtvm/tvm_file.c @@ -2,43 +2,45 @@ FILE *tvm_fopen(const char *filename, const char *extension, const char *mode) { - FILE *pFile = NULL; + FILE *filp = NULL; size_t fname_chars = strlen(filename) + strlen(extension) + 1; char *fname = calloc(fname_chars, sizeof(char)); int i; strcpy(fname, filename); - for(i = 0; i < 2 && !pFile; i++) - { - if(i > 0) strcat(fname, extension); - pFile = fopen(fname, mode); + for (i = 0; i < 2 && !filp; i++) { + if (i > 0) + strcat(fname, extension); + filp = fopen(fname, mode); } free(fname); - return pFile; + return filp; } -int tvm_fcopy(char *dest, size_t size, FILE* src) +int tvm_fcopy(char *dest, size_t size, FILE *filp) { size_t i; - long pos = ftell(src); + long pos = ftell(filp); - for(i = 0; i < size && !feof(src); i++) dest[i] = fgetc(src); + for (i = 0; i < size && !feof(filp); i++) + dest[i] = fgetc(filp); dest[i - 1] = 0; - fseek(src, pos, SEEK_SET); + fseek(filp, pos, SEEK_SET); return 0; } -int tvm_flength(FILE *f) +int tvm_flength(FILE *filp) { int length; - long pos = ftell(f); + long pos = ftell(filp); - for(length = 0; !feof(f); length++) fgetc(f); - fseek(f, pos, SEEK_SET); + for (length = 0; !feof(filp); length++) + fgetc(filp); + fseek(filp, pos, SEEK_SET); return length; } diff --git a/libtvm/tvm_htab.c b/libtvm/tvm_htab.c index 3ad5db3..ef1d8bb 100644 --- a/libtvm/tvm_htab.c +++ b/libtvm/tvm_htab.c @@ -5,27 +5,27 @@ #define HTAB_LOAD_FACTOR 0.7 -tvm_htab_t *htab_create() +struct tvm_htab_ctx *tvm_htab_create() { - tvm_htab_t *htab = (tvm_htab_t *)calloc(1, sizeof(tvm_htab_t)); + struct tvm_htab_ctx *htab = + (struct tvm_htab_ctx *)calloc(1, sizeof(struct tvm_htab_ctx)); + htab->size = HTAB_SIZE; - htab->nodes = (tvm_htab_node_t **)calloc(htab->size, sizeof(tvm_htab_node_t *)); + htab->nodes = (struct tvm_htab_node **)calloc( + htab->size, sizeof(struct tvm_htab_node *)); htab->num_nodes = 0; return htab; } -void htab_destroy(tvm_htab_t *htab) +void tvm_htab_destroy(struct tvm_htab_ctx *htab) { - int i; - tvm_htab_node_t *node, *next; + struct tvm_htab_node *node, *next; - for(i = 0; i < htab->size; i++) - { + for (int i = 0; i < htab->size; i++) { node = htab->nodes[i]; - while(node) - { + while (node) { next = node->next; - if(node->valptr) + if (node->valptr) free(node->valptr); free(node->key); free(node); @@ -37,43 +37,48 @@ void htab_destroy(tvm_htab_t *htab) free(htab); } -static inline unsigned htab_hash(const char *k, const unsigned int size) +static inline unsigned int htab_hash(const char *k, const unsigned int size) { unsigned int hash = 1; - char *c; for(c = (char*)k; *c; c++) + char *c; for (c = (char *)k; *c; c++) hash += (hash << *c) - *c; return hash % size; } -static void htab_rehash(tvm_htab_t *orig, unsigned int size) +static void htab_rehash(struct tvm_htab_ctx *orig, unsigned int size) { int i; - tvm_htab_node_t *node, *next; - tvm_htab_t *new; + struct tvm_htab_node *node, *next; + struct tvm_htab_ctx *new; - new = (tvm_htab_t *)calloc(1, sizeof(tvm_htab_t)); - new->nodes = (tvm_htab_node_t **)calloc(size, sizeof(tvm_htab_node_t *)); + new = (struct tvm_htab_ctx *)calloc(1, sizeof(struct tvm_htab_ctx)); + new->nodes = (struct tvm_htab_node **)calloc( + size, sizeof(struct tvm_htab_node *)); new->size = size; new->num_nodes = 0; /* Traverse the original hash table, rehashing - every entry into the new table and deleting - original entries */ - for(i = 0; i < orig->size; i++) - { + * every entry into the new table and deleting + * original entries + */ + for (i = 0; i < orig->size; i++) { node = orig->nodes[i]; - while(node) - { + while (node) { next = node->next; - if (node->valptr) - { - htab_add_ref(new, node->key, node->valptr, strlen(node->valptr) + 1); + if (node->valptr) { + tvm_htab_add_ref( + new, node->key, + node->valptr, + strlen(node->valptr) + 1 + ); + free(node->valptr); - } - else - htab_add(new, node->key, node->value); + + } else + tvm_htab_add(new, node->key, node->value); + free(node->key); free(node); node = next; @@ -83,24 +88,25 @@ static void htab_rehash(tvm_htab_t *orig, unsigned int size) free(orig->nodes); /* Transpose the new hash table onto the old one */ - memcpy(orig, new, sizeof(tvm_htab_t)); + memcpy(orig, new, sizeof(struct tvm_htab_ctx)); free(new); } -static tvm_htab_node_t *htab_add_core(tvm_htab_t *htab, const char *k) +static struct tvm_htab_node *htab_add_core( + struct tvm_htab_ctx *htab, const char *k) { /* Increase bucket count and rehash if the - load factor is too high */ - if((float)++htab->num_nodes / htab->size > HTAB_LOAD_FACTOR) + * load factor is too high + */ + if ((float) ++htab->num_nodes / htab->size > HTAB_LOAD_FACTOR) htab_rehash(htab, htab->num_nodes * 2); int hash = htab_hash(k, htab->size); - tvm_htab_node_t *node = htab->nodes[hash]; - tvm_htab_node_t *prev = NULL; + struct tvm_htab_node *node = htab->nodes[hash]; + struct tvm_htab_node *prev = NULL; - if(node) - { - while(node->next) + if (node) { + while (node->next) node = node->next; prev = node; @@ -109,22 +115,24 @@ static tvm_htab_node_t *htab_add_core(tvm_htab_t *htab, const char *k) /* Allocate space, and copy the key/value pair. */ - node = calloc(1, sizeof(tvm_htab_node_t)); + node = calloc(1, sizeof(struct tvm_htab_node)); node->key = (char *)calloc((strlen(k) + 1), sizeof(char)); strcpy(node->key, k); - if(prev) prev->next = node; - else htab->nodes[hash] = node; /* root node */ + if (prev) + prev->next = node; + else + htab->nodes[hash] = node; /* root node */ node->next = NULL; return node; } -int htab_add(tvm_htab_t *htab, const char *key, int value) +int tvm_htab_add(struct tvm_htab_ctx *htab, const char *key, int value) { - tvm_htab_node_t *node = htab_add_core(htab, key); + struct tvm_htab_node *node = htab_add_core(htab, key); if (!node) return -1; @@ -134,9 +142,10 @@ int htab_add(tvm_htab_t *htab, const char *key, int value) return 0; } -int htab_add_ref(tvm_htab_t *htab, const char *key, const void *valptr, int len) +int tvm_htab_add_ref( + struct tvm_htab_ctx *htab, const char *key, const void *valptr, int len) { - tvm_htab_node_t *node = htab_add_core(htab, key); + struct tvm_htab_node *node = htab_add_core(htab, key); if (!node) return -1; @@ -147,35 +156,35 @@ int htab_add_ref(tvm_htab_t *htab, const char *key, const void *valptr, int len) return 0; } -static tvm_htab_node_t *htab_find_core(tvm_htab_t *htab, const char *key) +static struct tvm_htab_node *htab_find_core( + struct tvm_htab_ctx *htab, const char *key) { int hash = htab_hash(key, htab->size); - tvm_htab_node_t *node = htab->nodes[hash]; + struct tvm_htab_node *node = htab->nodes[hash]; - while (node) - { - if(!strcmp(node->key, key)) + while (node) { + if (!strcmp(node->key, key)) return node; - else - node = node->next; + + node = node->next; } return NULL; } -int htab_find(tvm_htab_t *htab, const char *key) +int tvm_htab_find(struct tvm_htab_ctx *htab, const char *key) { - tvm_htab_node_t *node = htab_find_core(htab, key); - - if(!node) + struct tvm_htab_node *node = htab_find_core(htab, key); + + if (!node) return -1; return node->value; } -char *htab_find_ref(tvm_htab_t *htab, const char *key) +char *tvm_htab_find_ref(struct tvm_htab_ctx *htab, const char *key) { - tvm_htab_node_t *node = htab_find_core(htab, key); + struct tvm_htab_node *node = htab_find_core(htab, key); if (!node) return NULL; diff --git a/libtvm/tvm_lexer.c b/libtvm/tvm_lexer.c index a856fb3..b1b03b6 100644 --- a/libtvm/tvm_lexer.c +++ b/libtvm/tvm_lexer.c @@ -4,19 +4,19 @@ #include #include -tvm_lexer_t *lexer_create() +struct tvm_lexer_ctx *lexer_create() { - return (tvm_lexer_t *)calloc(1, sizeof(tvm_lexer_t)); + return (struct tvm_lexer_ctx *)calloc(1, sizeof(struct tvm_lexer_ctx)); } -void lexer_destroy(tvm_lexer_t *lexer) +void tvm_lexer_destroy(struct tvm_lexer_ctx *lexer) { - for(int i = 0; lexer->source_lines[i]; i++) free(lexer->source_lines[i]); + for (int i = 0; lexer->source_lines[i]; i++) + free(lexer->source_lines[i]); free(lexer->source_lines); - for(int i = 0; lexer->tokens[i]; i++) - { - for(int j = 0; j < MAX_TOKENS; j++) + for (int i = 0; lexer->tokens[i]; i++) { + for (int j = 0; j < MAX_TOKENS; j++) free(lexer->tokens[i][j]); free(lexer->tokens[i]); @@ -26,50 +26,51 @@ void lexer_destroy(tvm_lexer_t *lexer) free(lexer); } -void lex(tvm_lexer_t *lexer, char *source, tvm_htab_t *defines) +void tvm_lex( + struct tvm_lexer_ctx *lexer, char *source, struct tvm_htab_ctx *defines) { int i, j; - char *pToken, *pLine = strtok(source, "\n"); + char *tokp, *linep = strtok(source, "\n"); /* Split the source into individual lines */ - for(i = 0; pLine; i++) - { - lexer->source_lines = (char **)realloc(lexer->source_lines, sizeof(char *) * (i + 2)); - lexer->source_lines[i] = (char *)calloc(1, strlen(pLine) + 1); + for (i = 0; linep; i++) { + lexer->source_lines = (char **)realloc( + lexer->source_lines, sizeof(char *) * (i + 2)); + lexer->source_lines[i] = (char *)calloc(1, strlen(linep) + 1); - strcpy(lexer->source_lines[i], pLine); + strcpy(lexer->source_lines[i], linep); /* Ignore comments delimited by '#' */ - char* comment_delimiter = strchr(lexer->source_lines[i], '#'); + char *comment_delimiter = strchr(lexer->source_lines[i], '#'); - if(comment_delimiter) *comment_delimiter = 0; + if (comment_delimiter) + *comment_delimiter = 0; - pLine = strtok(NULL, "\n"); + linep = strtok(NULL, "\n"); } /* NULL terminate the array to make iteration later easier*/ lexer->source_lines[i] = NULL; /* Split the source into individual tokens */ - for(i = 0; lexer->source_lines[i]; i++) - { - lexer->tokens = (char ***)realloc(lexer->tokens, sizeof(char **) * (i + 2)); + for (i = 0; lexer->source_lines[i]; i++) { + lexer->tokens = (char ***)realloc( + lexer->tokens, sizeof(char **) * (i + 2)); lexer->tokens[i] = (char **)calloc(MAX_TOKENS, sizeof(char *)); - pToken = strtok(lexer->source_lines[i], " \t,"); + tokp = strtok(lexer->source_lines[i], " \t,"); - for(j = 0; (pToken && j < MAX_TOKENS); j++) - { - char *token = htab_find_ref(defines, pToken); - token = token ? token : pToken; + for (j = 0; (tokp && j < MAX_TOKENS); j++) { + char *token = tvm_htab_find_ref(defines, tokp); - lexer->tokens[i][j] = (char *)calloc(1, (strlen(token) + 1)); + token = token ? token : tokp; + lexer->tokens[i][j] = calloc(1, (strlen(token) + 1)); strcpy(lexer->tokens[i][j], token); - pToken = strtok(NULL, " \t,"); + tokp = strtok(NULL, " \t,"); } } lexer->tokens[i] = NULL; - htab_destroy(defines); + tvm_htab_destroy(defines); } diff --git a/libtvm/tvm_memory.c b/libtvm/tvm_memory.c index 3cf0977..dc9b9a8 100644 --- a/libtvm/tvm_memory.c +++ b/libtvm/tvm_memory.c @@ -5,11 +5,12 @@ #define NUM_REGISTERS 17 -tvm_memory_t *memory_create(size_t size) +struct tvm_mem *tvm_mem_create(size_t size) { - tvm_memory_t *m = (tvm_memory_t *)calloc(1, sizeof(tvm_memory_t)); + struct tvm_mem *m = + (struct tvm_mem *)calloc(1, sizeof(struct tvm_mem)); - m->registers = calloc(NUM_REGISTERS, sizeof(tvm_register_t)); + m->registers = calloc(NUM_REGISTERS, sizeof(union tvm_reg_u)); m->mem_space_size = size; m->mem_space = (int *)calloc(size, 1); @@ -17,7 +18,7 @@ tvm_memory_t *memory_create(size_t size) return m; } -void memory_destroy(tvm_memory_t *m) +void tvm_mem_destroy(struct tvm_mem *m) { free(m->mem_space); free(m->registers); diff --git a/libtvm/tvm_parser.c b/libtvm/tvm_parser.c index fa3f988..b849fc8 100644 --- a/libtvm/tvm_parser.c +++ b/libtvm/tvm_parser.c @@ -1,139 +1,212 @@ #include #include #include +#include -const char *tvm_opcode_map[] = {"nop", "int", "mov", "push", "pop", "pushf", "popf", "inc", "dec", "add", "sub", "mul", "div", "mod", "rem", - "not", "xor", "or", "and", "shl", "shr", "cmp", "jmp", "call", "ret", "je", "jne", "jg", "jge", "jl", "jle", "prn", 0}; - -const char *tvm_register_map[] = {"eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", "eip", "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15", 0}; - -static int *token_to_register(const char *token, tvm_memory_t *pMemory); +static int *token_to_register(const char *token, struct tvm_mem *mem); static int instr_to_opcode(const char *instr); -int parse_labels(tvm_program_t *p, const char ***tokens) +int tvm_parse_labels(struct tvm_ctx *vm, const char ***tokens) { - int num_instructions = 0; - for(int i = 0; tokens[i]; i++) - { + int num_instr = 0; + struct tvm_prog *p = vm->prog; + + for (int i = 0; tokens[i]; i++) { int valid_instruction = 0; - for(int token_idx = 0; token_idx < MAX_TOKENS; token_idx++) - { + + for (int token_idx = 0; token_idx < MAX_TOKENS; token_idx++) { /* If the token is empty, or non-existent, skip it */ - if(!tokens[i][token_idx]) continue; + if (!tokens[i][token_idx]) + continue; - /* Figure out if the source line we're on contains a valid instruction */ - if(instr_to_opcode(tokens[i][token_idx]) != -1) valid_instruction = 1; + /* Check the source line for a valid instruction */ + if (instr_to_opcode(tokens[i][token_idx]) != -1) + valid_instruction = 1; - /* Figure out if the token we're dealing with has a label delimiter */ - char* label_delimiter = strchr(tokens[i][token_idx], ':'); - if(label_delimiter == NULL) continue; + /* Check for a label delimiter*/ + char *label_delimiter = strchr( + tokens[i][token_idx], ':'); + + if (label_delimiter == NULL) + continue; *label_delimiter = 0; - /* If the label is "start," set the program to begin there */ - if(strcmp(tokens[i][token_idx], "start") == 0) p->start = num_instructions; + /* If the label is "start," make it the entry point */ + if (strcmp(tokens[i][token_idx], "start") == 0) + p->start = num_instr; /* Check if the label already exists */ - if(htab_find(p->label_htab, tokens[i][token_idx]) != -1) - { + int label_addr = tvm_htab_find( + p->label_htab, tokens[i][token_idx]); + + if (label_addr != -1) { printf("Label '%s' defined twice\n", tokens[i][token_idx]); return 1; } - else - { - /* Add that fucker to the hash table with the corresponding instruction index */ - htab_add(p->label_htab, tokens[i][token_idx], num_instructions); - } + + tvm_htab_add( + p->label_htab, + tokens[i][token_idx], + num_instr + ); } - if(valid_instruction) num_instructions++; + if (valid_instruction) + num_instr++; } return 0; } -int parse_instructions(tvm_program_t *p, const char ***tokens, tvm_memory_t *pMemory) +/* This function takes the instruction tokens, and location of the + * instruction inside the line, parses the arguments, and returns a pointer + * to the heap where they're stored. + */ +static int **tvm_parse_args( + struct tvm_ctx *vm, const char **instr_tokens, int *instr_place) +{ + int **args = calloc(sizeof(int *), MAX_ARGS); + + for (int i = 0; i < MAX_ARGS; ++i) { + if (!instr_tokens[*instr_place+1 + i] + || !strlen(instr_tokens[*instr_place+1 + i])) + continue; + + char *newline = strchr(instr_tokens[*instr_place+1 + i], '\n'); + + if (newline) + *newline = 0; + + /* Check to see if the token specifies a register */ + int *regp = token_to_register( + instr_tokens[*instr_place+1 + i], vm->mem); + + if (regp) { + args[i] = regp; + continue; + } + + /* Check to see whether the token specifies an address */ + if (instr_tokens[*instr_place+1 + i][0] == '[') { + char *end_symbol = strchr( + instr_tokens[*instr_place+1 + i], ']'); + + if (end_symbol) { + *end_symbol = 0; + args[i] = &((int *)vm->mem->mem_space)[ + tvm_parse_value(instr_tokens[ + *instr_place+1 + i] + 1)]; + + continue; + } + } + + /* Check if the argument is a label */ + int addr = tvm_htab_find( + vm->prog->label_htab, instr_tokens[*instr_place+1 + i]); + + if (addr != -1) { + args[i] = tvm_add_value(vm, addr); + continue; + } + + /* Fuck it, parse it as a value */ + args[i] = tvm_add_value( + vm, tvm_parse_value(instr_tokens[*instr_place+1 + i])); + } + + int args_set = 0; + for (int i = 0; i < MAX_ARGS; i++) { + if (args[i]) + args_set = 1; + } + + if (!args_set) + free(args); + + return args; +} + + + +/* This is a helper function that converts one instruction, + * from one line of code, to tvm bytecode + */ +static int tvm_parse_instr( + struct tvm_ctx *vm, const char **instr_tokens, int *instr_place) +{ + for (int token_idx = 0; token_idx < MAX_TOKENS; token_idx++) { + /* Skip empty tokens */ + if (!instr_tokens[token_idx]) + continue; + + int opcode = instr_to_opcode(instr_tokens[token_idx]); + + if (opcode == -1) + continue; + + if (instr_place) + *instr_place = token_idx; + + vm->prog->num_instr++; + return opcode; + } + + return -1; +} + +int tvm_parse_program( + struct tvm_ctx *vm, const char ***tokens) { int line_idx; - for(line_idx = 0; tokens[line_idx]; line_idx++) - { - p->instr = (int *)realloc(p->instr, sizeof(int) * (line_idx + 2)); - p->instr[line_idx] = 0; - p->args = (int ***)realloc(p->args, sizeof(int **) * (line_idx + 2)); - p->args[line_idx] = (int **)calloc(MAX_ARGS, sizeof(int *)); + for (line_idx = 0; tokens[line_idx]; line_idx++) { + int instr_place; - int token_idx; - for(token_idx = 0; token_idx < MAX_TOKENS; token_idx++) - { - int opcode = 0; + int opcode = tvm_parse_instr( + vm, tokens[line_idx], &instr_place); - /* Skip empty tokens */ - if(!tokens[line_idx][token_idx]) continue; + int **args = tvm_parse_args( + vm, tokens[line_idx], &instr_place); - opcode = instr_to_opcode(tokens[line_idx][token_idx]); + if (opcode == -1 || !args) + continue; - /* If it *isn't* an opcode, skip trying to parse arguments */ - if(opcode == -1) continue; + void *newptr; - int i, instr_idx = 0, num_instr = p->num_instructions; - p->instr[p->num_instructions++] = opcode; + newptr = realloc( + vm->prog->instr, sizeof(int) * (vm->prog->num_instr+1)); - for(i = ++token_idx; i < (token_idx + 2); ++i) - { - if(!tokens[line_idx][i] || strlen(tokens[line_idx][i]) <= 0) continue; + if (newptr != NULL) { + vm->prog->instr = newptr; + vm->prog->instr[vm->prog->num_instr - 1] = opcode; + } else + return -1; - char *newline = strchr(tokens[line_idx][i], '\n'); - if(newline) *newline = 0; + newptr = realloc( + vm->prog->args, + sizeof(int **) * (vm->prog->num_instr+1)); - /* Check to see if the token specifies a register */ - int *pRegister = token_to_register(tokens[line_idx][i], pMemory); - if(pRegister) - { - p->args[num_instr][i - token_idx] = pRegister; - continue; - } + if (newptr != NULL) + vm->prog->args = (int ***)newptr; + else + return -1; - /* Check to see whether the token specifies an address */ - if(tokens[line_idx][i][0] == '[') - { - char *end_symbol = strchr(tokens[line_idx][i], ']'); - if(end_symbol) - { - *end_symbol = 0; - p->args[num_instr][i - token_idx] = &((int *)pMemory->mem_space)[tvm_parse_value(tokens[line_idx][i] + 1)]; - - continue; - } - } - - /* Check if the argument is a label */ - instr_idx = htab_find(p->label_htab, tokens[line_idx][i]); - - if(instr_idx >= 0) - { - p->args[num_instr][i - token_idx] = tvm_add_value(p, instr_idx); - continue; - } - - /* Fuck it, parse it as a value */ - p->args[num_instr][i - token_idx] = tvm_add_value(p, tvm_parse_value(tokens[line_idx][i])); - } - } + vm->prog->args[vm->prog->num_instr - 1] = (int **)args; } - p->args[line_idx] = NULL; - p->instr[line_idx] = -0x1; + vm->prog->args[vm->prog->num_instr] = NULL; + vm->prog->instr[vm->prog->num_instr] = -0x1; return 0; } -int* token_to_register(const char *token, tvm_memory_t *pMemory) +int *token_to_register(const char *token, struct tvm_mem *mem) { - for(int i = 0; tvm_register_map[i]; i++) - { - if(strcmp(token, tvm_register_map[i]) == 0) - return &pMemory->registers[i].i32; + for (int i = 0; tvm_register_map[i]; i++) { + if (strcmp(token, tvm_register_map[i]) == 0) + return &mem->registers[i].i32; } return NULL; @@ -141,15 +214,17 @@ int* token_to_register(const char *token, tvm_memory_t *pMemory) int instr_to_opcode(const char *instr) { - for(int i = 0; tvm_opcode_map[i]; i++) - if(strcmp(instr, tvm_opcode_map[i]) == 0) + for (int i = 0; tvm_opcode_map[i]; i++) + if (strcmp(instr, tvm_opcode_map[i]) == 0) return i; return -1; } -int *tvm_add_value(tvm_program_t *p, const int val) +int *tvm_add_value(struct tvm_ctx *vm, const int val) { + struct tvm_prog *p = vm->prog; + p->values = realloc(p->values, sizeof(int *) * (p->num_values + 1)); p->values[p->num_values] = (int *)calloc(1, sizeof(int)); @@ -162,15 +237,19 @@ int tvm_parse_value(const char *str) { char *delimiter = strchr(str, '|'), base = 0; - if(delimiter) - { + if (delimiter) { char *identifier = delimiter + 1; - switch(*identifier) - { - case 'h': base = 16; break; - case 'b': base = 2; break; - default: base = 0; break; + switch (*identifier) { + case 'h': + base = 16; + break; + case 'b': + base = 2; + break; + default: + base = 0; + break; } } diff --git a/libtvm/tvm_preprocessor.c b/libtvm/tvm_preprocessor.c index a4b41eb..179a6f8 100644 --- a/libtvm/tvm_preprocessor.c +++ b/libtvm/tvm_preprocessor.c @@ -1,111 +1,145 @@ #include +#include #include #include -int tvm_preprocess(char *src, int *src_len, tvm_htab_t *defines) +static int process_includes( + char *src, int *src_len, struct tvm_htab_ctx *defines) { - char* pp_directive_delimiter = NULL; - if((pp_directive_delimiter = strstr(src, "%include"))) - { - char *strbegin = pp_directive_delimiter, *strend = strchr(strbegin, '\n'); + char *pp_directive_delimiter = strstr(src, TOK_INCLUDE); - if(!strend || !strbegin) return 0; + if (!pp_directive_delimiter) + return 0; - int linelen = strend - strbegin; - char* temp_str = calloc(linelen + 1, sizeof(char)); - memcpy(temp_str, strbegin, linelen); + char *strbegin = pp_directive_delimiter, + *strend = strchr(strbegin, '\n'); - char *filename = (strchr(temp_str, ' ') + 1); + if (!strend || !strbegin) + return 0; - FILE* pFile = tvm_fopen(filename, ".vm", "r"); - if(!pFile) - { - printf("Unable to open file \"%s\"\n", filename); - return -1; - } + int linelen = strend - strbegin; + char *temp_str = calloc(linelen + 1, sizeof(char)); - free(temp_str); + memcpy(temp_str, strbegin, linelen); - size_t addition_len = tvm_flength(pFile); - char *addition_str = calloc(addition_len, sizeof(char)); - tvm_fcopy(addition_str, addition_len, pFile); - fclose(pFile); + char *filename = (strchr(temp_str, ' ') + 1); + FILE *filp = tvm_fopen(filename, ".vm", "r"); - size_t first_block_len = (strbegin - src); - size_t second_block_len = ((src + *src_len) - strend); - size_t new_src_len = (first_block_len + addition_len + second_block_len); - - src = (char *)realloc((char *)src, sizeof(char) * new_src_len); - src[new_src_len] = 0; - - memmove(&src[first_block_len + addition_len], strend, second_block_len); - memcpy(&src[first_block_len], addition_str, addition_len); - - // Fuckin' hack - for(int i = 0; i < new_src_len; i++) if(src[i] == 0) src[i] = ' '; - - *src_len = strlen(src); - return 1; - } - else if((pp_directive_delimiter = strstr(src, "%define "))) - { - char *begin = pp_directive_delimiter; - char *end = strchr(begin, '\n'); - - if(!end) return 0; - - int offset = strlen("%define "); - - if(begin + offset >= end) - { - printf("Define missing arguments.\n"); - return -1; - } - - int length = (end - (begin + offset)); - char tempstr[length + 1]; - memset(tempstr, 0, length + 1); - memcpy(tempstr, begin + offset, length); - - char *keystr = tempstr; - char *valstr = strchr(tempstr, ' '); - - /* If there is a value, seperate the key and value - with a null character. */ - if(valstr) - { - *valstr = 0; - valstr += 1; - } - - if(!keystr || !valstr) - { - printf("Define missing arguments.\n"); - return -1; - } - - if(htab_find(defines, keystr) < 0) - htab_add_ref(defines, keystr, valstr, strlen(valstr) + 1); - else - { - printf("Multiple definitions for %s.\n", keystr); - return -1; - } - - /* Remove the define line so it is not processed again. */ - size_t new_length = *src_len - (end - begin); - size_t first_block_len = begin - src; - size_t second_block_len = (src + *src_len) - end; - - memmove(&src[first_block_len], end, second_block_len); - - src = realloc(src, sizeof(char) * new_length); - *src_len = new_length; - - return 1; + if (!filp) { + printf("Unable to open file \"%s\"\n", filename); + return -1; } - return 0; + free(temp_str); + size_t addition_len = tvm_flength(filp); + char *addition_str = calloc(addition_len, sizeof(char)); + + tvm_fcopy(addition_str, addition_len, filp); + fclose(filp); + + size_t first_block_len = (strbegin - src); + size_t second_block_len = ((src + *src_len) - strend); + size_t new_src_len = ( + first_block_len + addition_len + second_block_len); + + src = (char *)realloc((char *)src, sizeof(char) * new_src_len); + src[new_src_len] = 0; + + memmove(&src[first_block_len + addition_len], strend, second_block_len); + memcpy(&src[first_block_len], addition_str, addition_len); + + /* Fuckin' hack */ + for (int i = 0; i < new_src_len; i++) { + if (src[i] == 0) + src[i] = ' '; + } + + *src_len = strlen(src); + return 1; +} + +static int process_defines( + char *src, int *src_len, struct tvm_htab_ctx *defines) +{ + char *pp_directive_delimiter = strstr(src, TOK_DEFINE); + + if (!pp_directive_delimiter) + return 0; + + char *begin = pp_directive_delimiter; + char *end = strchr(begin, '\n'); + + if (!end) + return 0; + + int offset = strlen(TOK_DEFINE) + 1; + + if (begin + offset >= end) { + printf("Define missing arguments.\n"); + return -1; + } + + int length = (end - (begin + offset)); + char tempstr[length + 1]; + + memset(tempstr, 0, length + 1); + memcpy(tempstr, begin + offset, length); + + char *keystr = tempstr; + char *valstr = strchr(tempstr, ' '); + + /* If there is a value, seperate the key and value + * with a null character. + */ + if (valstr) { + *valstr = 0; + valstr += 1; + } + + if (!keystr || !valstr) { + printf("Define missing arguments.\n"); + return -1; + } + + if (tvm_htab_find(defines, keystr) < 0) + tvm_htab_add_ref(defines, keystr, valstr, strlen(valstr) + 1); + else { + printf("Multiple definitions for %s.\n", keystr); + return -1; + } + + /* Remove the define line so it is not processed again. */ + size_t new_length = *src_len - (end - begin); + size_t first_block_len = begin - src; + size_t second_block_len = (src + *src_len) - end; + + memmove(&src[first_block_len], end, second_block_len); + + src = realloc(src, sizeof(char) * new_length); + *src_len = new_length; + + return 1; +} + +static int preprocess_pass( + char *src, int *src_len, struct tvm_htab_ctx *defines) +{ + int ret = 0; + + ret += process_includes(src, src_len, defines); + ret += process_defines(src, src_len, defines); + return ret; +} + + +int tvm_preprocess(char *src, int *src_len, struct tvm_htab_ctx *defines) +{ + int ret = 1; + + while (ret > 0) + ret = preprocess_pass(src, src_len, defines); + + return ret; } diff --git a/libtvm/tvm_program.c b/libtvm/tvm_program.c index 2205022..fe0ef01 100644 --- a/libtvm/tvm_program.c +++ b/libtvm/tvm_program.c @@ -3,73 +3,35 @@ #include #include #include +#include -tvm_program_t *program_create() +struct tvm_prog *tvm_prog_create() { - tvm_program_t *p = (tvm_program_t *)calloc(1, sizeof(tvm_program_t)); - p->label_htab = htab_create(); - p->defines = htab_create(); + struct tvm_prog *p = calloc(1, sizeof(struct tvm_prog)); + + p->label_htab = tvm_htab_create(); + p->defines = tvm_htab_create(); return p; } -void program_destroy(tvm_program_t *p) +void tvm_prog_destroy(struct tvm_prog *p) { - htab_destroy(p->label_htab); + tvm_htab_destroy(p->label_htab); - if(p->values) - { - for(int i = 0; i < p->num_values; i++) free(p->values[i]); + if (p->values) { + for (int i = 0; i < p->num_values; i++) + free(p->values[i]); free(p->values); } - if(p->args) - { - for(int i = 0; p->args[i]; i++) free(p->args[i]); + if (p->args) { + for (int i = 0; p->args[i]; i++) + free(p->args[i]); free(p->args); } - if(p->instr) free(p->instr); + if (p->instr) + free(p->instr); free(p); } - -int program_interpret(tvm_program_t *p, char *filename, tvm_memory_t *pMemory) -{ - FILE *pFile = NULL; - int source_length = 0; - - /* Attempt to open the file. If the file cannot be opened, try once more. */ - if(filename) - for(int i = 0; i < 2; i++) - if(!pFile) pFile = tvm_fopen(filename, ".vm", "r"); - - if(!pFile) - { - printf("File was not found, or does not exist. Unable to interpret.\n"); - return 1; - } - - source_length = tvm_flength(pFile); - char *source = calloc(source_length, sizeof(char)); - - tvm_fcopy(source, source_length, pFile); - fclose(pFile); - - int err = 0; - while((err = tvm_preprocess(source, &source_length, p->defines)) > 0); - - /* The preprocessor encountered a problem. */ - if (err < 0) - return 1; - - tvm_lexer_t *lexer_ctx = lexer_create(); - lex(lexer_ctx, source, p->defines); - free(source); - - if(parse_labels(p, (const char ***)lexer_ctx->tokens) != 0) return 1; - if(parse_instructions(p, (const char ***)lexer_ctx->tokens, pMemory) != 0) return 1; - - lexer_destroy(lexer_ctx); - return 0; -} - diff --git a/src/tvmi.c b/src/tvmi.c index 5e10cb7..eb3e3c1 100644 --- a/src/tvmi.c +++ b/src/tvmi.c @@ -3,12 +3,14 @@ #include -int main(int argc, char** argv) +int main(int argc, char **argv) { - tvm_t* vm = tvm_create(); - if(vm != NULL && tvm_interpret(vm, argv[1]) == 0) tvm_run(vm); + struct tvm_ctx *vm = tvm_vm_create(); - tvm_destroy(vm); + if (vm != NULL && tvm_vm_interpret(vm, argv[1]) == 0) + tvm_vm_run(vm); + + tvm_vm_destroy(vm); return 0; } diff --git a/tdb/main.c b/tdb/main.c index c346418..4565770 100644 --- a/tdb/main.c +++ b/tdb/main.c @@ -3,10 +3,10 @@ int main(int argc, char **argv) { - tvm_t *vm = tvm_create(); - if(vm != NULL && tvm_interpret(vm, argv[1]) == 0) tdb_shell(vm); + struct tvm_ctx *vm = tvm_vm_create(); + if(vm != NULL && tvm_vm_interpret(vm, argv[1]) == 0) tdb_shell(vm); - tvm_destroy(vm); + tvm_vm_destroy(vm); return 0; } diff --git a/tdb/tdb.c b/tdb/tdb.c index 7476492..c8442b5 100644 --- a/tdb/tdb.c +++ b/tdb/tdb.c @@ -1,5 +1,6 @@ #include "tdb.h" #include +#include #include @@ -12,7 +13,7 @@ const char *commands[] = {"q", "run", "break", "step", "continue", 0}; static void tokenize(char *str, char **tokens); static int cmd_to_idx(char *cmd); -void tdb_shell(tvm_t *vm) +void tdb_shell(struct tvm_ctx *vm) { int run = 1, i; int running = 0; @@ -21,11 +22,11 @@ void tdb_shell(tvm_t *vm) char str[MAX_INPUT_LENGTH]; int num_breakpoints = 0; - tdb_breakpoint_t *breakpoints = NULL; + struct tdb_breakpoint *breakpoints = NULL; for(i = 0; i < MAX_TOKENS; i++) tokens[i] = malloc(TOKEN_LENGTH); - vm->pMemory->registers[0x8].i32 = vm->pProgram->start; + vm->mem->registers[0x8].i32 = vm->prog->start; while(run && !feof(stdin)) { @@ -45,18 +46,18 @@ void tdb_shell(tvm_t *vm) case 0x0: run = 0; break; case 0x1: if(running) printf("The program is already running.\n"); else { retcode = tdb_run(vm, breakpoints, num_breakpoints); running = 1; } break; - case 0x2: breakpoints = realloc(breakpoints, sizeof(tdb_breakpoint_t) * ++num_breakpoints); + case 0x2: breakpoints = realloc(breakpoints, sizeof(struct tdb_breakpoint) * ++num_breakpoints); breakpoints[num_breakpoints - 1].address = tvm_parse_value(tokens[1]); break; - case 0x3: tvm_step(vm, &vm->pMemory->registers[0x8].i32); - vm->pMemory->registers[0x8].i32++; - printf("Advancing instruction pointer to %i\n", vm->pMemory->registers[0x8].i32); break; - case 0x4: tvm_step(vm, &vm->pMemory->registers[0x8].i32); - vm->pMemory->registers[0x8].i32++; + case 0x3: tvm_step(vm, &vm->mem->registers[0x8].i32); + vm->mem->registers[0x8].i32++; + printf("Advancing instruction pointer to %i\n", vm->mem->registers[0x8].i32); break; + case 0x4: tvm_step(vm, &vm->mem->registers[0x8].i32); + vm->mem->registers[0x8].i32++; retcode = tdb_run(vm, breakpoints, num_breakpoints); break; }; - if(vm->pProgram->instr[vm->pMemory->registers[0x8].i32] == -0x1) printf("End of program reached\n"); - if(retcode == 1) printf("Breakpoint hit at address: %i\n", vm->pMemory->registers[0x8].i32); + if(vm->prog->instr[vm->mem->registers[0x8].i32] == -0x1) printf("End of program reached\n"); + if(retcode == 1) printf("Breakpoint hit at address: %i\n", vm->mem->registers[0x8].i32); } free(breakpoints); @@ -64,9 +65,9 @@ void tdb_shell(tvm_t *vm) for(i = 0; i < MAX_TOKENS; i++) free(tokens[i]); } -int tdb_run(tvm_t* vm, tdb_breakpoint_t* breakpoints, int num_breakpoints) +int tdb_run(struct tvm_ctx* vm, struct tdb_breakpoint* breakpoints, int num_breakpoints) { - for(int *instr_idx = &vm->pMemory->registers[0x8].i32; vm->pProgram->instr[*instr_idx] != -0x1; ++(*instr_idx)) + for(int *instr_idx = &vm->mem->registers[0x8].i32; vm->prog->instr[*instr_idx] != -0x1; ++(*instr_idx)) { for(int i = 0; i < num_breakpoints; i++) if(breakpoints[i].address == *instr_idx) return 1; /* Breakpoint hit */ tvm_step(vm, instr_idx); diff --git a/tdb/tdb.h b/tdb/tdb.h index 1ded93a..47c5ade 100644 --- a/tdb/tdb.h +++ b/tdb/tdb.h @@ -4,9 +4,9 @@ #include #include "tdb_breakpoint.h" -void tdb_shell(tvm_t *vm); +void tdb_shell(struct tvm_ctx *vm); -int tdb_run(tvm_t *vm, tdb_breakpoint_t *breakpoints, int num_breakpoints); -void tdb_step(tvm_t *vm); +int tdb_run(struct tvm_ctx *vm, struct tdb_breakpoint *breakpoints, int num_breakpoints); +void tdb_step(struct tvm_ctx *vm); #endif diff --git a/tdb/tdb_breakpoint.h b/tdb/tdb_breakpoint.h index e480bf7..c0d58c4 100644 --- a/tdb/tdb_breakpoint.h +++ b/tdb/tdb_breakpoint.h @@ -4,13 +4,13 @@ #define TDB_BREAKPOINT_LABEL 0x1 #define TDB_BREAKPOINT_ADDRESS 0x2 -typedef struct tdb_breakpoint_s +struct tdb_breakpoint { int address; char *label; int type; -} tdb_breakpoint_t; +}; #endif