]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - util.c
Cleanups
[xonotic/gmqcc.git] / util.c
diff --git a/util.c b/util.c
index c8d50f5b5fbc15fbff326efbaa45a40f4f734d49..ecae50516514e45db673cd10966ac408a010b0d1 100644 (file)
--- a/util.c
+++ b/util.c
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include <stdarg.h>
-#include <errno.h>
-#include "gmqcc.h"
-
-/* TODO: remove globals ... */
-static uint64_t mem_ab = 0;
-static uint64_t mem_db = 0;
-static uint64_t mem_at = 0;
-static uint64_t mem_dt = 0;
-static uint64_t mem_pk = 0;
-static uint64_t mem_hw = 0;
-
-struct memblock_t {
-    const char  *file;
-    unsigned int line;
-    size_t       byte;
-    struct memblock_t *next;
-    struct memblock_t *prev;
-};
-
-#define PEAK_MEM             \
-    do {                     \
-        if (mem_hw > mem_pk) \
-            mem_pk = mem_hw; \
-    } while (0)
-
-static struct memblock_t *mem_start = NULL;
-
-void *util_memory_a(size_t byte, unsigned int line, const char *file) {
-    struct memblock_t *info = (struct memblock_t*)malloc(sizeof(struct memblock_t) + byte);
-    void              *data = (void*)(info+1);
-    if (!info) return NULL;
-    info->line = line;
-    info->byte = byte;
-    info->file = file;
-    info->prev = NULL;
-    info->next = mem_start;
-    if (mem_start)
-        mem_start->prev = info;
-    mem_start = info;
-
-    mem_at++;
-    mem_ab += info->byte;
-    mem_hw += info->byte;
-
-    PEAK_MEM;
-
-    return data;
-}
-
-void util_memory_d(void *ptrn) {
-    struct memblock_t *info = NULL;
-
-    if (!ptrn) return;
-    info = ((struct memblock_t*)ptrn - 1);
-
-    mem_db += info->byte;
-    mem_hw -= info->byte;
-    mem_dt++;
-
-    if (info->prev)
-        info->prev->next = info->next;
-    if (info->next)
-        info->next->prev = info->prev;
-    if (info == mem_start)
-        mem_start = info->next;
-
-    free(info);
-}
-
-void *util_memory_r(void *ptrn, size_t byte, unsigned int line, const char *file) {
-    struct memblock_t *oldinfo = NULL;
-
-    struct memblock_t *newinfo;
-
-    if (!ptrn)
-        return util_memory_a(byte, line, file);
-    if (!byte) {
-        util_memory_d(ptrn);
-        return NULL;
-    }
-
-    oldinfo = ((struct memblock_t*)ptrn - 1);
-    newinfo = ((struct memblock_t*)malloc(sizeof(struct memblock_t) + byte));
-
-    /* new data */
-    if (!newinfo) {
-        util_memory_d(oldinfo+1);
-        return NULL;
-    }
-
-    /* copy old */
-    memcpy(newinfo+1, oldinfo+1, oldinfo->byte);
-
-    /* free old */
-    if (oldinfo->prev)
-        oldinfo->prev->next = oldinfo->next;
-    if (oldinfo->next)
-        oldinfo->next->prev = oldinfo->prev;
-    if (oldinfo == mem_start)
-        mem_start = oldinfo->next;
-
-    /* fill info */
-    newinfo->line = line;
-    newinfo->byte = byte;
-    newinfo->file = file;
-    newinfo->prev = NULL;
-    newinfo->next = mem_start;
-    if (mem_start)
-        mem_start->prev = newinfo;
-    mem_start = newinfo;
-
-    mem_ab -= oldinfo->byte;
-    mem_hw -= oldinfo->byte;
-    mem_ab += newinfo->byte;
-    mem_hw += newinfo->byte;
-
-    PEAK_MEM;
-
-    free(oldinfo);
-
-    return newinfo+1;
-}
-
-static void util_dumpmem(struct memblock_t *memory, uint16_t cols) {
-    uint32_t i, j;
-    for (i = 0; i < memory->byte + ((memory->byte % cols) ? (cols - memory->byte % cols) : 0); i++) {
-        if (i % cols == 0)    con_out("    0x%06X: ", i);
-        if (i < memory->byte) con_out("%02X "   , 0xFF & ((char*)(memory + 1))[i]);
-        else                  con_out("    ");
-
-        if ((uint16_t)(i % cols) == (cols - 1)) {
-            for (j = i - (cols - 1); j <= i; j++) {
-                con_out("%c",
-                    (j >= memory->byte)
-                        ? ' '
-                        : (isprint(((char*)(memory + 1))[j]))
-                            ? 0xFF & ((char*)(memory + 1)) [j]
-                            : '.'
-                );
-            }
-            con_out("\n");
-        }
-    }
-}
-
-void util_meminfo() {
-    struct memblock_t *info;
-
-
-    if (OPTS_OPTION_BOOL(OPTION_DEBUG)) {
-        for (info = mem_start; info; info = info->next) {
-            con_out("lost: %u (bytes) at %s:%u\n",
-                info->byte,
-                info->file,
-                info->line);
-
-            util_dumpmem(info, OPTS_OPTION_U16(OPTION_MEMDUMPCOLS));
-        }
-    }
+#include <string.h>
+#include <stdlib.h>
 
-    if (OPTS_OPTION_BOOL(OPTION_DEBUG) ||
-        OPTS_OPTION_BOOL(OPTION_MEMCHK)) {
-        con_out("Memory information:\n\
-            Total allocations:   %llu\n\
-            Total deallocations: %llu\n\
-            Total allocated:     %f (MB)\n\
-            Total deallocated:   %f (MB)\n\
-            Total peak memory:   %f (MB)\n\
-            Total leaked memory: %f (MB) in %llu allocations\n",
-                mem_at,
-                mem_dt,
-                (float)(mem_ab)           / 1048576.0f,
-                (float)(mem_db)           / 1048576.0f,
-                (float)(mem_pk)           / 1048576.0f,
-                (float)(mem_ab -  mem_db) / 1048576.0f,
-
-                /* could be more clever */
-                (mem_at -  mem_dt)
-        );
-    }
-}
+#include "gmqcc.h"
 
 /*
- * Some string utility functions, because strdup uses malloc, and we want
- * to track all memory (without replacing malloc).
+ * Initially this was handled with a table in the gmqcc.h header, but 
+ * much to my surprise the contents of the table was duplicated for
+ * each translation unit, causing all these strings to be duplicated
+ * for every .c file it was included into. This method culls back on
+ * it. This is a 'utility' function because the executor also depends
+ * on this for dissasembled bytecode.
  */
-char *_util_Estrdup(const char *s, const char *file, size_t line) {
-    size_t  len = 0;
-    char   *ptr = NULL;
-
-    /* in case of -DNOTRACK */
-    (void)file;
-    (void)line;
-
-    if (!s)
-        return NULL;
-
-    if ((len = strlen(s)) && (ptr = (char*)mem_af(len+1, line, file))) {
-        memcpy(ptr, s, len);
-        ptr[len] = '\0';
-    }
-    return ptr;
-}
-
-char *_util_Estrdup_empty(const char *s, const char *file, size_t line) {
-    size_t  len = 0;
-    char   *ptr = NULL;
-
-    /* in case of -DNOTRACK */
-    (void)file;
-    (void)line;
-
-    if (!s)
-        return NULL;
-
-    len = strlen(s);
-    if ((ptr = (char*)mem_af(len+1, line, file))) {
-        memcpy(ptr, s, len);
-        ptr[len] = '\0';
-    }
-    return ptr;
-}
+const char *util_instr_str[VINSTR_END] = {
+    "DONE",       "MUL_F",      "MUL_V",      "MUL_FV",
+    "MUL_VF",     "DIV_F",      "ADD_F",      "ADD_V",
+    "SUB_F",      "SUB_V",      "EQ_F",       "EQ_V",
+    "EQ_S",       "EQ_E",       "EQ_FNC",     "NE_F",
+    "NE_V",       "NE_S",       "NE_E",       "NE_FNC",
+    "LE",         "GE",         "LT",         "GT",
+    "LOAD_F",     "LOAD_V",     "LOAD_S",     "LOAD_ENT",
+    "LOAD_FLD",   "LOAD_FNC",   "ADDRESS",    "STORE_F",
+    "STORE_V",    "STORE_S",    "STORE_ENT",  "STORE_FLD",
+    "STORE_FNC",  "STOREP_F",   "STOREP_V",   "STOREP_S",
+    "STOREP_ENT", "STOREP_FLD", "STOREP_FNC", "RETURN",
+    "NOT_F",      "NOT_V",      "NOT_S",      "NOT_ENT",
+    "NOT_FNC",    "IF",         "IFNOT",      "CALL0",
+    "CALL1",      "CALL2",      "CALL3",      "CALL4",
+    "CALL5",      "CALL6",      "CALL7",      "CALL8",
+    "STATE",      "GOTO",       "AND",        "OR",
+    "BITAND",     "BITOR"
+};
 
 void util_debug(const char *area, const char *ms, ...) {
     va_list  va;
@@ -416,257 +225,31 @@ uint16_t util_crc16(const char *k, int len, const short clamp) {
 }
 #endif
 
-size_t util_strtocmd(const char *in, char *out, size_t outsz) {
-    size_t sz = 1;
-    for (; *in && sz < outsz; ++in, ++out, ++sz)
-        *out = (*in == '-') ? '_' : (isalpha(*in) && !isupper(*in)) ? *in + 'A' - 'a': *in;
-    *out = 0;
-    return sz-1;
-}
-
-size_t util_strtononcmd(const char *in, char *out, size_t outsz) {
+/* 
+ * modifier is the match to make and the transpsition from it, while add is the upper-value that determines the
+ * transposion from uppercase to lower case.
+ */
+static GMQCC_INLINE size_t util_strtransform(const char *in, char *out, size_t outsz, const char *mod, int add) {
     size_t sz = 1;
-    for (; *in && sz < outsz; ++in, ++out, ++sz)
-        *out = (*in == '_') ? '-' : (isalpha(*in) && isupper(*in)) ? *in + 'a' - 'A' : *in;
+    for (; *in && sz < outsz; ++in, ++out, ++sz) {
+        *out = (*in == mod[0])
+                    ? mod[1]
+                    : (util_isalpha(*in) && util_isupper(*in + add))
+                        ? *in + add
+                        : *in;
+    }
     *out = 0;
     return sz-1;
 }
 
-/* TODO: rewrite ... when I redo the ve cleanup */
-void _util_vec_grow(void **a, size_t i, size_t s) {
-    vector_t *d = vec_meta(*a);
-    size_t    m = *a ? 2 * d->allocated +i : i+1;
-    void     *p = mem_r((*a ? d : NULL), s * m + sizeof(vector_t));
-
-    if (!*a)
-        ((vector_t*)p)->used = 0;
-    *a = (vector_t*)p + 1;
-
-    vec_meta(*a)->allocated = m;
-}
-
-/*
- * Hash table for generic data, based on dynamic memory allocations
- * all around.  This is the internal interface, please look for
- * EXPOSED INTERFACE comment below
- */
-typedef struct hash_node_t {
-    char               *key;   /* the key for this node in table */
-    void               *value; /* pointer to the data as void*   */
-    struct hash_node_t *next;  /* next node (linked list)        */
-} hash_node_t;
-
-GMQCC_INLINE size_t util_hthash(hash_table_t *ht, const char *key) {
-    const uint32_t       mix   = 0x5BD1E995;
-    const uint32_t       rot   = 24;
-    size_t               size  = strlen(key);
-    uint32_t             hash  = 0x1EF0 /* LICRC TAB */  ^ size;
-    uint32_t             alias = 0;
-    const unsigned char *data  = (const unsigned char*)key;
-
-    while (size >= 4) {
-        alias  = (data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24));
-        alias *= mix;
-        alias ^= alias >> rot;
-        alias *= mix;
-
-        hash  *= mix;
-        hash  ^= alias;
-
-        data += 4;
-        size -= 4;
-    }
-
-    switch (size) {
-        case 3: hash ^= data[2] << 16;
-        case 2: hash ^= data[1] << 8;
-        case 1: hash ^= data[0];
-                hash *= mix;
-    }
-
-    hash ^= hash >> 13;
-    hash *= mix;
-    hash ^= hash >> 15;
-
-    return (size_t) (hash % ht->size);
-}
-
-hash_node_t *_util_htnewpair(const char *key, void *value) {
-    hash_node_t *node;
-    if (!(node = (hash_node_t*)mem_a(sizeof(hash_node_t))))
-        return NULL;
-
-    if (!(node->key = util_strdupe(key))) {
-        mem_d(node);
-        return NULL;
-    }
-
-    node->value = value;
-    node->next  = NULL;
-
-    return node;
-}
-
-/*
- * EXPOSED INTERFACE for the hashtable implementation
- * util_htnew(size)                             -- to make a new hashtable
- * util_htset(table, key, value, sizeof(value)) -- to set something in the table
- * util_htget(table, key)                       -- to get something from the table
- * util_htdel(table)                            -- to delete the table
- */
-hash_table_t *util_htnew(size_t size) {
-    hash_table_t *hashtable = NULL;
-    if (size < 1)
-        return NULL;
-
-    if (!(hashtable = (hash_table_t*)mem_a(sizeof(hash_table_t))))
-        return NULL;
-
-    if (!(hashtable->table = (hash_node_t**)mem_a(sizeof(hash_node_t*) * size))) {
-        mem_d(hashtable);
-        return NULL;
-    }
-
-    hashtable->size = size;
-    memset(hashtable->table, 0, sizeof(hash_node_t*) * size);
-
-    return hashtable;
-}
-
-void util_htseth(hash_table_t *ht, const char *key, size_t bin, void *value) {
-    hash_node_t *newnode = NULL;
-    hash_node_t *next    = NULL;
-    hash_node_t *last    = NULL;
-
-    next = ht->table[bin];
-
-    while (next && next->key && strcmp(key, next->key) > 0)
-        last = next, next = next->next;
-
-    /* already in table, do a replace */
-    if (next && next->key && strcmp(key, next->key) == 0) {
-        next->value = value;
-    } else {
-        /* not found, grow a pair man :P */
-        newnode = _util_htnewpair(key, value);
-        if (next == ht->table[bin]) {
-            newnode->next  = next;
-            ht->table[bin] = newnode;
-        } else if (!next) {
-            last->next = newnode;
-        } else {
-            newnode->next = next;
-            last->next = newnode;
-        }
-    }
-}
-
-void util_htset(hash_table_t *ht, const char *key, void *value) {
-    util_htseth(ht, key, util_hthash(ht, key), value);
-}
-
-void *util_htgeth(hash_table_t *ht, const char *key, size_t bin) {
-    hash_node_t *pair = ht->table[bin];
-
-    while (pair && pair->key && strcmp(key, pair->key) > 0)
-        pair = pair->next;
-
-    if (!pair || !pair->key || strcmp(key, pair->key) != 0)
-        return NULL;
-
-    return pair->value;
-}
-
-void *util_htget(hash_table_t *ht, const char *key) {
-    return util_htgeth(ht, key, util_hthash(ht, key));
-}
-
-void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin) {
-    hash_node_t *pair;
-    size_t len, keylen;
-    int cmp;
-
-    keylen = strlen(key);
-
-    pair = ht->table[bin];
-    while (pair && pair->key) {
-        len = strlen(pair->key);
-        if (len < keylen) {
-            pair = pair->next;
-            continue;
-        }
-        if (keylen == len) {
-            cmp = strcmp(key, pair->key);
-            if (cmp == 0)
-                return pair->value;
-            if (cmp < 0)
-                return NULL;
-            pair = pair->next;
-            continue;
-        }
-        cmp = strcmp(key, pair->key + len - keylen);
-        if (cmp == 0) {
-            uintptr_t up = (uintptr_t)pair->value;
-            up += len - keylen;
-            return (void*)up;
-        }
-        pair = pair->next;
-    }
-    return NULL;
-}
-
-/*
- * Free all allocated data in a hashtable, this is quite the amount
- * of work.
- */
-void util_htrem(hash_table_t *ht, void (*callback)(void *data)) {
-    size_t i = 0;
-    for (; i < ht->size; i++) {
-        hash_node_t *n = ht->table[i];
-        hash_node_t *p;
-
-        /* free in list */
-        while (n) {
-            if (n->key)
-                mem_d(n->key);
-            if (callback)
-                callback(n->value);
-            p = n;
-            n = n->next;
-            mem_d(p);
-        }
-
-    }
-    /* free table */
-    mem_d(ht->table);
-    mem_d(ht);
-}
-
-void util_htrmh(hash_table_t *ht, const char *key, size_t bin, void (*cb)(void*)) {
-    hash_node_t **pair = &ht->table[bin];
-    hash_node_t *tmp;
-
-    while (*pair && (*pair)->key && strcmp(key, (*pair)->key) > 0)
-        pair = &(*pair)->next;
-
-    tmp = *pair;
-    if (!tmp || !tmp->key || strcmp(key, tmp->key) != 0)
-        return;
-
-    if (cb)
-        (*cb)(tmp->value);
-
-    *pair = tmp->next;
-    mem_d(tmp->key);
-    mem_d(tmp);
+size_t util_strtocmd(const char *in, char *out, size_t outsz) {
+    return util_strtransform(in, out, outsz, "-_", 'A'-'a');
 }
-
-void util_htrm(hash_table_t *ht, const char *key, void (*cb)(void*)) {
-    util_htrmh(ht, key, util_hthash(ht, key), cb);
+size_t util_strtononcmd(const char *in, char *out, size_t outsz) {
+    return util_strtransform(in, out, outsz, "_-", 'a'-'A');
 }
-
-void util_htdel(hash_table_t *ht) {
-    util_htrem(ht, NULL);
+size_t util_optimizationtostr(const char *in, char *out, size_t outsz) {
+    return util_strtransform(in, out, outsz, "_ ", 'a'-'A');
 }
 
 /*
@@ -776,7 +359,7 @@ int util_asprintf(char **ret, const char *fmt, ...) {
 
         allocated = (char*)mem_a(4096); /* A page must be enough */
         strerror_s(allocated, 4096, num);
-    
+
         vec_push(vector, allocated);
         return (const char *)allocated;
     }
@@ -845,7 +428,7 @@ int util_asprintf(char **ret, const char *fmt, ...) {
 static uint32_t mt_state[MT_SIZE];
 static size_t   mt_index = 0;
 
-static GMQCC_INLINE void mt_generate() {
+static GMQCC_INLINE void mt_generate(void) {
     /*
      * The loop has been unrolled here: the original paper and implemenation
      * Called for the following code:
@@ -881,7 +464,7 @@ static GMQCC_INLINE void mt_generate() {
      * Said loop has been unrolled for MT_SPACE (226 iterations), opposed
      * to [0, MT_SIZE)  (634 iterations).
      */
-    for (i = 0; i < MT_SPACE; ++i) {
+    for (i = 0; i < MT_SPACE-1; ++i) {
         y           = (0x80000000 & mt_state[i]) | (0x7FFFFFF & mt_state[i + 1]);
         mt_state[i] = mt_state[i + MT_PERIOD] ^ (y >> 1) ^ matrix[y & 1];
 
@@ -896,7 +479,7 @@ static GMQCC_INLINE void mt_generate() {
      * = 2*2*3*3*11])
      */
     i = MT_SPACE;
-    while (i < MT_SIZE - 1) {
+    while (i < MT_SIZE-2) {
         /*
          * We expand this 11 times .. manually, no macros are required
          * here. This all fits in the CPU cache.