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