]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - util.c
More cleanup
[xonotic/gmqcc.git] / util.c
diff --git a/util.c b/util.c
index 84be6f31cc18cf89a542c6f9fda129f45b5f9cab..ceed4491aa96c59d24a11b29be567d673b6f3a71 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,39 +1,7 @@
-/*
- * Copyright (C) 2012, 2013
- *     Dale Weiler
- *     Wolfgang Bumiller
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#define GMQCC_PLATFORM_HEADER
 #include <stdlib.h>
+#include <string.h>
 #include "gmqcc.h"
-#include "platform.h"
 
-/*
- * 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 disassembled byte-code.
- */
 const char *util_instr_str[VINSTR_END] = {
     "DONE",       "MUL_F",      "MUL_V",      "MUL_FV",
     "MUL_VF",     "DIV_F",      "ADD_F",      "ADD_V",
@@ -58,7 +26,7 @@ const char *util_instr_str[VINSTR_END] = {
  * only required if big endian .. otherwise no need to swap
  * data.
  */
-#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG
+#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG || PLATFORM_BYTE_ORDER == -1
     static GMQCC_INLINE void util_swap16(uint16_t *d, size_t l) {
         while (l--) {
             d[l] = (d[l] << 8) | (d[l] >> 8);
@@ -77,55 +45,106 @@ const char *util_instr_str[VINSTR_END] = {
      * so let's go the safe way
      */
     static GMQCC_INLINE void util_swap64(uint32_t *d, size_t l) {
-        /*
         while (l--) {
             uint64_t v;
             v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF);
             v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF);
             d[l] = (v << 32) | (v >> 32);
         }
-        */
-        size_t i;
-        for (i = 0; i < l; i += 2) {
-            uint32_t v1 = d[i];
-            d[i] = d[i+1];
-            d[i+1] = v1;
-            util_swap32(d+i, 2);
-        }
     }
 #endif
 
-void util_endianswap(void *_data, size_t length, unsigned int typesize) {
+void util_endianswap(void *_data, size_t count, unsigned int typesize) {
 #   if PLATFORM_BYTE_ORDER == -1 /* runtime check */
     if (*((char*)&typesize))
         return;
 #else
-    /* prevent unused warnings */
-    (void) _data;
-    (void) length;
-    (void) typesize;
 
 #   if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE
+        /* prevent unused warnings */
+        (void) _data;
+        (void) count;
+        (void) typesize;
         return;
 #   else
         switch (typesize) {
             case 1: return;
             case 2:
-                util_swap16((uint16_t*)_data, length>>1);
+                util_swap16((uint16_t*)_data, count);
                 return;
             case 4:
-                util_swap32((uint32_t*)_data, length>>2);
+                util_swap32((uint32_t*)_data, count);
                 return;
             case 8:
-                util_swap64((uint32_t*)_data, length>>3);
+                util_swap64((uint32_t*)_data, count);
                 return;
 
-            default: exit(EXIT_FAILURE); /* please blow the fuck up! */
+            default:
+                con_err ("util_endianswap: I don't know how to swap a %u byte structure!\n", typesize);
+                exit(EXIT_FAILURE); /* please blow the fuck up! */
         }
 #   endif
 #endif
 }
 
+void util_swap_header(prog_header_t *code_header) {
+    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.offset,    1, sizeof(code_header->statements.offset));
+    util_endianswap(&code_header->statements.length,    1, sizeof(code_header->statements.length));
+    util_endianswap(&code_header->defs.offset,          1, sizeof(code_header->defs.offset));
+    util_endianswap(&code_header->defs.length,          1, sizeof(code_header->defs.length));
+    util_endianswap(&code_header->fields.offset,        1, sizeof(code_header->fields.offset));
+    util_endianswap(&code_header->fields.length,        1, sizeof(code_header->fields.length));
+    util_endianswap(&code_header->functions.offset,     1, sizeof(code_header->functions.offset));
+    util_endianswap(&code_header->functions.length,     1, sizeof(code_header->functions.length));
+    util_endianswap(&code_header->strings.offset,       1, sizeof(code_header->strings.offset));
+    util_endianswap(&code_header->strings.length,       1, sizeof(code_header->strings.length));
+    util_endianswap(&code_header->globals.offset,       1, sizeof(code_header->globals.offset));
+    util_endianswap(&code_header->globals.length,       1, sizeof(code_header->globals.length));
+    util_endianswap(&code_header->entfield,             1, sizeof(code_header->entfield));
+}
+
+void util_swap_statements(prog_section_statement_t *statements) {
+    size_t i;
+
+    for (i = 0; i < vec_size(statements); ++i) {
+        util_endianswap(&statements[i].opcode,  1, sizeof(statements[i].opcode));
+        util_endianswap(&statements[i].o1,      1, sizeof(statements[i].o1));
+        util_endianswap(&statements[i].o2,      1, sizeof(statements[i].o2));
+        util_endianswap(&statements[i].o3,      1, sizeof(statements[i].o3));
+    }
+}
+
+void util_swap_defs_fields(prog_section_both_t *section) {
+    size_t i;
+
+    for (i = 0; i < vec_size(section); ++i) {
+        util_endianswap(&section[i].type,   1, sizeof(section[i].type));
+        util_endianswap(&section[i].offset, 1, sizeof(section[i].offset));
+        util_endianswap(&section[i].name,   1, sizeof(section[i].name));
+    }
+}
+
+void util_swap_functions(prog_section_function_t *functions) {
+    size_t i;
+
+    for (i = 0; i < vec_size(functions); ++i) {
+        util_endianswap(&functions[i].entry,        1, sizeof(functions[i].entry));
+        util_endianswap(&functions[i].firstlocal,   1, sizeof(functions[i].firstlocal));
+        util_endianswap(&functions[i].locals,       1, sizeof(functions[i].locals));
+        util_endianswap(&functions[i].profile,      1, sizeof(functions[i].profile));
+        util_endianswap(&functions[i].name,         1, sizeof(functions[i].name));
+        util_endianswap(&functions[i].file,         1, sizeof(functions[i].file));
+        util_endianswap(&functions[i].nargs,        1, sizeof(functions[i].nargs));
+        /* Don't swap argsize[] - it's just a byte array, which Quake uses only as such. */
+    }
+}
+
+void util_swap_globals(int32_t *globals) {
+    util_endianswap(globals, vec_size(globals), sizeof(int32_t));
+}
+
 /*
 * Based On:
 *   Slicing-by-8 algorithms by Michael E.
@@ -458,7 +477,7 @@ static const uint16_t util_crc16_table[8][256] = {{
 
 /* Non - Reflected */
 uint16_t util_crc16(uint16_t current, const char *GMQCC_RESTRICT k, size_t len) {
-    register uint16_t h = current;
+    uint16_t h = current;
 
     /* don't load twice */
     const uint8_t *GMQCC_RESTRICT data = (const uint8_t *GMQCC_RESTRICT)k;
@@ -523,64 +542,144 @@ size_t util_optimizationtostr(const char *in, char *out, size_t outsz) {
     return util_strtransform(in, out, outsz, "_ ", 'a'-'A');
 }
 
+static int util_vasprintf(char **dat, const char *fmt, va_list args) {
+    int     ret;
+    int     len;
+    char   *tmp = NULL;
+    char    buf[128];
+    va_list cpy;
+
+    va_copy(cpy, args);
+    len = vsnprintf(buf, sizeof(buf), fmt, cpy);
+    va_end (cpy);
+
+    if (len < 0)
+        return len;
+
+    if (len < (int)sizeof(buf)) {
+        *dat = util_strdup(buf);
+        return len;
+    }
+
+    tmp = (char*)mem_a(len + 1);
+    if ((ret = vsnprintf(tmp, len + 1, fmt, args)) != len) {
+        mem_d(tmp);
+        *dat = NULL;
+        return -1;
+    }
+
+    *dat = tmp;
+    return len;
+}
+
 int util_snprintf(char *str, size_t size, const char *fmt, ...) {
     va_list  arg;
-    int      ret;
-
+    int ret;
     va_start(arg, fmt);
-    ret = platform_vsnprintf(str, size, fmt, arg);
+    ret = vsnprintf(str, size, fmt, arg);
     va_end(arg);
-
     return ret;
 }
 
 int util_asprintf(char **ret, const char *fmt, ...) {
     va_list  args;
-    int      read;
-
+    int read;
     va_start(args, fmt);
-    read = platform_vasprintf(ret, fmt, args);
-    va_end  (args);
-
+    read = util_vasprintf(ret, fmt, args);
+    va_end(args);
     return read;
 }
 
 int util_sscanf(const char *str, const char *format, ...) {
     va_list  args;
-    int      read;
-
+    int read;
     va_start(args, format);
-    read = platform_vsscanf(str, format, args);
+    read = vsscanf(str, format, args);
     va_end(args);
-
     return read;
 }
 
 char *util_strncpy(char *dest, const char *src, size_t n) {
-    return platform_strncpy(dest, src, n);
+    return strncpy(dest, src, n);
 }
+
 char *util_strncat(char *dest, const char *src, size_t n) {
-    return platform_strncat(dest, src, n);
+    return strncat(dest, src, n);
 }
+
 char *util_strcat(char *dest, const char *src) {
-    return platform_strcat(dest, src);
+    return strcat(dest, src);
 }
+
 const char *util_strerror(int err) {
-    return platform_strerror(err);
+    return strerror(err);
 }
 
 const struct tm *util_localtime(const time_t *timer) {
-    return platform_localtime(timer);
+    return localtime(timer);
 }
+
 const char *util_ctime(const time_t *timer) {
-    return platform_ctime(timer);
+    return ctime(timer);
 }
 
-bool util_isatty(fs_file_t *file) {
-    if (file == (fs_file_t*)stdout) return !!platform_isatty(STDOUT_FILENO);
-    if (file == (fs_file_t*)stderr) return !!platform_isatty(STDERR_FILENO);
+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 = (char*)mem_a((*n=64))))
+            return -1;
+    }
+
+    chr = *n;
+    pos = *lineptr;
+
+    for (;;) {
+        int c = getc(stream);
+
+        if (chr < 2) {
+            *n += (*n > 16) ? *n : 64;
+            chr = *n + *lineptr - pos;
+            if (!(*lineptr = (char*)mem_r(*lineptr,*n)))
+                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);
+}
+
+#ifndef _WIN32
+#include <unistd.h>
+bool util_isatty(FILE *file) {
+    if (file == stdout) return !!isatty(STDOUT_FILENO);
+    if (file == stderr) return !!isatty(STDERR_FILENO);
     return false;
 }
+#else
+bool util_isatty(FILE *file) {
+    return false;
+}
+#endif
+
 /*
  * A small noncryptographic PRNG based on:
  * http://burtleburtle.net/bob/rand/smallprng.html
@@ -618,3 +717,16 @@ void util_seed(uint32_t value) {
         (void)util_rand();
 }
 
+size_t hash(const char *string) {
+    size_t hash = 0;
+    for(; *string; ++string) {
+        hash += *string;
+        hash += (hash << 10);
+        hash ^= (hash >> 6);
+    }
+    hash += hash << 3;
+    hash ^= hash >> 11;
+    hash += hash << 15;
+    return hash;
+}
+