Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Raduly, Csaba | |
12 | * | |
13 | ******************************************************************************/ | |
970ed795 EL |
14 | #include "error.h" |
15 | #include "CompilerError.hh" | |
16 | #include "../common/memory.h" | |
17 | #include "../common/path.h" | |
18 | #include "main.hh" | |
19 | #include "Setting.hh" | |
20 | ||
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <stdarg.h> | |
24 | #include <errno.h> | |
25 | #ifndef MINGW | |
26 | # include <sys/wait.h> | |
27 | #endif | |
28 | ||
29 | unsigned verb_level=0x0007; /* default value */ | |
30 | ||
31 | const char *argv0; /* the programname :) */ | |
32 | ||
33 | void fatal_error(const char *filename, int lineno, const char *fmt, ...) | |
34 | { | |
35 | va_list parameters; | |
36 | #ifdef FATAL_DEBUG | |
37 | va_start(parameters, fmt); | |
38 | Common::Location loc(filename, lineno); | |
39 | Common::Error_Context::report_error(&loc, fmt, parameters); | |
40 | va_end(parameters); | |
41 | #else | |
42 | fprintf(stderr, "FATAL ERROR: %s: In line %d of %s: ", | |
43 | argv0, lineno, filename); | |
44 | va_start(parameters, fmt); | |
45 | vfprintf(stderr, fmt, parameters); | |
46 | va_end(parameters); | |
47 | putc('\n', stderr); | |
48 | #endif | |
49 | fflush(stderr); | |
50 | abort(); | |
51 | } | |
52 | ||
53 | void ERROR(const char *fmt, ...) | |
54 | { | |
55 | fprintf(stderr, "%s: error: ", argv0); | |
56 | va_list parameters; | |
57 | va_start(parameters, fmt); | |
58 | vfprintf(stderr, fmt, parameters); | |
59 | va_end(parameters); | |
60 | putc('\n', stderr); | |
61 | fflush(stderr); | |
62 | Common::Error_Context::increment_error_count(); | |
63 | } | |
64 | ||
65 | void WARNING(const char *fmt, ...) | |
66 | { | |
67 | if(!(verb_level & 2)) return; | |
68 | fprintf(stderr, "%s: warning: ", argv0); | |
69 | va_list parameters; | |
70 | va_start(parameters, fmt); | |
71 | vfprintf(stderr, fmt, parameters); | |
72 | va_end(parameters); | |
73 | putc('\n', stderr); | |
74 | fflush(stderr); | |
75 | Common::Error_Context::increment_warning_count(); | |
76 | } | |
77 | ||
78 | void NOTSUPP(const char *fmt, ...) | |
79 | { | |
80 | if(!(verb_level & 1)) return; | |
81 | fprintf(stderr, "%s: warning: not supported: ", argv0); | |
82 | va_list parameters; | |
83 | va_start(parameters, fmt); | |
84 | vfprintf(stderr, fmt, parameters); | |
85 | va_end(parameters); | |
86 | putc('\n', stderr); | |
87 | fflush(stderr); | |
88 | Common::Error_Context::increment_warning_count(); | |
89 | } | |
90 | ||
91 | void NOTIFY(const char *fmt, ...) | |
92 | { | |
93 | if(!(verb_level & 4)) return; | |
94 | fprintf(stderr, "Notify: "); | |
95 | va_list parameters; | |
96 | va_start(parameters, fmt); | |
97 | vfprintf(stderr, fmt, parameters); | |
98 | va_end(parameters); | |
99 | putc('\n', stderr); | |
100 | fflush(stderr); | |
101 | } | |
102 | ||
103 | void DEBUG(unsigned level, const char *fmt, ...) | |
104 | { | |
105 | if((level>7?7:level)>((verb_level>>3)&0x07)) return; | |
106 | fprintf(stderr, "%*sDebug: ", level, ""); | |
107 | va_list parameters; | |
108 | va_start(parameters, fmt); | |
109 | vfprintf(stderr, fmt, parameters); | |
110 | va_end(parameters); | |
111 | putc('\n', stderr); | |
112 | fflush(stderr); | |
113 | } | |
114 | ||
115 | unsigned int get_error_count(void) | |
116 | { | |
117 | return Common::Error_Context::get_error_count(); | |
118 | } | |
119 | ||
120 | unsigned int get_warning_count(void) | |
121 | { | |
122 | return Common::Error_Context::get_warning_count(); | |
123 | } | |
124 | ||
125 | void path_error(const char *fmt, ...) | |
126 | { | |
127 | va_list ap; | |
128 | va_start(ap, fmt); | |
129 | char *err_msg = mprintf_va_list(fmt, ap); | |
130 | va_end(ap); | |
131 | ERROR("%s", err_msg); | |
132 | Free(err_msg); | |
133 | } | |
134 | ||
135 | namespace Common { | |
136 | ||
137 | unsigned int Error_Context::error_count = 0, Error_Context::warning_count = 0; | |
138 | unsigned int Error_Context::max_errors = (unsigned)-1; | |
139 | ||
140 | bool Error_Context::chain_printed = false; | |
141 | ||
142 | Error_Context *Error_Context::head = 0, *Error_Context::tail = 0; | |
143 | ||
144 | void Error_Context::print_context(FILE *fp) | |
145 | { | |
146 | int level = 0; | |
147 | for (Error_Context *ptr = head; ptr; ptr = ptr->next) { | |
148 | if (ptr->is_restorer) FATAL_ERROR("Error_Context::print()"); | |
149 | else if (!ptr->str) continue; | |
150 | else if (!ptr->is_printed) { | |
151 | for (int i = 0; i < level; i++) putc(' ', fp); | |
152 | if (ptr->location) ptr->location->print_location(fp); | |
153 | if (gcc_compat) fputs("note: ", fp); // CDT ignores "note" | |
154 | fputs(ptr->str, fp); | |
155 | fputs(":\n", fp); | |
156 | ptr->is_printed = true; | |
157 | } | |
158 | level++; | |
159 | } | |
160 | for (int i = 0; i < level; i++) putc(' ', fp); | |
161 | chain_printed = true; | |
162 | } | |
163 | ||
164 | Error_Context::Error_Context(size_t n_keep) | |
165 | : prev(0), next(0), location(0), str(0), is_printed(false), | |
166 | is_restorer(true), outer_printed(false) | |
167 | { | |
168 | Error_Context *begin = head; | |
169 | for (size_t i = 0; i < n_keep; i++) { | |
170 | if (!begin) break; | |
171 | begin = begin->next; | |
172 | } | |
173 | if (begin == head) { | |
174 | // complete backup | |
175 | next = head; | |
176 | head = 0; | |
177 | prev = tail; | |
178 | tail = 0; | |
179 | } else { | |
180 | // partial backup (only elements before begin are kept) | |
181 | next = begin; | |
182 | if (begin) { | |
183 | prev = tail; | |
184 | tail = begin->prev; | |
185 | tail->next = 0; | |
186 | begin->prev = 0; | |
187 | } else prev = 0; | |
188 | } | |
189 | outer_printed = chain_printed; | |
190 | chain_printed = false; | |
191 | } | |
192 | ||
193 | Error_Context::Error_Context(const Location *p_location) | |
194 | : prev(0), next(0), location(p_location), str(0), is_printed(false), | |
195 | is_restorer(false), outer_printed(false) | |
196 | { | |
197 | if (!head) head = this; | |
198 | if (tail) tail->next = this; | |
199 | prev = tail; | |
200 | next = 0; | |
201 | tail = this; | |
202 | } | |
203 | ||
204 | Error_Context::Error_Context(const Location *p_location, | |
205 | const char *p_fmt, ...) | |
206 | : prev(0), next(0), location(p_location), str(0), is_printed(false), | |
207 | is_restorer(false), outer_printed(false) | |
208 | { | |
209 | va_list args; | |
210 | va_start(args, p_fmt); | |
211 | str = mprintf_va_list(p_fmt, args); | |
212 | va_end(args); | |
213 | ||
214 | if (!head) head = this; | |
215 | if (tail) tail->next = this; | |
216 | prev = tail; | |
217 | next = 0; | |
218 | tail = this; | |
219 | } | |
220 | ||
221 | Error_Context::~Error_Context() | |
222 | { | |
223 | if (is_restorer) { | |
224 | if (chain_printed) { | |
225 | for (Error_Context *ptr = next; ptr; ptr = ptr->next) | |
226 | ptr->is_printed = false; | |
227 | } else chain_printed = outer_printed; | |
228 | if (head) { | |
229 | // partial restoration | |
230 | if (next) { | |
231 | tail->next = next; | |
232 | next->prev = tail; | |
233 | tail = prev; | |
234 | } | |
235 | } else { | |
236 | // full restoration | |
237 | head = next; | |
238 | tail = prev; | |
239 | } | |
240 | } else { | |
241 | Free(str); | |
242 | if (tail != this) FATAL_ERROR("Error_Context::~Error_Context()"); | |
243 | if (prev) prev->next = 0; | |
244 | else head = 0; | |
245 | tail = prev; | |
246 | } | |
247 | } | |
248 | ||
249 | void Error_Context::set_message(const char *p_fmt, ...) | |
250 | { | |
251 | if (is_restorer) FATAL_ERROR("Error_Context::set_message()"); | |
252 | Free(str); | |
253 | va_list args; | |
254 | va_start(args, p_fmt); | |
255 | str = mprintf_va_list(p_fmt, args); | |
256 | va_end(args); | |
257 | is_printed = false; | |
258 | } | |
259 | ||
260 | void Error_Context::report_error(const Location *loc, const char *fmt, | |
261 | va_list args) | |
262 | { | |
263 | if (!suppress_context) print_context(stderr); | |
264 | Location my_location; | |
265 | if (tail != 0 && loc && loc->get_filename() == 0) { | |
266 | // borrow location information from the innermost context | |
267 | my_location.set_location( *(tail->location) ); | |
268 | loc = &my_location; | |
269 | } | |
270 | if (loc) loc->print_location(stderr); | |
271 | fputs("error: ", stderr); | |
272 | vfprintf(stderr, fmt, args); | |
273 | putc('\n', stderr); | |
274 | fflush(stderr); | |
275 | increment_error_count(); | |
276 | } | |
277 | ||
278 | void Error_Context::report_warning(const Location *loc, const char *fmt, | |
279 | va_list args) | |
280 | { | |
281 | if(!(verb_level & 2)) return; | |
282 | if (!suppress_context) print_context(stderr); | |
283 | if (loc) loc->print_location(stderr); | |
284 | fputs("warning: ", stderr); | |
285 | vfprintf(stderr, fmt, args); | |
286 | putc('\n', stderr); | |
287 | fflush(stderr); | |
288 | increment_warning_count(); | |
289 | } | |
290 | ||
291 | void Error_Context::report_note(const Location *loc, const char *fmt, | |
292 | va_list args) | |
293 | { | |
294 | if (!suppress_context) print_context(stderr); | |
295 | if (loc) loc->print_location(stderr); | |
296 | fputs("note: ", stderr); | |
297 | vfprintf(stderr, fmt, args); | |
298 | putc('\n', stderr); | |
299 | fflush(stderr); | |
300 | } | |
301 | ||
302 | void Error_Context::increment_error_count() | |
303 | { | |
304 | if (++error_count >= max_errors) { | |
305 | fputs("Maximum number of errors reached, aborting.\n", stderr); | |
306 | fflush(stderr); | |
af710487 | 307 | exit(EXIT_FAILURE); |
970ed795 EL |
308 | } |
309 | } | |
310 | ||
311 | void Error_Context::increment_warning_count() | |
312 | { | |
313 | warning_count++; | |
314 | } | |
315 | ||
316 | void Error_Context::print_error_statistics() | |
317 | { | |
318 | if (error_count == 0) { | |
319 | if (warning_count == 0) NOTIFY("No errors or warnings were detected."); | |
320 | else NOTIFY("No errors and %u warning%s were detected.", | |
321 | warning_count, warning_count > 1 ? "s" : ""); | |
322 | } else { | |
323 | if (warning_count == 0) NOTIFY("%u error%s and no warnings were " | |
324 | "detected.", error_count, error_count > 1 ? "s" : ""); | |
325 | else NOTIFY("%u error%s and %u warning%s were detected.", | |
326 | error_count, error_count > 1 ? "s" : "", | |
327 | warning_count, warning_count > 1 ? "s" : ""); | |
328 | } | |
329 | } | |
330 | ||
331 | } // namespace Common |