]>
Commit | Line | Data |
---|---|---|
5ff904cd | 1 | /* bad.c -- Implementation File (module.c template V1.0) |
77f9b92c | 2 | Copyright (C) 1995, 2002, 2003 Free Software Foundation, Inc. |
25d7717e | 3 | Contributed by James Craig Burley. |
5ff904cd JL |
4 | |
5 | This file is part of GNU Fortran. | |
6 | ||
7 | GNU Fortran is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU Fortran is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU Fortran; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
20 | 02111-1307, USA. | |
21 | ||
22 | Related Modules: | |
23 | None | |
24 | ||
25 | Description: | |
26 | Handles the displaying of diagnostic messages regarding the user's source | |
27 | files. | |
28 | ||
29 | Modifications: | |
30 | */ | |
31 | ||
32 | /* If there's a %E or %4 in the messages, set this to at least 5, | |
33 | for example. */ | |
34 | ||
35 | #define FFEBAD_MAX_ 6 | |
36 | ||
37 | /* Include files. */ | |
38 | ||
39 | #include "proj.h" | |
5ff904cd | 40 | #include "bad.h" |
15a40ced | 41 | #include "flags.h" |
5ff904cd | 42 | #include "com.h" |
15a40ced | 43 | #include "toplev.h" |
5ff904cd | 44 | #include "where.h" |
f1685b7c | 45 | #include "intl.h" |
47b69537 | 46 | #include "diagnostic.h" |
5ff904cd JL |
47 | |
48 | /* Externals defined here. */ | |
49 | ||
50 | bool ffebad_is_inhibited_ = FALSE; | |
51 | ||
52 | /* Simple definitions and enumerations. */ | |
53 | ||
54 | #define FFEBAD_LONG_MSGS_ 1 /* 0 to use short (or same) messages. */ | |
55 | ||
56 | /* Internal typedefs. */ | |
57 | ||
58 | ||
59 | /* Private include files. */ | |
60 | ||
61 | ||
62 | /* Internal structure definitions. */ | |
63 | ||
64 | struct _ffebad_message_ | |
65 | { | |
8b60264b KG |
66 | const ffebadSeverity severity; |
67 | const char *const message; | |
5ff904cd JL |
68 | }; |
69 | ||
70 | /* Static objects accessed by functions in this module. */ | |
71 | ||
8b60264b | 72 | static const struct _ffebad_message_ ffebad_messages_[] |
5ff904cd JL |
73 | = |
74 | { | |
f1685b7c | 75 | #define FFEBAD_MSG(kwd,sev,msgid) { sev, msgid }, |
5ff904cd | 76 | #if FFEBAD_LONG_MSGS_ == 0 |
f1685b7c ZW |
77 | #define LONG(m) |
78 | #define SHORT(m) m | |
5ff904cd | 79 | #else |
f1685b7c ZW |
80 | #define LONG(m) m |
81 | #define SHORT(m) | |
5ff904cd JL |
82 | #endif |
83 | #include "bad.def" | |
f1685b7c ZW |
84 | #undef FFEBAD_MSG |
85 | #undef LONG | |
86 | #undef SHORT | |
5ff904cd JL |
87 | }; |
88 | ||
89 | static struct | |
90 | { | |
91 | ffewhereLine line; | |
92 | ffewhereColumn col; | |
93 | ffebadIndex tag; | |
94 | } | |
95 | ||
96 | ffebad_here_[FFEBAD_MAX_]; | |
26f096f9 | 97 | static const char *ffebad_string_[FFEBAD_MAX_]; |
5ff904cd JL |
98 | static ffebadIndex ffebad_order_[FFEBAD_MAX_]; |
99 | static ffebad ffebad_errnum_; | |
100 | static ffebadSeverity ffebad_severity_; | |
26f096f9 | 101 | static const char *ffebad_message_; |
5ff904cd JL |
102 | static unsigned char ffebad_index_; |
103 | static ffebadIndex ffebad_places_; | |
104 | static bool ffebad_is_temp_inhibited_; /* Effective setting of | |
105 | _is_inhibited_ for this | |
106 | _start/_finish invocation. */ | |
107 | ||
108 | /* Static functions (internal). */ | |
109 | ||
26f096f9 | 110 | static int ffebad_bufputs_ (char buf[], int bufi, const char *s); |
5ff904cd JL |
111 | |
112 | /* Internal macros. */ | |
113 | ||
114 | #define ffebad_bufflush_(buf, bufi) \ | |
115 | (((buf)[bufi] = '\0'), fputs ((buf), stderr), 0) | |
116 | #define ffebad_bufputc_(buf, bufi, c) \ | |
117 | (((bufi) == ARRAY_SIZE (buf)) \ | |
118 | ? (ffebad_bufflush_ ((buf), (bufi)), ((buf)[0] = (c)), 1) \ | |
119 | : (((buf)[bufi] = (c)), (bufi) + 1)) | |
120 | \f | |
121 | ||
122 | static int | |
26f096f9 | 123 | ffebad_bufputs_ (char buf[], int bufi, const char *s) |
5ff904cd JL |
124 | { |
125 | for (; *s != '\0'; ++s) | |
126 | bufi = ffebad_bufputc_ (buf, bufi, *s); | |
127 | return bufi; | |
128 | } | |
129 | ||
130 | /* ffebad_init_0 -- Initialize | |
131 | ||
132 | ffebad_init_0(); */ | |
133 | ||
134 | void | |
77f9b92c | 135 | ffebad_init_0 (void) |
5ff904cd JL |
136 | { |
137 | assert (FFEBAD == ARRAY_SIZE (ffebad_messages_)); | |
138 | } | |
139 | ||
140 | ffebadSeverity | |
141 | ffebad_severity (ffebad errnum) | |
142 | { | |
143 | return ffebad_messages_[errnum].severity; | |
144 | } | |
145 | ||
146 | /* ffebad_start_ -- Start displaying an error message | |
147 | ||
148 | ffebad_start(FFEBAD_SOME_ERROR_CODE); | |
149 | ||
150 | Call ffebad_start to establish the message, ffebad_here and ffebad_string | |
151 | to send run-time data to it as necessary, then ffebad_finish when through | |
152 | to actually get it to print (to stderr). | |
153 | ||
154 | Note: ffebad_start(errnum) turns into ffebad_start_(FALSE,errnum). No | |
155 | outside caller should call ffebad_start_ directly (as indicated by the | |
156 | trailing underscore). | |
157 | ||
158 | Call ffebad_start to start a normal message, one that might be inhibited | |
159 | by the current state of statement guessing. Call ffebad_start_lex | |
160 | instead to start a message that is global to all statement guesses and | |
161 | happens only once for all guesses (i.e. the lexer). | |
162 | ||
163 | sev and message are overrides for the severity and messages when errnum | |
164 | is FFEBAD, meaning the caller didn't want to have to put a message in | |
165 | bad.def to produce a diagnostic. */ | |
166 | ||
167 | bool | |
168 | ffebad_start_ (bool lex_override, ffebad errnum, ffebadSeverity sev, | |
f1685b7c | 169 | const char *msgid) |
5ff904cd JL |
170 | { |
171 | unsigned char i; | |
172 | ||
173 | if (ffebad_is_inhibited_ && !lex_override) | |
174 | { | |
175 | ffebad_is_temp_inhibited_ = TRUE; | |
176 | return FALSE; | |
177 | } | |
178 | ||
179 | if (errnum != FFEBAD) | |
180 | { | |
181 | ffebad_severity_ = ffebad_messages_[errnum].severity; | |
f1685b7c | 182 | ffebad_message_ = gettext (ffebad_messages_[errnum].message); |
5ff904cd JL |
183 | } |
184 | else | |
185 | { | |
186 | ffebad_severity_ = sev; | |
f1685b7c | 187 | ffebad_message_ = gettext (msgid); |
5ff904cd JL |
188 | } |
189 | ||
516b69ff RH |
190 | switch (ffebad_severity_) |
191 | { /* Tell toplev.c about this message. */ | |
192 | case FFEBAD_severityINFORMATIONAL: | |
193 | case FFEBAD_severityTRIVIAL: | |
194 | if (inhibit_warnings) | |
195 | { /* User wants no warnings. */ | |
196 | ffebad_is_temp_inhibited_ = TRUE; | |
197 | return FALSE; | |
198 | } | |
199 | /* Fall through. */ | |
200 | case FFEBAD_severityWARNING: | |
201 | case FFEBAD_severityPECULIAR: | |
202 | case FFEBAD_severityPEDANTIC: | |
203 | if ((ffebad_severity_ != FFEBAD_severityPEDANTIC) | |
204 | || !flag_pedantic_errors) | |
205 | { | |
9804f5fb | 206 | if (!diagnostic_report_warnings_p ()) |
516b69ff RH |
207 | { /* User wants no warnings. */ |
208 | ffebad_is_temp_inhibited_ = TRUE; | |
209 | return FALSE; | |
210 | } | |
9804f5fb | 211 | diagnostic_kind_count (global_dc, DK_WARNING)++; |
516b69ff RH |
212 | break; |
213 | } | |
214 | /* Fall through (PEDANTIC && flag_pedantic_errors). */ | |
215 | case FFEBAD_severityFATAL: | |
216 | case FFEBAD_severityWEIRD: | |
217 | case FFEBAD_severitySEVERE: | |
218 | case FFEBAD_severityDISASTER: | |
9804f5fb | 219 | diagnostic_kind_count (global_dc, DK_ERROR)++; |
516b69ff | 220 | break; |
5ff904cd | 221 | |
516b69ff RH |
222 | default: |
223 | break; | |
224 | } | |
5ff904cd JL |
225 | |
226 | ffebad_is_temp_inhibited_ = FALSE; | |
227 | ffebad_errnum_ = errnum; | |
228 | ffebad_index_ = 0; | |
229 | ffebad_places_ = 0; | |
230 | for (i = 0; i < FFEBAD_MAX_; ++i) | |
231 | { | |
232 | ffebad_string_[i] = NULL; | |
233 | ffebad_here_[i].line = ffewhere_line_unknown (); | |
234 | ffebad_here_[i].col = ffewhere_column_unknown (); | |
235 | } | |
236 | ||
237 | return TRUE; | |
238 | } | |
239 | ||
240 | /* ffebad_here -- Establish source location of some diagnostic concern | |
241 | ||
242 | ffebad_here(ffebadIndex i,ffewhereLine line,ffewhereColumn col); | |
243 | ||
244 | Call ffebad_start to establish the message, ffebad_here and ffebad_string | |
245 | to send run-time data to it as necessary, then ffebad_finish when through | |
246 | to actually get it to print (to stderr). */ | |
247 | ||
248 | void | |
249 | ffebad_here (ffebadIndex index, ffewhereLine line, ffewhereColumn col) | |
250 | { | |
251 | ffewhereLineNumber line_num; | |
252 | ffewhereLineNumber ln; | |
253 | ffewhereColumnNumber col_num; | |
254 | ffewhereColumnNumber cn; | |
255 | ffebadIndex i; | |
256 | ffebadIndex j; | |
257 | ||
258 | if (ffebad_is_temp_inhibited_) | |
259 | return; | |
260 | ||
261 | assert (index < FFEBAD_MAX_); | |
262 | ffebad_here_[index].line = ffewhere_line_use (line); | |
263 | ffebad_here_[index].col = ffewhere_column_use (col); | |
264 | if (ffewhere_line_is_unknown (line) | |
265 | || ffewhere_column_is_unknown (col)) | |
266 | { | |
267 | ffebad_here_[index].tag = FFEBAD_MAX_; | |
268 | return; | |
269 | } | |
270 | ffebad_here_[index].tag = 0; /* For now, though it shouldn't matter. */ | |
271 | ||
272 | /* Sort the source line/col points into the order they occur in the source | |
273 | file. Deal with duplicates appropriately. */ | |
274 | ||
275 | line_num = ffewhere_line_number (line); | |
276 | col_num = ffewhere_column_number (col); | |
277 | ||
278 | /* Determine where in the ffebad_order_ array this new place should go. */ | |
279 | ||
280 | for (i = 0; i < ffebad_places_; ++i) | |
281 | { | |
282 | ln = ffewhere_line_number (ffebad_here_[ffebad_order_[i]].line); | |
283 | cn = ffewhere_column_number (ffebad_here_[ffebad_order_[i]].col); | |
284 | if (line_num < ln) | |
285 | break; | |
286 | if (line_num == ln) | |
287 | { | |
288 | if (col_num == cn) | |
289 | { | |
290 | ffebad_here_[index].tag = i; | |
291 | return; /* Shouldn't go in, has equivalent. */ | |
292 | } | |
293 | else if (col_num < cn) | |
294 | break; | |
295 | } | |
296 | } | |
297 | ||
298 | /* Before putting new place in ffebad_order_[i], first increment all tags | |
299 | that are i or greater. */ | |
300 | ||
301 | if (i != ffebad_places_) | |
302 | { | |
303 | for (j = 0; j < FFEBAD_MAX_; ++j) | |
304 | { | |
305 | if (ffebad_here_[j].tag >= i) | |
306 | ++ffebad_here_[j].tag; | |
307 | } | |
308 | } | |
309 | ||
310 | /* Then slide all ffebad_order_[] entries at and above i up one entry. */ | |
311 | ||
312 | for (j = ffebad_places_; j > i; --j) | |
313 | ffebad_order_[j] = ffebad_order_[j - 1]; | |
314 | ||
315 | /* Finally can put new info in ffebad_order_[i]. */ | |
316 | ||
317 | ffebad_order_[i] = index; | |
318 | ffebad_here_[index].tag = i; | |
319 | ++ffebad_places_; | |
320 | } | |
321 | ||
322 | /* Establish string for next index (always in order) of message | |
323 | ||
26f096f9 | 324 | ffebad_string(const char *string); |
5ff904cd JL |
325 | |
326 | Call ffebad_start to establish the message, ffebad_here and ffebad_string | |
327 | to send run-time data to it as necessary, then ffebad_finish when through | |
328 | to actually get it to print (to stderr). Note: don't trash the string | |
329 | until after calling ffebad_finish, since we just maintain a pointer to | |
330 | the argument passed in until then. */ | |
331 | ||
332 | void | |
26f096f9 | 333 | ffebad_string (const char *string) |
5ff904cd JL |
334 | { |
335 | if (ffebad_is_temp_inhibited_) | |
336 | return; | |
337 | ||
338 | assert (ffebad_index_ != FFEBAD_MAX_); | |
339 | ffebad_string_[ffebad_index_++] = string; | |
340 | } | |
341 | ||
342 | /* ffebad_finish -- Display error message with where & run-time info | |
343 | ||
344 | ffebad_finish(); | |
345 | ||
346 | Call ffebad_start to establish the message, ffebad_here and ffebad_string | |
347 | to send run-time data to it as necessary, then ffebad_finish when through | |
348 | to actually get it to print (to stderr). */ | |
349 | ||
350 | void | |
77f9b92c | 351 | ffebad_finish (void) |
5ff904cd JL |
352 | { |
353 | #define MAX_SPACES 132 | |
83182544 | 354 | static const char *const spaces |
5ff904cd JL |
355 | = "...>\ |
356 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
357 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
358 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
359 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
360 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
361 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
362 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
363 | \040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\ | |
364 | \040\040\040"; /* MAX_SPACES - 1 spaces. */ | |
365 | ffewhereLineNumber last_line_num; | |
366 | ffewhereLineNumber ln; | |
367 | ffewhereLineNumber rn; | |
368 | ffewhereColumnNumber last_col_num; | |
369 | ffewhereColumnNumber cn; | |
370 | ffewhereColumnNumber cnt; | |
371 | ffewhereLine l; | |
372 | ffebadIndex bi; | |
373 | unsigned short i; | |
374 | char pointer; | |
0816ebdd | 375 | unsigned char c; |
26f096f9 KG |
376 | unsigned const char *s; |
377 | const char *fn; | |
5ff904cd JL |
378 | static char buf[1024]; |
379 | int bufi; | |
380 | int index; | |
381 | ||
382 | if (ffebad_is_temp_inhibited_) | |
383 | return; | |
384 | ||
385 | switch (ffebad_severity_) | |
386 | { | |
387 | case FFEBAD_severityINFORMATIONAL: | |
f1685b7c | 388 | s = _("note:"); |
5ff904cd JL |
389 | break; |
390 | ||
391 | case FFEBAD_severityWARNING: | |
f1685b7c | 392 | s = _("warning:"); |
5ff904cd JL |
393 | break; |
394 | ||
395 | case FFEBAD_severitySEVERE: | |
f1685b7c | 396 | s = _("fatal:"); |
5ff904cd JL |
397 | break; |
398 | ||
399 | default: | |
400 | s = ""; | |
401 | break; | |
402 | } | |
403 | ||
404 | /* Display the annoying source references. */ | |
405 | ||
406 | last_line_num = 0; | |
407 | last_col_num = 0; | |
408 | ||
409 | for (bi = 0; bi < ffebad_places_; ++bi) | |
410 | { | |
411 | if (ffebad_places_ == 1) | |
412 | pointer = '^'; | |
413 | else | |
414 | pointer = '1' + bi; | |
415 | ||
416 | l = ffebad_here_[ffebad_order_[bi]].line; | |
417 | ln = ffewhere_line_number (l); | |
418 | rn = ffewhere_line_filelinenum (l); | |
419 | cn = ffewhere_column_number (ffebad_here_[ffebad_order_[bi]].col); | |
420 | fn = ffewhere_line_filename (l); | |
421 | if (ln != last_line_num) | |
422 | { | |
423 | if (bi != 0) | |
424 | fputc ('\n', stderr); | |
47b69537 | 425 | diagnostic_report_current_function (global_dc); |
5ff904cd | 426 | fprintf (stderr, |
5ff904cd JL |
427 | /* the trailing space on the <file>:<line>: line |
428 | fools emacs19 compilation mode into finding the | |
429 | report */ | |
430 | "%s:%" ffewhereLineNumber_f "u: %s\n %s\n %s%c", | |
431 | fn, rn, | |
5ff904cd JL |
432 | s, |
433 | ffewhere_line_content (l), | |
434 | &spaces[cn > MAX_SPACES ? 0 : MAX_SPACES - cn + 4], | |
435 | pointer); | |
436 | last_line_num = ln; | |
437 | last_col_num = cn; | |
f1685b7c | 438 | s = _("(continued):"); |
5ff904cd JL |
439 | } |
440 | else | |
441 | { | |
442 | cnt = cn - last_col_num; | |
443 | fprintf (stderr, | |
444 | "%s%c", &spaces[cnt > MAX_SPACES | |
445 | ? 0 : MAX_SPACES - cnt + 4], | |
446 | pointer); | |
447 | last_col_num = cn; | |
448 | } | |
449 | } | |
450 | if (ffebad_places_ == 0) | |
451 | { | |
452 | /* Didn't output "warning:" string, capitalize it for message. */ | |
f6bbde28 | 453 | if (s[0] != '\0') |
5ff904cd JL |
454 | { |
455 | char c; | |
456 | ||
92a438d1 | 457 | c = TOUPPER (s[0]); |
5ff904cd JL |
458 | fprintf (stderr, "%c%s ", c, &s[1]); |
459 | } | |
460 | else if (s[0] != '\0') | |
461 | fprintf (stderr, "%s ", s); | |
462 | } | |
463 | else | |
464 | fputc ('\n', stderr); | |
465 | ||
466 | /* Release the ffewhere info. */ | |
467 | ||
468 | for (bi = 0; bi < FFEBAD_MAX_; ++bi) | |
469 | { | |
470 | ffewhere_line_kill (ffebad_here_[bi].line); | |
471 | ffewhere_column_kill (ffebad_here_[bi].col); | |
472 | } | |
473 | ||
474 | /* Now display the message. */ | |
475 | ||
476 | bufi = 0; | |
477 | for (i = 0; (c = ffebad_message_[i]) != '\0'; ++i) | |
478 | { | |
479 | if (c == '%') | |
480 | { | |
481 | c = ffebad_message_[++i]; | |
0df6c2c7 | 482 | if (ISUPPER (c)) |
5ff904cd JL |
483 | { |
484 | index = c - 'A'; | |
485 | ||
486 | if ((index < 0) || (index >= FFEBAD_MAX_)) | |
487 | { | |
f1685b7c | 488 | bufi = ffebad_bufputs_ (buf, bufi, _("[REPORT BUG!!] %")); |
5ff904cd JL |
489 | bufi = ffebad_bufputc_ (buf, bufi, c); |
490 | } | |
491 | else | |
492 | { | |
493 | s = ffebad_string_[index]; | |
494 | if (s == NULL) | |
f1685b7c | 495 | bufi = ffebad_bufputs_ (buf, bufi, _("[REPORT BUG!!]")); |
5ff904cd JL |
496 | else |
497 | bufi = ffebad_bufputs_ (buf, bufi, s); | |
498 | } | |
499 | } | |
8b45da67 | 500 | else if (ISDIGIT (c)) |
5ff904cd JL |
501 | { |
502 | index = c - '0'; | |
503 | ||
504 | if ((index < 0) || (index >= FFEBAD_MAX_)) | |
505 | { | |
f1685b7c | 506 | bufi = ffebad_bufputs_ (buf, bufi, _("[REPORT BUG!!] %")); |
5ff904cd JL |
507 | bufi = ffebad_bufputc_ (buf, bufi, c); |
508 | } | |
509 | else | |
510 | { | |
511 | pointer = ffebad_here_[index].tag + '1'; | |
512 | if (pointer == FFEBAD_MAX_ + '1') | |
513 | pointer = '?'; | |
514 | else if (ffebad_places_ == 1) | |
515 | pointer = '^'; | |
516 | bufi = ffebad_bufputc_ (buf, bufi, '('); | |
517 | bufi = ffebad_bufputc_ (buf, bufi, pointer); | |
518 | bufi = ffebad_bufputc_ (buf, bufi, ')'); | |
519 | } | |
520 | } | |
521 | else if (c == '\0') | |
522 | break; | |
523 | else if (c == '%') | |
524 | bufi = ffebad_bufputc_ (buf, bufi, '%'); | |
525 | else | |
526 | { | |
f1685b7c | 527 | bufi = ffebad_bufputs_ (buf, bufi, _("[REPORT BUG!!]")); |
5ff904cd JL |
528 | bufi = ffebad_bufputc_ (buf, bufi, '%'); |
529 | bufi = ffebad_bufputc_ (buf, bufi, c); | |
530 | } | |
531 | } | |
532 | else | |
533 | bufi = ffebad_bufputc_ (buf, bufi, c); | |
534 | } | |
535 | bufi = ffebad_bufputc_ (buf, bufi, '\n'); | |
536 | bufi = ffebad_bufflush_ (buf, bufi); | |
537 | } |