X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=asm.c;h=b1f48802658c14e319760d47221aef36c5764f0a;hb=de01d34925cb609607e76b3cb7e7a48312f2cc8e;hp=ae50a0520013d26df7ca107d0087f2a092bb9127;hpb=20f203495d88a919408a45011308c2cdc86edc4f;p=xonotic%2Fgmqcc.git diff --git a/asm.c b/asm.c index ae50a05..b1f4880 100644 --- a/asm.c +++ b/asm.c @@ -22,18 +22,25 @@ */ #include "gmqcc.h" /* - * Some assembler keywords not part of the opcodes above: these are - * for creating functions, or constants. + * Following parse states: + * ASM_FUNCTION -- in a function accepting input statements + * .... */ -const char *const asm_keys[] = { - "FLOAT" , /* define float */ - "VECTOR" , /* define vector */ - "ENTITY" , /* define ent */ - "FIELD" , /* define field */ - "STRING" , /* define string */ - "FUNCTION" -}; +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); +/* + * Assembly text processing: this handles the internal collection + * of text to allow parsing and assemblation. + */ static char *const asm_getline(size_t *byte, FILE *fp) { char *line = NULL; ssize_t read = util_getline(&line, byte, fp); @@ -45,32 +52,18 @@ static char *const asm_getline(size_t *byte, FILE *fp) { return line; } +/* + * Entire external interface for main.c - to perform actual assemblation + * of assembly files. + */ 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++) @@ -85,11 +78,34 @@ void asm_clear() { * are locals. */ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *state) { - if (strstr(skip, "FLOAT:") == &skip[0]) { return true; } - if (strstr(skip, "VECTOR:") == &skip[0]) { return true; } - if (strstr(skip, "ENTITY:") == &skip[0]) { return true; } - if (strstr(skip, "FIELD:") == &skip[0]) { return true; } - if (strstr(skip, "STRING:") == &skip[0]) { return true; } + if (!(strstr(skip, "FLOAT:") == &skip[0]) && + (strstr(skip, "VECTOR:") == &skip[0]) && + (strstr(skip, "ENTITY:") == &skip[0]) && + (strstr(skip, "FIELD:") == &skip[0]) && + (strstr(skip, "STRING:") == &skip[0])) return false; + + /* TODO: determine if constant, global, or local */ + switch (*skip) { + /* VECTOR */ case 'V': { + const char *find = skip + 7; + while (*find == ' ' || *find == '\t') find++; + printf("found VECTOR %s\n", find); + break; + } + /* ENTITY */ case 'E': { + const char *find = skip + 7; + while (*find == ' ' || *find == '\t') find++; + printf("found ENTITY %s\n", find); + break; + } + /* STRING */ case 'S': { + const char *find = skip + 7; + while (*find == ' ' || *find == '\t') find++; + printf("found STRING %s\n", find); + break; + } + } + return false; } @@ -103,8 +119,92 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat return false; if (strstr(skip, "FUNCTION:") == &skip[0]) { - *state = ASM_FUNCTION; /* update state */ - /* TODO */ + char *copy = util_strsws(skip+10); + char *name = util_strchp(copy, strchr(copy, '\0')); + + /* TODO: failure system, missing name */ + if (!name) { + printf("expected name on function\n"); + mem_d(copy); + mem_d(name); + return false; + } + /* TODO: failure system, invalid name */ + if (!isalpha(*name) || util_strupper(name)) { + printf("invalid identifer for function name\n"); + mem_d(copy); + mem_d(name); + return false; + } + + /* + * Function could be internal function, look for $ + * to determine this. + */ + if (strchr(name, ',')) { + char *find = strchr(name, ',') + 1; + + /* skip whitespace */ + while (*find == ' ' || *find == '\t') + find++; + + if (*find != '$') { + printf("expected $ for internal function selection, got %s instead\n", find); + mem_d(copy); + mem_d(name); + return false; + } + find ++; + if (!isdigit(*find)) { + printf("invalid internal identifier, expected valid number\n"); + mem_d(copy); + mem_d(name); + return false; + } + /* reassign name */ + mem_d(name); + name = util_strchp(name, strchr(name, ',')); + + /* + * Now add the following items to the code system: + * function + * definition (optional) + * global (optional) + * name + */ + code_functions_add((prog_section_function){ + -atoi(find), /* needs to be negated */ + 0, 0, 0, + .name = code_chars_elements, + 0, 0,{0} + }); + code_defs_add((prog_section_def){ + .type = TYPE_FUNCTION, + .offset = code_globals_elements, + .name = code_chars_elements + }); + code_globals_add(code_chars_elements); + + code_chars_put(name, strlen(name)); + code_chars_add('\0'); + + /* + * Sanatize the numerical constant used to select the + * internal function. Must ensure it's all numeric, since + * atoi can silently drop characters from a string and still + * produce a valid constant that would lead to runtime problems. + */ + if (util_strdigit(find)) + printf("found internal function %s, -%d\n", name, atoi(find)); + else + printf("invalid internal function identifier, must be all numeric\n"); + + } else { + /* TODO: function bodies */ + } + + mem_d(copy); + mem_d(name); return true; } return false; @@ -117,19 +217,32 @@ void asm_parse(FILE *fp) { size_t size = 0; /* size of line */ asm_state state = ASM_NULL; - #define asm_end(x) do { mem_d(data); line++; printf(x); } while (0); continue + #define asm_end(x) \ + do { \ + mem_d(data); \ + mem_d(copy); \ + line++; \ + util_debug("ASM", x); \ + } while (0); continue while ((data = asm_getline (&size, fp)) != NULL) { - data = util_strsws(data,&skip); /* skip whitespace */ - data = util_strrnl(data); /* delete newline */ + char *copy = util_strsws(data); /* skip whitespace */ + skip = util_strrnl(copy); /* delete newline */ /* parse type */ - if(asm_parse_type(skip, line, &state)){ asm_end(""); } + if(asm_parse_type(skip, line, &state)){ asm_end("asm_parse_type\n"); } /* parse func */ - if(asm_parse_func(skip, line, &state)){ asm_end(""); } + if(asm_parse_func(skip, line, &state)){ asm_end("asm_parse_func\n"); } + + /* statement closure */ + if (state == ASM_FUNCTION && ( + (strstr(skip, "DONE") == &skip[0])|| + (strstr(skip, "RETURN") == &skip[0]))) state = ASM_NULL; /* TODO: everything */ (void)state; + asm_end("asm_parse_end\n"); } + #undef asm_end asm_clear(); }