]> git.rm.cloudns.org Git - xonotic/gmqcc.git/commitdiff
Implemented support for having codegen (and lno files) be wrote out to memory, this...
authorDale Weiler <killfieldengine@gmail.com>
Sun, 28 Apr 2013 04:29:20 +0000 (04:29 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Sun, 28 Apr 2013 04:29:20 +0000 (04:29 +0000)
code.c

diff --git a/code.c b/code.c
index b0ce2baa04aa138b24a81004257414b7ad81a3cc..77bba3ec651dbadbf9d0085e665aaf0456a82e07 100644 (file)
--- a/code.c
+++ b/code.c
@@ -114,30 +114,26 @@ qcint code_alloc_field (code_t *code, size_t qcsize)
     return pos;
 }
 
-bool code_write(code_t *code, const char *filename, const char *lnofile) {
-    prog_header  code_header;
-    FILE        *fp           = NULL;
-    size_t       it           = 2;
-
-    code_header.statements.offset = sizeof(prog_header);
-    code_header.statements.length = vec_size(code->statements);
-    code_header.defs.offset       = code_header.statements.offset + (sizeof(prog_section_statement) * vec_size(code->statements));
-    code_header.defs.length       = vec_size(code->defs);
-    code_header.fields.offset     = code_header.defs.offset       + (sizeof(prog_section_def)       * vec_size(code->defs));
-    code_header.fields.length     = vec_size(code->fields);
-    code_header.functions.offset  = code_header.fields.offset     + (sizeof(prog_section_field)     * vec_size(code->fields));
-    code_header.functions.length  = vec_size(code->functions);
-    code_header.globals.offset    = code_header.functions.offset  + (sizeof(prog_section_function)  * vec_size(code->functions));
-    code_header.globals.length    = vec_size(code->globals);
-    code_header.strings.offset    = code_header.globals.offset    + (sizeof(int32_t)                * vec_size(code->globals));
-    code_header.strings.length    = vec_size(code->chars);
-    code_header.version           = 6;
+static void code_create_header(code_t *code, prog_header *code_header) {
+    code_header->statements.offset = sizeof(prog_header);
+    code_header->statements.length = vec_size(code->statements);
+    code_header->defs.offset       = code_header->statements.offset + (sizeof(prog_section_statement) * vec_size(code->statements));
+    code_header->defs.length       = vec_size(code->defs);
+    code_header->fields.offset     = code_header->defs.offset       + (sizeof(prog_section_def)       * vec_size(code->defs));
+    code_header->fields.length     = vec_size(code->fields);
+    code_header->functions.offset  = code_header->fields.offset     + (sizeof(prog_section_field)     * vec_size(code->fields));
+    code_header->functions.length  = vec_size(code->functions);
+    code_header->globals.offset    = code_header->functions.offset  + (sizeof(prog_section_function)  * vec_size(code->functions));
+    code_header->globals.length    = vec_size(code->globals);
+    code_header->strings.offset    = code_header->globals.offset    + (sizeof(int32_t)                * vec_size(code->globals));
+    code_header->strings.length    = vec_size(code->chars);
+    code_header->version           = 6;
 
     if (OPTS_OPTION_BOOL(OPTION_FORCECRC))
-        code_header.crc16         = OPTS_OPTION_U16(OPTION_FORCED_CRC);
+        code_header->crc16         = OPTS_OPTION_U16(OPTION_FORCED_CRC);
     else
-        code_header.crc16         = code->crc;
-    code_header.entfield          = code->entfields;
+        code_header->crc16         = code->crc;
+    code_header->entfield          = code->entfields;
 
     if (OPTS_FLAG(DARKPLACES_STRING_TABLE_BUG)) {
         util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
@@ -149,20 +145,118 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
     }
 
     /* ensure all data is in LE format */
-    util_endianswap(&code_header.version,    1, sizeof(code_header.version));
-    util_endianswap(&code_header.crc16,      1, sizeof(code_header.crc16));
-    util_endianswap(&code_header.statements, 2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.defs,       2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.fields,     2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.functions,  2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.strings,    2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.globals,    2, sizeof(code_header.statements.offset));
-    util_endianswap(&code_header.entfield,   1, sizeof(code_header.entfield));
+    util_endianswap(&code_header->version,    1, sizeof(code_header->version));
+    util_endianswap(&code_header->crc16,      1, sizeof(code_header->crc16));
+    util_endianswap(&code_header->statements, 2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->defs,       2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->fields,     2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->functions,  2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->strings,    2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->globals,    2, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->entfield,   1, sizeof(code_header->entfield));
+
+    /*
+     * These are not part of the header but we ensure LE format here to save on duplicated
+     * code.
+     */  
     util_endianswap(code->statements, vec_size(code->statements), sizeof(prog_section_statement));
     util_endianswap(code->defs,       vec_size(code->defs),       sizeof(prog_section_def));
     util_endianswap(code->fields,     vec_size(code->fields),     sizeof(prog_section_field));
     util_endianswap(code->functions,  vec_size(code->functions),  sizeof(prog_section_function));
     util_endianswap(code->globals,    vec_size(code->globals),    sizeof(int32_t));
+}
+
+/*
+ * Same principle except this one allocates memory and writes the lno(optional) and the dat file
+ * directly out to allocated memory. Which is actually very useful for the future library support
+ * we're going to add.
+ */   
+bool code_write_memory(code_t *code, uint8_t **datmem, size_t *sizedat, uint8_t **lnomem, size_t *sizelno) {
+    prog_header code_header;
+    uint32_t    offset  = 0;
+
+    if (!datmem)
+        return false;
+
+    code_create_header(code, &code_header);
+
+    #define WRITE_CHUNK(C,X,S)                                     \
+        do {                                                       \
+            memcpy((void*)(&(*C)[offset]), (const void*)(X), (S)); \
+            offset += (S);                                         \
+        } while (0)
+
+    /* Calculate size required to store entire file out to memory */
+    if (lnomem) {
+        uint32_t version = 1;
+
+        *sizelno += 4;               /* LNOF */
+        *sizelno += sizeof(version);
+        *sizelno += sizeof(code_header.defs.length);
+        *sizelno += sizeof(code_header.globals.length);
+        *sizelno += sizeof(code_header.fields.length);
+        *sizelno += sizeof(code_header.statements.length);
+        *sizelno += sizeof(code->linenums[0]) * vec_size(code->linenums);
+
+        *lnomem   = (uint8_t*)mem_a(*sizelno);
+
+        WRITE_CHUNK(lnomem, "LNOF",                         4);
+        WRITE_CHUNK(lnomem, &version,                       sizeof(version));
+        WRITE_CHUNK(lnomem, &code_header.defs.length,       sizeof(code_header.defs.length));
+        WRITE_CHUNK(lnomem, &code_header.globals.length,    sizeof(code_header.globals.length));
+        WRITE_CHUNK(lnomem, &code_header.fields.length,     sizeof(code_header.fields.length));
+        WRITE_CHUNK(lnomem, &code_header.statements.length, sizeof(code_header.statements.length));
+
+        /* something went terribly wrong */
+        if (offset != *sizelno) {
+            mem_d(*lnomem);
+            *sizelno = 0;
+            return false;
+        }
+        offset = 0;
+    }
+
+    /* Write out the dat */
+    *sizedat += sizeof(prog_header);
+    *sizedat += sizeof(prog_section_statement) * vec_size(code->statements);
+    *sizedat += sizeof(prog_section_def)       * vec_size(code->defs);
+    *sizedat += sizeof(prog_section_field)     * vec_size(code->fields);
+    *sizedat += sizeof(prog_section_function)  * vec_size(code->functions);
+    *sizedat += sizeof(int32_t)                * vec_size(code->globals);
+    *sizedat += 1                              * vec_size(code->chars);
+
+    *datmem = (uint8_t*)mem_a(*sizedat);
+
+    WRITE_CHUNK(datmem, &code_header,     sizeof(prog_header));
+    WRITE_CHUNK(datmem, code->statements, sizeof(prog_section_statement) * vec_size(code->statements));
+    WRITE_CHUNK(datmem, code->defs,       sizeof(prog_section_def)       * vec_size(code->defs));
+    WRITE_CHUNK(datmem, code->fields,     sizeof(prog_section_field)     * vec_size(code->fields));
+    WRITE_CHUNK(datmem, code->functions,  sizeof(prog_section_function)  * vec_size(code->functions));
+    WRITE_CHUNK(datmem, code->globals,    sizeof(int32_t)                * vec_size(code->globals));
+    WRITE_CHUNK(datmem, code->chars,      1                              * vec_size(code->chars));
+
+    #undef WRITE_CHUNK
+
+    vec_free(code->statements);
+    vec_free(code->linenums);
+    vec_free(code->defs);
+    vec_free(code->fields);
+    vec_free(code->functions);
+    vec_free(code->globals);
+    vec_free(code->chars);
+
+    util_htdel(code->string_cache);
+    mem_d(code);
+
+    return true;
+}
+
+bool code_write(code_t *code, const char *filename, const char *lnofile) {
+    prog_header  code_header;
+    FILE        *fp           = NULL;
+    size_t       it           = 2;
+
+    code_create_header(code, &code_header);
 
     if (lnofile) {
         uint32_t version = 1;
@@ -175,13 +269,13 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
         util_endianswap(code->linenums, vec_size(code->linenums), sizeof(code->linenums[0]));
 
 
-        if (fs_file_write("LNOF",                           4,                                       1,                        fp) != 1 ||
-            fs_file_write(&version,                         sizeof(version),                         1,                        fp) != 1 ||
+        if (fs_file_write("LNOF",                          4,                                      1,                        fp) != 1 ||
+            fs_file_write(&version,                        sizeof(version),                        1,                        fp) != 1 ||
             fs_file_write(&code_header.defs.length,        sizeof(code_header.defs.length),        1,                        fp) != 1 ||
             fs_file_write(&code_header.globals.length,     sizeof(code_header.globals.length),     1,                        fp) != 1 ||
             fs_file_write(&code_header.fields.length,      sizeof(code_header.fields.length),      1,                        fp) != 1 ||
             fs_file_write(&code_header.statements.length,  sizeof(code_header.statements.length),  1,                        fp) != 1 ||
-            fs_file_write(code->linenums,                   sizeof(code->linenums[0]),               vec_size(code->linenums), fp) != vec_size(code->linenums))
+            fs_file_write(code->linenums,                  sizeof(code->linenums[0]),              vec_size(code->linenums), fp) != vec_size(code->linenums))
         {
             con_err("failed to write lno file\n");
         }
@@ -194,7 +288,7 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) {
     if (!fp)
         return false;
 
-    if (1                          != fs_file_write(&code_header,    sizeof(prog_header)           , 1                         , fp) ||
+    if (1                          != fs_file_write(&code_header,     sizeof(prog_header)           , 1                         , fp) ||
         vec_size(code->statements) != fs_file_write(code->statements, sizeof(prog_section_statement), vec_size(code->statements), fp) ||
         vec_size(code->defs)       != fs_file_write(code->defs,       sizeof(prog_section_def)      , vec_size(code->defs)      , fp) ||
         vec_size(code->fields)     != fs_file_write(code->fields,     sizeof(prog_section_field)    , vec_size(code->fields)    , fp) ||