New diagnostic functions diagnosticf(), errorf() and warningf() replacing the ad...
authorChristoph Mallon <christoph.mallon@gmx.de>
Fri, 7 Dec 2007 15:27:39 +0000 (15:27 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Fri, 7 Dec 2007 15:27:39 +0000 (15:27 +0000)
[r18640]

diagnostic.c
diagnostic.h
format_check.c
parser.c

index 952bf19..9a7ca82 100644 (file)
 #include <stdarg.h>
 #include <stdio.h>
 
+#include "adt/error.h"
+#include "ast.h"
 #include "diagnostic.h"
+#include "token_t.h"
+#include "type.h"
 
 
-void parser_print_prefix_pos(const source_position_t pos)
+//#define ABORT_ON_ERROR
+
+
+bool found_error;
+
+
+static void diagnosticvf(const char *const fmt, va_list ap)
 {
-       fprintf(stderr, "%s:%u: ", pos.input_name, pos.linenr);
+       for (const char* f = fmt; *f != '\0'; ++f) {
+               if (*f == '%') {
+                       ++f;
+
+                       bool extended = false;
+                       if (*f == '#') {
+                               extended = true;
+                               ++f;
+                       }
+
+                       switch (*f) {
+                               case '%':
+                                       fputc(*f, stderr);
+                                       break;
+
+                               case 'C': {
+                                       const wint_t val = va_arg(ap, wint_t);
+                                       fputwc(val, stderr);
+                                       break;
+                               }
+
+                               case 'c': {
+                                       const unsigned char val = va_arg(ap, int);
+                                       fputc(val, stderr);
+                                       break;
+                               }
+
+                               case 'd': {
+                                       const int val = va_arg(ap, int);
+                                       fprintf(stderr, "%d", val);
+                                       break;
+                               }
+
+                               case 's': {
+                                       const char* const str = va_arg(ap, const char*);
+                                       fputs(str, stderr);
+                                       break;
+                               }
+
+                               case 'E': {
+                                       const expression_t* const expr = va_arg(ap, const expression_t*);
+                                       print_expression(expr);
+                                       break;
+                               }
+
+                               case 'Q': {
+                                       const unsigned qualifiers = va_arg(ap, unsigned);
+                                       print_type_qualifiers(qualifiers);
+                                       break;
+                               }
+
+                               case 'T': {
+                                       const type_t* const type = va_arg(ap, const type_t*);
+                                       const symbol_t*     sym  = NULL;
+                                       if (extended) {
+                                               sym = va_arg(ap, const symbol_t*);
+                                       }
+                                       print_type_ext(type, sym, NULL);
+                                       break;
+                               }
+
+                               case 'K': {
+                                       const token_t* const token = va_arg(ap, const token_t*);
+                                       print_token(stderr, token);
+                                       break;
+                               }
+
+                               case 'k': {
+                                       if (extended) {
+                                               bool              first     = false;
+                                               va_list*          toks      = va_arg(ap, va_list*);
+                                               const char* const delimiter = va_arg(ap, const char*);
+                                               for (;;) {
+                                                       const token_type_t tok = va_arg(*toks, token_type_t);
+                                                       if (tok == 0)
+                                                               break;
+                                                       if (first) {
+                                                               first = false;
+                                                       } else {
+                                                               fputs(delimiter, stderr);
+                                                       }
+                                                       print_token_type(stderr, tok);
+                                               }
+                                       } else {
+                                               const token_type_t token = va_arg(ap, token_type_t);
+                                               print_token_type(stderr, token);
+                                       }
+                                       break;
+                               }
+
+                               default:
+                                       panic("unknown format specifier");
+                       }
+               } else {
+                       fputc(*f, stderr);
+               }
+       }
 }
 
-void parser_print_warning_prefix_pos(const source_position_t pos)
+void diagnosticf(const char *const fmt, ...)
 {
-       parser_print_prefix_pos(pos);
-       fputs("warning: ", stderr);
+       va_list ap;
+       va_start(ap, fmt);
+       diagnosticvf(fmt, ap);
+       va_end(ap);
 }
 
-void parse_warning_pos(const source_position_t pos, const char *const message)
+void errorf(const source_position_t pos, const char *const fmt, ...)
 {
-       parser_print_prefix_pos(pos);
-       fprintf(stderr, "warning: %s\n", message);
+       found_error = true;
+       fprintf(stderr, "%s:%u: error: ", pos.input_name, pos.linenr);
+       va_list ap;
+       va_start(ap, fmt);
+       diagnosticvf(fmt, ap);
+       va_end(ap);
+       fputc('\n', stderr);
+
+#ifdef ABORT_ON_ERROR
+       abort();
+#endif
 }
 
-void parse_warning_posf(const source_position_t pos, const char *const fmt, ...)
+void warningf(const source_position_t pos, const char *const fmt, ...)
 {
-       parser_print_prefix_pos(pos);
-       fputs("warning: ", stderr);
+       fprintf(stderr, "%s:%u: warning: ", pos.input_name, pos.linenr);
        va_list ap;
        va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
+       diagnosticvf(fmt, ap);
        va_end(ap);
        fputc('\n', stderr);
 }
index 44e74c8..1b07521 100644 (file)
@@ -4,9 +4,10 @@
 #include "token_t.h"
 
 
-void parser_print_prefix_pos(source_position_t);
-void parser_print_warning_prefix_pos(source_position_t);
-void parse_warning_pos(source_position_t, const char *message);
-void parse_warning_posf(source_position_t, const char *fmt, ...);
+void diagnosticf(const char *fmt, ...);
+void errorf(source_position_t pos, const char *fmt, ...);
+void warningf(source_position_t pos, const char *fmt, ...);
+
+extern bool found_error;
 
 #endif
index 63f2e38..a0f2cbc 100644 (file)
@@ -49,7 +49,7 @@ static void warn_invalid_length_modifier(const source_position_t pos,
        };
        assert(mod < sizeof(names) / sizeof(*names));
 
-       parse_warning_posf(pos,
+       warningf(pos,
                "invalid length modifier '%s' for conversion specifier '%%%c'",
                names[mod], conversion
        );
@@ -108,14 +108,14 @@ static void check_format_arguments(const call_argument_t *const fmt_arg, const c
 
                                        case ' ':
                                                if (fmt_flags & FMT_FLAG_PLUS) {
-                                                       parse_warning_pos(pos, "' ' is overridden by prior '+' in conversion specification");
+                                                       warningf(pos, "' ' is overridden by prior '+' in conversion specification");
                                                }
                                                flag = FMT_FLAG_SPACE;
                                                break;
 
                                        case '+':
                                                if (fmt_flags & FMT_FLAG_SPACE) {
-                                                       parse_warning_pos(pos, "'+' overrides prior ' ' in conversion specification");
+                                                       warningf(pos, "'+' overrides prior ' ' in conversion specification");
                                                }
                                                flag = FMT_FLAG_PLUS;
                                                break;
@@ -123,7 +123,7 @@ static void check_format_arguments(const call_argument_t *const fmt_arg, const c
                                        default: goto break_fmt_flags;
                                }
                                if (fmt_flags & flag) {
-                                       parse_warning_posf(pos, "repeated flag '%c' in conversion specification", (char)*fmt);
+                                       warningf(pos, "repeated flag '%c' in conversion specification", (char)*fmt);
                                }
                                fmt_flags |= flag;
                                ++fmt;
@@ -133,14 +133,12 @@ break_fmt_flags:
                        /* minimum field width */
                        if (*fmt == '*') {
                                if (arg == NULL) {
-                                       parse_warning_pos(pos, "missing argument for '*' field width in conversion specification");
+                                       warningf(pos, "missing argument for '*' field width in conversion specification");
                                        return;
                                }
                                const type_t *const arg_type = arg->expression->base.datatype;
                                if (arg_type != type_int) {
-                                       parse_warning_pos(pos, "argument for '*' field width in conversion specification is not an 'int', but an '");
-                                       print_type(arg_type);
-                                       fputc('\'', stderr);
+                                       warningf(pos, "argument for '*' field width in conversion specification is not an 'int', but an '%T'", arg_type);
                                }
                                arg = arg->next;
                        } else {
@@ -155,14 +153,12 @@ break_fmt_flags:
                        ++fmt;
                        if (*fmt == '*') {
                                if (arg == NULL) {
-                                       parse_warning_pos(pos, "missing argument for '*' precision in conversion specification");
+                                       warningf(pos, "missing argument for '*' precision in conversion specification");
                                        return;
                                }
                                const type_t *const arg_type = arg->expression->base.datatype;
                                if (arg_type != type_int) {
-                                       parse_warning_pos(pos, "argument for '*' precision in conversion specification is not an 'int', but an '");
-                                       print_type(arg_type);
-                                       fputc('\'', stderr);
+                                       warningf(pos, "argument for '*' precision in conversion specification is not an 'int', but an '%T'", arg_type);
                                }
                                arg = arg->next;
                        } else {
@@ -205,7 +201,7 @@ break_fmt_flags:
                }
 
                if (*fmt == '\0') {
-                       parse_warning_pos(pos, "dangling % in format string");
+                       warningf(pos, "dangling %% in format string");
                        break;
                }
 
@@ -345,36 +341,33 @@ eval_fmt_mod_unsigned:
                                break;
 
                        default:
-                               parse_warning_posf(pos, "encountered unknown conversion specifier '%%%C'", (wint_t)*fmt);
+                               warningf(pos, "encountered unknown conversion specifier '%%%C'", (wint_t)*fmt);
                                arg = arg->next;
                                continue;
                }
 
                if ((fmt_flags & ~allowed_flags) != 0) {
                        /* TODO better warning message text */
-                       parse_warning_pos(pos, "invalid format flags in conversion specification");
+                       warningf(pos, "invalid format flags in conversion specification");
                }
 
                if (arg == NULL) {
-                       parse_warning_pos(pos, "too few arguments for format string");
+                       warningf(pos, "too few arguments for format string");
                        return;
                }
 
                const type_t *const arg_type = arg->expression->base.datatype;
                if (arg_type != expected_type) {
-                       parser_print_warning_prefix_pos(pos);
-                       fputs("argument type '", stderr);
-                       print_type(arg_type);
-                       fprintf(stderr, "' does not match conversion specifier '%%%c'\n", (char)*fmt);
+                       warningf(pos, "argument type '%T' does not match conversion specifier '%%%c'\n", arg_type, (char)*fmt);
                }
 
                arg = arg->next;
        }
        if (fmt + 1 != wstring->begin + wstring->size) {
-               parse_warning_pos(pos, "format string contains NUL");
+               warningf(pos, "format string contains NUL");
        }
        if (arg != NULL) {
-               parse_warning_pos(pos, "too many arguments for format string");
+               warningf(pos, "too many arguments for format string");
        }
 }
 
index 5ad72c2..0dde06f 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -49,7 +49,8 @@ static context_t      *context           = NULL;
 static declaration_t  *last_declaration  = NULL;
 static declaration_t  *current_function  = NULL;
 static struct obstack  temp_obst;
-static bool            found_error;
+
+#define HERE token.source_position
 
 static type_t *type_valist;
 
@@ -298,97 +299,27 @@ static inline const token_t *look_ahead(int num)
 
 #define eat(token_type)  do { assert(token.type == token_type); next_token(); } while(0)
 
-static void error(void)
-{
-       found_error = true;
-#ifdef ABORT_ON_ERROR
-       abort();
-#endif
-}
-
-static void parser_print_error_prefix_pos(
-               const source_position_t source_position)
-{
-       parser_print_prefix_pos(source_position);
-       fputs("error: ", stderr);
-       error();
-}
-
-static void parser_print_error_prefix(void)
-{
-       parser_print_error_prefix_pos(token.source_position);
-}
-
-static void parse_error(const char *message)
-{
-       parser_print_error_prefix();
-       fprintf(stderr, "parse error: %s\n", message);
-}
-
-static void parser_print_warning_prefix(void)
-{
-       parser_print_warning_prefix_pos(token.source_position);
-}
-
-static void parse_warning(const char *message)
-{
-       parse_warning_pos(token.source_position, message);
-}
-
 static void parse_error_expected(const char *message, ...)
 {
-       va_list args;
-       int first = 1;
-
        if(message != NULL) {
-               parser_print_error_prefix();
-               fprintf(stderr, "%s\n", message);
-       }
-       parser_print_error_prefix();
-       fputs("Parse error: got ", stderr);
-       print_token(stderr, &token);
-       fputs(", expected ", stderr);
-
-       va_start(args, message);
-       token_type_t token_type = va_arg(args, token_type_t);
-       while(token_type != 0) {
-               if(first == 1) {
-                       first = 0;
-               } else {
-                       fprintf(stderr, ", ");
-               }
-               print_token_type(stderr, token_type);
-               token_type = va_arg(args, token_type_t);
+               errorf(HERE, "%s", message);
        }
-       va_end(args);
-       fprintf(stderr, "\n");
-}
-
-static void print_type_quoted(type_t *type)
-{
-       fputc('\'', stderr);
-       print_type(type);
-       fputc('\'', stderr);
+       va_list ap;
+       va_start(ap, message);
+       errorf(HERE, "got '%K', expected %#k", &token, &ap, ", ");
+       va_end(ap);
 }
 
 static void type_error(const char *msg, const source_position_t source_position,
                        type_t *type)
 {
-       parser_print_error_prefix_pos(source_position);
-       fprintf(stderr, "%s, but found type ", msg);
-       print_type_quoted(type);
-       fputc('\n', stderr);
+       errorf(source_position, "%s, but found type '%T'", msg, type);
 }
 
 static void type_error_incompatible(const char *msg,
                const source_position_t source_position, type_t *type1, type_t *type2)
 {
-       parser_print_error_prefix_pos(source_position);
-       fprintf(stderr, "%s, incompatible types: ", msg);
-       print_type_quoted(type1);
-       fprintf(stderr, " - ");
-       print_type_quoted(type2);
-       fprintf(stderr, ")\n");
+       errorf(source_position, "%s, incompatible types: '%T' - '%T'", msg, type1, type2);
 }
 
 static void eat_block(void)
@@ -550,17 +481,8 @@ static declaration_t *stack_push(stack_entry_t **stack_ptr,
        if(previous_declaration != NULL
                        && previous_declaration->parent_context == context) {
                if(!is_compatible_declaration(declaration, previous_declaration)) {
-                       parser_print_error_prefix_pos(declaration->source_position);
-                       fprintf(stderr, "definition of symbol '%s%s' with type ",
-                                       get_namespace_prefix(namespc), symbol->string);
-                       print_type_quoted(declaration->type);
-                       fputc('\n', stderr);
-                       parser_print_error_prefix_pos(
-                                       previous_declaration->source_position);
-                       fprintf(stderr, "is incompatible with previous declaration "
-                                       "of type ");
-                       print_type_quoted(previous_declaration->type);
-                       fputc('\n', stderr);
+                       errorf(declaration->source_position, "definition of symbol '%s%s' with type '%T'", get_namespace_prefix(namespc), symbol->string, declaration->type);
+                       errorf(previous_declaration->source_position, "is incompatible with previous declaration of type '%T'", previous_declaration->type);
                } else {
                        unsigned  old_storage_class = previous_declaration->storage_class;
                        unsigned  new_storage_class = declaration->storage_class;
@@ -570,46 +492,30 @@ static declaration_t *stack_push(stack_entry_t **stack_ptr,
                        if (current_function == NULL) {
                                if (old_storage_class != STORAGE_CLASS_STATIC &&
                                    new_storage_class == STORAGE_CLASS_STATIC) {
-                                       parser_print_error_prefix_pos(declaration->source_position);
-                                       fprintf(stderr,
-                                               "static declaration of '%s' follows non-static declaration\n",
-                                               symbol->string);
-                                       parser_print_error_prefix_pos(previous_declaration->source_position);
-                                       fprintf(stderr, "previous declaration of '%s' was here\n",
-                                               symbol->string);
+                                       errorf(declaration->source_position, "static declaration of '%s' follows non-static declaration", symbol->string);
+                                       errorf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
                                } else {
                                        if (old_storage_class == STORAGE_CLASS_EXTERN) {
                                                if (new_storage_class == STORAGE_CLASS_NONE) {
                                                        previous_declaration->storage_class = STORAGE_CLASS_NONE;
                                                }
                                        } else if(!is_type_function(type)) {
-                                               parser_print_warning_prefix_pos(declaration->source_position);
-                                               fprintf(stderr, "redundant declaration for '%s'\n",
-                                                                               symbol->string);
-                                               parser_print_warning_prefix_pos(previous_declaration->source_position);
-                                               fprintf(stderr, "previous declaration of '%s' was here\n",
-                                                                               symbol->string);
+                                               warningf(declaration->source_position, "redundant declaration for '%s'\n", symbol->string);
+                                               warningf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
                                        }
                                }
                        } else {
                                if (old_storage_class == STORAGE_CLASS_EXTERN &&
                                                new_storage_class == STORAGE_CLASS_EXTERN) {
-                                       parser_print_warning_prefix_pos(declaration->source_position);
-                                       fprintf(stderr, "redundant extern declaration for '%s'\n",
-                                               symbol->string);
-                                       parser_print_warning_prefix_pos(previous_declaration->source_position);
-                                       fprintf(stderr, "previous declaration of '%s' was here\n",
-                                               symbol->string);
+                                       warningf(declaration->source_position, "redundant extern declaration for '%s'\n", symbol->string);
+                                       warningf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
                                } else {
-                                       parser_print_error_prefix_pos(declaration->source_position);
                                        if (old_storage_class == new_storage_class) {
-                                               fprintf(stderr, "redeclaration of '%s'\n", symbol->string);
+                                               errorf(declaration->source_position, "redeclaration of '%s'\n", symbol->string);
                                        } else {
-                                               fprintf(stderr, "redeclaration of '%s' with different linkage\n", symbol->string);
+                                               errorf(declaration->source_position, "redeclaration of '%s' with different linkage\n", symbol->string);
                                        }
-                                       parser_print_error_prefix_pos(previous_declaration->source_position);
-                                       fprintf(stderr, "previous declaration of '%s' was here\n",
-                                               symbol->string);
+                                       errorf(previous_declaration->source_position, "previous declaration of '%s' was here", symbol->string);
                                }
                        }
                }
@@ -878,14 +784,7 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
                unsigned missing_qualifiers
                        = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers;
                if(missing_qualifiers != 0) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "destination type ");
-                       print_type_quoted(type_left);
-                       fprintf(stderr, " in %s from type ", context);
-                       print_type_quoted(type_right);
-                       fprintf(stderr, " lacks qualifiers '");
-                       print_type_qualifiers(missing_qualifiers);
-                       fprintf(stderr, "' in pointed-to type\n");
+                       errorf(HERE, "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointed-to type", type_left, context, type_right, missing_qualifiers);
                        return;
                }
 
@@ -910,13 +809,8 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right,
 
 incompatible_assign_types:
        /* TODO: improve error message */
-       parser_print_error_prefix();
-       fprintf(stderr, "incompatible types in %s\n", context);
-       parser_print_error_prefix();
-       print_type_quoted(orig_type_left);
-       fputs(" <- ", stderr);
-       print_type_quoted(orig_type_right);
-       fputs("\n", stderr);
+       errorf(HERE, "incompatible types in %s", context);
+       errorf(HERE, "'%T' <- '%T'", orig_type_left, orig_type_right);
 }
 
 static expression_t *parse_constant_expression(void)
@@ -925,10 +819,7 @@ static expression_t *parse_constant_expression(void)
        expression_t *result = parse_sub_expression(7);
 
        if(!is_constant_expression(result)) {
-               parser_print_error_prefix_pos(result->base.source_position);
-               fprintf(stderr, "expression '");
-               print_expression(result);
-               fprintf(stderr, "' is not constant\n");
+               errorf(result->base.source_position, "expression '%E' is not constant\n", result);
        }
 
        return result;
@@ -986,7 +877,7 @@ static void parse_attributes(void)
                        while(depth > 0) {
                                switch(token.type) {
                                case T_EOF:
-                                       parse_error("EOF while parsing attribute");
+                                       errorf(HERE, "EOF while parsing attribute");
                                        break;
                                case '(':
                                        next_token();
@@ -1166,7 +1057,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                if(token.type == '{') {
                        next_token();
                        if(!had_initializer_brace_warning) {
-                               parse_warning("braces around scalar initializer");
+                               warningf(HERE, "braces around scalar initializer");
                                had_initializer_brace_warning = true;
                        }
                        initializer_t *result = parse_sub_initializer(type, NULL, NULL);
@@ -1233,7 +1124,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        sub = parse_sub_initializer_elem(element_type);
                        if(sub == NULL) {
                                /* TODO error, do nicer cleanup */
-                               parse_error("member initializer didn't match");
+                               errorf(HERE, "member initializer didn't match");
                                DEL_ARR_F(elems);
                                return NULL;
                        }
@@ -1286,7 +1177,7 @@ static initializer_t *parse_sub_initializer(type_t *type,
                        sub = parse_sub_initializer_elem(iter_type);
                        if(sub == NULL) {
                                /* TODO error, do nicer cleanup */
-                               parse_error("member initializer didn't match");
+                               errorf(HERE, "member initializer didn't match");
                                DEL_ARR_F(elems);
                                return NULL;
                        }
@@ -1324,14 +1215,7 @@ static initializer_t *parse_initializer(type_t *type)
                expression_t  *expression  = parse_assignment_expression();
                initializer_t *initializer = initializer_from_expression(type, expression);
                if(initializer == NULL) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "initializer expression '");
-                       print_expression(expression);
-                       fprintf(stderr, "', type ");
-                       print_type_quoted(expression->base.datatype);
-                       fprintf(stderr, " is incompatible with type ");
-                       print_type_quoted(type);
-                       fprintf(stderr, "\n");
+                       errorf(HERE, "initializer expression '%E', type '%T' is incompatible with type '%T'", expression, expression->base.datatype, type);
                }
                return initializer;
        }
@@ -1410,9 +1294,7 @@ static declaration_t *parse_compound_type_specifier(bool is_struct)
        if(token.type == '{') {
                if(declaration->init.is_defined) {
                        assert(symbol != NULL);
-                       parser_print_error_prefix();
-                       fprintf(stderr, "multiple definition of %s %s\n",
-                                       is_struct ? "struct" : "union", symbol->string);
+                       errorf(HERE, "multiple definition of %s %s", is_struct ? "struct" : "union", symbol->string);
                        declaration->context.declarations = NULL;
                }
                declaration->init.is_defined = true;
@@ -1438,7 +1320,7 @@ static void parse_enum_entries(enum_type_t *const enum_type)
 
        if(token.type == '}') {
                next_token();
-               parse_error("empty enum not allowed");
+               errorf(HERE, "empty enum not allowed");
                return;
        }
 
@@ -1507,9 +1389,7 @@ static type_t *parse_enum_specifier(void)
 
        if(token.type == '{') {
                if(declaration->init.is_defined) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "multiple definitions of enum %s\n",
-                               symbol->string);
+                       errorf(HERE, "multiple definitions of enum %s", symbol->string);
                }
                record_declaration(declaration);
                declaration->init.is_defined = 1;
@@ -1643,8 +1523,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
 #define MATCH_STORAGE_CLASS(token, class)                                \
                case token:                                                      \
                        if(specifiers->storage_class != STORAGE_CLASS_NONE) {        \
-                               parse_error("multiple storage classes in declaration "   \
-                                           "specifiers");                               \
+                               errorf(HERE, "multiple storage classes in declaration specifiers"); \
                        }                                                            \
                        specifiers->storage_class = class;                           \
                        next_token();                                                \
@@ -1671,7 +1550,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                                        break;
 
                                default:
-                                       parse_error("multiple storage classes in declaration specifiers");
+                                       errorf(HERE, "multiple storage classes in declaration specifiers");
                                        break;
                        }
                        next_token();
@@ -1698,7 +1577,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                case token:                                                     \
                        next_token();                                               \
                        if(type_specifiers & specifier) {                           \
-                               parse_error("multiple " name " type specifiers given"); \
+                               errorf(HERE, "multiple " name " type specifiers given"); \
                        } else {                                                    \
                                type_specifiers |= specifier;                           \
                        }                                                           \
@@ -1729,7 +1608,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                case T_long:
                        next_token();
                        if(type_specifiers & SPECIFIER_LONG_LONG) {
-                               parse_error("multiple type specifiers given");
+                               errorf(HERE, "multiple type specifiers given");
                        } else if(type_specifiers & SPECIFIER_LONG) {
                                type_specifiers |= SPECIFIER_LONG_LONG;
                        } else {
@@ -1880,19 +1759,19 @@ finish_specifiers:
                        /* invalid specifier combination, give an error message */
                        if(type_specifiers == 0) {
 #ifndef STRICT_C99
-                               parse_warning("no type specifiers in declaration, using int");
+                               warningf(HERE, "no type specifiers in declaration, using int");
                                atomic_type = ATOMIC_TYPE_INT;
                                break;
 #else
-                               parse_error("no type specifiers given in declaration");
+                               errorf(HERE, "no type specifiers given in declaration");
 #endif
                        } else if((type_specifiers & SPECIFIER_SIGNED) &&
                                  (type_specifiers & SPECIFIER_UNSIGNED)) {
-                               parse_error("signed and unsigned specifiers gives");
+                               errorf(HERE, "signed and unsigned specifiers gives");
                        } else if(type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) {
-                               parse_error("only integer types can be signed or unsigned");
+                               errorf(HERE, "only integer types can be signed or unsigned");
                        } else {
-                               parse_error("multiple datatypes in declaration");
+                               errorf(HERE, "multiple datatypes in declaration");
                        }
                        atomic_type = ATOMIC_TYPE_INVALID;
                }
@@ -1902,7 +1781,7 @@ finish_specifiers:
                newtype            = 1;
        } else {
                if(type_specifiers != 0) {
-                       parse_error("multiple datatypes in declaration");
+                       errorf(HERE, "multiple datatypes in declaration");
                }
        }
 
@@ -1964,10 +1843,10 @@ static void semantic_parameter(declaration_t *declaration)
        /* TODO: improve error messages */
 
        if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
-               parse_error("typedef not allowed in parameter list");
+               errorf(HERE, "typedef not allowed in parameter list");
        } else if(declaration->storage_class != STORAGE_CLASS_NONE
                        && declaration->storage_class != STORAGE_CLASS_REGISTER) {
-               parse_error("parameter may only have none or register storage class");
+               errorf(HERE, "parameter may only have none or register storage class");
        }
 
        type_t *orig_type = declaration->type;
@@ -1987,11 +1866,7 @@ static void semantic_parameter(declaration_t *declaration)
        }
 
        if(is_type_incomplete(type)) {
-               parser_print_error_prefix();
-               fprintf(stderr, "incomplete type (");
-               print_type_quoted(orig_type);
-               fprintf(stderr, ") not allowed for parameter '%s'\n",
-                       declaration->symbol->string);
+               errorf(HERE, "incomplete type ('%T') not allowed for parameter '%s'", orig_type, declaration->symbol->string);
        }
 }
 
@@ -2207,7 +2082,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
        switch(token.type) {
        case T_IDENTIFIER:
                if(declaration == NULL) {
-                       parse_error("no identifier expected in typename");
+                       errorf(HERE, "no identifier expected in typename");
                } else {
                        declaration->symbol          = token.v.symbol;
                        declaration->source_position = token.source_position;
@@ -2394,11 +2269,8 @@ static declaration_t *record_declaration(declaration_t *declaration)
 static void parser_error_multiple_definition(declaration_t *declaration,
                const source_position_t source_position)
 {
-       parser_print_error_prefix_pos(source_position);
-       fprintf(stderr, "multiple definition of symbol '%s'\n",
-               declaration->symbol->string);
-       parser_print_error_prefix_pos(declaration->source_position);
-       fprintf(stderr, "this is the location of the previous definition.\n");
+       errorf(source_position, "multiple definition of symbol '%s'", declaration->symbol->string);
+       errorf(declaration->source_position, "this is the location of the previous definition.");
 }
 
 static bool is_declaration_specifier(const token_t *token,
@@ -2473,11 +2345,7 @@ static void parse_init_declarator_rest(declaration_t *declaration)
        }
 
        if(type != NULL && is_type_function(type)) {
-               parser_print_error_prefix_pos(declaration->source_position);
-               fprintf(stderr, "initializers not allowed for function types at "
-                               "declator '%s' (type ", declaration->symbol->string);
-               print_type_quoted(orig_type);
-               fprintf(stderr, ")\n");
+               errorf(declaration->source_position, "initializers not allowed for function types at declator '%s' (type '%T')", declaration->symbol->string, orig_type);
        } else {
                declaration->init.initializer = initializer;
        }
@@ -2497,8 +2365,7 @@ static void parse_anonymous_declaration_rest(
        declaration->source_position = specifiers->source_position;
 
        if (declaration->storage_class != STORAGE_CLASS_NONE) {
-               parse_warning_pos(declaration->source_position,
-                               "useless storage class in empty declaration");
+               warningf(declaration->source_position, "useless storage class in empty declaration");
        }
 
        type_t *type = declaration->type;
@@ -2507,8 +2374,7 @@ static void parse_anonymous_declaration_rest(
                case TYPE_COMPOUND_UNION: {
                        const compound_type_t *compound_type = &type->compound;
                        if (compound_type->declaration->symbol == NULL) {
-                               parse_warning_pos(declaration->source_position,
-                                               "unnamed struct/union that defines no instances");
+                               warningf(declaration->source_position, "unnamed struct/union that defines no instances");
                        }
                        break;
                }
@@ -2517,8 +2383,7 @@ static void parse_anonymous_declaration_rest(
                        break;
 
                default:
-                       parse_warning_pos(declaration->source_position,
-                                         "empty declaration");
+                       warningf(declaration->source_position, "empty declaration");
                        break;
        }
 
@@ -2536,9 +2401,7 @@ static void parse_declaration_rest(declaration_t *ndeclaration,
                type_t *type      = skip_typeref(orig_type);
 
                if(type->kind != TYPE_FUNCTION && declaration->is_inline) {
-                       parser_print_warning_prefix_pos(declaration->source_position);
-                       fprintf(stderr, "variable '%s' declared 'inline'\n",
-                                       declaration->symbol->string);
+                       warningf(declaration->source_position, "variable '%s' declared 'inline'\n", declaration->symbol->string);
                }
 
                if(token.type == '=') {
@@ -2619,13 +2482,9 @@ static void parse_kr_declaration_list(declaration_t *declaration)
                type_t *parameter_type = parameter_declaration->type;
                if(parameter_type == NULL) {
 #ifdef STRICT_C99
-                       parser_print_error_prefix();
-                       fprintf(stderr, "no type specified for function parameter '%s'\n",
-                               parameter_declaration->symbol->string);
+                       errorf(HERE, "no type specified for function parameter '%s'", parameter_declaration->symbol->string);
 #else
-                       parser_print_warning_prefix();
-                       fprintf(stderr, "no type specified for function parameter '%s', "
-                               "using int\n", parameter_declaration->symbol->string);
+                       warningf(HERE, "no type specified for function parameter '%s', using int", parameter_declaration->symbol->string);
                        parameter_type              = type_int;
                        parameter_declaration->type = parameter_type;
 #endif
@@ -2697,10 +2556,7 @@ static void parse_external_declaration(void)
        /* note that we don't skip typerefs: the standard doesn't allow them here
         * (so we can't use is_type_function here) */
        if(type->kind != TYPE_FUNCTION) {
-               parser_print_error_prefix();
-               fprintf(stderr, "declarator '");
-               print_type_ext(type, ndeclaration->symbol, NULL);
-               fprintf(stderr, "' has a body but is not a function type.\n");
+               errorf(HERE, "declarator '%#T' has a body but is not a function type", type, ndeclaration->symbol);
                eat_block();
                return;
        }
@@ -2798,7 +2654,7 @@ static void parse_compound_type_entries(void)
                parse_struct_declarators(&specifiers);
        }
        if(token.type == T_EOF) {
-               parse_error("EOF while parsing struct");
+               errorf(HERE, "EOF while parsing struct");
        }
        next_token();
 }
@@ -2812,7 +2668,7 @@ static type_t *parse_typename(void)
                /* TODO: improve error message, user does probably not know what a
                 * storage class is...
                 */
-               parse_error("typename may not have a storage class");
+               errorf(HERE, "typename may not have a storage class");
        }
 
        type_t *result = parse_abstract_declarator(specifiers.type);
@@ -2846,10 +2702,7 @@ static expression_t *create_invalid_expression(void)
 
 static expression_t *expected_expression_error(void)
 {
-       parser_print_error_prefix();
-       fprintf(stderr, "expected expression, got token ");
-       print_token(stderr, &token);
-       fprintf(stderr, "\n");
+       errorf(HERE, "expected expression, got token '%K'", &token);
 
        next_token();
 
@@ -3056,17 +2909,14 @@ static expression_t *parse_reference(void)
 #ifndef STRICT_C99
                /* an implicitly defined function */
                if(token.type == '(') {
-                       parser_print_prefix_pos(token.source_position);
-                       fprintf(stderr, "warning: implicit declaration of function '%s'\n",
-                               ref->symbol->string);
+                       warningf(HERE, "implicit declaration of function '%s'\n", ref->symbol->string);
 
                        declaration = create_implicit_function(ref->symbol,
                                                               source_position);
                } else
 #endif
                {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
+                       errorf(HERE, "unknown symbol '%s' found.\n", ref->symbol->string);
                        return expression;
                }
        }
@@ -3173,7 +3023,7 @@ static expression_t *parse_function_keyword(void)
        /* TODO */
 
        if (current_function == NULL) {
-               parse_error("'__func__' used outside of a function");
+               errorf(HERE, "'__func__' used outside of a function");
        }
 
        string_literal_expression_t *expression
@@ -3192,7 +3042,7 @@ static expression_t *parse_pretty_function_keyword(void)
        /* TODO */
 
        if (current_function == NULL) {
-               parse_error("'__PRETTY_FUNCTION__' used outside of a function");
+               errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
        }
 
        string_literal_expression_t *expression
@@ -3291,9 +3141,7 @@ static expression_t *parse_va_start(void)
                        return expression;
                }
        }
-       parser_print_error_prefix_pos(expr->base.source_position);
-       fprintf(stderr, "second argument of 'va_start' must be last parameter "
-                       "of the current function\n");
+       errorf(expr->base.source_position, "second argument of 'va_start' must be last parameter of the current function");
 
        return create_invalid_expression();
 }
@@ -3473,10 +3321,7 @@ static expression_t *parse_primary_expression(void)
                return parse_brace_expression();
        }
 
-       parser_print_error_prefix();
-       fprintf(stderr, "unexpected token ");
-       print_token(stderr, &token);
-       fprintf(stderr, "\n");
+       errorf(HERE, "unexpected token '%K'", &token);
        eat_statement();
 
        return create_invalid_expression();
@@ -3516,12 +3361,7 @@ static expression_t *parse_array_expression(unsigned precedence,
                        array_access->index     = left;
                        array_access->flipped   = true;
                } else {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "array access on object with non-pointer types ");
-                       print_type_quoted(type_left);
-                       fprintf(stderr, ", ");
-                       print_type_quoted(type_inside);
-                       fprintf(stderr, "\n");
+                       errorf(HERE, "array access on object with non-pointer types '%T', '%T'", type_left, type_inside);
                }
        } else {
                array_access->array_ref = left;
@@ -3593,10 +3433,7 @@ static expression_t *parse_select_expression(unsigned precedence,
        type_t *type_left = type;
        if(is_pointer) {
                if(type->kind != TYPE_POINTER) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "left hand side of '->' is not a pointer, but ");
-                       print_type_quoted(orig_type);
-                       fputc('\n', stderr);
+                       errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type);
                        return create_invalid_expression();
                }
                pointer_type_t *pointer_type = &type->pointer;
@@ -3606,11 +3443,7 @@ static expression_t *parse_select_expression(unsigned precedence,
 
        if(type_left->kind != TYPE_COMPOUND_STRUCT
                        && type_left->kind != TYPE_COMPOUND_UNION) {
-               parser_print_error_prefix();
-               fprintf(stderr, "request for member '%s' in something not a struct or "
-                       "union, but ", symbol->string);
-               print_type_quoted(type_left);
-               fputc('\n', stderr);
+               errorf(HERE, "request for member '%s' in something not a struct or union, but '%T'", symbol->string, type_left);
                return create_invalid_expression();
        }
 
@@ -3618,11 +3451,7 @@ static expression_t *parse_select_expression(unsigned precedence,
        declaration_t   *declaration   = compound_type->declaration;
 
        if(!declaration->init.is_defined) {
-               parser_print_error_prefix();
-               fprintf(stderr, "request for member '%s' of incomplete type ",
-                       symbol->string);
-               print_type_quoted(type_left);
-               fputc('\n', stderr);
+               errorf(HERE, "request for member '%s' of incomplete type '%T'", symbol->string, type_left);
                return create_invalid_expression();
        }
 
@@ -3633,9 +3462,7 @@ static expression_t *parse_select_expression(unsigned precedence,
                }
        }
        if(iter == NULL) {
-               parser_print_error_prefix();
-               print_type_quoted(type_left);
-               fprintf(stderr, " has no member named '%s'\n", symbol->string);
+               errorf(HERE, "'%T' has no member names '%s'", type_left, symbol->string);
                return create_invalid_expression();
        }
 
@@ -3673,12 +3500,7 @@ static expression_t *parse_call_expression(unsigned precedence,
                        }
                }
                if(function_type == NULL) {
-                       parser_print_error_prefix();
-                       fputs("called object '", stderr);
-                       print_expression(expression);
-                       fputs("' (type ", stderr);
-                       print_type_quoted(orig_type);
-                       fputs(") is not a pointer to a function\n", stderr);
+                       errorf(HERE, "called object '%E' (type '%T') is not a pointer to a function", expression, orig_type);
 
                        function_type             = NULL;
                        call->expression.datatype = NULL;
@@ -3721,18 +3543,12 @@ static expression_t *parse_call_expression(unsigned precedence,
                }
                /* too few parameters */
                if(parameter != NULL) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "too few arguments to function '");
-                       print_expression(expression);
-                       fprintf(stderr, "'\n");
+                       errorf(HERE, "too few arguments to function '%E'", expression);
                } else if(argument != NULL) {
                        /* too many parameters */
                        if(!function_type->variadic
                                        && !function_type->unspecified_parameters) {
-                               parser_print_error_prefix();
-                               fprintf(stderr, "too many arguments to function '");
-                               print_expression(expression);
-                               fprintf(stderr, "'\n");
+                               errorf(HERE, "too many arguments to function '%E'", expression);
                        } else {
                                /* do default promotion */
                                for( ; argument != NULL; argument = argument->next) {
@@ -3876,8 +3692,7 @@ static void semantic_incdec(unary_expression_t *expression)
        type_t *type = skip_typeref(orig_type);
        if(!is_type_arithmetic(type) && type->kind != TYPE_POINTER) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs an arithmetic or pointer type\n");
+               errorf(HERE, "operation needs an arithmetic or pointer type");
                return;
        }
 
@@ -3893,8 +3708,7 @@ static void semantic_unexpr_arithmetic(unary_expression_t *expression)
        type_t *type = skip_typeref(orig_type);
        if(!is_type_arithmetic(type)) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs an arithmetic type\n");
+               errorf(HERE, "operation needs an arithmetic type");
                return;
        }
 
@@ -3909,7 +3723,7 @@ static void semantic_unexpr_scalar(unary_expression_t *expression)
 
        type_t *type = skip_typeref(orig_type);
        if (!is_type_scalar(type)) {
-               parse_error("operand of ! must be of scalar type\n");
+               errorf(HERE, "operand of ! must be of scalar type");
                return;
        }
 
@@ -3924,7 +3738,7 @@ static void semantic_unexpr_integer(unary_expression_t *expression)
 
        type_t *type = skip_typeref(orig_type);
        if (!is_type_integer(type)) {
-               parse_error("operand of ~ must be of integer type\n");
+               errorf(HERE, "operand of ~ must be of integer type");
                return;
        }
 
@@ -3939,10 +3753,7 @@ static void semantic_dereference(unary_expression_t *expression)
 
        type_t *type = skip_typeref(orig_type);
        if(!is_type_pointer(type)) {
-               parser_print_error_prefix();
-               fputs("Unary '*' needs pointer or arrray type, but type ", stderr);
-               print_type_quoted(orig_type);
-               fputs(" given.\n", stderr);
+               errorf(HERE, "Unary '*' needs pointer or arrray type, but type '%T' given", orig_type);
                return;
        }
 
@@ -4081,8 +3892,7 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
 
        if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs arithmetic types\n");
+               errorf(HERE, "operation needs arithmetic types");
                return;
        }
 
@@ -4107,8 +3917,7 @@ static void semantic_shift_op(binary_expression_t *expression)
 
        if(!is_type_integer(type_left) || !is_type_integer(type_right)) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs integer types\n");
+               errorf(HERE, "operation needs integer types");
                return;
        }
 
@@ -4145,12 +3954,7 @@ static void semantic_add(binary_expression_t *expression)
        } else if(is_type_pointer(type_right) && is_type_integer(type_left)) {
                expression->expression.datatype = type_right;
        } else {
-               parser_print_error_prefix();
-               fprintf(stderr, "invalid operands to binary + (");
-               print_type_quoted(orig_type_left);
-               fprintf(stderr, ", ");
-               print_type_quoted(orig_type_right);
-               fprintf(stderr, ")\n");
+               errorf(HERE, "invalid operands to binary + ('%T', '%T')", orig_type_left, orig_type_right);
        }
 }
 
@@ -4178,22 +3982,12 @@ static void semantic_sub(binary_expression_t *expression)
                expression->expression.datatype = type_left;
        } else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
                if(!pointers_compatible(type_left, type_right)) {
-                       parser_print_error_prefix();
-                       fprintf(stderr, "pointers to incompatible objects to binary - (");
-                       print_type_quoted(orig_type_left);
-                       fprintf(stderr, ", ");
-                       print_type_quoted(orig_type_right);
-                       fprintf(stderr, ")\n");
+                       errorf(HERE, "pointers to incompatible objects to binary - ('%T', '%T')", orig_type_left, orig_type_right);
                } else {
                        expression->expression.datatype = type_ptrdiff_t;
                }
        } else {
-               parser_print_error_prefix();
-               fprintf(stderr, "invalid operands to binary - (");
-               print_type_quoted(orig_type_left);
-               fprintf(stderr, ", ");
-               print_type_quoted(orig_type_right);
-               fprintf(stderr, ")\n");
+               errorf(HERE, "invalid operands to binary - ('%T', '%T')", orig_type_left, orig_type_right);
        }
 }
 
@@ -4244,8 +4038,7 @@ static void semantic_arithmetic_assign(binary_expression_t *expression)
 
        if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs arithmetic types\n");
+               errorf(HERE, "operation needs arithmetic types");
                return;
        }
 
@@ -4282,12 +4075,7 @@ static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
        } else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
                expression->expression.datatype = type_left;
        } else {
-               parser_print_error_prefix();
-               fputs("Incompatible types ", stderr);
-               print_type_quoted(orig_type_left);
-               fputs(" and ", stderr);
-               print_type_quoted(orig_type_right);
-               fputs(" in assignment\n", stderr);
+               errorf(HERE, "incompatible types '%T' and '%T' in assignment", orig_type_left, orig_type_right);
                return;
        }
 }
@@ -4307,8 +4095,7 @@ static void semantic_logical_op(binary_expression_t *expression)
 
        if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) {
                /* TODO: improve error message */
-               parser_print_error_prefix();
-               fprintf(stderr, "operation needs scalar types\n");
+               errorf(HERE, "operation needs scalar types");
                return;
        }
 
@@ -4335,37 +4122,19 @@ static void semantic_binexpr_assign(binary_expression_t *expression)
 
        /* must be a modifiable lvalue */
        if (is_type_array(type_left)) {
-               parser_print_error_prefix();
-               fprintf(stderr, "Cannot assign to arrays ('");
-               print_expression(left);
-               fprintf(stderr, "')\n");
+               errorf(HERE, "cannot assign to arrays ('%E')", left);
                return;
        }
        if(type_left->base.qualifiers & TYPE_QUALIFIER_CONST) {
-               parser_print_error_prefix();
-               fprintf(stderr, "assignment to readonly location '");
-               print_expression(left);
-               fprintf(stderr, "' (type ");
-               print_type_quoted(orig_type_left);
-               fprintf(stderr, ")\n");
+               errorf(HERE, "assignment to readonly location '%E' (type '%T')", left, orig_type_left);
                return;
        }
        if(is_type_incomplete(type_left)) {
-               parser_print_error_prefix();
-               fprintf(stderr, "left-hand side of assignment '");
-               print_expression(left);
-               fprintf(stderr, "' has incomplete type ");
-               print_type_quoted(orig_type_left);
-               fprintf(stderr, "\n");
+               errorf(HERE, "left-hand side of assignment '%E' has incomplete type '%T'", left, orig_type_left);
                return;
        }
        if(is_type_compound(type_left) && has_const_fields(type_left)) {
-               parser_print_error_prefix();
-               fprintf(stderr, "can't assign to '");
-               print_expression(left);
-               fprintf(stderr, "' because compound type ");
-               print_type_quoted(orig_type_left);
-               fprintf(stderr, " has readonly fields\n");
+               errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields", left, orig_type_left);
                return;
        }
 
@@ -4502,9 +4271,7 @@ static void register_expression_parser(parse_expression_function parser,
        expression_parser_function_t *entry = &expression_parsers[token_type];
 
        if(entry->parser != NULL) {
-               fprintf(stderr, "for token ");
-               print_token_type(stderr, (token_type_t) token_type);
-               fprintf(stderr, "\n");
+               diagnosticf("for token '%k'\n", (token_type_t)token_type);
                panic("trying to register multiple expression parsers for a token");
        }
        entry->parser     = parser;
@@ -4517,9 +4284,7 @@ static void register_infix_parser(parse_expression_infix_function parser,
        expression_parser_function_t *entry = &expression_parsers[token_type];
 
        if(entry->infix_parser != NULL) {
-               fprintf(stderr, "for token ");
-               print_token_type(stderr, (token_type_t) token_type);
-               fprintf(stderr, "\n");
+               diagnosticf("for token '%k'\n", (token_type_t)token_type);
                panic("trying to register multiple infix expression parsers for a "
                      "token");
        }
@@ -4760,11 +4525,8 @@ static statement_t *parse_label_statement(void)
        /* if source position is already set then the label is defined twice,
         * otherwise it was just mentioned in a goto so far */
        if(label->source_position.input_name != NULL) {
-               parser_print_error_prefix();
-               fprintf(stderr, "duplicate label '%s'\n", symbol->string);
-               parser_print_error_prefix_pos(label->source_position);
-               fprintf(stderr, "previous definition of '%s' was here\n",
-                       symbol->string);
+               errorf(HERE, "duplicate label '%s'\n", symbol->string);
+               errorf(label->source_position, "previous definition of '%s' was here\n", symbol->string);
        } else {
                label->source_position = token.source_position;
        }
@@ -4778,7 +4540,8 @@ static statement_t *parse_label_statement(void)
        expect(':');
 
        if(token.type == '}') {
-               parse_error("label at end of compound statement");
+               /* TODO only warn? */
+               errorf(HERE, "label at end of compound statement");
                return (statement_t*) label_statement;
        } else {
                label_statement->label_statement = parse_statement();
@@ -4981,7 +4744,7 @@ static statement_t *parse_return(void)
 
                if(is_type_atomic(return_type, ATOMIC_TYPE_VOID)
                                && !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) {
-                       parse_warning("'return' with a value, in function returning void");
+                       warningf(HERE, "'return' with a value, in function returning void");
                        return_value = NULL;
                } else {
                        if(return_type != NULL) {
@@ -4990,8 +4753,7 @@ static statement_t *parse_return(void)
                }
        } else {
                if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
-                       parse_warning("'return' without value, in function returning "
-                                     "non-void");
+                       warningf(HERE, "'return' without value, in function returning non-void");
                }
        }
        statement->return_value = return_value;
@@ -5164,9 +4926,7 @@ static statement_t *parse_compound_statement(void)
        }
 
        if(token.type != '}') {
-               parser_print_error_prefix_pos(
-                               compound_statement->statement.source_position);
-               fprintf(stderr, "end of file while looking for closing '}'\n");
+               errorf(compound_statement->statement.source_position, "end of file while looking for closing '}'");
        }
        next_token();