*/
#include "gmqcc.h"
+uint32_t opts_warn [1 + (COUNT_WARNINGS / 32)];
+bool opts_werror = false;
+
/*
* isatty/STDERR_FILENO/STDOUT_FILNO
* + some other things likewise.
#include <unistd.h>
#endif
-#define GMQCC_IS_STDOUT(X) ((X) == stdout)
-#define GMQCC_IS_STDERR(X) ((X) == stderr)
+#define GMQCC_IS_STDOUT(X) ((FILE*)((void*)X) == stdout)
+#define GMQCC_IS_STDERR(X) ((FILE*)((void*)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;
* with yay, another macro :P
*/
#define isatty _isatty
-
+
enum {
RESET = 0,
BOLD = 1,
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(
(GMQCC_IS_STDOUT(h)) ?
GetStdHandle(STD_ERROR_HANDLE), &cinfo
);
icolor = cinfo.wAttributes;
-
+
while (*str) {
if (*str == '\e')
state = '\e';
acolor += (colors[find] - 48) * mult;
mult *= 10;
}
-
+
/* convert to windows color */
if (acolor == BOLD)
intense = WINTENSE;
wcolor = WWHITE;
intense = WBLACK;
}
-
+
SetConsoleTextattribute(
(h == stdout) ?
GetStdHandle(STD_OUTPUT_HANDLE) :
GetStdHandle(STD_ERROR_HANDLE),
-
+
wcolor | intense | (icolor & 0xF0)
);
colorpos = 1;
* 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.
*/
*/
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;
+
+ 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;
-
- if (GMQCC_IS_DEFINE((FILE*)err)) {
- console.handle_err = (((FILE*)err) == stdout) ? stdout : stderr;
+
+ 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);
+
return 1;
}
CON_CYAN,
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 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);
else
print("%s:%d: %s: ", name, (int)line, msgtype);
-
- con_verr(msg, ap);
- fprintf (stderr, "\n");
+
+ vprint(msg, ap);
+ print("\n");
}
void con_printmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, ...) {
con_cvprintmsg(ctx, lvl, msgtype, msg, va);
va_end (va);
}
+
+/* General error interface */
+size_t compile_errors = 0;
+size_t compile_warnings = 0;
+
+void compile_error(lex_ctx ctx, const char *msg, ...)
+{
+ va_list ap;
+ ++compile_errors;
+ va_start(ap, msg);
+ con_cvprintmsg((void*)&ctx, LVL_ERROR, "error", msg, ap);
+ va_end(ap);
+}
+
+bool GMQCC_WARN compile_warning(lex_ctx ctx, int warntype, const char *fmt, ...)
+{
+ va_list ap;
+ int lvl = LVL_WARNING;
+
+ if (!OPTS_WARN(warntype))
+ return false;
+
+ if (opts_werror) {
+ ++compile_errors;
+ lvl = LVL_ERROR;
+ }
+ else
+ ++compile_warnings;
+
+ va_start(ap, fmt);
+ con_vprintmsg(lvl, ctx.file, ctx.line, (opts_werror ? "error" : "warning"), fmt, ap);
+ va_end(ap);
+
+ return opts_werror;
+}