]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - conout.c
Cleanups
[xonotic/gmqcc.git] / conout.c
index 2c9962d4a50329cc588e4f14934150c6ed35eca6..aedff4da20b32e036fefd64ef4e3e0085d365546 100644 (file)
--- a/conout.c
+++ b/conout.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012
+ * Copyright (C) 2012, 2013
  *     Dale Weiler
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -53,7 +53,7 @@ typedef struct {
  * Doing colored output on windows is fucking stupid.  The linux way is
  * the real way. So we emulate it on windows :)
  */
-#ifdef _MSC_VER
+#ifdef _WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
@@ -77,7 +77,7 @@ enum {
     MAGENTA,
     CYAN,
     GRAY,
-    WHITE
+    WHITE = GRAY
 };
 
 enum {
@@ -90,9 +90,9 @@ enum {
     WMAGENTA = WBLUE  | WRED,
     WYELLOW  = WGREEN | WRED,
     WWHITE   = WBLUE  | WGREEN | WRED
-}
+};
 
-static const ansi2win[] = {
+static const int ansi2win[] = {
     WBLACK,
     WRED,
     WGREEN,
@@ -103,20 +103,18 @@ static const ansi2win[] = {
     WWHITE
 };
 
-static void win_fputs(char *str, FILE *h) {
+static int win_fputs(FILE *h, const char *str) {
     /* state for translate */
-    int acolor;
-    int wcolor;
-    int icolor;
-
-    int state;
-    int place;
+    int acolor = 0;
+    int wcolor = 0;
+    int icolor = 0;
+    int state  = 0;
 
     /* attributes */
     int intense  =  -1;
     int colors[] = {-1, -1 };
     int colorpos = 1;
-
+    int length   = 0;
     CONSOLE_SCREEN_BUFFER_INFO cinfo;
     GetConsoleScreenBufferInfo (
         (GMQCC_IS_STDOUT(h)) ?
@@ -126,9 +124,9 @@ static void win_fputs(char *str, FILE *h) {
     icolor = cinfo.wAttributes;
 
     while (*str) {
-        if (*str == '\e')
-            state = '\e';
-        else if (state == '\e' && *str == '[')
+        if (*str == '\x1B')
+            state = '\x1B';
+        else if (state == '\x1B' && *str == '[')
             state = '[';
         else if (state == '[') {
             if (*str != 'm') {
@@ -149,7 +147,7 @@ static void win_fputs(char *str, FILE *h) {
                     intense = WBLACK;
                     wcolor  = icolor;
                 }
-                else if (BLACK < acolor && acolor <= WHITE)
+                else if (BLACK <= acolor && acolor <= WHITE)
                     wcolor = ansi2win[acolor - 30];
                 else if (acolor == 90) {
                     /* special gray really white man */
@@ -158,7 +156,7 @@ static void win_fputs(char *str, FILE *h) {
                 }
 
                 SetConsoleTextAttribute (
-                    (h == stdout) ?
+                    (GMQCC_IS_STDOUT(h)) ?
                     GetStdHandle(STD_OUTPUT_HANDLE) :
                     GetStdHandle(STD_ERROR_HANDLE),
 
@@ -168,8 +166,10 @@ static void win_fputs(char *str, FILE *h) {
                 state    = -1;
             }
         } else {
-            fputc(*str, h);
+            fs_file_write(str, 1, 1, stdout);
+            length ++;
         }
+        str++;
     }
     /* restore */
     SetConsoleTextAttribute(
@@ -178,6 +178,7 @@ static void win_fputs(char *str, FILE *h) {
         GetStdHandle(STD_ERROR_HANDLE),
         icolor
     );
+    return length;
 }
 #endif
 
@@ -195,7 +196,7 @@ static con_t console;
  * NOTE: This prevents colored output to piped stdout/err via isatty
  * checks.
  */
-static void con_enablecolor() {
+static void con_enablecolor(void) {
     if (console.handle_err == stderr || console.handle_err == stdout)
         console.color_err = !!(isatty(STDERR_FILENO));
     if (console.handle_out == stderr || console.handle_out == stdout)
@@ -209,20 +210,18 @@ static void con_enablecolor() {
  */
 static int con_write(FILE *handle, const char *fmt, va_list va) {
     int      ln;
-    #ifndef _MSC_VER
+    #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);
+        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
+        ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(handle, data) : fs_file_puts(handle, data);
     }
     #endif
     return ln;
@@ -234,9 +233,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);
+        fs_file_close(console.handle_err);
     if (!GMQCC_IS_DEFINE(console.handle_out))
-        fclose(console.handle_out);
+        fs_file_close(console.handle_out);
 }
 
 void con_color(int state) {
@@ -272,23 +271,33 @@ 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 = fs_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;
-
-    /* no buffering */
-    setvbuf(console.handle_out, NULL, _IONBF, 0);
-    setvbuf(console.handle_err, NULL, _IONBF, 0);
+    } else if (!(console.handle_err = fs_file_open(err, "w"))) return 0;
 
     return 1;
 }
 
+/*
+ * Defaultizer because stdio.h shouldn't be used anywhere except here
+ * and inside file.c To prevent mis-match of wrapper-interfaces.
+ */
+FILE *con_default_out() {
+    return (console.handle_out = stdout);
+}
+FILE *con_default_err() {
+    return (console.handle_err = stderr);
+}
+
 int con_verr(const char *fmt, va_list va) {
     return con_write(console.handle_err, fmt, va);
 }
@@ -317,12 +326,13 @@ int con_out(const char *fmt, ...) {
     return   ln;
 }
 
+#ifndef QCVM_EXECUTOR
 /*
  * Utility console message writes for lexer contexts.  These will allow
  * for reporting of file:line based on lexer context, These are used
  * heavily in the parser/ir/ast.
  */
-void con_vprintmsg_c(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap, const char *condname) {
+static void con_vprintmsg_c(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap, const char *condname) {
     /* color selection table */
     static int sel[] = {
         CON_WHITE,
@@ -336,9 +346,9 @@ void con_vprintmsg_c(int level, const char *name, size_t line, const char *msgty
     int (*vprint)(const char *, va_list) = (err) ? &con_verr : &con_vout;
 
     if (color)
-        print("\033[0;%dm%s:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, sel[level], msgtype);
+        print("\033[0;%dm%s:%d:%d: \033[0;%dm%s: \033[0m", CON_CYAN, name, (int)line, (int)column, sel[level], msgtype);
     else
-        print("%s:%d: %s: ", name, (int)line, msgtype);
+        print("%s:%d:%d: %s: ", name, (int)line, (int)column, msgtype);
 
     vprint(msg, ap);
     if (condname)
@@ -347,22 +357,22 @@ void con_vprintmsg_c(int level, const char *name, size_t line, const char *msgty
         print("\n");
 }
 
-void con_vprintmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap) {
-    con_vprintmsg_c(level, name, line, msgtype, msg, ap, NULL);
+void con_vprintmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, va_list ap) {
+    con_vprintmsg_c(level, name, line, column, msgtype, msg, ap, NULL);
 }
 
-void con_printmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, ...) {
+void con_printmsg(int level, const char *name, size_t line, size_t column, const char *msgtype, const char *msg, ...) {
     va_list   va;
     va_start(va, msg);
-    con_vprintmsg(level, name, line, msgtype, msg, va);
+    con_vprintmsg(level, name, line, column, msgtype, msg, va);
     va_end  (va);
 }
 
-void con_cvprintmsg(void *ctx, int lvl, const char *msgtype, const char *msg, va_list ap) {
-    con_vprintmsg(lvl, ((lex_ctx*)ctx)->file, ((lex_ctx*)ctx)->line, msgtype, msg, ap);
+void con_cvprintmsg(lex_ctx_t ctx, int lvl, const char *msgtype, const char *msg, va_list ap) {
+    con_vprintmsg(lvl, ctx.file, ctx.line, ctx.column, msgtype, msg, ap);
 }
 
-void con_cprintmsg (void *ctx, int lvl, const char *msgtype, const char *msg, ...) {
+void con_cprintmsg(lex_ctx_t ctx, int lvl, const char *msgtype, const char *msg, ...) {
     va_list   va;
     va_start(va, msg);
     con_cvprintmsg(ctx, lvl, msgtype, msg, va);
@@ -370,16 +380,23 @@ void con_cprintmsg (void *ctx, int lvl, const char *msgtype, const char *msg, ..
 }
 
 /* General error interface */
-size_t compile_errors = 0;
+size_t compile_errors   = 0;
 size_t compile_warnings = 0;
+size_t compile_Werrors  = 0;
+static lex_ctx_t first_werror;
+
+void compile_show_werrors()
+{
+    con_cprintmsg(first_werror, LVL_ERROR, "first warning", "was here");
+}
 
-void vcompile_error(lex_ctx ctx, const char *msg, va_list ap)
+void vcompile_error(lex_ctx_t ctx, const char *msg, va_list ap)
 {
     ++compile_errors;
-    con_cvprintmsg((void*)&ctx, LVL_ERROR, "error", msg, ap);
+    con_cvprintmsg(ctx, LVL_ERROR, "error", msg, ap);
 }
 
-void compile_error(lex_ctx ctx, const char *msg, ...)
+void compile_error(lex_ctx_t ctx, const char *msg, ...)
 {
     va_list ap;
     va_start(ap, msg);
@@ -387,10 +404,11 @@ void compile_error(lex_ctx ctx, const char *msg, ...)
     va_end(ap);
 }
 
-bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_list ap)
+bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, va_list ap)
 {
-    int lvl = LVL_WARNING;
-    char warn_name[1024];
+    const char *msgtype = "warning";
+    int         lvl     = LVL_WARNING;
+    char        warn_name[1024];
 
     if (!OPTS_WARN(warntype))
         return false;
@@ -399,19 +417,25 @@ bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_
     warn_name[1] = 'W';
     (void)util_strtononcmd(opts_warn_list[warntype].name, warn_name+2, sizeof(warn_name)-2);
 
+    ++compile_warnings;
     if (OPTS_WERROR(warntype)) {
-        ++compile_errors;
+        if (!compile_Werrors)
+            first_werror = ctx;
+        ++compile_Werrors;
+        msgtype = "Werror";
+        if (OPTS_FLAG(BAIL_ON_WERROR)) {
+            msgtype = "error";
+            ++compile_errors;
+        }
         lvl = LVL_ERROR;
     }
-    else
-        ++compile_warnings;
 
-    con_vprintmsg_c(lvl, ctx.file, ctx.line, (opts.werror ? "error" : "warning"), fmt, ap, warn_name);
+    con_vprintmsg_c(lvl, ctx.file, ctx.line, ctx.column, msgtype, fmt, ap, warn_name);
 
-    return OPTS_WERROR(warntype);
+    return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR);
 }
 
-bool GMQCC_WARN compile_warning(lex_ctx ctx, int warntype, const char *fmt, ...)
+bool GMQCC_WARN compile_warning(lex_ctx_t ctx, int warntype, const char *fmt, ...)
 {
     bool r;
     va_list ap;
@@ -420,3 +444,4 @@ bool GMQCC_WARN compile_warning(lex_ctx ctx, int warntype, const char *fmt, ...)
     va_end(ap);
     return r;
 }
+#endif