Initial platform / compiler specific code refactoring.
authorDale Weiler <killfieldengine@gmail.com>
Fri, 11 Oct 2013 06:39:30 +0000 (02:39 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Fri, 11 Oct 2013 06:39:30 +0000 (02:39 -0400)
19 files changed:
Makefile
ansi.c [new file with mode: 0644]
ast.c
conout.c
exec.c
fold.c
fs.c
ftepp.c
gmqcc.h
include.mk
intrin.c
ir.c
lexer.c
msvc.c [new file with mode: 0644]
opts.c
pak.c
parser.c
test.c
util.c

index a89d8c2..f7255d4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -148,12 +148,13 @@ install-doc:
 
 # DO NOT DELETE
 
+pak.o: gmqcc.h opts.def
+ansi.o: gmqcc.h opts.def
 util.o: gmqcc.h opts.def
+stat.o: gmqcc.h opts.def
 fs.o: gmqcc.h opts.def
 conout.o: gmqcc.h opts.def
 opts.o: gmqcc.h opts.def
-pak.o: gmqcc.h opts.def
-stat.o: gmqcc.h opts.def
 test.o: gmqcc.h opts.def
 main.o: gmqcc.h opts.def lexer.h
 lexer.o: gmqcc.h opts.def lexer.h
diff --git a/ansi.c b/ansi.c
new file mode 100644 (file)
index 0000000..adc7907
--- /dev/null
+++ b/ansi.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012, 2013
+ *     Dale Weiler
+ *
+ * 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.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "gmqcc.h"
+
+int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg) {
+    return vsnprintf(buffer, bytes, format, arg);
+}
+
+int platform_sscanf(const char *str, const char *format, ...) {
+    int     rt;
+    va_list va;
+
+    va_start(va, format);
+    rt = vsscanf(str, format, va);
+    va_end (va);
+
+    return rt;
+}
+
+const struct tm *platform_localtime(const time_t *timer) {
+    return localtime(timer);
+}
+
+const char *platform_ctime(const time_t *timer) {
+    return ctime(timer);
+}
+
+char *platform_strncat(char *dest, const char *src, size_t num) {
+    return strncat(dest, src, num);
+}
+
+const char *platform_tmpnam(char *str) {
+    return tmpnam(str);
+}
+
+const char *platform_getenv(char *var) {
+    return getenv(var);
+}
+
+int platform_snprintf(char *src, size_t bytes, const char *format, ...) {
+    int     rt;
+    va_list va;
+
+    va_start(va, format);
+    rt = vsnprintf(src, bytes, format, va);
+    va_end(va);
+
+    return rt;
+}
+
+char *platform_strcat(char *dest, const char *src) {
+    return strcat(dest, src);
+}
+
+char *platform_strncpy(char *dest, const char *src, size_t num) {
+    return strncpy(dest, src, num);
+}
+
+const char *platform_strerror(int err) {
+    return strerror(err);
+}
diff --git a/ast.c b/ast.c
index 362a06f..56dc1e5 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -259,7 +259,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
     if (!e) {
         if (pos + 6 >= bufsize)
             goto full;
-        util_strncpy(buf + pos, "(null)", 6);
+        platform_strncpy(buf + pos, "(null)", 6);
         return pos + 6;
     }
 
@@ -268,7 +268,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
 
     switch (e->vtype) {
         case TYPE_VARIANT:
-            util_strncpy(buf + pos, "(variant)", 9);
+            platform_strncpy(buf + pos, "(variant)", 9);
             return pos + 9;
 
         case TYPE_FIELD:
@@ -314,7 +314,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
             if (pos + 1 >= bufsize)
                 goto full;
             buf[pos++] = '[';
-            pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count);
+            pos += platform_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count);
             if (pos + 1 >= bufsize)
                 goto full;
             buf[pos++] = ']';
@@ -325,7 +325,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
             typelen = strlen(typestr);
             if (pos + typelen >= bufsize)
                 goto full;
-            util_strncpy(buf + pos, typestr, typelen);
+            platform_strncpy(buf + pos, typestr, typelen);
             return pos + typelen;
     }
 
@@ -1463,12 +1463,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
             namelen = strlen(self->name);
             name    = (char*)mem_a(namelen + 16);
-            util_strncpy(name, self->name, namelen);
+            platform_strncpy(name, self->name, namelen);
 
             array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count);
             array->ir_values[0] = v;
             for (ai = 1; ai < array->expression.count; ++ai) {
-                util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
+                platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
                 array->ir_values[ai] = ir_builder_create_field(ir, name, vtype);
                 if (!array->ir_values[ai]) {
                     mem_d(name);
@@ -1532,12 +1532,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
-        util_strncpy(name, self->name, namelen);
+        platform_strncpy(name, self->name, namelen);
 
         self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count);
         self->ir_values[0] = v;
         for (ai = 1; ai < self->expression.count; ++ai) {
-            util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
+            platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
             self->ir_values[ai] = ir_builder_create_global(ir, name, vtype);
             if (!self->ir_values[ai]) {
                 mem_d(name);
@@ -1677,11 +1677,11 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
 
         namelen = strlen(self->name);
         name    = (char*)mem_a(namelen + 16);
-        util_strncpy(name, self->name, namelen);
+        platform_strncpy(name, self->name, namelen);
 
         self->ir_values[0] = v;
         for (ai = 1; ai < self->expression.count; ++ai) {
-            util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
+            platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai);
             self->ir_values[ai] = ir_function_create_local(func, name, vtype, param);
             if (!self->ir_values[ai]) {
                 compile_error(ast_ctx(self), "internal_error: ir_builder_create_global failed on `%s`", name);
index 63391d6..f89d68c 100644 (file)
--- a/conout.c
+++ b/conout.c
@@ -216,11 +216,7 @@ static int con_write(FILE *handle, const char *fmt, va_list va) {
     {
         char data[4096];
         memset(data, 0, sizeof(data));
-#ifdef _MSC_VER
-        vsnprintf_s(data, sizeof(data), sizeof(data), fmt, va);
-#else
-        vsnprintf(data, sizeof(data), fmt, va);
-#endif
+        platform_vsnprintf(data, sizeof(data), fmt, va);
         ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(handle, data) : fs_file_puts(handle, data);
     }
     #endif
diff --git a/exec.c b/exec.c
index c4de8ad..d614ebf 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -37,7 +37,7 @@ static void loaderror(const char *fmt, ...)
     va_start(ap, fmt);
     vprintf(fmt, ap);
     va_end(ap);
-    printf(": %s\n", util_strerror(err));
+    printf(": %s\n", platform_strerror(err));
 }
 
 static void qcvmerror(qc_program_t *prog, const char *fmt, ...)
@@ -91,11 +91,11 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
     }
 
 #define read_data(hdrvar, progvar, reserved)                           \
-    if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) {        \
+    if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) {     \
         loaderror("seek failed");                                      \
         goto error;                                                    \
     }                                                                  \
-    if (fs_file_read (                                                    \
+    if (fs_file_read (                                                 \
             vec_add(prog->progvar, header.hdrvar.length + reserved),   \
             sizeof(*prog->progvar),                                    \
             header.hdrvar.length,                                      \
@@ -661,7 +661,7 @@ static int qc_ftos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    util_snprintf(buffer, sizeof(buffer), "%g", num->_float);
+    platform_snprintf(buffer, sizeof(buffer), "%g", num->_float);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -683,7 +683,7 @@ static int qc_vtos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    util_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]);
+    platform_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -695,7 +695,7 @@ static int qc_etos(qc_program_t *prog) {
     qcany_t str;
     CheckArgs(1);
     num = GetArg(0);
-    util_snprintf(buffer, sizeof(buffer), "%i", num->_int);
+    platform_snprintf(buffer, sizeof(buffer), "%i", num->_int);
     str.string = prog_tempstring(prog, buffer);
     Return(str);
     return 0;
@@ -877,17 +877,10 @@ static void prog_main_setparams(qc_program_t *prog) {
         arg->vector[2] = 0;
         switch (main_params[i].vtype) {
             case TYPE_VECTOR:
-#ifdef _MSC_VER
-                (void)sscanf_s(main_params[i].value, " %f %f %f ",
-                               &arg->vector[0],
-                               &arg->vector[1],
-                               &arg->vector[2]);
-#else
-                (void)sscanf(main_params[i].value, " %f %f %f ",
-                             &arg->vector[0],
-                             &arg->vector[1],
-                             &arg->vector[2]);
-#endif
+                (void)platform_sscanf(main_params[i].value, " %f %f %f ",
+                                       &arg->vector[0],
+                                       &arg->vector[1],
+                                       &arg->vector[2]);
                 break;
             case TYPE_FLOAT:
                 arg->_float = atof(main_params[i].value);
diff --git a/fold.c b/fold.c
index ffa0f65..d485ed2 100644 (file)
--- a/fold.c
+++ b/fold.c
@@ -338,7 +338,7 @@ ast_expression *fold_constgen_string(fold_t *fold, const char *str, bool transla
 
     if (translate) {
         char name[32];
-        util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(fold->parser->translated++));
+        platform_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(fold->parser->translated++));
         out                    = ast_value_new(parser_ctx(fold->parser), name, TYPE_STRING);
         out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
     } else
diff --git a/fs.c b/fs.c
index 501041f..7844703 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -229,7 +229,7 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) {
         if (!dir)
             return NULL;
 
-        util_strncpy(dir->dd_name, name, strlen(name));
+        platform_strncpy(dir->dd_name, name, strlen(name));
         return dir;
     }
 
@@ -249,8 +249,8 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) {
             if (*dir->dd_name) {
                 size_t n = strlen(dir->dd_name);
                 if ((dirname  = (char*)mem_a(n + 5) /* 4 + 1 */)) {
-                    util_strncpy(dirname, dir->dd_name, n);
-                    util_strncpy(dirname + n, "\\*.*", 4);   /* 4 + 1 */
+                    platform_strncpy(dirname, dir->dd_name, n);
+                    platform_strncpy(dirname + n, "\\*.*", 4);   /* 4 + 1 */
                 }
             } else {
                 if (!(dirname = util_strdup("\\*.*")))
@@ -270,7 +270,7 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) {
             return NULL;
 
         if ((data = (struct dirent*)mem_a(sizeof(struct dirent)))) {
-            util_strncpy(data->d_name, info.cFileName, FILENAME_MAX - 1);
+            platform_strncpy(data->d_name, info.cFileName, FILENAME_MAX - 1);
             data->d_name[FILENAME_MAX - 1] = '\0'; /* terminate */
             data->d_namlen                 = strlen(data->d_name);
         }
diff --git a/ftepp.c b/ftepp.c
index 050d6d8..f6c850c 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -85,22 +85,14 @@ static uint32_t ftepp_predef_randval  = 0;
 
 /* __DATE__ */
 static char *ftepp_predef_date(lex_file *context) {
-    struct tm *itime = NULL;
-    time_t     rtime;
-    char      *value = (char*)mem_a(82);
-    /* 82 is enough for strftime but we also have " " in our string */
+    const struct tm *itime = NULL;
+    char            *value = (char*)mem_a(82);
+    time_t           rtime;
 
     (void)context;
 
-    /* get time */
     time (&rtime);
-
-#ifdef _MSC_VER
-    localtime_s(itime, &rtime);
-#else
-    itime = localtime(&rtime);
-#endif
-
+    itime = platform_localtime(&rtime);
     strftime(value, 82, "\"%b %d %Y\"", itime);
 
     return value;
@@ -108,22 +100,14 @@ static char *ftepp_predef_date(lex_file *context) {
 
 /* __TIME__ */
 static char *ftepp_predef_time(lex_file *context) {
-    struct tm *itime = NULL;
-    time_t     rtime;
-    char      *value = (char*)mem_a(82);
-    /* 82 is enough for strftime but we also have " " in our string */
+    const struct tm *itime = NULL;
+    char            *value = (char*)mem_a(82);
+    time_t           rtime;
 
     (void)context;
 
-    /* get time */
     time (&rtime);
-
-#ifdef _MSC_VER
-    localtime_s(itime, &rtime);
-#else
-    itime = localtime(&rtime);
-#endif
-
+    itime = platform_localtime(&rtime);
     strftime(value, 82, "\"%X\"", itime);
 
     return value;
@@ -139,7 +123,7 @@ static char *ftepp_predef_line(lex_file *context) {
 static char *ftepp_predef_file(lex_file *context) {
     size_t  length = strlen(context->name) + 3; /* two quotes and a terminator */
     char   *value  = (char*)mem_a(length);
-    util_snprintf(value, length, "\"%s\"", context->name);
+    platform_snprintf(value, length, "\"%s\"", context->name);
 
     return value;
 }
@@ -180,27 +164,14 @@ static char *ftepp_predef_randomlast(lex_file *context) {
 /* __TIMESTAMP__ */
 static char *ftepp_predef_timestamp(lex_file *context) {
     struct stat finfo;
-    char       *find;
+    const char *find;
     char       *value;
     size_t      size;
-#ifdef _MSC_VER
-    char        buffer[64];
-#endif
+
     if (stat(context->name, &finfo))
         return util_strdup("\"<failed to determine timestamp>\"");
 
-    /*
-     * ctime and its fucking annoying newline char, no worries, we're
-     * professionals here.
-     */
-
-#ifndef _MSC_VER
-    find  = ctime(&finfo.st_mtime);
-#else
-    ctime_s(buffer, sizeof(buffer), &finfo.st_mtime);
-    find = buffer;
-#endif
-
+    find = platform_ctime(&finfo.st_mtime);
     value = (char*)mem_a(strlen(find) + 1);
     memcpy(&value[1], find, (size = strlen(find)) - 1);
 
@@ -893,7 +864,7 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
 
     if (resetline && !ftepp->in_macro) {
         char lineno[128];
-        util_snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline));
+        platform_snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline));
         ftepp_out(ftepp, lineno, false);
     }
 
@@ -1493,7 +1464,7 @@ static bool ftepp_include(ftepp_t *ftepp)
 
     ftepp_out(ftepp, "\n#pragma file(", false);
     ftepp_out(ftepp, ctx.file, false);
-    util_snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1));
+    platform_snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1));
     ftepp_out(ftepp, lineno, false);
 
     /* skip the line */
@@ -1872,12 +1843,12 @@ ftepp_t *ftepp_create()
         minor[2] = '"';
     } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) {
         ftepp_add_define(ftepp, NULL, "__STD_GMQCC__");
-        util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
-        util_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
+        platform_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
+        platform_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
     } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCCX) {
         ftepp_add_define(ftepp, NULL, "__STD_QCCX__");
-        util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
-        util_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
+        platform_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
+        platform_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
     } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) {
         ftepp_add_define(ftepp, NULL, "__STD_QCC__");
         /* 1.0 */
diff --git a/gmqcc.h b/gmqcc.h
index cb70d66..75f70a5 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -24,6 +24,7 @@
 #ifndef GMQCC_HDR
 #define GMQCC_HDR
 #include <stdarg.h>
+#include <time.h>  /* TODO: remove this? */
 #include <stdio.h> /* TODO: remove this */
 
 /*
@@ -343,18 +344,8 @@ uint16_t util_crc16(uint16_t crc, const char *data, size_t len);
 void     util_seed(uint32_t);
 uint32_t util_rand(void);
 
-/*
- * String functions (formatting, copying, concatenating, errors). These are wrapped
- * to use the MSVC _safe_ versions when using MSVC, plus some implementations of
- * these are non-conformant or don't exist such as asprintf and snprintf, which are
- * not supported in C90, but do exist in C99.
- */
-int         util_vasprintf(char **ret, const char *fmt, va_list);
-int         util_asprintf (char **ret, const char *fmt, ...);
-int         util_snprintf (char *src,  size_t bytes, const char *format, ...);
-char       *util_strcat   (char *dest, const char *src);
-char       *util_strncpy  (char *dest, const char *src, size_t num);
-const char *util_strerror (int num);
+int      util_vasprintf(char **ret, const char *fmt, va_list);
+int      util_asprintf (char **ret, const char *fmt, ...);
 
 /*
  * A flexible vector implementation: all vector pointers contain some
@@ -470,6 +461,18 @@ int            fs_dir_close   (DIR *);
 struct dirent *fs_dir_read    (DIR *);
 
 
+int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg);
+int platform_sscanf(const char *str, const char *format, ...);
+const struct tm *platform_localtime(const time_t *timer);
+const char *platform_ctime(const time_t *timer);
+char *platform_strncat(char *dest, const char *src, size_t num);
+const char *platform_tmpnam(char *str);
+const char *platform_getenv(char *var);
+int platform_snprintf(char *src, size_t bytes, const char *format, ...);
+char *platform_strcat(char *dest, const char *src);
+char *platform_strncpy(char *dest, const char *src, size_t num);
+const char *platform_strerror(int err);
+
 /*===================================================================*/
 /*=========================== correct.c =============================*/
 /*===================================================================*/
index 20ffdd4..ed7822a 100644 (file)
@@ -14,10 +14,10 @@ LDFLAGS +=
 LIBS    += -lm
 
 #objects
-OBJ_C = main.o lexer.o parser.o fs.o stat.o util.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o intrin.o
-OBJ_P = util.o fs.o conout.o opts.o pak.o stat.o
-OBJ_T = test.o util.o opts.o conout.o fs.o stat.o
-OBJ_X = exec-standalone.o util.o opts.o conout.o fs.o stat.o
+OBJ_C = main.o ansi.o util.o stat.o fs.o lexer.o parser.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o intrin.o
+OBJ_P = pak.o ansi.o util.o stat.o fs.o conout.o opts.o pak.o
+OBJ_T = test.o ansi.o util.o stat.o fs.o opts.o conout.o
+OBJ_X = exec-standalone.o ansi.o util.o stat.o fs.o opts.o conout.o
 
 #gource flags
 GOURCEFLAGS =                 \
index 94b4202..49de952 100644 (file)
--- a/intrin.c
+++ b/intrin.c
@@ -39,8 +39,8 @@ static GMQCC_INLINE ast_function *intrin_value(intrin_t *intrin, ast_value **val
     char          buffer[1024];
     char          stype [1024];
 
-    util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
-    util_snprintf(stype,  sizeof(stype),   "<%s>",        type_name[vtype]);
+    platform_snprintf(buffer, sizeof(buffer), "__builtin_%s", name);
+    platform_snprintf(stype,  sizeof(stype),   "<%s>",        type_name[vtype]);
 
     *value                      = ast_value_new(intrin_ctx(intrin), buffer, TYPE_FUNCTION);
     (*value)->intrinsic         = true;
diff --git a/ir.c b/ir.c
index f0274e1..1da5d7c 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -3320,7 +3320,7 @@ static ir_value* ir_gen_extparam_proto(ir_builder *ir)
     ir_value *global;
     char      name[128];
 
-    util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos)));
+    platform_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos)));
     global = ir_value_var(name, store_global, TYPE_VECTOR);
 
     vec_push(ir->extparam_protos, global);
@@ -3977,10 +3977,6 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
 
 #define IND_BUFSZ 1024
 
-#ifdef _MSC_VER
-#   define strncat(dst, src, sz) strncat_s(dst, sz, src, _TRUNCATE)
-#endif
-
 static const char *qc_opname(int op)
 {
     if (op < 0) return "<INVALID>";
@@ -4039,7 +4035,7 @@ void ir_function_dump(ir_function *f, char *ind,
         return;
     }
     oprintf("%sfunction %s\n", ind, f->name);
-    strncat(ind, "\t", IND_BUFSZ-1);
+    platform_strncat(ind, "\t", IND_BUFSZ-1);
     if (vec_size(f->locals))
     {
         oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals));
@@ -4135,7 +4131,7 @@ void ir_block_dump(ir_block* b, char *ind,
 {
     size_t i;
     oprintf("%s:%s\n", ind, b->label);
-    strncat(ind, "\t", IND_BUFSZ-1);
+    platform_strncat(ind, "\t", IND_BUFSZ-1);
 
     if (b->instr && b->instr[0])
         oprintf("%s (%i) [entry]\n", ind, (int)(b->instr[0]->eid-1));
@@ -4169,7 +4165,7 @@ void ir_instr_dump(ir_instr *in, char *ind,
         return;
     }
 
-    strncat(ind, "\t", IND_BUFSZ-1);
+    platform_strncat(ind, "\t", IND_BUFSZ-1);
 
     if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) {
         ir_value_dump(in->_ops[0], oprintf);
diff --git a/lexer.c b/lexer.c
index 5882bdb..2d36afb 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -1473,14 +1473,10 @@ int lex_do(lex_file *lex)
         lex_endtoken(lex);
 
         lex->tok.ttype = TOKEN_CHARCONST;
-         /* It's a vector if we can successfully scan 3 floats */
-#ifdef _MSC_VER
-        if (sscanf_s(lex->tok.value, " %f %f %f ",
-                   &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
-#else
-        if (sscanf(lex->tok.value, " %f %f %f ",
+
+        /* It's a vector if we can successfully scan 3 floats */
+        if (platform_sscanf(lex->tok.value, " %f %f %f ",
                    &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
-#endif
 
         {
              lex->tok.ttype = TOKEN_VECTORCONST;
diff --git a/msvc.c b/msvc.c
new file mode 100644 (file)
index 0000000..904ef28
--- /dev/null
+++ b/msvc.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012, 2013
+ *     Dale Weiler
+ *
+ * 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.
+ */
+#include "gmqcc.h"
+
+#define CTIME_BUFFER    64
+#define GETENV_BUFFER   4096
+#define STRERROR_BUFFER 128
+
+static void **platform_mem_pool = NULL;
+static void platform_mem_atexit() {
+    size_t i;
+    for (i = 0; i < vec_size(platform_mem_pool); i++)
+        mem_d(platform_mem_pool[i]);
+    vec_free(platform_mem_pool);
+}
+
+static void *platform_mem_allocate(size_t bytes) {
+    void *mem = NULL;
+    if (!platform_mem_pool) {
+        atexit(&platform_mem_atexit);
+        vec_push(platform_mem_pool, NULL);
+    }
+
+    mem = mem_a(bytes);
+    vec_push(platform_mem_pool, mem);
+
+    return mem;
+}
+
+int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg) {
+    vsnprintf_s(buffer, bytes, bytes, format, arg);
+}
+
+int platform_sscanf(const char *str, const char *format, ...) {
+    va_list va;
+    va_start(va, format);
+    vsscanf_s(str, format, va);
+    va_end(va);
+}
+
+const struct tm *platform_localtime(const time_t *timer) {
+    struct tm *t;
+    t = (struct tm*)platform_mem_allocate(sizeof(struct tm));
+    localtime_s(&t, timer);
+    return &t;
+}
+
+const char *platform_ctime(const time_t *timer) {
+    char *buffer = (char *)platform_mem_allocate(CTIME_BUFFER);
+    ctime_s(buffer, CTIME_BUFFER, timer);
+    return buffer;
+}
+
+char *platform_strncat(char *dest, const char *src, size_t num) {
+    return strncat_s(dest, num, src, _TRUNCATE);
+}
+
+const char *platform_tmpnam(char *str) {
+    return tmpnam_s(str, L_tmpnam);
+}
+
+const char *platform_getenv(char *var) {
+    char  *buffer = (char *)platform_mem_allocate(GETENV_BUFFER);
+    size_t size;
+    getenv_s(&size, buffer, GETENV_BUFFER, var);
+    return buffer;
+}
+
+int platform_snprintf(char *src, size_t bytes, const char *format, ...) {
+    int      rt;
+    va_list  va;
+    va_start(va, format);
+
+    rt = vsprintf_s(src, bytes, format, va);
+    va_end  (va);
+
+    return rt;
+}
+
+char *platform_strcat(char *dest, const char *src) {
+    strcat_s(dest, strlen(src), src);
+    return dest;
+}
+
+char *platform_strncpy(char *dest, const char *src, size_t num) {
+    strncpy_s(dest, num, src, num);
+    return dest;
+}
+
+const char *platform_strerror(int err) {
+    char *buffer = (char*)platform_mem_allocate(STRERROR_BUFFER);
+    strerror_s(buffer, STRERROR_BUFFER, err);
+    return buffer;
+}
diff --git a/opts.c b/opts.c
index 27d6a56..570b578 100644 (file)
--- a/opts.c
+++ b/opts.c
@@ -251,7 +251,7 @@ static size_t opts_ini_parse (
             /* section found */
             if (*(parse_end = opts_ini_next(parse_beg + 1, ']')) == ']') {
                 * parse_end = '\0'; /* terminate bro */
-                util_strncpy(section_data, parse_beg + 1, sizeof(section_data));
+                platform_strncpy(section_data, parse_beg + 1, sizeof(section_data));
                 section_data[sizeof(section_data) - 1] = '\0';
                 *oldname_data                          = '\0';
             } else if (!error) {
@@ -272,7 +272,7 @@ static size_t opts_ini_parse (
                 opts_ini_rstrip(read_value);
 
                 /* valid name value pair, lets call down to handler */
-                util_strncpy(oldname_data, read_name, sizeof(oldname_data));
+                platform_strncpy(oldname_data, read_name, sizeof(oldname_data));
                 oldname_data[sizeof(oldname_data) - 1] ='\0';
 
                 if ((*errorhandle = loadhandle(section_data, read_name, read_value)) && !error)
diff --git a/pak.c b/pak.c
index 0b3f221..fbc2262 100644 (file)
--- a/pak.c
+++ b/pak.c
@@ -98,14 +98,14 @@ static void pak_tree_build(const char *entry) {
 
     memset(pathsplit, 0, 56);
 
-    util_strncpy(directory, entry, 56);
+    platform_strncpy(directory, entry, 56);
     for (itr = 0; (token = pak_tree_sep(&directory, "/")) != NULL; itr++) {
         elements[itr] = token;
     }
 
     for (jtr = 0; jtr < itr - 1; jtr++) {
-        util_strcat(pathsplit, elements[jtr]);
-        util_strcat(pathsplit, "/");
+        platform_strcat(pathsplit, elements[jtr]);
+        platform_strcat(pathsplit, "/");
 
         if (fs_dir_make(pathsplit)) {
             mem_d(pathsplit);
@@ -366,7 +366,7 @@ static bool pak_insert_one(pak_file_t *pak, const char *file) {
     if (strlen(file) >= 56)
         goto err;
 
-    util_strncpy(dir.name, file, strlen(file));
+    platform_strncpy(dir.name, file, strlen(file));
 
     /*
      * Allocate some memory for loading in the data that will be
index 15bb921..47563f3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -4023,13 +4023,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         varargs->expression.flags |= AST_FLAG_IS_VARARG;
         varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR);
         varargs->expression.count = 0;
-        util_snprintf(name, sizeof(name), "%s##va##SET", var->name);
+        platform_snprintf(name, sizeof(name), "%s##va##SET", var->name);
         if (!parser_create_array_setter_proto(parser, varargs, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
             goto enderrfn;
         }
-        util_snprintf(name, sizeof(name), "%s##va##GET", var->name);
+        platform_snprintf(name, sizeof(name), "%s##va##GET", var->name);
         if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) {
             ast_delete(varargs);
             ast_block_delete(block);
@@ -4926,10 +4926,10 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons
 static bool create_array_accessors(parser_t *parser, ast_value *var)
 {
     char name[1024];
-    util_snprintf(name, sizeof(name), "%s##SET", var->name);
+    platform_snprintf(name, sizeof(name), "%s##SET", var->name);
     if (!parser_create_array_setter(parser, var, name))
         return false;
-    util_snprintf(name, sizeof(name), "%s##GET", var->name);
+    platform_snprintf(name, sizeof(name), "%s##GET", var->name);
     if (!parser_create_array_getter(parser, var, var->expression.next, name))
         return false;
     return true;
@@ -5457,14 +5457,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
                 goto cleanup;
             }
 
-            util_snprintf(name, sizeof(name), "%s##SETF", var->name);
+            platform_snprintf(name, sizeof(name), "%s##SETF", var->name);
             if (!parser_create_array_field_setter(parser, array, name))
                 goto cleanup;
 
             telem = ast_type_copy(ast_ctx(var), array->expression.next);
             tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD);
             tfield->expression.next = telem;
-            util_snprintf(name, sizeof(name), "%s##GETFP", var->name);
+            platform_snprintf(name, sizeof(name), "%s##GETFP", var->name);
             if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) {
                 ast_delete(tfield);
                 goto cleanup;
diff --git a/test.c b/test.c
index fdf3777..07ca9ca 100644 (file)
--- a/test.c
+++ b/test.c
@@ -162,13 +162,8 @@ static int task_pclose(FILE **handles) {
         char    *cmd  = NULL;
         popen_t *open = (popen_t*)mem_a(sizeof(popen_t));
 
-#ifndef _MSC_VER
-        tmpnam(open->name_err);
-        tmpnam(open->name_out);
-#else
-        tmpnam_s(open->name_err, L_tmpnam);
-        tmpnam_s(open->name_out, L_tmpnam);
-#endif
+        platform_tmpnam(open->name_err);
+        platform_tmpnam(open->name_out);
 
         (void)mode; /* excluded */
 
@@ -507,7 +502,7 @@ static task_template_t *task_template_compile(const char *file, const char *dir,
     FILE            *tempfile = NULL;
     task_template_t *tmpl     = NULL;
 
-    util_snprintf(fullfile,    sizeof(fullfile), "%s/%s", dir, file);
+    platform_snprintf(fullfile,    sizeof(fullfile), "%s/%s", dir, file);
 
     tempfile = fs_file_open(fullfile, "r");
     tmpl     = (task_template_t*)mem_a(sizeof(task_template_t));
@@ -717,7 +712,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
         dir = fs_dir_open(directories[i]);
 
         while ((files = fs_dir_read(dir))) {
-            util_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name);
+            platform_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name);
             if (stat(buffer, &directory) == -1) {
                 con_err("internal error: stat failed, aborting\n");
                 abort();
@@ -733,7 +728,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
             if (strcmp(files->d_name + strlen(files->d_name) - 5, ".tmpl") == 0) {
                 task_template_t *tmpl = task_template_compile(files->d_name, directories[i], pad);
                 char             buf[4096]; /* one page should be enough */
-                char            *qcflags = NULL;
+                const char      *qcflags = NULL;
                 task_t           task;
 
                 found ++;
@@ -754,16 +749,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                  * to test compile flags for all tests.  This needs to be
                  * BEFORE other flags (so that the .tmpl can override them)
                  */
-                #ifdef _MSC_VER
-                {
-                    char   buffer[4096];
-                    size_t size;
-                    getenv_s(&size, buffer, sizeof(buffer), "QCFLAGS");
-                    qcflags = buffer;
-                }
-                #else
-                qcflags = getenv("QCFLAGS");
-                #endif
+                qcflags = platform_getenv("QCFLAGS");
 
                 /*
                  * Generate the command required to open a pipe to a process
@@ -773,7 +759,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                 if (strcmp(tmpl->proceduretype, "-pp")) {
                     if (qcflags) {
                         if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
-                            util_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s",
+                            platform_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s",
                                 task_bins[TASK_COMPILE],
                                 directories[i],
                                 tmpl->sourcefile,
@@ -782,7 +768,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                                 tmpl->tempfilename
                             );
                         } else {
-                            util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s",
+                            platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s",
                                 task_bins[TASK_COMPILE],
                                 curdir,
                                 defs,
@@ -795,7 +781,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                         }
                     } else {
                         if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
-                            util_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s",
+                            platform_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s",
                                 task_bins[TASK_COMPILE],
                                 directories[i],
                                 tmpl->sourcefile,
@@ -803,7 +789,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                                 tmpl->tempfilename
                             );
                         } else {
-                            util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s",
+                            platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s",
                                 task_bins[TASK_COMPILE],
                                 curdir,
                                 defs,
@@ -817,14 +803,14 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                 } else {
                     /* Preprocessing (qcflags mean shit all here we don't allow them) */
                     if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
-                        util_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s",
+                        platform_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s",
                             task_bins[TASK_COMPILE],
                             directories[i],
                             tmpl->sourcefile,
                             tmpl->tempfilename
                         );
                     } else {
-                        util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s",
+                        platform_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s",
                             task_bins[TASK_COMPILE],
                             curdir,
                             defs,
@@ -850,14 +836,14 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
                  * Open up some file desciptors for logging the stdout/stderr
                  * to our own.
                  */
-                util_snprintf(buf,  sizeof(buf), "%s.stdout", tmpl->tempfilename);
+                platform_snprintf(buf,  sizeof(buf), "%s.stdout", tmpl->tempfilename);
                 task.stdoutlogfile = util_strdup(buf);
                 if (!(task.stdoutlog     = fs_file_open(buf, "w"))) {
                     con_err("error opening %s for stdout\n", buf);
                     continue;
                 }
 
-                util_snprintf(buf,  sizeof(buf), "%s.stderr", tmpl->tempfilename);
+                platform_snprintf(buf,  sizeof(buf), "%s.stderr", tmpl->tempfilename);
                 task.stderrlogfile = util_strdup(buf);
                 if (!(task.stderrlog = fs_file_open(buf, "w"))) {
                     con_err("error opening %s for stderr\n", buf);
@@ -892,7 +878,7 @@ static void task_precleanup(const char *curdir) {
             strstr(files->d_name, ".stdout") ||
             strstr(files->d_name, ".stderr"))
         {
-            util_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name);
+            platform_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name);
             if (remove(buffer))
                 con_err("error removing temporary file: %s\n", buffer);
         }
@@ -961,12 +947,12 @@ static bool task_trymatch(size_t i, char ***line) {
          * actually specified.
          */
         if (!strcmp(tmpl->executeflags, "$null")) {
-            util_snprintf(buffer,  sizeof(buffer), "%s %s",
+            platform_snprintf(buffer,  sizeof(buffer), "%s %s",
                 task_bins[TASK_EXECUTE],
                 tmpl->tempfilename
             );
         } else {
-            util_snprintf(buffer,  sizeof(buffer), "%s %s %s",
+            platform_snprintf(buffer,  sizeof(buffer), "%s %s %s",
                 task_bins[TASK_EXECUTE],
                 tmpl->executeflags,
                 tmpl->tempfilename
@@ -1111,11 +1097,11 @@ static size_t task_schedualize(size_t *pad) {
     size_t j        = 0;
     size_t failed   = 0;
 
-    util_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks));
+    platform_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks));
 
     for (; i < vec_size(task_tasks); i++) {
         memset(space[1], 0, sizeof(space[1]));
-        util_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1));
+        platform_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1));
 
         con_out("test #%u %*s", i + 1, strlen(space[0]) - strlen(space[1]), "");
 
diff --git a/util.c b/util.c
index 9b32e48..f454ae7 100644 (file)
--- a/util.c
+++ b/util.c
@@ -295,93 +295,6 @@ int util_asprintf(char **ret, const char *fmt, ...) {
     return read;
 }
 
-/*
- * These are various re-implementations (wrapping the real ones) of
- * string functions that MSVC considers unsafe. We wrap these up and
- * use the safe variations on MSVC.
- */
-#ifdef _MSC_VER
-    static char **util_strerror_allocated() {
-        static char **data = NULL;
-        return data;
-    }
-
-    static void util_strerror_cleanup(void) {
-        size_t i;
-        char  **data = util_strerror_allocated();
-        for (i = 0; i < vec_size(data); i++)
-            mem_d(data[i]);
-        vec_free(data);
-    }
-
-    const char *util_strerror(int num) {
-        char         *allocated = NULL;
-        static bool   install   = false;
-        static size_t tries     = 0;
-        char        **vector    = util_strerror_allocated();
-
-        /* try installing cleanup handler */
-        while (!install) {
-            if (tries == 32)
-                return "(unknown)";
-
-            install = !atexit(&util_strerror_cleanup);
-            tries ++;
-        }
-
-        allocated = (char*)mem_a(4096); /* A page must be enough */
-        strerror_s(allocated, 4096, num);
-
-        vec_push(vector, allocated);
-        return (const char *)allocated;
-    }
-
-    int util_snprintf(char *src, size_t bytes, const char *format, ...) {
-        int      rt;
-        va_list  va;
-        va_start(va, format);
-
-        rt = vsprintf_s(src, bytes, format, va);
-        va_end  (va);
-
-        return rt;
-    }
-
-    char *util_strcat(char *dest, const char *src) {
-        strcat_s(dest, strlen(src), src);
-        return dest;
-    }
-
-    char *util_strncpy(char *dest, const char *src, size_t num) {
-        strncpy_s(dest, num, src, num);
-        return dest;
-    }
-#else
-    const char *util_strerror(int num) {
-        return strerror(num);
-    }
-
-    int util_snprintf(char *src, size_t bytes, const char *format, ...) {
-        int      rt;
-        va_list  va;
-        va_start(va, format);
-        rt = vsnprintf(src, bytes, format, va);
-        va_end  (va);
-
-        return rt;
-    }
-
-    char *util_strcat(char *dest, const char *src) {
-        return strcat(dest, src);
-    }
-
-    char *util_strncpy(char *dest, const char *src, size_t num) {
-        return strncpy(dest, src, num);
-    }
-
-#endif /*! _MSC_VER */
-
-
 void util_seed(uint32_t value) {
     srand((int)value);
 }