From 0f81682eb83746829c5059484a830c8285338ddf Mon Sep 17 00:00:00 2001 From: Veit Heller Date: Wed, 8 Oct 2014 11:51:34 +0200 Subject: [PATCH] Added parser and test vo vm --- .travis.yml | 2 +- vvm/src/main.c | 12 +++++-- vvm/src/util.h | 2 +- vvm/src/vm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++-- vvm/src/vm.h | 17 ++++++++- 5 files changed, 122 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2b2557c..f1266c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ compiler: - clang - gcc -script: cd vvm && make && bin/vvm && make clean && cd ../nbfi && make && bash test.sh && make clean +script: cd vvm && make && bash test.sh && make clean && cd ../nbfi && make && bash test.sh && make clean diff --git a/vvm/src/main.c b/vvm/src/main.c index d58a203..d0190fc 100644 --- a/vvm/src/main.c +++ b/vvm/src/main.c @@ -23,17 +23,23 @@ int factorial[] = { /** * @brief main + * argc -> the argument counter + * argv -> the argument vector * * executes code in my dsl. */ -int main(){ - int code[] = { ICONST, 72, PRINT, ICONST, 101, PRINT, ICONST, 108, +int main(int argc, char** argv){ + /*int code[] = { ICONST, 72, PRINT, ICONST, 101, PRINT, ICONST, 108, PRINT, ICONST, 108, PRINT, ICONST, 111, PRINT, ICONST, 44, PRINT, ICONST, 32, PRINT, ICONST, 119, PRINT, ICONST, 111, PRINT, ICONST, 114, PRINT, ICONST, 108, PRINT, ICONST, 100, PRINT, ICONST, 33, GSTORE, 0, GLOAD, 0, PRINT, ICONST, 10, PRINT, HALT }; vm_execute(factorial, 22, 0, sizeof(factorial) / sizeof(factorial[0])); printf("\n"); - vm_execute(code, 0, 1, sizeof(code) / sizeof(code[0])); + vm_execute(code, 0, 1, sizeof(code) / sizeof(code[0]));*/ + if(argc != 2) + die(127, "Please specify exactly one file to execute."); + program prog = vm_parse(argv[1]); + vm_execute(prog.code, 22, 0, prog.length); return 0; } diff --git a/vvm/src/util.h b/vvm/src/util.h index 3f4f5aa..9acfa39 100644 --- a/vvm/src/util.h +++ b/vvm/src/util.h @@ -11,7 +11,7 @@ * Lets the program die and emits an error message. */ static inline void die(int code, const char* message){ - fprintf(stderr, "%s", message); + fprintf(stderr, "%s\n", message); exit(code); } #endif diff --git a/vvm/src/vm.c b/vvm/src/vm.c index 6b3dde6..322e2af 100644 --- a/vvm/src/vm.c +++ b/vvm/src/vm.c @@ -32,7 +32,7 @@ static inline void disassemble(int sp, int fp, int ip, int opcode, instruction* printf("\n"); } -void vm_execute(int code[], int ip, int datasize, int length){ +void vm_execute(int code[], int ip, int datasize, unsigned long length){ int data[datasize]; int stack[MAX_SIZE]; int sp = -1; @@ -161,8 +161,101 @@ void vm_execute(int code[], int ip, int datasize, int length){ sp--; default: fprintf(stderr, "Unrecognized: %d\n", opcode); - die(1, "Exit on program failure."); + die(127, "Exit on program failure."); } } return; } + +program vm_parse(char *filename){ + FILE* file = fopen(filename, "r"); + char* line = NULL; + char** command; + unsigned long size = 100; + int* code = malloc(size * sizeof(int)); + unsigned long codep = 0; + register int i; + instruction* ins = setup_instructions(); + unsigned int len = IDEC; + size_t linelength = 0; + + if(!file) + die(127, "Could not open file."); + + while(getline(&line, &linelength, file) != -1){ + short found = FALSE; + strtok(line, "\n"); + command = str_split(line, ' '); + + if(codep == size){ + size += 100; + code = (int *) realloc(code, size * sizeof(int)); + if(code == NULL) + die(127, "Program too big, could not allocate enough storage."); + } + + for(i = 1; i < len; i++) + if(strcmp(ins[i].name, command[0]) == 0){ + code[codep++] = i; + found = TRUE; + break; + } + + if(found && ins[i].operands > 0){ + int nargs = ins[i].operands; + for(i = 1; i <= nargs; i++){ + code[codep++] = (int) strtol(command[i], (char **) NULL, 10); + } + } + } + + fclose(file); + + if(line) + free(line); + + code = (int *) realloc(code, codep * sizeof(int)); + + program prog = {codep, code}; + + return prog; +} + +char** str_split(char* a_str, const char a_delim){ + char** result = 0; + size_t count = 0; + char* tmp = a_str; + char* last_comma = 0; + char delim[2]; + delim[0] = a_delim; + delim[1] = 0; + + while (*tmp){ + if (a_delim == *tmp){ + count++; + last_comma = tmp; + } + tmp++; + } + + count += last_comma < (a_str + strlen(a_str) - 1); + + count++; + + result = malloc(sizeof(char*) * count); + + if (result){ + size_t idx = 0; + char* token = strtok(a_str, delim); + + while (token){ + assert(idx < count); + *(result + idx++) = strdup(token); + token = strtok(0, delim); + } + assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} diff --git a/vvm/src/vm.h b/vvm/src/vm.h index 29abd45..97d5a2e 100644 --- a/vvm/src/vm.h +++ b/vvm/src/vm.h @@ -2,10 +2,17 @@ #define VM_H #include +#include +#include #include "util.h" #include "opcode.h" +typedef struct{ + unsigned long length; + int* code; +} program; + /** * @brief vm_execute * @param code -> instructions @@ -13,6 +20,14 @@ * @param datasize -> maximum data size * @param length -> length of program */ -void vm_execute(int[], int, int, int); +void vm_execute(int[], int, int, unsigned long); + +/** + * @brief vm_parse + * @param file -> filename + */ +program vm_parse(char*); + +char** str_split(char*, const char); #endif