* 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 = 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)) ?
- 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)
* 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);
}
/*
* 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));
-#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;
+static int con_write(fs_file_t *handle, const char *fmt, va_list va) {
+ return vfprintf((FILE*)handle, fmt, va);
}
/**********************************************************************
}
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();
}
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;
* 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) {
* 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,
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)
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);
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;
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;