-Werror implemented
[cparser] / diagnostic.c
1 #include <stdarg.h>
2 #include <stdio.h>
3
4 #include "adt/error.h"
5 #include "ast.h"
6 #include "diagnostic.h"
7 #include "token_t.h"
8 #include "type.h"
9
10 //#define ABORT_ON_ERROR
11
12 /** Number of occurred diagnostics. */
13 unsigned diagnostic_count = 0;
14 /** Number of occurred errors. */
15 unsigned error_count      = 0;
16 /** Number of occurred warnings. */
17 unsigned warning_count    = 0;
18 /* true if warnings should be treated as errors */
19 bool warnings_are_errors  = false;
20
21 /**
22  * Issue a diagnostic message.
23  */
24 static void diagnosticvf(const char *const fmt, va_list ap)
25 {
26         for (const char* f = fmt; *f != '\0'; ++f) {
27                 if (*f == '%') {
28                         ++f;
29
30                         bool extended = false;
31                         if (*f == '#') {
32                                 extended = true;
33                                 ++f;
34                         }
35
36                         switch (*f) {
37                                 case '%':
38                                         fputc(*f, stderr);
39                                         break;
40
41                                 case 'C': {
42                                         const wint_t val = va_arg(ap, wint_t);
43                                         fputwc(val, stderr);
44                                         break;
45                                 }
46
47                                 case 'c': {
48                                         const unsigned char val = (unsigned char) va_arg(ap, int);
49                                         fputc(val, stderr);
50                                         break;
51                                 }
52
53                                 case 'd': {
54                                         const int val = va_arg(ap, int);
55                                         fprintf(stderr, "%d", val);
56                                         break;
57                                 }
58
59                                 case 's': {
60                                         const char* const str = va_arg(ap, const char*);
61                                         fputs(str, stderr);
62                                         break;
63                                 }
64
65                                 case 'Y': {
66                                         const symbol_t *const symbol = va_arg(ap, const symbol_t*);
67                                         fputs(symbol->string, stderr);
68                                         break;
69                                 }
70
71                                 case 'E': {
72                                         const expression_t* const expr = va_arg(ap, const expression_t*);
73                                         print_expression(expr);
74                                         break;
75                                 }
76
77                                 case 'Q': {
78                                         const unsigned qualifiers = va_arg(ap, unsigned);
79                                         print_type_qualifiers(qualifiers);
80                                         break;
81                                 }
82
83                                 case 'T': {
84                                         const type_t* const type = va_arg(ap, const type_t*);
85                                         const symbol_t*     sym  = NULL;
86                                         if (extended) {
87                                                 sym = va_arg(ap, const symbol_t*);
88                                         }
89                                         print_type_ext(type, sym, NULL);
90                                         break;
91                                 }
92
93                                 case 'K': {
94                                         const token_t* const token = va_arg(ap, const token_t*);
95                                         print_token(stderr, token);
96                                         break;
97                                 }
98
99                                 case 'k': {
100                                         if (extended) {
101                                                 bool              first     = false;
102                                                 va_list*          toks      = va_arg(ap, va_list*);
103                                                 const char* const delimiter = va_arg(ap, const char*);
104                                                 for (;;) {
105                                                         const token_type_t tok = va_arg(*toks, token_type_t);
106                                                         if (tok == 0)
107                                                                 break;
108                                                         if (first) {
109                                                                 first = false;
110                                                         } else {
111                                                                 fputs(delimiter, stderr);
112                                                         }
113                                                         print_token_type(stderr, tok);
114                                                 }
115                                         } else {
116                                                 const token_type_t token = va_arg(ap, token_type_t);
117                                                 print_token_type(stderr, token);
118                                         }
119                                         break;
120                                 }
121
122                                 default:
123                                         panic("unknown format specifier");
124                         }
125                 } else {
126                         fputc(*f, stderr);
127                 }
128         }
129 }
130
131 void diagnosticf(const char *const fmt, ...)
132 {
133         va_list ap;
134         va_start(ap, fmt);
135         ++diagnostic_count;
136         diagnosticvf(fmt, ap);
137         va_end(ap);
138 }
139
140 void errorf(const source_position_t pos, const char *const fmt, ...)
141 {
142         va_list ap;
143         va_start(ap, fmt);
144         fprintf(stderr, "%s:%u: error: ", pos.input_name, pos.linenr);
145         ++error_count;
146         diagnosticvf(fmt, ap);
147         va_end(ap);
148         fputc('\n', stderr);
149
150 #ifdef ABORT_ON_ERROR
151         abort();
152 #endif
153 }
154
155 void warningf(const source_position_t pos, const char *const fmt, ...)
156 {
157         va_list ap;
158         va_start(ap, fmt);
159         if (warnings_are_errors) {
160                 fprintf(stderr, "%s:%u: error: ", pos.input_name, pos.linenr);
161                 ++error_count;
162         } else {
163                 fprintf(stderr, "%s:%u: warning: ", pos.input_name, pos.linenr);
164                 ++warning_count;
165         }
166         diagnosticvf(fmt, ap);
167         va_end(ap);
168         fputc('\n', stderr);
169 }