OSDN Git Service

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