]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - assembler.c
replaced getline with util_getline
[xonotic/gmqcc.git] / assembler.c
index a022a20f64de74764985a4b7251e48657449de7a..14255ff36030d8bfa20d881c65fad015d1b185be 100644 (file)
@@ -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 ++;
        }
 }