X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=conout.c;h=c4c285bb59ec0f21c5c71d6af175a3f6d1626546;hp=00b81580760e90989ab4c46d9255c976d57e75f1;hb=b640049912e2a8caa5164a9718ad5a7903600d70;hpb=21c6079b7a4b17f7110094a94f7fc3c850c295ae diff --git a/conout.c b/conout.c index 00b8158..c4c285b 100644 --- a/conout.c +++ b/conout.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014, 2015 * Dale Weiler * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -20,170 +20,20 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "gmqcc.h" #include +#include "gmqcc.h" -/* - * isatty/STDERR_FILENO/STDOUT_FILNO - * + some other things likewise. - */ -#ifndef _WIN32 -# include -#else -# include - /* - * 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 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 { - fs_file_write(str, 1, 1, stdout); - 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) : fs_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); } /********************************************************************** @@ -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,16 +106,16 @@ 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 = 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 = fs_file_open(err, "w"))) return 0; @@ -288,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) { @@ -329,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, @@ -337,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) @@ -354,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); @@ -402,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; @@ -428,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;