]> de.git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
preliminary segregated console subsystem
authorDale Weiler <killfieldengine@gmail.com>
Wed, 14 Nov 2012 19:17:43 +0000 (19:17 +0000)
committerDale Weiler <killfieldengine@gmail.com>
Wed, 14 Nov 2012 19:17:43 +0000 (19:17 +0000)
Makefile
con.c [new file with mode: 0644]
gmqcc.h
main.c
parser.c
util.c

index e00e384fa1eb465cc2038230dba523e96dc7ac8c..c800ecaf6200af9d98b8002999e290736522e713 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,8 @@ OBJ     = \
           code.o      \
           ast.o       \
           ir.o        \
-          error.o
+          error.o     \
+          con.o
 OBJ_A = test/ast-test.o
 OBJ_I = test/ir-test.o
 OBJ_C = main.o lexer.o parser.o
diff --git a/con.c b/con.c
new file mode 100644 (file)
index 0000000..623cb99
--- /dev/null
+++ b/con.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2012
+ *     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"
+
+/*
+ * isatty/STDERR_FILENO/STDOUT_FILNO
+ * + some other things likewise.
+ */
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#define GMQCC_IS_STDOUT(X) ((X) == stdout)
+#define GMQCC_IS_STDERR(X) ((X) == stderr)
+#define GMQCC_IS_DEFINE(X) (GMQCC_IS_STDERR(X) || GMQCC_IS_STDOUT(X))
+
+typedef struct {
+    FILE *handle_err;
+    FILE *handle_out;
+    
+    int   color_err;
+    int   color_out;
+} con_t;
+
+/*
+ * Doing colored output on windows is fucking stupid.  The linux way is
+ * the real way. So we emulate it on windows :)
+ */
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/*
+ * Windows doesn't have constants for FILENO, sadly but the docs tell
+ * use the constant values.
+ */
+#undef  STDERR_FILENO
+#undef  STDOUT_FILENO
+#define STDERR_FILENO 2
+#define STDOUT_FILENO 1
+
+/*
+ * Windows and it's posix underscore bullshit.  We simply fix this
+ * with yay, another macro :P
+ */
+#define isatty _isatty
+enum {
+    RESET = 0,
+    BOLD  = 1,
+    BLACK = 30,
+    RED,
+    GREEN,
+    YELLOW,
+    BLUE,
+    MAGENTA,
+    CYAN,
+    GRAY,
+    WHITE
+};
+
+enum {
+    WBLACK,
+    WBLUE,
+    WGREEN   = 2,
+    WRED     = 4,
+    WINTENSE = 8,
+    WCYAN    = WBLUE  | WGREEN,
+    WMAGENTA = WBLUE  | WRED,
+    WYELLOW  = WGREEN | WRED,
+    WWHITE   = WBLUE  | WGREEN | WRED
+}
+
+static const ansi2win[] = {
+    WBLACK,
+    WRED,
+    WGREEN,
+    WYELLOW,
+    WBLUE,
+    WMAGENTA,
+    WCYAN,
+    WWHITE
+};
+
+static void win_fputs(char *str, FILE *f) {
+    /* state for translate */
+    int acolor;
+    int wcolor;
+    int icolor;
+    
+    int state;
+    int place;
+    
+    /* attributes */
+    int intense  =  -1;
+    int colors[] = {-1, -1 };
+    int colorpos = 1;
+    
+    CONSOLE_SCREEN_BUFFER_INFO cinfo;
+    GetConsoleScreenBufferInfo(
+        (h == stdout) ?
+            GetStdHandle(STD_OUTPUT_HANDLE) :
+            GetStdHandle(STD_ERROR_HANDLE), &cinfo
+    );
+    icolor = cinfo.wAttributes;
+    
+    while (*str) {
+        if (*str == '\e')
+            state = '\e';
+        else if (state == '\e' && *str == '[')
+            state = '[';
+        else if (state == '[') {
+            if (*str != 'm') {
+                colors[colorpos] = *str;
+                colorpos--;
+            } else {
+                int find;
+                int mult;
+                for (find = colorpos + 1, acolor = 0, mult = 1; find < 2; find++) {
+                    acolor += (colors[find] - 48) * mult;
+                    mult   *= 10;
+                }
+                
+                /* convert to windows color */
+                if (acolor == BOLD)
+                    intense = WINTENSE;
+                else if (acolor == RESET) {
+                    intense = WBLACK;
+                    wcolor  = icolor;
+                }
+                else if (BLACK < acolor && acolor <= WHITE)
+                    wcolor = ansi2win[acolor - 30];
+                else if (acolor == 90) {
+                    /* special gray really white man */
+                    wcolor  = WWHITE;
+                    intense = WBLACK;
+                }
+                
+                SetConsoleTextattribute(
+                    (h == stdout) ?
+                    GetStdHandle(STD_OUTPUT_HANDLE) :
+                    GetStdHandle(STD_ERROR_HANDLE),
+                    
+                    wcolor | intense | (icolor & 0xF0)
+                );
+                colorpos =  1;
+                state    = -1;
+            }
+        } else {
+            fputc(*str, h);
+        }
+    }
+    /* restore */
+    SetConsoleTextAttribute(
+        (h == stdout) ?
+        GetStdHandle(STD_OUTPUT_HANDLE) :
+        GetStdHandle(STD_ERROR_HANDLE),
+        icolor
+    );
+}
+#endif
+
+/*
+ * We use standard files as default. These can be changed at any time
+ * with con_change(F, F)
+ */
+static con_t console;
+
+/*
+ * Enables color on output if supported.
+ * NOTE: The support for checking colors is NULL.  On windows this will
+ * always work, on *nix it depends if the term has colors.
+ * 
+ * NOTE: This prevents colored output to piped stdout/err via isatty
+ * checks.
+ */
+static void con_enablecolor() {
+    if (console.handle_err == stderr || console.handle_err == stdout)
+        console.color_err = !!(isatty(STDERR_FILENO));
+    if (console.handle_out == stderr || console.handle_out == stdout)
+        console.color_out = !!(isatty(STDOUT_FILENO));
+}
+
+/*
+ * Does a write to the handle with the format string and list of
+ * arguments.  This colorizes for windows as well via translate
+ * step.
+ */
+static int con_write(FILE *handle, const char *fmt, va_list va) {
+    int      ln;
+    #ifndef _WIN32
+    ln = vfprintf(handle, fmt, va);
+    #else
+    {
+        char *data = NULL;
+        ln   = _vscprintf(fmt, va);
+        data = malloc(ln + 1);
+        data[ln] = 0;
+        vsprintf(data, fmt, va);
+        if (GMQCC_IS_DEFINE(handle))
+            ln = win_fputs(data, handle);
+        else
+            ln = fputs(data, handle);
+        free(data);
+    }
+    #endif
+    return ln;
+}
+
+/**********************************************************************
+ * EXPOSED INTERFACE BEGINS
+ *********************************************************************/
+
+void con_close() {
+    if (!GMQCC_IS_DEFINE(console.handle_err))
+        fclose(console.handle_err);
+    if (!GMQCC_IS_DEFINE(console.handle_out))
+        fclose(console.handle_out);
+}
+
+void con_color(int state) {
+    if (state)
+        con_enablecolor();
+    else {
+        console.color_err = 0;
+        console.color_out = 0;
+    }
+}
+
+void con_init() {
+    console.handle_err = stderr;
+    console.handle_out = stdout;
+    con_enablecolor();
+}
+
+void con_reset() {
+    con_close();
+    con_init ();
+}
+
+/*
+ * This is clever, say you want to change the console to use two
+ * files for out/err.  You pass in two strings, it will properly
+ * close the existing handles (if they're not std* handles) and
+ * open them.  Now say you want TO use stdout and stderr, this
+ * allows you to do that so long as you cast them to (char*).
+ * Say you need stdout for out, but want a file for error, you can
+ * do this too, just cast the stdout for (char*) and stick to a
+ * string for the error file.
+ */
+int con_change(const char *out, const char *err) {
+    con_close();
+    
+    if (GMQCC_IS_DEFINE((FILE*)out)) {
+        console.handle_out = (((FILE*)err) == stdout) ? stdout : stderr;
+        con_enablecolor();
+    } else if (!(console.handle_out = fopen(out, "w"))) return 0;
+    
+    if (GMQCC_IS_DEFINE((FILE*)err)) {
+        console.handle_err = (((FILE*)err) == stdout) ? stdout : stderr;
+        con_enablecolor();
+    } else if (!(console.handle_err = fopen(err, "w"))) return 0;
+    
+    return 1;
+}
+
+int con_verr(const char *fmt, va_list va) {
+    return con_write(console.handle_err, fmt, va);
+}
+int con_vout(const char *fmt, va_list va) {
+    return con_write(console.handle_out, fmt, va);
+}
+
+int con_err(const char *fmt, ...) {
+    va_list  va;
+    int      ln = 0;
+    va_start(va, fmt);
+    con_verr(fmt, va);
+    va_end  (va);
+    return   ln;
+}
+int con_out(const char *fmt, ...) {
+    va_list  va;
+    int      ln = 0;
+    va_start(va, fmt);
+    con_vout(fmt, va);
+    va_end  (va);
+    return   ln;
+}
diff --git a/gmqcc.h b/gmqcc.h
index 7b100139bbf54191e71a43299d3c25edd02b29a1..c8d1649a3682e5b1c20d7c066922609a5eec831b 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -528,6 +528,19 @@ uint32_t code_genstring   (const char *string);
 uint32_t code_cachedstring(const char *string);
 qcint    code_alloc_field (size_t qcsize);
 
+/*===================================================================*/
+/*============================ con.c ================================*/
+/*===================================================================*/
+void con_close();
+void con_color(int state);
+void con_init ();
+void con_reset();
+int  con_change(const char *out, const char *err);
+int  con_verr  (const char *fmt, va_list va);
+int  con_vout  (const char *fmt, va_list va);
+int  con_err   (const char *fmt, ...);
+int  con_out   (const char *fmt, ...);
+
 /*===================================================================*/
 /*========================= assembler.c =============================*/
 /*===================================================================*/
@@ -605,10 +618,6 @@ static const struct {
 
     { "END"       , 0, 3 } /* virtual assembler instruction */
 };
-
-void asm_init (const char *, FILE **);
-void asm_close(FILE *);
-void asm_parse(FILE *);
 /*===================================================================*/
 /*============================= ast.c ===============================*/
 /*===================================================================*/
diff --git a/main.c b/main.c
index 03e077de495a0a3bfa03a52db528f396e924e3f0..d8a097c446c5942c57b9b919479f937b8d36a3d0 100644 (file)
--- a/main.c
+++ b/main.c
@@ -54,28 +54,28 @@ VECTOR_MAKE(argitem, items);
 static const char *app_name;
 
 static int usage() {
-    printf("usage: %s [options] [files...]", app_name);
-    printf("options:\n"
+    con_out("usage: %s [options] [files...]", app_name);
+    con_out("options:\n"
            "  -h, --help             show this help message\n"
            "  -debug                 turns on compiler debug messages\n"
            "  -memchk                turns on compiler memory leak check\n");
-    printf("  -o, --output=file      output file, defaults to progs.dat\n"
+    con_out("  -o, --output=file      output file, defaults to progs.dat\n"
            "  -a filename            add an asm file to be assembled\n"
            "  -s filename            add a progs.src file to be used\n");
-    printf("  -E                     stop after preprocessing\n");
-    printf("  -f<flag>               enable a flag\n"
+    con_out("  -E                     stop after preprocessing\n");
+    con_out("  -f<flag>               enable a flag\n"
            "  -fno-<flag>            disable a flag\n"
            "  -std standard          select one of the following standards\n"
            "       -std=qcc          original QuakeC\n"
            "       -std=fteqcc       fteqcc QuakeC\n"
            "       -std=gmqcc        this compiler (default)\n");
-    printf("  -W<warning>            enable a warning\n"
+    con_out("  -W<warning>            enable a warning\n"
            "  -Wno-<warning>         disable a warning\n"
            "  -Wall                  enable all warnings\n"
            "  -Werror                treat warnings as errors\n");
-    printf("  -force-crc=num         force a specific checksum into the header\n");
-    printf("\n");
-    printf("flags:\n"
+    con_out("  -force-crc=num         force a specific checksum into the header\n");
+    con_out("\n");
+    con_out("flags:\n"
            "  -fadjust-vector-fields\n"
            "            when assigning a vector field, its _y and _z fields also get assigned\n"
            );
@@ -184,7 +184,7 @@ static bool options_parse(int argc, char **argv) {
                 else if (!strcmp(argarg, "qccx"))
                     opts_standard = COMPILER_QCCX;
                 else {
-                    printf("Unknown standard: %s\n", argarg);
+                    con_out("Unknown standard: %s\n", argarg);
                     return false;
                 }
                 continue;
@@ -222,31 +222,31 @@ static bool options_parse(int argc, char **argv) {
                 case 'f':
                     util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
                     if (!strcmp(argv[0]+2, "HELP")) {
-                        printf("Possible flags:\n");
+                        con_out("Possible flags:\n");
                         for (itr = 0; itr < COUNT_FLAGS; ++itr) {
                             util_strtononcmd(opts_flag_list[itr].name, buffer, sizeof(buffer));
-                            printf(" -f%s\n", buffer);
+                            con_out(" -f%s\n", buffer);
                         }
                         exit(0);
                     }
                     else if (!strncmp(argv[0]+2, "NO_", 3)) {
                         if (!options_setflag(argv[0]+5, false)) {
-                            printf("unknown flag: %s\n", argv[0]+2);
+                            con_out("unknown flag: %s\n", argv[0]+2);
                             return false;
                         }
                     }
                     else if (!options_setflag(argv[0]+2, true)) {
-                        printf("unknown flag: %s\n", argv[0]+2);
+                        con_out("unknown flag: %s\n", argv[0]+2);
                         return false;
                     }
                     break;
                 case 'W':
                     util_strtocmd(argv[0]+2, argv[0]+2, strlen(argv[0]+2)+1);
                     if (!strcmp(argv[0]+2, "HELP")) {
-                        printf("Possible warnings:\n");
+                        con_out("Possible warnings:\n");
                         for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
                             util_strtononcmd(opts_warn_list[itr].name, buffer, sizeof(buffer));
-                            printf(" -W%s\n", buffer);
+                            con_out(" -W%s\n", buffer);
                         }
                         exit(0);
                     }
@@ -270,19 +270,19 @@ static bool options_parse(int argc, char **argv) {
                     }
                     if (!strncmp(argv[0]+2, "NO_", 3)) {
                         if (!options_setwarn(argv[0]+5, false)) {
-                            printf("unknown warning: %s\n", argv[0]+2);
+                            con_out("unknown warning: %s\n", argv[0]+2);
                             return false;
                         }
                     }
                     else if (!options_setwarn(argv[0]+2, true)) {
-                        printf("unknown warning: %s\n", argv[0]+2);
+                        con_out("unknown warning: %s\n", argv[0]+2);
                         return false;
                     }
                     break;
 
                 case 'O':
                     if (!options_witharg(&argc, &argv, &argarg)) {
-                        printf("option -O requires a numerical argument\n");
+                        con_out("option -O requires a numerical argument\n");
                         return false;
                     }
                     opts_O = atoi(argarg);
@@ -290,7 +290,7 @@ static bool options_parse(int argc, char **argv) {
 
                 case 'o':
                     if (!options_witharg(&argc, &argv, &argarg)) {
-                        printf("option -o requires an argument: the output file name\n");
+                        con_out("option -o requires an argument: the output file name\n");
                         return false;
                     }
                     opts_output = argarg;
@@ -301,7 +301,7 @@ static bool options_parse(int argc, char **argv) {
                 case 's':
                     item.type = argv[0][1] == 'a' ? TYPE_ASM : TYPE_SRC;
                     if (!options_witharg(&argc, &argv, &argarg)) {
-                        printf("option -a requires a filename %s\n",
+                        con_out("option -a requires a filename %s\n",
                                 (argv[0][1] == 'a' ? "containing QC-asm" : "containing a progs.src formatted list"));
                         return false;
                     }
@@ -326,14 +326,14 @@ static bool options_parse(int argc, char **argv) {
                             opts_output = argarg;
                             opts_output_wasset = true;
                         } else {
-                            printf("Unknown parameter: %s\n", argv[0]);
+                            con_out("Unknown parameter: %s\n", argv[0]);
                             return false;
                         }
                     }
                     break;
 
                 default:
-                    printf("Unknown parameter: %s\n", argv[0]);
+                    con_out("Unknown parameter: %s\n", argv[0]);
                     return false;
             }
         }
@@ -398,6 +398,7 @@ int main(int argc, char **argv) {
     bool opts_output_free = false;
 
     app_name = argv[0];
+    con_init();
 
     /* default options / warn flags */
     options_set(opts_warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true);
@@ -431,18 +432,18 @@ int main(int argc, char **argv) {
 
     if (opts_dump) {
         for (itr = 0; itr < COUNT_FLAGS; ++itr) {
-            printf("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
+            con_out("Flag %s = %i\n", opts_flag_list[itr].name, OPTS_FLAG(itr));
         }
         for (itr = 0; itr < COUNT_WARNINGS; ++itr) {
-            printf("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
+            con_out("Warning %s = %i\n", opts_warn_list[itr].name, OPTS_WARN(itr));
         }
-        printf("output = %s\n", opts_output);
-        printf("optimization level = %i\n", (int)opts_O);
-        printf("standard = %i\n", opts_standard);
+        con_out("output = %s\n", opts_output);
+        con_out("optimization level = %i\n", (int)opts_O);
+        con_out("standard = %i\n", opts_standard);
     }
 
     if (!parser_init()) {
-        printf("failed to initialize parser\n");
+        con_out("failed to initialize parser\n");
         retval = 1;
         goto cleanup;
     }
@@ -450,23 +451,17 @@ int main(int argc, char **argv) {
     util_debug("COM", "starting ...\n");
 
     if (items_elements) {
-        printf("Mode: manual\n");
-        printf("There are %lu items to compile:\n", (unsigned long)items_elements);
+        con_out("Mode: manual\n");
+        con_out("There are %lu items to compile:\n", (unsigned long)items_elements);
         for (itr = 0; itr < items_elements; ++itr) {
-            #ifndef JS
-            printf("  item: %s (%s)\n",
+            con_out("  item: %s (%s)\n",
                    items_data[itr].filename,
                    ( (items_data[itr].type == TYPE_QC ? "qc" :
                      (items_data[itr].type == TYPE_ASM ? "asm" :
                      (items_data[itr].type == TYPE_SRC ? "progs.src" :
                      ("unknown"))))));
-            #endif
 
-        #ifdef JS
-            if (!parser_compile_string("js.qc", items_data[itr].filename))
-        #else
-            if (!parser_compile_file(items_data[itr].filename))
-        #endif
+        if (!parser_compile_file(items_data[itr].filename))
         {
                 retval = 1;
                 goto cleanup;
@@ -483,17 +478,17 @@ int main(int argc, char **argv) {
         char *line;
         size_t linelen = 0;
 
-        printf("Mode: progs.src\n");
+        con_out("Mode: progs.src\n");
         src = util_fopen("progs.src", "rb");
         if (!src) {
-            printf("failed to open `progs.src` for reading\n");
+            con_out("failed to open `progs.src` for reading\n");
             retval = 1;
             goto cleanup;
         }
 
         line = NULL;
         if (!progs_nextline(&line, &linelen, src) || !line[0]) {
-            printf("illformatted progs.src file: expected output filename in first line\n");
+            con_out("illformatted progs.src file: expected output filename in first line\n");
             retval = 1;
             goto srcdone;
         }
@@ -506,7 +501,7 @@ int main(int argc, char **argv) {
         while (progs_nextline(&line, &linelen, src)) {
             if (!line[0] || (line[0] == '/' && line[1] == '/'))
                 continue;
-            printf("  src: %s\n", line);
+            con_out("  src: %s\n", line);
             if (!parser_compile_file(line)) {
                 retval = 1;
                 goto srcdone;
index 0f0d52e2cde599676b320c37fd205c5c1d6906ce..ce3c778a977a17418177af5545b6f337bf0170ec 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -522,7 +522,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
     op = &operators[sy->ops[sy->ops_count-1].etype - 1];
     ctx = sy->ops[sy->ops_count-1].ctx;
 
-    DEBUGSHUNTDO(printf("apply %s\n", op->op));
+    DEBUGSHUNTDO(con_out("apply %s\n", op->op));
 
     if (sy->out_count < op->operands) {
         parseerror(parser, "internal error: not enough operands: %i (operator %s (%i))", sy->out_count,
@@ -826,7 +826,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
                 return false;
             }
             if (opts_standard == COMPILER_GMQCC)
-                printf("TODO: early out logic\n");
+                con_out("TODO: early out logic\n");
             if (CanConstFold(exprs[0], exprs[1]))
                 out = (ast_expression*)parser_const_float(parser,
                     (generated_op == INSTR_OR ? (ConstF(0) || ConstF(1)) : (ConstF(0) && ConstF(1))));
@@ -956,7 +956,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
         return false;
     }
 
-    DEBUGSHUNTDO(printf("applied %s\n", op->op));
+    DEBUGSHUNTDO(con_out("applied %s\n", op->op));
     sy->out[sy->out_count++] = syexp(ctx, out);
     return true;
 }
@@ -1183,7 +1183,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 parseerror(parser, "out of memory");
                 goto onerr;
             }
-            DEBUGSHUNTDO(printf("push %s\n", parser_tokval(parser)));
+            DEBUGSHUNTDO(con_out("push %s\n", parser_tokval(parser)));
         }
         else if (parser->tok == TOKEN_FLOATCONST) {
             ast_value *val;
@@ -1199,7 +1199,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 parseerror(parser, "out of memory");
                 goto onerr;
             }
-            DEBUGSHUNTDO(printf("push %g\n", parser_token(parser)->constval.f));
+            DEBUGSHUNTDO(con_out("push %g\n", parser_token(parser)->constval.f));
         }
         else if (parser->tok == TOKEN_INTCONST) {
             ast_value *val;
@@ -1215,7 +1215,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 parseerror(parser, "out of memory");
                 goto onerr;
             }
-            DEBUGSHUNTDO(printf("push %i\n", parser_token(parser)->constval.i));
+            DEBUGSHUNTDO(con_out("push %i\n", parser_token(parser)->constval.i));
         }
         else if (parser->tok == TOKEN_STRINGCONST) {
             ast_value *val;
@@ -1231,7 +1231,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 parseerror(parser, "out of memory");
                 goto onerr;
             }
-            DEBUGSHUNTDO(printf("push string\n"));
+            DEBUGSHUNTDO(con_out("push string\n"));
         }
         else if (parser->tok == TOKEN_VECTORCONST) {
             ast_value *val;
@@ -1247,7 +1247,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 parseerror(parser, "out of memory");
                 goto onerr;
             }
-            DEBUGSHUNTDO(printf("push '%g %g %g'\n",
+            DEBUGSHUNTDO(con_out("push '%g %g %g'\n",
                                 parser_token(parser)->constval.v.x,
                                 parser_token(parser)->constval.v.y,
                                 parser_token(parser)->constval.v.z));
@@ -1258,7 +1258,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
         }
         else if (parser->tok == ')') {
             if (wantop) {
-                DEBUGSHUNTDO(printf("do[op] )\n"));
+                DEBUGSHUNTDO(con_out("do[op] )\n"));
                 --parens;
                 if (parens < 0)
                     break;
@@ -1267,7 +1267,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                 if (!parser_close_paren(parser, &sy, false))
                     goto onerr;
             } else {
-                DEBUGSHUNTDO(printf("do[nop] )\n"));
+                DEBUGSHUNTDO(con_out("do[nop] )\n"));
                 --parens;
                 if (parens < 0)
                     break;
@@ -1348,7 +1348,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
 
             if (op->id == opid1('(')) {
                 if (wantop) {
-                    DEBUGSHUNTDO(printf("push [op] (\n"));
+                    DEBUGSHUNTDO(con_out("push [op] (\n"));
                     ++parens;
                     /* we expected an operator, this is the function-call operator */
                     if (!shunt_ops_add(&sy, syparen(parser_ctx(parser), 'f', sy.out_count-1))) {
@@ -1361,11 +1361,11 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
                         parseerror(parser, "out of memory");
                         goto onerr;
                     }
-                    DEBUGSHUNTDO(printf("push [nop] (\n"));
+                    DEBUGSHUNTDO(con_out("push [nop] (\n"));
                 }
                 wantop = false;
             } else {
-                DEBUGSHUNTDO(printf("push operator %s\n", op->op));
+                DEBUGSHUNTDO(con_out("push operator %s\n", op->op));
                 if (!shunt_ops_add(&sy, syop(parser_ctx(parser), op)))
                     goto onerr;
                 wantop = false;
@@ -1392,7 +1392,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma
         expr = sy.out[0].out;
     MEM_VECTOR_CLEAR(&sy, out);
     MEM_VECTOR_CLEAR(&sy, ops);
-    DEBUGSHUNTDO(printf("shunt done\n"));
+    DEBUGSHUNTDO(con_out("shunt done\n"));
     return expr;
 
 onerr:
@@ -2891,7 +2891,7 @@ bool parser_compile_file(const char *filename)
 {
     parser->lex = lex_open(filename);
     if (!parser->lex) {
-        printf("failed to open file \"%s\"\n", filename);
+        con_out("failed to open file \"%s\"\n", filename);
         return false;
     }
     return parser_compile();
@@ -2901,7 +2901,7 @@ bool parser_compile_string(const char *name, const char *str)
 {
     parser->lex = lex_open_string(str, strlen(str), name);
     if (!parser->lex) {
-        printf("failed to create lexer for string \"%s\"\n", name);
+        con_out("failed to create lexer for string \"%s\"\n", name);
         return false;
     }
     return parser_compile();
@@ -3023,7 +3023,7 @@ bool parser_finish(const char *output)
     {
         ir = ir_builder_new("gmqcc_out");
         if (!ir) {
-            printf("failed to allocate builder\n");
+            con_out("failed to allocate builder\n");
             return false;
         }
 
@@ -3036,7 +3036,7 @@ bool parser_finish(const char *output)
             isconst = field->isconst;
             field->isconst = false;
             if (!ast_global_codegen((ast_value*)field, ir)) {
-                printf("failed to generate field %s\n", field->name);
+                con_out("failed to generate field %s\n", field->name);
                 ir_builder_delete(ir);
                 return false;
             }
@@ -3067,40 +3067,40 @@ bool parser_finish(const char *output)
                 }
             }
             if (!ast_global_codegen(asvalue, ir)) {
-                printf("failed to generate global %s\n", parser->globals[i].name);
+                con_out("failed to generate global %s\n", parser->globals[i].name);
                 ir_builder_delete(ir);
                 return false;
             }
         }
         for (i = 0; i < parser->imm_float_count; ++i) {
             if (!ast_global_codegen(parser->imm_float[i], ir)) {
-                printf("failed to generate global %s\n", parser->imm_float[i]->name);
+                con_out("failed to generate global %s\n", parser->imm_float[i]->name);
                 ir_builder_delete(ir);
                 return false;
             }
         }
         for (i = 0; i < parser->imm_string_count; ++i) {
             if (!ast_global_codegen(parser->imm_string[i], ir)) {
-                printf("failed to generate global %s\n", parser->imm_string[i]->name);
+                con_out("failed to generate global %s\n", parser->imm_string[i]->name);
                 ir_builder_delete(ir);
                 return false;
             }
         }
         for (i = 0; i < parser->imm_vector_count; ++i) {
             if (!ast_global_codegen(parser->imm_vector[i], ir)) {
-                printf("failed to generate global %s\n", parser->imm_vector[i]->name);
+                con_out("failed to generate global %s\n", parser->imm_vector[i]->name);
                 ir_builder_delete(ir);
                 return false;
             }
         }
         for (i = 0; i < parser->functions_count; ++i) {
             if (!ast_function_codegen(parser->functions[i], ir)) {
-                printf("failed to generate function %s\n", parser->functions[i]->name);
+                con_out("failed to generate function %s\n", parser->functions[i]->name);
                 ir_builder_delete(ir);
                 return false;
             }
             if (!ir_function_finalize(parser->functions[i]->ir_func)) {
-                printf("failed to finalize function %s\n", parser->functions[i]->name);
+                con_out("failed to finalize function %s\n", parser->functions[i]->name);
                 ir_builder_delete(ir);
                 return false;
             }
@@ -3108,12 +3108,12 @@ bool parser_finish(const char *output)
 
         if (retval) {
             if (opts_dump)
-                ir_builder_dump(ir, printf);
+                ir_builder_dump(ir, con_out);
 
             generate_checksum(parser);
 
             if (!ir_builder_generate(ir, output)) {
-                printf("*** failed to generate output file\n");
+                con_out("*** failed to generate output file\n");
                 ir_builder_delete(ir);
                 return false;
             }
@@ -3123,6 +3123,6 @@ bool parser_finish(const char *output)
         return retval;
     }
 
-    printf("*** there were compile errors\n");
+    con_out("*** there were compile errors\n");
     return false;
 }
diff --git a/util.c b/util.c
index ec115cdddb4097897e49d6fd0bf64ca914f35506..2689bc062e5389cf1682c6bfbfbf3e12fdf89a0c 100644 (file)
--- a/util.c
+++ b/util.c
@@ -242,11 +242,8 @@ void util_debug(const char *area, const char *ms, ...) {
         return;
 
     va_start(va, ms);
-    fprintf (stdout, "DEBUG: ");
-    fputc   ('[',  stdout);
-    fprintf(stdout, "%s", area);
-    fputs   ("] ", stdout);
-    vfprintf(stdout, ms, va);
+    con_out ("[%s] ", area);
+    con_vout(ms, va); 
     va_end  (va);
 }