From: Dale Weiler Date: Tue, 24 Apr 2012 20:19:05 +0000 (-0400) Subject: assembler.c -> asm.c X-Git-Tag: 0.1-rc1~636 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=988009a4b35e88c380dc98e0111d4158625ed086;p=xonotic%2Fgmqcc.git assembler.c -> asm.c --- diff --git a/Makefile b/Makefile index 10198d0..f55f705 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OBJ = main.o \ typedef.o \ util.o \ code.o \ - assembler.c + asm.c %.o: %.c $(CC) -c $< -o $@ $(CFLAGS) diff --git a/asm.c b/asm.c new file mode 100644 index 0000000..ece24a2 --- /dev/null +++ b/asm.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2012 + * Dale Weiler + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "gmqcc.h" +/* + * Some assembler keywords not part of the opcodes above: these are + * for creating functions, or constants. + */ +const char *const asm_keys[] = { + "FLOAT" , /* define float */ + "VECTOR" , /* define vector */ + "ENTITY" , /* define ent */ + "FIELD" , /* define field */ + "STRING" , /* define string */ + "FUNCTION" +}; + +static char *const asm_getline(size_t *byte, FILE *fp) { + char *line = NULL; + ssize_t read = util_getline(&line, byte, fp); + *byte = read; + if (read == -1) { + mem_d (line); + return NULL; + } + return line; +} + +void asm_init(const char *file, FILE **fp) { + *fp = fopen(file, "r"); + code_init(); +} + +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_clear() { + size_t i = 0; + for (; i < assembly_constants_elements; i++) + mem_d(assembly_constants_data[i].name); + mem_d(assembly_constants_data); +} + +int asm_parsetype(const char *key, char **skip, long line) { + size_t keylen = strlen(key); + if (!strncmp(key, *skip, keylen)) { + if ((*skip)[keylen] != ':'){ + printf("%li: Missing `:` after decltype\n", line); + exit(1); + } + *skip += keylen+1; + while (**skip == ' ' || **skip == '\t') + (*skip)++; + + if (!isalpha(**skip)) { + printf("%li: Invalid identififer: %s\n", line, *skip); + exit(1); + } else { + assembly_constants_add((globals) { + .name = util_strdup("empty"), + .offset = code_globals_elements + }); + return 1; + } + } + return 0; +} + +void asm_parse(FILE *fp) { + 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 = skip = asm_getline(&size, fp)) != NULL) { + /* remove any whitespace at start */ + while (*skip == ' ' || *skip == '\t') + skip++; + /* remove newline at end of string */ + *(skip+*(&size)-1) = '\0'; + + if (asm_parsetype(asm_keys[5], &skip, line)) { + 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 = code_globals_elements, + .name = code_chars_elements + }); + code_globals_add(code_functions_elements); + code_functions_add((prog_section_function) { + .entry = code_statements_elements, + .firstlocal = 0, + .locals = 0, + .profile = 0, + .name = code_chars_elements, + .file = 0, + .nargs = 0, + .argsize = {0} + }); + code_strings_add(skip); + }; + + #if 0 + /* if we make it this far then we have statements */ + { + size_t i = 0; /* counter */ + size_t o = 0; /* operands */ + size_t c = 0; /* copy */ + 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)) { + 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 */ + c = i; + 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 ++; + } + + /* 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){ + c, + { atof(op[0]) }, + { atof(op[1]) }, + { atof(op[2]) } + }); + goto end; + } + } + } + #endif + + /* if we made it this far something is wrong */ + if (*skip != '\0') + printf("%li: Invalid statement %s, expression, or decleration\n", line, skip); + + end: + mem_d(data); + line ++; + } + asm_clear(); +} diff --git a/assembler.c b/assembler.c deleted file mode 100644 index ece24a2..0000000 --- a/assembler.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2012 - * Dale Weiler - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "gmqcc.h" -/* - * Some assembler keywords not part of the opcodes above: these are - * for creating functions, or constants. - */ -const char *const asm_keys[] = { - "FLOAT" , /* define float */ - "VECTOR" , /* define vector */ - "ENTITY" , /* define ent */ - "FIELD" , /* define field */ - "STRING" , /* define string */ - "FUNCTION" -}; - -static char *const asm_getline(size_t *byte, FILE *fp) { - char *line = NULL; - ssize_t read = util_getline(&line, byte, fp); - *byte = read; - if (read == -1) { - mem_d (line); - return NULL; - } - return line; -} - -void asm_init(const char *file, FILE **fp) { - *fp = fopen(file, "r"); - code_init(); -} - -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_clear() { - size_t i = 0; - for (; i < assembly_constants_elements; i++) - mem_d(assembly_constants_data[i].name); - mem_d(assembly_constants_data); -} - -int asm_parsetype(const char *key, char **skip, long line) { - size_t keylen = strlen(key); - if (!strncmp(key, *skip, keylen)) { - if ((*skip)[keylen] != ':'){ - printf("%li: Missing `:` after decltype\n", line); - exit(1); - } - *skip += keylen+1; - while (**skip == ' ' || **skip == '\t') - (*skip)++; - - if (!isalpha(**skip)) { - printf("%li: Invalid identififer: %s\n", line, *skip); - exit(1); - } else { - assembly_constants_add((globals) { - .name = util_strdup("empty"), - .offset = code_globals_elements - }); - return 1; - } - } - return 0; -} - -void asm_parse(FILE *fp) { - 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 = skip = asm_getline(&size, fp)) != NULL) { - /* remove any whitespace at start */ - while (*skip == ' ' || *skip == '\t') - skip++; - /* remove newline at end of string */ - *(skip+*(&size)-1) = '\0'; - - if (asm_parsetype(asm_keys[5], &skip, line)) { - 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 = code_globals_elements, - .name = code_chars_elements - }); - code_globals_add(code_functions_elements); - code_functions_add((prog_section_function) { - .entry = code_statements_elements, - .firstlocal = 0, - .locals = 0, - .profile = 0, - .name = code_chars_elements, - .file = 0, - .nargs = 0, - .argsize = {0} - }); - code_strings_add(skip); - }; - - #if 0 - /* if we make it this far then we have statements */ - { - size_t i = 0; /* counter */ - size_t o = 0; /* operands */ - size_t c = 0; /* copy */ - 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)) { - 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 */ - c = i; - 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 ++; - } - - /* 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){ - c, - { atof(op[0]) }, - { atof(op[1]) }, - { atof(op[2]) } - }); - goto end; - } - } - } - #endif - - /* if we made it this far something is wrong */ - if (*skip != '\0') - printf("%li: Invalid statement %s, expression, or decleration\n", line, skip); - - end: - mem_d(data); - line ++; - } - asm_clear(); -}