From: Dale Weiler Date: Tue, 17 Apr 2012 20:14:00 +0000 (-0400) Subject: replaced getline with util_getline X-Git-Tag: 0.1-rc1~654 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=7501444addfdbbc1ded33fde15a656cb6f6ac40b;p=xonotic%2Fgmqcc.git replaced getline with util_getline --- diff --git a/assembler.c b/assembler.c index a022a20..14255ff 100644 --- a/assembler.c +++ b/assembler.c @@ -31,16 +31,16 @@ static const struct { const size_t o; /* operands */ const size_t l; /* menomic len */ } const asm_instr[] = { - [INSTR_DONE] = { "DONE" , 0, 4 }, - [INSTR_MUL_F] = { "MUL_F" , 0, 5 }, - [INSTR_MUL_V] = { "MUL_V" , 0, 5 }, - [INSTR_MUL_FV] = { "MUL_FV" , 0, 6 }, - [INSTR_MUL_VF] = { "MUL_VF" , 0, 6 }, + [INSTR_DONE] = { "DONE" , 1, 4 }, + [INSTR_MUL_F] = { "MUL_F" , 3, 5 }, + [INSTR_MUL_V] = { "MUL_V" , 3, 5 }, + [INSTR_MUL_FV] = { "MUL_FV" , 3, 6 }, + [INSTR_MUL_VF] = { "MUL_VF" , 3, 6 }, [INSTR_DIV_F] = { "DIV" , 0, 3 }, - [INSTR_ADD_F] = { "ADD_F" , 0, 5 }, - [INSTR_ADD_V] = { "ADD_V" , 0, 5 }, - [INSTR_SUB_F] = { "SUB_F" , 0, 5 }, - [INSTR_SUB_V] = { "DUB_V" , 0, 5 }, + [INSTR_ADD_F] = { "ADD_F" , 3, 5 }, + [INSTR_ADD_V] = { "ADD_V" , 3, 5 }, + [INSTR_SUB_F] = { "SUB_F" , 3, 5 }, + [INSTR_SUB_V] = { "DUB_V" , 3, 5 }, [INSTR_EQ_F] = { "EQ_F" , 0, 4 }, [INSTR_EQ_V] = { "EQ_V" , 0, 4 }, [INSTR_EQ_S] = { "EQ_S" , 0, 4 }, @@ -114,10 +114,10 @@ const char *const asm_keys[] = { static char *const asm_getline(size_t *byte, FILE *fp) { char *line = NULL; - ssize_t read = getline(&line, byte, fp); + ssize_t read = util_getline(&line, byte, fp); *byte = read; if (read == -1) { - free (line); + mem_d (line); return NULL; } return line; @@ -138,12 +138,29 @@ void asm_close(FILE *fp) { fclose(fp); code_write(); } + +/* + * Following parse states: + * ASM_FUNCTION -- in a function accepting input statements + * .... + */ +typedef enum { + ASM_NULL, + ASM_FUNCTION +} asm_state; + +typedef struct { + char *name; /* name of constant */ + int offset; /* location in globals */ +} globals; +VECTOR_MAKE(globals, assembly_constants); void asm_parse(FILE *fp) { - char *data = NULL; - char *skip = NULL; - long line = 1; /* current line */ - size_t size = 0; /* size of line */ + char *data = NULL; + char *skip = NULL; + long line = 1; /* current line */ + size_t size = 0; /* size of line */ + asm_state state = ASM_NULL; while ((data = asm_getline(&size, fp)) != NULL) { skip = data; @@ -176,6 +193,10 @@ void asm_parse(FILE *fp) { (void)offset_functions; \ (void)offset_fields; \ (void)offset_defs; \ + assembly_constants_add((globals){ \ + .name = util_strdup(skip), \ + .offset = offset_globals \ + }); \ } \ goto end; \ } @@ -213,10 +234,17 @@ void asm_parse(FILE *fp) { .offset = offset_globals, /* offset to offset in string table (for data)*/ .name = offset_chars /* location of name in string table (for name)*/ }); + code_strings_add('h'); }); /* FUNCTION */ DECLTYPE(asm_keys[5], { /* TODO: parse */ + if (state != ASM_NULL) { + printf("%li: Error unfinished function block, expected DONE or RETURN\n", line); + goto end; + } + + state = ASM_FUNCTION; code_defs_add((prog_section_def){ .type = TYPE_VOID, .offset = offset_globals, @@ -237,19 +265,64 @@ void asm_parse(FILE *fp) { /* if we make it this far then we have statements */ { - size_t i = 0; + size_t i = 0; /* counter */ + size_t o = 0; /* operands */ + char *t = NULL; /* token */ + + /* + * Most ops a single statement can have is three. + * lets allocate some space for all of those here. + */ + char op[3][32768] = {{0},{0},{0}}; for (; i < sizeof(asm_instr)/sizeof(*asm_instr); i++) { if (!strncmp(skip, asm_instr[i].m, asm_instr[i].l)) { - /* TODO */ + if (state != ASM_FUNCTION) { + printf("%li: Statement not inside function block\n", line); + goto end; + } + + /* update parser state */ + if (i == INSTR_DONE || i == INSTR_RETURN) { + goto end; + state = ASM_NULL; + } + + /* parse the statement */ + o = asm_instr[i].o; /* operands */ + skip += asm_instr[i].l; /* skip instruction */ + t = strtok(skip, " ,"); + i = 0; + while (t != NULL && i < 3) { + strcpy(op[i], t); + t = strtok(NULL, " ,"); + i ++; + } + + util_debug("ASM", "Operand 1: %s\n", util_strrnl(op[0])); + util_debug("ASM", "Operand 2: %s\n", util_strrnl(op[1])); + util_debug("ASM", "Operand 3: %s\n", util_strrnl(op[2])); + + /* check */ + if (i != o) { + printf("not enough operands, expected: %li, got %li\n", o, i); + } + + /* TODO: hashtable value LOAD .... etc */ + code_statements_add((prog_section_statement){ + i, {0}, {0}, {0} + }); goto end; } } } /* if we made it this far something is wrong */ - printf("ERROR"); + if (*skip != '\0') + printf("%li: Invalid statement, expression, or decleration\n", line); end: - free(data); + //free(data); + mem_d(data); + line ++; } } diff --git a/code.c b/code.c index c2ae9c8..f6b64ad 100644 --- a/code.c +++ b/code.c @@ -158,43 +158,26 @@ void code_write() { fwrite(code_globals_data, 1, sizeof(int) *code_globals_elements, fp); fwrite(code_strings_data, 1, 1 *code_strings_elements, fp); - free(code_statements_data); - free(code_defs_data); - free(code_fields_data); - free(code_functions_data); - free(code_globals_data); - free(code_strings_data); + mem_d(code_statements_data); + mem_d(code_defs_data); + mem_d(code_fields_data); + mem_d(code_functions_data); + mem_d(code_globals_data); + mem_d(code_strings_data); - util_debug("CODE","wrote program.dat\n\ + util_debug("GEN","wrote program.dat:\n\ version: = %d\n\ crc16: = %d\n\ - statements {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - defs {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - fields {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - functions {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - globals {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - strings {\n\ - .offset = %d\n\ - .length = %d\n\ - }\n\ - entfield: = %d\n", + entfield: = %d\n\ + statements {.offset = % 8d, .length = % 8d}\n\ + defs {.offset = % 8d, .length = % 8d}\n\ + fields {.offset = % 8d, .length = % 8d}\n\ + functions {.offset = % 8d, .length = % 8d}\n\ + globals {.offset = % 8d, .length = % 8d}\n\ + strings {.offset = % 8d, .length = % 8d}\n", code_header.version, code_header.crc16, + code_header.entfield, code_header.statements.offset, code_header.statements.length, code_header.defs.offset, @@ -206,8 +189,7 @@ void code_write() { code_header.strings.offset, code_header.strings.length, code_header.globals.offset, - code_header.globals.length, - code_header.entfield + code_header.globals.length ); fclose(fp); diff --git a/gmqcc.h b/gmqcc.h index e5d1a56..d9e3a9c 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -160,7 +160,9 @@ void *util_memory_a(unsigned int, unsigned int, const char *); void util_memory_d(void *, unsigned int, const char *); char *util_strdup (const char *); char *util_strrq (char *); +char *util_strrnl (char *); void util_debug (const char *, const char *, ...); +int util_getline (char **, size_t *, FILE *); #ifdef NOTRACK # define mem_a(x) malloc(x) @@ -181,11 +183,12 @@ void util_debug (const char *, const char *, ...); } else { \ N##_allocated *= 2; \ } \ - void *temp = realloc(N##_data, (N##_allocated * sizeof(T))); \ + void *temp = mem_a(N##_allocated * sizeof(T)); \ if (!temp) { \ free(temp); \ return -1; \ } \ + memcpy(temp, N##_data, (N##_elements * sizeof(T))); \ N##_data = (T*)temp; \ } \ N##_data[N##_elements] = element; \ diff --git a/util.c b/util.c index 6e02fe7..6e044ac 100644 --- a/util.c +++ b/util.c @@ -21,6 +21,7 @@ * SOFTWARE. */ #include +#include #include "gmqcc.h" struct memblock_t { @@ -79,7 +80,7 @@ char *util_strdup(const char *s) { } /* - * Removed quotes from a string, escapes from \ in string + * Remove quotes from a string, escapes from \ in string * as well. This function shouldn't be used to create a * char array that is later freed (it uses pointer arith) */ @@ -100,6 +101,20 @@ char *util_strrq(char *s) { return dst; } +/* + * Remove newline from a string (if it exists). This is + * done pointer wise instead of strlen(), and an array + * access. + */ +char *util_strrnl(char *s) { + char *cpy = s; + while (cpy && *cpy && *cpy != '\n') + cpy++; + + *cpy = '\0'; + return s; +} + void util_debug(const char *area, const char *ms, ...) { va_list va; va_start(va, ms); @@ -110,3 +125,57 @@ void util_debug(const char *area, const char *ms, ...) { vfprintf(stdout, ms, va); va_end (va); } + +/* + * Implements libc getline for systems that don't have it, which is + * assmed all. This works the same as getline(). + */ +int util_getline(char **lineptr, size_t *n, FILE *stream) { + int chr; + int ret; + char *pos; + + if (!lineptr || !n || !stream) + return -1; + if (!*lineptr) { + if (!(*lineptr = mem_a((*n = 64)))) + return -1; + } + + chr = *n; + pos = *lineptr; + + for (;;) { + int c = getc(stream); + + if (chr < 2) { + char *tmp = mem_a((*n+=(*n>16)?*n:64)); + if (!tmp) + return -1; + + chr = *n + *lineptr - pos; + strcpy(tmp,*lineptr); + + if (!(*lineptr = tmp)) + return -1; + + pos = *n - chr + *lineptr; + } + + if (ferror(stream)) + return -1; + if (c == EOF) { + if (pos == *lineptr) + return -1; + else + break; + } + + *pos++ = c; + chr--; + if (c == '\n') + break; + } + *pos = '\0'; + return (ret = pos - *lineptr); +}