]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - conout.c
Arithmetic exception flag and a plethora of tests.
[xonotic/gmqcc.git] / conout.c
index 81cf48135433264abeffa2e659ab1d7915dc6f00..746275d3cf870d2372b35212cb8b55649a5f3571 100644 (file)
--- a/conout.c
+++ b/conout.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014
  *     Dale Weiler
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "gmqcc.h"
 #include <stdio.h>
+#include "gmqcc.h"
 
-/*
- * isatty/STDERR_FILENO/STDOUT_FILNO
- * + some other things likewise.
- */
-#ifndef _WIN32
-#   include <unistd.h>
-#else
-#   include <io.h>
-    /*
-     * Windows and it's posix underscore bullshit.  We simply fix this
-     * with yay, another macro :P
-     */
-#   define isatty _isatty
-#endif
-
-#define GMQCC_IS_STDOUT(X) ((FILE*)((void*)X) == stdout)
-#define GMQCC_IS_STDERR(X) ((FILE*)((void*)X) == stderr)
+#define GMQCC_IS_STDOUT(X) ((fs_file_t*)((void*)X) == (fs_file_t*)stdout)
+#define GMQCC_IS_STDERR(X) ((fs_file_t*)((void*)X) == (fs_file_t*)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;
+    fs_file_t *handle_err;
+    fs_file_t *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
-
-enum {
-    RESET = 0,
-    BOLD  = 1,
-    BLACK = 30,
-    RED,
-    GREEN,
-    YELLOW,
-    BLUE,
-    MAGENTA,
-    CYAN,
-    GRAY,
-    WHITE = GRAY
-};
-
-enum {
-    WBLACK,
-    WBLUE,
-    WGREEN   = 2,
-    WRED     = 4,
-    WINTENSE = 8,
-    WCYAN    = WBLUE  | WGREEN,
-    WMAGENTA = WBLUE  | WRED,
-    WYELLOW  = WGREEN | WRED,
-    WWHITE   = WBLUE  | WGREEN | WRED
-};
-
-static const int ansi2win[] = {
-    WBLACK,
-    WRED,
-    WGREEN,
-    WYELLOW,
-    WBLUE,
-    WMAGENTA,
-    WCYAN,
-    WWHITE
-};
-
-static int win_fputs(FILE *h, const char *str) {
-    /* state for translate */
-    int acolor;
-    int wcolor;
-    int icolor;
-
-    int state;
-
-    /* attributes */
-    int intense  =  -1;
-    int colors[] = {-1, -1 };
-    int colorpos = 1;
-    int length   = 0;
-    CONSOLE_SCREEN_BUFFER_INFO cinfo;
-    GetConsoleScreenBufferInfo (
-        (GMQCC_IS_STDOUT(h)) ?
-            GetStdHandle(STD_OUTPUT_HANDLE) :
-            GetStdHandle(STD_ERROR_HANDLE), &cinfo
-    );
-    icolor = cinfo.wAttributes;
-
-    while (*str) {
-        if (*str == '\x1B')
-            state = '\x1B';
-        else if (state == '\x1B' && *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 (
-                    (GMQCC_IS_STDOUT(h)) ?
-                    GetStdHandle(STD_OUTPUT_HANDLE) :
-                    GetStdHandle(STD_ERROR_HANDLE),
-
-                    wcolor | intense | (icolor & 0xF0)
-                );
-                colorpos =  1;
-                state    = -1;
-            }
-        } else {
-            file_putc(h, *str);
-            length ++;
-        }
-        str++;
-    }
-    /* restore */
-    SetConsoleTextAttribute(
-        (GMQCC_IS_STDOUT(h)) ?
-        GetStdHandle(STD_OUTPUT_HANDLE) :
-        GetStdHandle(STD_ERROR_HANDLE),
-        icolor
-    );
-    return length;
-}
-#endif
-
 /*
  * We use standard files as default. These can be changed at any time
  * with con_change(F, F)
@@ -198,11 +48,9 @@ static con_t console;
  * 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));
+static void con_enablecolor(void) {
+    console.color_err = util_isatty(console.handle_err);
+    console.color_out = util_isatty(console.handle_out);
 }
 
 /*
@@ -210,19 +58,8 @@ static void con_enablecolor() {
  * 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[4096];
-        memset(data, 0, sizeof(data));
-        vsnprintf(data, sizeof(data), fmt, va);
-        ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(handle, data) : file_puts(handle, data);
-    }
-    #endif
-    return ln;
+static int con_write(fs_file_t *handle, const char *fmt, va_list va) {
+    return vfprintf((FILE*)handle, fmt, va);
 }
 
 /**********************************************************************
@@ -231,9 +68,9 @@ static int con_write(FILE *handle, const char *fmt, va_list va) {
 
 void con_close() {
     if (!GMQCC_IS_DEFINE(console.handle_err))
-        file_close(console.handle_err);
+        fs_file_close(console.handle_err);
     if (!GMQCC_IS_DEFINE(console.handle_out))
-        file_close(console.handle_out);
+        fs_file_close(console.handle_out);
 }
 
 void con_color(int state) {
@@ -246,8 +83,8 @@ void con_color(int state) {
 }
 
 void con_init() {
-    console.handle_err = stderr;
-    console.handle_out = stdout;
+    console.handle_err = (fs_file_t*)stderr;
+    console.handle_out = (fs_file_t*)stdout;
     con_enablecolor();
 }
 
@@ -269,22 +106,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 (!out) out = (const char *)((!console.handle_out) ? (fs_file_t*)stdout : console.handle_out);
+    if (!err) err = (const char *)((!console.handle_err) ? (fs_file_t*)stderr : console.handle_err);
 
     if (GMQCC_IS_DEFINE(out)) {
-        console.handle_out = GMQCC_IS_STDOUT(out) ? stdout : stderr;
+        console.handle_out = (fs_file_t*)(GMQCC_IS_STDOUT(out) ? stdout : stderr);
         con_enablecolor();
-    } else if (!(console.handle_out = file_open(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;
+        console.handle_err = (fs_file_t*)(GMQCC_IS_STDOUT(err) ? stdout : stderr);
         con_enablecolor();
-    } else if (!(console.handle_err = file_open(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;
 }
@@ -292,12 +125,12 @@ int con_change(const char *out, const char *err) {
 /*
  * 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);
+ */
+fs_file_t *con_default_out() {
+    return (fs_file_t*)(console.handle_out = (fs_file_t*)stdout);
 }
-FILE *con_default_err() {
-    return (console.handle_err = stderr);
+fs_file_t *con_default_err() {
+    return (fs_file_t*)(console.handle_err = (fs_file_t*)stderr);
 }
 
 int con_verr(const char *fmt, va_list va) {
@@ -333,7 +166,7 @@ int con_out(const char *fmt, ...) {
  * 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,
@@ -341,15 +174,15 @@ void con_vprintmsg_c(int level, const char *name, size_t line, const char *msgty
         CON_RED
     };
 
-    int  err                         = !!(level == LVL_ERROR);
-    int  color                       = (err) ? console.color_err : console.color_out;
-    int (*print) (const char *, ...)  = (err) ? &con_err          : &con_out;
-    int (*vprint)(const char *, va_list) = (err) ? &con_verr : &con_vout;
+    int  err                             = !!(level == LVL_ERROR);
+    int  color                           = (err) ? console.color_err : console.color_out;
+    int (*print) (const char *, ...)     = (err) ? &con_err          : &con_out;
+    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)
@@ -358,47 +191,46 @@ 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);
     va_end  (va);
 }
 
-/* General error interface */
-size_t compile_errors = 0;
+/* General error interface: TODO seperate as part of the compiler front-end */
+size_t compile_errors   = 0;
 size_t compile_warnings = 0;
-
-size_t compile_Werrors = 0;
-static lex_ctx first_werror;
+size_t compile_Werrors  = 0;
+static lex_ctx_t first_werror;
 
 void compile_show_werrors()
 {
-    con_cprintmsg((void*)&first_werror, LVL_ERROR, "first warning", "was here");
+    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);
@@ -406,7 +238,7 @@ 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)
 {
     const char *msgtype = "warning";
     int         lvl     = LVL_WARNING;
@@ -432,12 +264,12 @@ bool GMQCC_WARN vcompile_warning(lex_ctx ctx, int warntype, const char *fmt, va_
         lvl = LVL_ERROR;
     }
 
-    con_vprintmsg_c(lvl, ctx.file, ctx.line, msgtype, fmt, ap, warn_name);
+    con_vprintmsg_c(lvl, ctx.file, ctx.line, ctx.column, msgtype, fmt, ap, warn_name);
 
     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;