Wrapper around FILE to take advantage of MSVC "secure" CRT. We don't actually defend...
authorDale Weiler <killfieldengine@gmail.com>
Sun, 23 Dec 2012 06:05:22 +0000 (06:05 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Sun, 23 Dec 2012 06:05:22 +0000 (06:05 +0000)
12 files changed:
Makefile
code.c
conout.c
exec.c
file.c [new file with mode: 0644]
ftepp.c
gmqcc.h
lexer.c
main.c
opts.c
test.c
util.c

index 0d1cee7025918aca55abc5311559c46f23a88a7a..94b25e377ad4afdca79c5cfab92c249fe107aa68 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -27,10 +27,10 @@ ifeq ($(track), no)
     CFLAGS += -DNOTRACK
 endif
 
-OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o
-OBJ_T = test.o util.o conout.o
-OBJ_C = main.o lexer.o parser.o
-OBJ_X = exec-standalone.o util.o conout.o
+OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o file.o
+OBJ_T = test.o util.o conout.o file.o
+OBJ_C = main.o lexer.o parser.o file.o
+OBJ_X = exec-standalone.o util.o conout.o file.o
 
 ifneq ("$(CYGWIN)", "")
        #nullify the common variables that
diff --git a/code.c b/code.c
index 42a55959ff131282d48ab71250087970cecb78ae..0ad8becb8de54bc50c47cb434164bb46a95f2c62 100644 (file)
--- a/code.c
+++ b/code.c
@@ -154,41 +154,42 @@ bool code_write(const char *filename, const char *lnofile) {
         uint32_t lnotype = *(unsigned int*)"LNOF";
         uint32_t version = 1;
 
-        fp = util_fopen(lnofile, "wb");
+        fp = file_open(lnofile, "wb");
         if (!fp)
             return false;
 
         util_endianswap(&version,      1,                       sizeof(version));
         util_endianswap(code_linenums, vec_size(code_linenums), sizeof(code_linenums[0]));
 
-        if (fwrite(&lnotype,                        sizeof(lnotype),                        1,                       fp) != 1 ||
-            fwrite(&version,                        sizeof(version),                        1,                       fp) != 1 ||
-            fwrite(&code_header.defs.length,        sizeof(code_header.defs.length),        1,                       fp) != 1 ||
-            fwrite(&code_header.globals.length,     sizeof(code_header.globals.length),     1,                       fp) != 1 ||
-            fwrite(&code_header.fields.length,      sizeof(code_header.fields.length),      1,                       fp) != 1 ||
-            fwrite(&code_header.statements.length,  sizeof(code_header.statements.length),  1,                       fp) != 1 ||
-            fwrite(code_linenums,                   sizeof(code_linenums[0]),               vec_size(code_linenums), fp) != vec_size(code_linenums))
+
+        if (file_write(&lnotype,                        sizeof(lnotype),                        1,                       fp) != 1 ||
+            file_write(&version,                        sizeof(version),                        1,                       fp) != 1 ||
+            file_write(&code_header.defs.length,        sizeof(code_header.defs.length),        1,                       fp) != 1 ||
+            file_write(&code_header.globals.length,     sizeof(code_header.globals.length),     1,                       fp) != 1 ||
+            file_write(&code_header.fields.length,      sizeof(code_header.fields.length),      1,                       fp) != 1 ||
+            file_write(&code_header.statements.length,  sizeof(code_header.statements.length),  1,                       fp) != 1 ||
+            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");
         }
 
-        fclose(fp);
+        file_close(fp);
         fp = NULL;
     }
 
-    fp = util_fopen(filename, "wb");
+    fp = file_open(filename, "wb");
     if (!fp)
         return false;
 
-    if (1                         != fwrite(&code_header,    sizeof(prog_header)           , 1                        , fp) ||
-        vec_size(code_statements) != fwrite(code_statements, sizeof(prog_section_statement), vec_size(code_statements), fp) ||
-        vec_size(code_defs)       != fwrite(code_defs,       sizeof(prog_section_def)      , vec_size(code_defs)      , fp) ||
-        vec_size(code_fields)     != fwrite(code_fields,     sizeof(prog_section_field)    , vec_size(code_fields)    , fp) ||
-        vec_size(code_functions)  != fwrite(code_functions,  sizeof(prog_section_function) , vec_size(code_functions) , fp) ||
-        vec_size(code_globals)    != fwrite(code_globals,    sizeof(int32_t)               , vec_size(code_globals)   , fp) ||
-        vec_size(code_chars)      != fwrite(code_chars,      1                             , vec_size(code_chars)     , fp))
+    if (1                         != file_write(&code_header,    sizeof(prog_header)           , 1                        , fp) ||
+        vec_size(code_statements) != file_write(code_statements, sizeof(prog_section_statement), vec_size(code_statements), fp) ||
+        vec_size(code_defs)       != file_write(code_defs,       sizeof(prog_section_def)      , vec_size(code_defs)      , fp) ||
+        vec_size(code_fields)     != file_write(code_fields,     sizeof(prog_section_field)    , vec_size(code_fields)    , fp) ||
+        vec_size(code_functions)  != file_write(code_functions,  sizeof(prog_section_function) , vec_size(code_functions) , fp) ||
+        vec_size(code_globals)    != file_write(code_globals,    sizeof(int32_t)               , vec_size(code_globals)   , fp) ||
+        vec_size(code_chars)      != file_write(code_chars,      1                             , vec_size(code_chars)     , fp))
     {
-        fclose(fp);
+        file_close(fp);
         return false;
     }
 
@@ -253,6 +254,6 @@ bool code_write(const char *filename, const char *lnofile) {
     vec_free(code_functions);
     vec_free(code_globals);
     vec_free(code_chars);
-    fclose(fp);
+    file_close(fp);
     return true;
 }
index b8227e5b07b882401bb5387d7abeaab2bd27a5b1..bf8b522648802b1b342760fdd81ecb8abfce20f2 100644 (file)
--- a/conout.c
+++ b/conout.c
@@ -21,6 +21,7 @@
  * SOFTWARE.
  */
 #include "gmqcc.h"
+#include <stdio.h>
 
 /*
  * isatty/STDERR_FILENO/STDOUT_FILNO
@@ -167,7 +168,7 @@ static int win_fputs(const char *str, FILE *h) {
                 state    = -1;
             }
         } else {
-            fputc(*str, h);
+            file_putc(*str, h);
             length ++;
         }
         str++;
@@ -218,7 +219,7 @@ static int con_write(FILE *handle, const char *fmt, va_list va) {
         char data[4096];
         memset(data, 0, sizeof(data));
         vsnprintf(data, sizeof(data), fmt, va);
-        ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(data, handle) : fputs(data, handle);
+        ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(data, handle) : file_puts(data, handle);
     }
     #endif
     return ln;
@@ -230,9 +231,9 @@ static int con_write(FILE *handle, const char *fmt, va_list va) {
 
 void con_close() {
     if (!GMQCC_IS_DEFINE(console.handle_err))
-        fclose(console.handle_err);
+        file_close(console.handle_err);
     if (!GMQCC_IS_DEFINE(console.handle_out))
-        fclose(console.handle_out);
+        file_close(console.handle_out);
 }
 
 void con_color(int state) {
@@ -268,15 +269,18 @@ void con_reset() {
 int con_change(const char *out, const char *err) {
     con_close();
 
+    if (!out) out = (const char *)((!console.handle_out) ? stdout : console.handle_out);
+    if (!err) err = (const char *)((!console.handle_err) ? stderr : console.handle_err);
+
     if (GMQCC_IS_DEFINE(out)) {
         console.handle_out = GMQCC_IS_STDOUT(out) ? stdout : stderr;
         con_enablecolor();
-    } else if (!(console.handle_out = fopen(out, "w"))) return 0;
+    } else if (!(console.handle_out = file_open(out, "w"))) return 0;
 
     if (GMQCC_IS_DEFINE(err)) {
         console.handle_err = GMQCC_IS_STDOUT(err) ? stdout : stderr;
         con_enablecolor();
-    } else if (!(console.handle_err = fopen(err, "w"))) return 0;
+    } else if (!(console.handle_err = file_open(err, "w"))) return 0;
 
     /* no buffering */
     setvbuf(console.handle_out, NULL, _IONBF, 0);
diff --git a/exec.c b/exec.c
index f4a986ed8e6cb2e2def9b3ac73086070e8c5cc9f..0b9b3621f308536e4e9b58e1e48098577f943c67 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -53,29 +53,28 @@ static void qcvmerror(qc_program *prog, const char *fmt, ...)
 
 qc_program* prog_load(const char *filename)
 {
-    qc_program *prog;
-    prog_header header;
-    FILE *file;
+    qc_program   *prog;
+    prog_header   header;
+    FILE         *file   = file_open(filename, "rb");
 
-    file = util_fopen(filename, "rb");
     if (!file)
         return NULL;
 
-    if (fread(&header, sizeof(header), 1, file) != 1) {
+    if (file_read(&header, sizeof(header), 1, file) != 1) {
         loaderror("failed to read header from '%s'", filename);
-        fclose(file);
+        file_close(file);
         return NULL;
     }
 
     if (header.version != 6) {
         loaderror("header says this is a version %i progs, we need version 6\n", header.version);
-        fclose(file);
+        file_close(file);
         return NULL;
     }
 
     prog = (qc_program*)mem_a(sizeof(qc_program));
     if (!prog) {
-        fclose(file);
+        file_close(file);
         printf("failed to allocate program data\n");
         return NULL;
     }
@@ -91,15 +90,17 @@ qc_program* prog_load(const char *filename)
     }
 
 #define read_data(hdrvar, progvar, reserved)                           \
-    if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) {            \
+    if (file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) {        \
         loaderror("seek failed");                                      \
         goto error;                                                    \
     }                                                                  \
-    if (fread(vec_add(prog->progvar, header.hdrvar.length + reserved), \
-              sizeof(*prog->progvar),                                  \
-              header.hdrvar.length, file)                              \
-        != header.hdrvar.length)                                       \
-    {                                                                  \
+    if (file_read (                                                    \
+            vec_add(prog->progvar, header.hdrvar.length + reserved),   \
+            sizeof(*prog->progvar),                                    \
+            header.hdrvar.length,                                      \
+            file                                                       \
+        )!= header.hdrvar.length                                       \
+    ) {                                                                \
         loaderror("read failed");                                      \
         goto error;                                                    \
     }
@@ -113,7 +114,7 @@ qc_program* prog_load(const char *filename)
     read_data1(strings);
     read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
 
-    fclose(file);
+    file_close(file);
 
     /* profile counters */
     memset(vec_add(prog->profile, vec_size(prog->code)), 0, sizeof(prog->profile[0]) * vec_size(prog->code));
diff --git a/file.c b/file.c
new file mode 100644 (file)
index 0000000..2bbd81f
--- /dev/null
+++ b/file.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2012
+ *     Wolfgang Bumiller
+ *     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"
+
+/*
+ * This is essentially a "wrapper" interface around standard C's IO
+ * library.  There is two reason we implement this, 1) visual studio
+ * hearts for "secure" varations, as part of it's "Security Enhancements
+ * in the CRT" (http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx).
+ * 2) But one of the greater reasons is for the possibility of large file
+ * support in the future.  I don't expect to reach the 2GB limit any
+ * time soon (mainly because that would be insane).  But when it comes
+ * to adding support for some other larger IO tasks (in the test-suite,
+ * or even the QCVM we'll need it). There is also a third possibility of
+ * building .dat files directly from zip files (which would be very cool
+ * at least I think so).  
+ */
+#ifdef _MSC_VER
+/* {{{ */
+    /*
+     * Visual Studio has security CRT features which I actually want to support
+     * if we ever port to Windows 8, and want GMQCC to be API safe.
+     *
+     * We handle them here, for all file-operations. 
+     */
+
+    static void file_exception (
+        const wchar_t *expression,
+        const wchar_t *function,
+        const wchar_t *file,
+        unsigned int   line,
+        uintptr_t      reserved
+    ) {
+        wprintf(L"Invalid parameter dectected %s:%d %s [%s]\n", file, line, function, expression);
+        wprintf(L"Aborting ...\n");
+        abort();
+    }
+
+    static void file_init() {
+        static bool init = false;
+
+        if (init)
+            return;
+
+        _set_invalid_parameter_handler(&file_exception);
+
+        /*
+         * Turnoff the message box for CRT asserations otherwise
+         * we don't get the error reported to the console as we should
+         * otherwise get.
+         */
+        _CrtSetReportMode(_CRT_ASSERT, 0);
+        init = !init;
+    }
+
+
+    FILE *file_open(const char *filename, const char *mode) {
+        FILE *handle = NULL;
+        file_init();
+
+        return ((fopen_s(&handle, filename, mode) != 0) ? NULL : handle;
+    }
+
+    size_t file_read(void *buffer, size_t size, size_t count, FILE *fp) {
+        file_init();
+        return fread_s(buffer, size*count, size, count, fp);
+    }
+
+    int file_printf(FILE *fp, const char *format, ...) {
+        int      rt;
+        va_list  va;
+        va_start(va, format);
+
+        file_init();
+        rt = vfprintf_s(fp, format, va);
+        va_end  (va);
+
+        return rt;
+    }
+
+/* }}} */
+#else
+/* {{{ */
+    /*
+     * All other compilers/platforms that don't restrict insane policies on
+     * IO for no aparent reason.
+     */
+    FILE *file_open(const char *filename, const char *mode) {
+        return fopen(filename, mode);
+    }
+
+    size_t file_read(void *buffer, size_t size, size_t count, FILE *fp) {
+        return fread(buffer, size, count, fp);
+    }
+
+    int file_printf(FILE *fp, const char *format, ...) {
+        int      rt;
+        va_list  va;
+        va_start(va, format);
+        rt = vfprintf(fp, format, va);
+        va_end  (va);
+
+        return rt;
+    }
+
+/* }}} */
+#endif
+
+/*
+ * These are implemented as just generic wrappers to keep consistency in
+ * the API.  Not as macros though  
+ */
+void GMQCC_INLINE file_close(FILE *fp) {
+    /* Invokes file_exception on windows if fp is null */
+    fclose (fp);
+}
+
+size_t GMQCC_INLINE file_write (
+    const void    *buffer,
+    size_t         size,
+    size_t         count,
+    FILE          *fp
+) {
+    /* Invokes file_exception on windows if fp is null */
+    return fwrite(buffer, size, count, fp);
+}
+
+int GMQCC_INLINE file_error(FILE *fp) {
+    /* Invokes file_exception on windows if fp is null */
+    return ferror(fp);
+}
+
+int GMQCC_INLINE file_getc(FILE *fp) {
+    /* Invokes file_exception on windows if fp is null */
+    return fgetc(fp);
+}
+
+int GMQCC_INLINE file_puts(FILE *fp, const char *str) {
+    /* Invokes file_exception on windows if fp is null */
+    return fputs(str, fp);
+}
+
+int GMQCC_INLINE file_seek(FILE *fp, long int off, int whence) {
+    /* Invokes file_exception on windows if fp is null */
+    return fseek(fp, off, whence);
+}
+
+/*
+ * Implements libc getline for systems that don't have it, which is
+ * assmed all.  This works the same as getline().
+ */
+int file_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 = file_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);
+}
diff --git a/ftepp.c b/ftepp.c
index 96c20bf4f937f7ad0d55c9050e31b6813a3ab1a3..ed501a50a43c7b229e80afcdabbdbb46d49e4e4d 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -991,9 +991,9 @@ static char *ftepp_include_find_path(const char *file, const char *pathfile)
     memcpy(vec_add(filename, len+1), file, len);
     vec_last(filename) = 0;
 
-    fp = util_fopen(filename, "rb");
+    fp = file_open(filename, "rb");
     if (fp) {
-        fclose(fp);
+        file_close(fp);
         return filename;
     }
     vec_free(filename);
diff --git a/gmqcc.h b/gmqcc.h
index af98f3f3b74bb1c924a74196ae2b2e1c952e24e4..1e4fe3b18f2701c7675a5cfe348270e153877825 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -26,8 +26,8 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <ctype.h>
 
 /*
 #      define strtof(X, Y)          (float)(strtod(X, Y))
 #endif
 
-
 /*
  * Very roboust way at determining endianess at compile time: this handles
  * almost every possible situation.  Otherwise a runtime check has to be
 /*===================================================================*/
 /*=========================== util.c ================================*/
 /*===================================================================*/
-FILE *util_fopen(const char *filename, const char *mode);
-
 void *util_memory_a      (size_t,       unsigned int, const char *);
 void  util_memory_d      (void       *, unsigned int, const char *);
 void *util_memory_r      (void       *, size_t,       unsigned int, const char *);
@@ -257,7 +254,6 @@ bool  util_strupper      (const char *);
 bool  util_strdigit      (const char *);
 char *util_strdup        (const char *);
 void  util_debug         (const char *, const char *, ...);
-int   util_getline       (char **, size_t *, FILE *);
 void  util_endianswap    (void *,  size_t, unsigned int);
 
 size_t util_strtocmd    (const char *, char *, size_t);
@@ -383,10 +379,31 @@ void          util_htdel (hash_table_t *ht);
 size_t        util_hthash(hash_table_t *ht, const char *key);
 void         *util_htgeth(hash_table_t *ht, const char *key, size_t hash);
 void          util_htseth(hash_table_t *ht, const char *key, size_t hash, void *value);
+
+/*===================================================================*/
+/*============================ file.c ===============================*/
+/*===================================================================*/
+void   GMQCC_INLINE file_close  (FILE *);
+
+int    GMQCC_INLINE file_error  (FILE *);
+int    GMQCC_INLINE file_getc   (FILE *);
+int    GMQCC_INLINE file_printf (FILE *, const char *, ...);
+int    GMQCC_INLINE file_puts   (FILE *, const char *);
+int    GMQCC_INLINE file_seek   (FILE *, long int, int);
+
+size_t GMQCC_INLINE file_read   (void *,        size_t, size_t, FILE *);
+size_t GMQCC_INLINE file_write  (const void *,  size_t, size_t, FILE *);
+
+FILE*  GMQCC_INLINE file_open   (const char *, const char *);
+
+int   /*NO_INLINE*/ file_getline(char  **, size_t *, FILE *);
+
+
 /*===================================================================*/
 /*=========================== code.c ================================*/
 /*===================================================================*/
 
+/* TODO: cleanup */
 /* Note: if you change the order, fix type_sizeof in ir.c */
 enum {
     TYPE_VOID     ,
@@ -806,6 +823,7 @@ vector  vec3_mulvf(vector, float);
 /*============================= exec.c ==============================*/
 /*===================================================================*/
 
+/* TODO: cleanup */
 /*
  * Darkplaces has (or will have) a 64 bit prog loader
  * where the 32 bit qc program is autoconverted on load.
@@ -910,6 +928,8 @@ bool parser_compile_file  (const char *filename);
 bool parser_compile_string(const char *name, const char *str);
 bool parser_finish        (const char *output);
 void parser_cleanup       ();
+
+/* TODO: make compile_string accept len and remove this */
 /* There's really no need to strlen() preprocessed files */
 bool parser_compile_string_len(const char *name, const char *str, size_t len);
 
@@ -1015,6 +1035,7 @@ typedef enum {
     COMPILER_GMQCC    /* this   QuakeC */
 } opts_std_t;
 
+/* TODO: cleanup this */
 typedef struct {
     uint32_t    O;              /* -Ox           */
     const char *output;         /* -o file       */
diff --git a/lexer.c b/lexer.c
index 7fc606c22d56962882702f7303568c5713c250ba..cf554fb2d41fb2512766f647a2c9810f76373f67 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -186,7 +186,7 @@ static void lex_token_new(lex_file *lex)
 lex_file* lex_open(const char *file)
 {
     lex_file *lex;
-    FILE *in = util_fopen(file, "rb");
+    FILE *in = file_open(file, "rb");
 
     if (!in) {
         lexerror(NULL, "open failed: '%s'\n", file);
@@ -195,7 +195,7 @@ lex_file* lex_open(const char *file)
 
     lex = (lex_file*)mem_a(sizeof(*lex));
     if (!lex) {
-        fclose(in);
+        file_close(in);
         lexerror(NULL, "out of memory\n");
         return NULL;
     }
@@ -260,7 +260,7 @@ void lex_close(lex_file *lex)
         vec_free(lex->modelname);
 
     if (lex->file)
-        fclose(lex->file);
+        file_close(lex->file);
 #if 0
     if (lex->tok)
         token_delete(lex->tok);
diff --git a/main.c b/main.c
index d6edd5cbf46fe9ed9b1aad9d19a07407259fb7d2..d732ef9bd0d1c8175cd750ac0ca10a7839a6b622 100644 (file)
--- a/main.c
+++ b/main.c
@@ -139,8 +139,8 @@ static bool options_parse(int argc, char **argv) {
     bool argend = false;
     size_t itr;
     char  buffer[1024];
-    char *redirout = (char*)stdout;
-    char *redirerr = (char*)stderr;
+    char *redirout = NULL;
+    char *redirerr = NULL;
     char *config   = NULL;
 
     while (!argend && argc > 1) {
@@ -474,7 +474,7 @@ static bool progs_nextline(char **out, size_t *alen,FILE *src) {
     char  *end;
 
     line = *out;
-    len = util_getline(&line, alen, src);
+    len  = file_getline(&line, alen, src);
     if (len == -1)
         return false;
 
@@ -553,15 +553,16 @@ int main(int argc, char **argv) {
 
     if (opts.pp_only) {
         if (opts_output_wasset) {
-            outfile = util_fopen(opts.output, "wb");
+            outfile = file_open(opts.output, "wb");
             if (!outfile) {
                 con_err("failed to open `%s` for writing\n", opts.output);
                 retval = 1;
                 goto cleanup;
             }
         }
-        else
-            outfile = stdout;
+        else {
+         /* TODO: stdout without stdout .. */
+        }
     }
 
     if (!opts.pp_only) {
@@ -604,7 +605,7 @@ int main(int argc, char **argv) {
 
         progs_src = true;
 
-        src = util_fopen("progs.src", "rb");
+        src = file_open("progs.src", "rb");
         if (!src) {
             con_err("failed to open `progs.src` for reading\n");
             retval = 1;
@@ -633,7 +634,7 @@ int main(int argc, char **argv) {
         }
 
 srcdone:
-        fclose(src);
+        file_close(src);
         mem_d(line);
     }
 
@@ -663,7 +664,7 @@ srcdone:
                 }
                 out = ftepp_get();
                 if (out)
-                    fprintf(outfile, "%s", out);
+                    file_printf(outfile, "%s", out);
                 ftepp_flush();
             }
             else {
diff --git a/opts.c b/opts.c
index 6008fb1dfa55f0307eee6af56f4e3a12a3b94ae0..69e93b428fdcdb84689a3c3ddb3a817c2589b75c 100644 (file)
--- a/opts.c
+++ b/opts.c
@@ -169,7 +169,7 @@ static size_t opts_ini_parse (
     char *read_name;
     char *read_value;
 
-    while (util_getline(&line, &linesize, filehandle) != EOF) {
+    while (file_getline(&line, &linesize, filehandle) != EOF) {
         parse_beg = line;
 
         /* handle BOM */
@@ -315,11 +315,11 @@ void opts_ini_init(const char *file) {
     
     if (!file) {
         /* try ini */
-        if (!(ini = fopen((file = "gmqcc.ini"), "r")))
+        if (!(ini = file_open((file = "gmqcc.ini"), "r")))
             /* try cfg */
-            if (!(ini = fopen((file = "gmqcc.cfg"), "r")))
+            if (!(ini = file_open((file = "gmqcc.cfg"), "r")))
                 return;
-    } else if (!(ini = fopen(file, "r")))
+    } else if (!(ini = file_open(file, "r")))
         return;
 
     con_out("found ini file `%s`\n", file);
@@ -330,5 +330,5 @@ void opts_ini_init(const char *file) {
         vec_free(error);
     }
 
-    fclose(ini);
+    file_close(ini);
 }  
diff --git a/test.c b/test.c
index b29a3d4c1b1a7ca9176ed89f1d60128cf43571b2..495b547183f3f2530c89d325ae30ba305c2e3c4d 100644 (file)
--- a/test.c
+++ b/test.c
@@ -451,7 +451,7 @@ bool task_template_parse(const char *file, task_template_t *template, FILE *fp)
         return false;
 
     /* top down parsing */
-    while (util_getline(&back, &size, fp) != EOF) {
+    while (file_getline(&back, &size, fp) != EOF) {
         /* skip whitespace */
         data = back;
         if (*data && (*data == ' ' || *data == '\t'))
@@ -592,7 +592,7 @@ task_template_t *task_template_compile(const char *file, const char *dir) {
     memset  (fullfile, 0, sizeof(fullfile));
     snprintf(fullfile,    sizeof(fullfile), "%s/%s", dir, file);
 
-    tempfile = fopen(fullfile, "r");
+    tempfile = file_open(fullfile, "r");
     template = mem_a(sizeof(task_template_t));
     task_template_nullify(template);
 
@@ -667,7 +667,7 @@ task_template_t *task_template_compile(const char *file, const char *dir) {
     }
 
 success:
-    fclose(tempfile);
+    file_close(tempfile);
     return template;
 
 failure:
@@ -676,7 +676,7 @@ failure:
      * so the check to see if it's not null here is required.
      */
     if (tempfile)
-        fclose(tempfile);
+        file_close(tempfile);
     mem_d (template);
 
     return NULL;
@@ -812,7 +812,7 @@ bool task_propagate(const char *curdir) {
             memset  (buf,0,sizeof(buf));
             snprintf(buf,  sizeof(buf), "%s.stdout", template->tempfilename);
             task.stdoutlogfile = util_strdup(buf);
-            if (!(task.stdoutlog     = fopen(buf, "w"))) {
+            if (!(task.stdoutlog     = file_open(buf, "w"))) {
                 con_err("error opening %s for stdout\n", buf);
                 continue;
             }
@@ -820,7 +820,7 @@ bool task_propagate(const char *curdir) {
             memset  (buf,0,sizeof(buf));
             snprintf(buf,  sizeof(buf), "%s.stderr", template->tempfilename);
             task.stderrlogfile = util_strdup(buf);
-            if (!(task.stderrlog     = fopen(buf, "w"))) {
+            if (!(task.stderrlog     = file_open(buf, "w"))) {
                 con_err("error opening %s for stderr\n", buf);
                 continue;
             }
@@ -904,8 +904,8 @@ void task_destroy(const char *curdir) {
          * annoying to have to do all this cleanup work.
          */
         if (task_tasks[i].runhandles) task_pclose(task_tasks[i].runhandles);
-        if (task_tasks[i].stdoutlog)  fclose     (task_tasks[i].stdoutlog);
-        if (task_tasks[i].stderrlog)  fclose     (task_tasks[i].stderrlog);
+        if (task_tasks[i].stdoutlog)  file_close (task_tasks[i].stdoutlog);
+        if (task_tasks[i].stderrlog)  file_close (task_tasks[i].stderrlog);
 
         /*
          * Only remove the log files if the test actually compiled otherwise
@@ -983,7 +983,7 @@ bool task_execute(task_template_t *template, char ***line) {
         char  *data    = NULL;
         size_t size    = 0;
         size_t compare = 0;
-        while (util_getline(&data, &size, execute) != EOF) {
+        while (file_getline(&data, &size, execute) != EOF) {
             if (!strcmp(data, "No main function found\n")) {
                 con_err("test failure: `%s` [%s] (No main function found)\n",
                     template->description,
@@ -1059,8 +1059,8 @@ void task_schedualize() {
          * Read data from stdout first and pipe that stuff into a log file
          * then we do the same for stderr.
          */
-        while (util_getline(&data, &size, task_tasks[i].runhandles[1]) != EOF) {
-            fputs(data, task_tasks[i].stdoutlog);
+        while (file_getline(&data, &size, task_tasks[i].runhandles[1]) != EOF) {
+            file_puts(task_tasks[i].stdoutlog, data);
 
             if (strstr(data, "failed to open file")) {
                 task_tasks[i].compiled = false;
@@ -1069,7 +1069,7 @@ void task_schedualize() {
 
             fflush(task_tasks[i].stdoutlog);
         }
-        while (util_getline(&data, &size, task_tasks[i].runhandles[2]) != EOF) {
+        while (file_getline(&data, &size, task_tasks[i].runhandles[2]) != EOF) {
             /*
              * If a string contains an error we just dissalow execution
              * of it in the vm.
@@ -1083,7 +1083,7 @@ void task_schedualize() {
                 task_tasks[i].compiled = false;
             }
 
-            fputs(data, task_tasks[i].stderrlog);
+            file_puts(task_tasks[i].stderrlog, data);
             fflush(task_tasks[i].stdoutlog);
         }
 
diff --git a/util.c b/util.c
index 2b2f1b0e1ffa5d00d0e58c9d11a400cd692cea91..c744b15d66a6a241ebaa6b25d41ea460b9744474 100644 (file)
--- a/util.c
+++ b/util.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include "gmqcc.h"
 
+/* TODO: remove globals ... */
 uint64_t mem_ab = 0;
 uint64_t mem_db = 0;
 uint64_t mem_at = 0;
@@ -347,54 +348,6 @@ uint16_t util_crc16(const char *k, int len, const short clamp) {
 }
 #endif
 
-/*
- * 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 = (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);
-}
-
 size_t util_strtocmd(const char *in, char *out, size_t outsz) {
     size_t sz = 1;
     for (; *in && sz < outsz; ++in, ++out, ++sz)
@@ -411,19 +364,7 @@ size_t util_strtononcmd(const char *in, char *out, size_t outsz) {
     return sz-1;
 }
 
-
-FILE *util_fopen(const char *filename, const char *mode)
-{
-#ifdef _MSC_VER
-    FILE *out;
-    if (fopen_s(&out, filename, mode) != 0)
-        return NULL;
-    return out;
-#else
-    return fopen(filename, mode);
-#endif
-}
-
+/* TODO: rewrite ... when I redo the ve cleanup */
 void _util_vec_grow(void **a, size_t i, size_t s) {
     size_t m = *a ? 2*_vec_beg(*a)+i : i+1;
     void  *p = mem_r((*a ? _vec_raw(*a) : NULL), s * m + sizeof(size_t)*2);