2 * This file is part of cparser.
3 * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
8 #include "diagnostic.h"
11 #include "separator_t.h"
17 /** Number of occurred errors. */
18 unsigned error_count = 0;
19 /** Number of occurred warnings. */
20 unsigned warning_count = 0;
21 bool show_column = true;
22 bool diagnostics_show_option = true;
24 static const position_t *curr_pos = NULL;
27 * prints an additional source position
29 static void print_position(FILE *out, const position_t *pos)
31 fprintf(out, "at line %u", pos->lineno);
33 fprintf(out, ":%u", (unsigned)pos->colno);
34 if (curr_pos == NULL || curr_pos->input_name != pos->input_name)
35 fprintf(out, " of \"%s\"", pos->input_name);
38 static void fpututf32(utf32 const c, FILE *const out)
42 } else if (c < 0x800) {
43 fputc(0xC0 | (c >> 6), out);
44 fputc(0x80 | (c & 0x3F), out);
45 } else if (c < 0x10000) {
46 fputc(0xE0 | ( c >> 12), out);
47 fputc(0x80 | ((c >> 6) & 0x3F), out);
48 fputc(0x80 | ( c & 0x3F), out);
50 fputc(0xF0 | ( c >> 18), out);
51 fputc(0x80 | ((c >> 12) & 0x3F), out);
52 fputc(0x80 | ((c >> 6) & 0x3F), out);
53 fputc(0x80 | ( c & 0x3F), out);
58 * Issue a diagnostic message.
60 static void diagnosticvf(char const *fmt, va_list ap)
62 for (char const *f; (f = strchr(fmt, '%')); fmt = f) {
63 fwrite(fmt, sizeof(*fmt), f - fmt, stderr); // Print till '%'.
66 bool extended = false;
67 bool flag_zero = false;
68 bool flag_long = false;
71 case '#': extended = true; break;
72 case '0': flag_zero = true; break;
73 case 'l': flag_long = true; break;
74 default: goto done_flags;
82 field_width = va_arg(ap, int);
92 const utf32 val = va_arg(ap, utf32);
93 fpututf32(val, stderr);
95 const unsigned char val = (unsigned char) va_arg(ap, int);
102 const int val = va_arg(ap, int);
103 fprintf(stderr, "%d", val);
108 const char* const str = va_arg(ap, const char*);
114 const string_t *str = va_arg(ap, const string_t*);
115 for (size_t i = 0; i < str->size; ++i) {
116 fputc(str->begin[i], stderr);
122 const unsigned int val = va_arg(ap, unsigned int);
123 fprintf(stderr, "%u", val);
128 unsigned int const val = va_arg(ap, unsigned int);
129 char const *const xfmt = flag_zero ? "%0*X" : "%*X";
130 fprintf(stderr, xfmt, field_width, val);
135 const symbol_t *const symbol = va_arg(ap, const symbol_t*);
137 fputs("(null)", stderr);
139 fputs(symbol->string, stderr);
144 const expression_t* const expr = va_arg(ap, const expression_t*);
145 print_expression(expr);
150 const unsigned qualifiers = va_arg(ap, unsigned);
151 print_type_qualifiers(qualifiers, QUAL_SEP_NONE);
156 const type_t* const type = va_arg(ap, const type_t*);
157 const symbol_t* sym = NULL;
159 sym = va_arg(ap, const symbol_t*);
161 print_type_ext(type, sym, NULL);
166 const token_t* const token = va_arg(ap, const token_t*);
167 print_token(stderr, token);
173 va_list* const toks = va_arg(ap, va_list*);
174 separator_t sep = { "", va_arg(ap, const char*) };
176 const token_kind_t tok = (token_kind_t)va_arg(*toks, int);
179 fputs(sep_next(&sep), stderr);
180 print_token_kind(stderr, tok);
183 const token_kind_t token = (token_kind_t)va_arg(ap, int);
184 print_token_kind(stderr, token);
190 entity_t const *const ent = va_arg(ap, entity_t const*);
191 if (extended && is_declaration(ent)) {
192 print_type_ext(ent->declaration.type, ent->base.symbol, NULL);
194 char const *const kind = get_entity_kind_name(ent->kind);
195 symbol_t const *const sym = ent->base.symbol;
197 fprintf(stderr, "%s %s", kind, sym->string);
199 fprintf(stderr, "anonymous %s", kind);
206 const position_t *pos = va_arg(ap, const position_t *);
207 print_position(stderr, pos);
212 panic("unknown format specifier");
215 fputs(fmt, stderr); // Print rest.
218 void diagnosticf(const char *const fmt, ...)
223 diagnosticvf(fmt, ap);
227 static void diagnosticposvf(position_t const *const pos, char const *const kind, char const *const fmt, va_list ap)
229 FILE *const out = stderr;
231 fprintf(out, "%s:", pos->input_name);
232 if (pos->lineno != 0) {
233 fprintf(out, "%u:", pos->lineno);
235 fprintf(out, "%u:", (unsigned)pos->colno);
239 fprintf(out, "%s: ", kind);
241 diagnosticvf(fmt, ap);
244 static void errorvf(const position_t *pos,
245 const char *const fmt, va_list ap)
248 diagnosticposvf(pos, "error", fmt, ap);
250 if (is_warn_on(WARN_FATAL_ERRORS))
254 void errorf(const position_t *pos, const char *const fmt, ...)
258 errorvf(pos, fmt, ap);
262 void warningf(warning_t const warn, position_t const* pos, char const *const fmt, ...)
264 if (pos->is_system_header && !is_warn_on(WARN_SYSTEM))
267 warning_switch_t const *const s = get_warn_switch(warn);
268 switch ((unsigned) s->state) {
271 if (is_warn_on(WARN_ERROR)) {
272 case WARN_STATE_ON | WARN_STATE_ERROR:
276 case WARN_STATE_ON | WARN_STATE_NO_ERROR:
282 diagnosticposvf(pos, kind, fmt, ap);
284 if (diagnostics_show_option)
285 fprintf(stderr, " [-W%s]\n", s->name);
295 static void internal_errorvf(const position_t *pos,
296 const char *const fmt, va_list ap)
298 diagnosticposvf(pos, "internal error", fmt, ap);
302 void internal_errorf(const position_t *pos, const char *const fmt, ...)
306 internal_errorvf(pos, fmt, ap);