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"
26 #include "separator_t.h"
33 /** Number of occurred errors. */
34 unsigned error_count = 0;
35 /** Number of occurred warnings. */
36 unsigned warning_count = 0;
37 bool show_column = true;
38 bool diagnostics_show_option = true;
40 static const position_t *curr_pos = NULL;
43 * prints an additional source position
45 static void print_position(FILE *out, const position_t *pos)
47 fprintf(out, "at line %u", pos->lineno);
49 fprintf(out, ":%u", (unsigned)pos->colno);
50 if (curr_pos == NULL || curr_pos->input_name != pos->input_name)
51 fprintf(out, " of \"%s\"", pos->input_name);
54 static void fpututf32(utf32 const c, FILE *const out)
58 } else if (c < 0x800) {
59 fputc(0xC0 | (c >> 6), out);
60 fputc(0x80 | (c & 0x3F), out);
61 } else if (c < 0x10000) {
62 fputc(0xE0 | ( c >> 12), out);
63 fputc(0x80 | ((c >> 6) & 0x3F), out);
64 fputc(0x80 | ( c & 0x3F), out);
66 fputc(0xF0 | ( c >> 18), out);
67 fputc(0x80 | ((c >> 12) & 0x3F), out);
68 fputc(0x80 | ((c >> 6) & 0x3F), out);
69 fputc(0x80 | ( c & 0x3F), out);
74 * Issue a diagnostic message.
76 static void diagnosticvf(char const *fmt, va_list ap)
78 for (char const *f; (f = strchr(fmt, '%')); fmt = f) {
79 fwrite(fmt, sizeof(*fmt), f - fmt, stderr); // Print till '%'.
82 bool extended = false;
83 bool flag_zero = false;
84 bool flag_long = false;
87 case '#': extended = true; break;
88 case '0': flag_zero = true; break;
89 case 'l': flag_long = true; break;
90 default: goto done_flags;
98 field_width = va_arg(ap, int);
108 const utf32 val = va_arg(ap, utf32);
109 fpututf32(val, stderr);
111 const unsigned char val = (unsigned char) va_arg(ap, int);
118 const int val = va_arg(ap, int);
119 fprintf(stderr, "%d", val);
124 const char* const str = va_arg(ap, const char*);
130 const string_t *str = va_arg(ap, const string_t*);
131 for (size_t i = 0; i < str->size; ++i) {
132 fputc(str->begin[i], stderr);
138 const unsigned int val = va_arg(ap, unsigned int);
139 fprintf(stderr, "%u", val);
144 unsigned int const val = va_arg(ap, unsigned int);
145 char const *const fmt = flag_zero ? "%0*X" : "%*X";
146 fprintf(stderr, fmt, field_width, val);
151 const symbol_t *const symbol = va_arg(ap, const symbol_t*);
153 fputs("(null)", stderr);
155 fputs(symbol->string, stderr);
160 const expression_t* const expr = va_arg(ap, const expression_t*);
161 print_expression(expr);
166 const unsigned qualifiers = va_arg(ap, unsigned);
167 print_type_qualifiers(qualifiers, QUAL_SEP_NONE);
172 const type_t* const type = va_arg(ap, const type_t*);
173 const symbol_t* sym = NULL;
175 sym = va_arg(ap, const symbol_t*);
177 print_type_ext(type, sym, NULL);
182 const token_t* const token = va_arg(ap, const token_t*);
183 print_token(stderr, token);
189 va_list* const toks = va_arg(ap, va_list*);
190 separator_t sep = { "", va_arg(ap, const char*) };
192 const token_kind_t tok = (token_kind_t)va_arg(*toks, int);
195 fputs(sep_next(&sep), stderr);
196 print_token_kind(stderr, tok);
199 const token_kind_t token = (token_kind_t)va_arg(ap, int);
200 print_token_kind(stderr, token);
206 entity_t const *const ent = va_arg(ap, entity_t const*);
207 if (extended && is_declaration(ent)) {
208 print_type_ext(ent->declaration.type, ent->base.symbol, NULL);
210 char const *const kind = get_entity_kind_name(ent->kind);
211 symbol_t const *const sym = ent->base.symbol;
213 fprintf(stderr, "%s %s", kind, sym->string);
215 fprintf(stderr, "anonymous %s", kind);
222 const position_t *pos = va_arg(ap, const position_t *);
223 print_position(stderr, pos);
228 panic("unknown format specifier");
231 fputs(fmt, stderr); // Print rest.
234 void diagnosticf(const char *const fmt, ...)
239 diagnosticvf(fmt, ap);
243 static void diagnosticposvf(position_t const *const pos, char const *const kind, char const *const fmt, va_list ap)
245 FILE *const out = stderr;
247 fprintf(out, "%s:", pos->input_name);
248 if (pos->lineno != 0) {
249 fprintf(out, "%u:", pos->lineno);
251 fprintf(out, "%u:", (unsigned)pos->colno);
255 fprintf(out, "%s: ", kind);
257 diagnosticvf(fmt, ap);
260 static void errorvf(const position_t *pos,
261 const char *const fmt, va_list ap)
264 diagnosticposvf(pos, "error", fmt, ap);
266 if (is_warn_on(WARN_FATAL_ERRORS))
270 void errorf(const position_t *pos, const char *const fmt, ...)
274 errorvf(pos, fmt, ap);
278 void warningf(warning_t const warn, position_t const* pos, char const *const fmt, ...)
282 warning_switch_t const *const s = get_warn_switch(warn);
283 switch ((unsigned) s->state) {
286 if (is_warn_on(WARN_ERROR)) {
287 case WARN_STATE_ON | WARN_STATE_ERROR:
291 case WARN_STATE_ON | WARN_STATE_NO_ERROR:
295 diagnosticposvf(pos, kind, fmt, ap);
296 if (diagnostics_show_option)
297 fprintf(stderr, " [-W%s]\n", s->name);
308 static void internal_errorvf(const position_t *pos,
309 const char *const fmt, va_list ap)
311 diagnosticposvf(pos, "internal error", fmt, ap);
315 void internal_errorf(const position_t *pos, const char *const fmt, ...)
319 internal_errorvf(pos, fmt, ap);