+
+/*
+ * 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(int level, const char *name, size_t line, const char *msgtype, const char *msg, va_list ap) {
+ /* color selection table */
+ static int sel[] = {
+ CON_WHITE,
+ 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 (*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);
+
+ vprint(msg, ap);
+ print("\n");
+}
+
+void con_printmsg(int level, const char *name, size_t line, const char *msgtype, const char *msg, ...) {
+ va_list va;
+ va_start(va, msg);
+ con_vprintmsg(level, name, line, 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_cprintmsg (void *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;
+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;
+}