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"
18 /** Number of occurred errors. */
19 unsigned error_count = 0;
20 /** Number of occurred warnings. */
21 unsigned warning_count = 0;
22 bool show_column = true;
23 bool diagnostics_show_option = true;
25 static const position_t *curr_pos = NULL;
28 * prints an additional source position
30 static void print_position(FILE *out, const position_t *pos)
32 fprintf(out, "at line %u", pos->lineno);
34 fprintf(out, ":%u", (unsigned)pos->colno);
35 if (curr_pos == NULL || curr_pos->input_name != pos->input_name)
36 fprintf(out, " of \"%s\"", pos->input_name);
39 static void fpututf32(utf32 const c, FILE *const out)
43 } else if (c < 0x800) {
44 fputc(0xC0 | (c >> 6), out);
45 fputc(0x80 | (c & 0x3F), out);
46 } else if (c < 0x10000) {
47 fputc(0xE0 | ( c >> 12), out);
48 fputc(0x80 | ((c >> 6) & 0x3F), out);
49 fputc(0x80 | ( c & 0x3F), out);
51 fputc(0xF0 | ( c >> 18), out);
52 fputc(0x80 | ((c >> 12) & 0x3F), out);
53 fputc(0x80 | ((c >> 6) & 0x3F), out);
54 fputc(0x80 | ( c & 0x3F), out);
59 * Issue a diagnostic message.
61 static void diagnosticvf(char const *fmt, va_list ap)
63 for (char const *f; (f = strchr(fmt, '%')); fmt = f) {
64 fwrite(fmt, sizeof(*fmt), f - fmt, stderr); // Print till '%'.
67 bool extended = false;
68 bool flag_zero = false;
69 bool flag_long = false;
72 case '#': extended = true; break;
73 case '0': flag_zero = true; break;
74 case 'l': flag_long = true; break;
75 default: goto done_flags;
83 field_width = va_arg(ap, int);
93 const utf32 val = va_arg(ap, utf32);
94 fpututf32(val, stderr);
96 const unsigned char val = (unsigned char) va_arg(ap, int);
103 const int val = va_arg(ap, int);
104 fprintf(stderr, "%d", val);
109 const char* const str = va_arg(ap, const char*);
115 const string_t *str = va_arg(ap, const string_t*);
116 for (size_t i = 0; i < str->size; ++i) {
117 fputc(str->begin[i], stderr);
123 const unsigned int val = va_arg(ap, unsigned int);
124 fprintf(stderr, "%u", val);
129 unsigned int const val = va_arg(ap, unsigned int);
130 char const *const fmt = flag_zero ? "%0*X" : "%*X";
131 fprintf(stderr, fmt, field_width, val);
136 const symbol_t *const symbol = va_arg(ap, const symbol_t*);
138 fputs("(null)", stderr);
140 fputs(symbol->string, stderr);
145 const expression_t* const expr = va_arg(ap, const expression_t*);
146 print_expression(expr);
151 const unsigned qualifiers = va_arg(ap, unsigned);
152 print_type_qualifiers(qualifiers, QUAL_SEP_NONE);
157 const type_t* const type = va_arg(ap, const type_t*);
158 const symbol_t* sym = NULL;
160 sym = va_arg(ap, const symbol_t*);
162 print_type_ext(type, sym, NULL);
167 const token_t* const token = va_arg(ap, const token_t*);
168 print_token(stderr, token);
174 va_list* const toks = va_arg(ap, va_list*);
175 separator_t sep = { "", va_arg(ap, const char*) };
177 const token_kind_t tok = (token_kind_t)va_arg(*toks, int);
180 fputs(sep_next(&sep), stderr);
181 print_token_kind(stderr, tok);
184 const token_kind_t token = (token_kind_t)va_arg(ap, int);
185 print_token_kind(stderr, token);
191 entity_t const *const ent = va_arg(ap, entity_t const*);
192 if (extended && is_declaration(ent)) {
193 print_type_ext(ent->declaration.type, ent->base.symbol, NULL);
195 char const *const kind = get_entity_kind_name(ent->kind);
196 symbol_t const *const sym = ent->base.symbol;
198 fprintf(stderr, "%s %s", kind, sym->string);
200 fprintf(stderr, "anonymous %s", kind);
207 const position_t *pos = va_arg(ap, const position_t *);
208 print_position(stderr, pos);
213 panic("unknown format specifier");
216 fputs(fmt, stderr); // Print rest.
219 void diagnosticf(const char *const fmt, ...)
224 diagnosticvf(fmt, ap);
228 static void diagnosticposvf(position_t const *const pos, char const *const kind, char const *const fmt, va_list ap)
230 FILE *const out = stderr;
232 fprintf(out, "%s:", pos->input_name);
233 if (pos->lineno != 0) {
234 fprintf(out, "%u:", pos->lineno);
236 fprintf(out, "%u:", (unsigned)pos->colno);
240 fprintf(out, "%s: ", kind);
242 diagnosticvf(fmt, ap);
245 static void errorvf(const position_t *pos,
246 const char *const fmt, va_list ap)
249 diagnosticposvf(pos, "error", fmt, ap);
251 if (is_warn_on(WARN_FATAL_ERRORS))
255 void errorf(const position_t *pos, const char *const fmt, ...)
259 errorvf(pos, fmt, ap);
263 void warningf(warning_t const warn, position_t const* pos, char const *const fmt, ...)
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:
280 diagnosticposvf(pos, kind, fmt, ap);
281 if (diagnostics_show_option)
282 fprintf(stderr, " [-W%s]\n", s->name);
293 static void internal_errorvf(const position_t *pos,
294 const char *const fmt, va_list ap)
296 diagnosticposvf(pos, "internal error", fmt, ap);
300 void internal_errorf(const position_t *pos, const char *const fmt, ...)
304 internal_errorvf(pos, fmt, ap);