]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
replaced getline with util_getline
authorDale Weiler <killfieldengine@gmail.com>
Tue, 17 Apr 2012 20:14:00 +0000 (16:14 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Tue, 17 Apr 2012 20:14:00 +0000 (16:14 -0400)
assembler.c
code.c
gmqcc.h
util.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 ++;
        }
 }
diff --git a/code.c b/code.c
index c2ae9c8bf41f811e3917545bc18045e52e54c3f7..f6b64adb79b6caab0b8c5f636edebbb9f2330d17 100644 (file)
--- 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 e5d1a5603bb5965cb7d31c9eedab700771063161..d9e3a9c4c1a1ad7d4b9f8de5b9bf1ff46b0e4d68 100644 (file)
--- 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 6e02fe76aa18225953f4173f070dee5253b52e90..6e044ac14c05c59ba7ebaa65bad1828f0e574dcd 100644 (file)
--- a/util.c
+++ b/util.c
@@ -21,6 +21,7 @@
  * SOFTWARE.
  */
 #include <stdarg.h>
+#include <errno.h>
 #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);
+}