2 * This file is part of cparser.
3 * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 #include "diagnostic.h"
24 #include "adt/error.h"
32 /** Number of occurred errors. */
33 unsigned error_count = 0;
34 /** Number of occurred warnings. */
35 unsigned warning_count = 0;
36 bool show_column = true;
37 bool diagnostics_show_option = true;
39 static const source_position_t *curr_pos = NULL;
42 * prints an additional source position
44 static void print_source_position(FILE *out, const source_position_t *pos)
46 fprintf(out, "at line %u", pos->lineno);
48 fprintf(out, ":%u", (unsigned)pos->colno);
49 if (curr_pos == NULL || curr_pos->input_name != pos->input_name)
50 fprintf(out, " of \"%s\"", pos->input_name);
53 static void fpututf32(utf32 const c, FILE *const out)
57 } else if (c < 0x800) {
58 fputc(0xC0 | (c >> 6), out);
59 fputc(0x80 | (c & 0x3F), out);
60 } else if (c < 0x10000) {
61 fputc(0xE0 | ( c >> 12), out);
62 fputc(0x80 | ((c >> 6) & 0x3F), out);
63 fputc(0x80 | ( c & 0x3F), out);
65 fputc(0xF0 | ( c >> 18), out);
66 fputc(0x80 | ((c >> 12) & 0x3F), out);
67 fputc(0x80 | ((c >> 6) & 0x3F), out);
68 fputc(0x80 | ( c & 0x3F), out);
73 * Issue a diagnostic message.
75 static void diagnosticvf(char const *fmt, va_list ap)
77 for (char const *f; (f = strchr(fmt, '%')); fmt = f) {
78 fwrite(fmt, sizeof(*fmt), f - fmt, stderr); // Print till '%'.
81 bool extended = false;
82 bool flag_zero = false;
83 bool flag_long = false;
86 case '#': extended = true; break;
87 case '0': flag_zero = true; break;
88 case 'l': flag_long = true; break;
89 default: goto done_flags;
97 field_width = va_arg(ap, int);
107 const utf32 val = va_arg(ap, utf32);
108 fpututf32(val, stderr);
110 const unsigned char val = (unsigned char) va_arg(ap, int);
117 const int val = va_arg(ap, int);
118 fprintf(stderr, "%d", val);
123 const char* const str = va_arg(ap, const char*);
129 const string_t *str = va_arg(ap, const string_t*);
130 for (size_t i = 0; i < str->size; ++i) {
131 fputc(str->begin[i], stderr);
137 const unsigned int val = va_arg(ap, unsigned int);
138 fprintf(stderr, "%u", val);
143 unsigned int const val = va_arg(ap, unsigned int);
144 char const *const fmt = flag_zero ? "%0*X" : "%*X";
145 fprintf(stderr, fmt, field_width, val);
150 const symbol_t *const symbol = va_arg(ap, const symbol_t*);
152 fputs("(null)", stderr);
154 fputs(symbol->string, stderr);
159 const expression_t* const expr = va_arg(ap, const expression_t*);
160 print_expression(expr);
165 const unsigned qualifiers = va_arg(ap, unsigned);
166 print_type_qualifiers(qualifiers, QUAL_SEP_NONE);
171 const type_t* const type = va_arg(ap, const type_t*);
172 const symbol_t* sym = NULL;
174 sym = va_arg(ap, const symbol_t*);
176 print_type_ext(type, sym, NULL);
181 const token_t* const token = va_arg(ap, const token_t*);
182 print_token(stderr, token);
189 va_list* toks = va_arg(ap, va_list*);
190 const char* const delimiter = va_arg(ap, const char*);
192 const token_kind_t tok = (token_kind_t)va_arg(*toks, int);
198 fputs(delimiter, stderr);
200 print_token_kind(stderr, tok);
203 const token_kind_t token = (token_kind_t)va_arg(ap, int);
204 print_token_kind(stderr, token);
210 entity_t const *const ent = va_arg(ap, entity_t const*);
211 if (extended && is_declaration(ent)) {
212 print_type_ext(ent->declaration.type, ent->base.symbol, NULL);
214 char const *const kind = get_entity_kind_name(ent->kind);
215 symbol_t const *const sym = ent->base.symbol;
217 fprintf(stderr, "%s %s", kind, sym->string);
219 fprintf(stderr, "anonymous %s", kind);
226 const source_position_t *pos = va_arg(ap, const source_position_t *);
227 print_source_position(stderr, pos);
232 panic("unknown format specifier");
235 fputs(fmt, stderr); // Print rest.
238 void diagnosticf(const char *const fmt, ...)
243 diagnosticvf(fmt, ap);
247 static void diagnosticposvf(source_position_t const *const pos, char const *const kind, char const *const fmt, va_list ap)
249 FILE *const out = stderr;
250 fprintf(out, "%s:%u:", pos->input_name, pos->lineno);
252 fprintf(out, "%u:", (unsigned)pos->colno);
253 fprintf(out, " %s: ", kind);
255 diagnosticvf(fmt, ap);
258 static void errorvf(const source_position_t *pos,
259 const char *const fmt, va_list ap)
262 diagnosticposvf(pos, "error", fmt, ap);
264 if (is_warn_on(WARN_FATAL_ERRORS))
268 void errorf(const source_position_t *pos, const char *const fmt, ...)
272 errorvf(pos, fmt, ap);
276 void warningf(warning_t const warn, source_position_t const* pos, char const *const fmt, ...)
280 warning_switch_t const *const s = get_warn_switch(warn);
281 switch ((unsigned) s->state) {
284 if (is_warn_on(WARN_ERROR)) {
285 case WARN_STATE_ON | WARN_STATE_ERROR:
289 case WARN_STATE_ON | WARN_STATE_NO_ERROR:
293 diagnosticposvf(pos, kind, fmt, ap);
294 if (diagnostics_show_option)
295 fprintf(stderr, " [-W%s]\n", s->name);
304 static void internal_errorvf(const source_position_t *pos,
305 const char *const fmt, va_list ap)
307 diagnosticposvf(pos, "internal error", fmt, ap);
311 void internal_errorf(const source_position_t *pos, const char *const fmt, ...)
315 internal_errorvf(pos, fmt, ap);