OSDN Git Service

2005-01-16 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / error.c
1 /* Handle errors.
2    Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation,
3    Inc.
4    Contributed by Andy Vaught & Niels Kristian Bech Jensen
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 /* Handle the inevitable errors.  A major catch here is that things
24    flagged as errors in one match subroutine can conceivably be legal
25    elsewhere.  This means that error messages are recorded and saved
26    for possible use later.  If a line does not match a legal
27    construction, then the saved error message is reported.  */
28
29 #include "config.h"
30 #include "system.h"
31 #include "flags.h"
32 #include "gfortran.h"
33
34 int gfc_suppress_error = 0;
35
36 static int terminal_width, buffer_flag, errors,
37   use_warning_buffer, warnings;
38
39 static char *error_ptr, *warning_ptr;
40
41 static gfc_error_buf error_buffer, warning_buffer;
42
43
44 /* Per-file error initialization.  */
45
46 void
47 gfc_error_init_1 (void)
48 {
49   terminal_width = gfc_terminal_width ();
50   errors = 0;
51   warnings = 0;
52   buffer_flag = 0;
53 }
54
55
56 /* Set the flag for buffering errors or not.  */
57
58 void
59 gfc_buffer_error (int flag)
60 {
61   buffer_flag = flag;
62 }
63
64
65 /* Add a single character to the error buffer or output depending on
66    buffer_flag.  */
67
68 static void
69 error_char (char c)
70 {
71   if (buffer_flag)
72     {
73       if (use_warning_buffer)
74         {
75           *warning_ptr++ = c;
76           if (warning_ptr - warning_buffer.message >= MAX_ERROR_MESSAGE)
77             gfc_internal_error ("error_char(): Warning buffer overflow");
78         }
79       else
80         {
81           *error_ptr++ = c;
82           if (error_ptr - error_buffer.message >= MAX_ERROR_MESSAGE)
83             gfc_internal_error ("error_char(): Error buffer overflow");
84         }
85     }
86   else
87     {
88       if (c != 0)
89         {
90           /* We build up complete lines before handing things
91              over to the library in order to speed up error printing.  */
92           static char line[MAX_ERROR_MESSAGE + 1];
93           static int index = 0;
94
95           line[index++] = c;
96           if (c == '\n' || index == MAX_ERROR_MESSAGE)
97             {
98               line[index] = '\0';
99               fputs (line, stderr);
100               index = 0;
101             }
102         }
103     }
104 }
105
106
107 /* Copy a string to wherever it needs to go.  */
108
109 static void
110 error_string (const char *p)
111 {
112   while (*p)
113     error_char (*p++);
114 }
115
116
117 /* Show the file, where it was included and the source line, give a
118    locus.  Calls error_printf() recursively, but the recursion is at
119    most one level deep.  */
120
121 static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1;
122
123 static void
124 show_locus (int offset, locus * loc)
125 {
126   gfc_linebuf *lb;
127   gfc_file *f;
128   char c, *p;
129   int i, m;
130
131   /* TODO: Either limit the total length and number of included files
132      displayed or add buffering of arbitrary number of characters in
133      error messages.  */
134
135   lb = loc->lb;
136   f = lb->file;
137   error_printf ("In file %s:%d\n", f->filename,
138 #ifdef USE_MAPPED_LOCATION
139                 LOCATION_LINE (lb->location)
140 #else
141                 lb->linenum
142 #endif
143                 );
144
145   for (;;)
146     {
147       i = f->inclusion_line;
148
149       f = f->included_by;
150       if (f == NULL) break;
151
152       error_printf ("    Included at %s:%d\n", f->filename, i);
153     }
154
155   /* Show the line itself, taking care not to print more than what can
156      show up on the terminal.  Tabs are converted to spaces.  */
157
158   p = lb->line + offset;
159   i = strlen (p);
160   if (i > terminal_width)
161     i = terminal_width - 1;
162
163   for (; i > 0; i--)
164     {
165       c = *p++;
166       if (c == '\t')
167         c = ' ';
168
169       if (ISPRINT (c))
170         error_char (c);
171       else
172         {
173           error_char ('\\');
174           error_char ('x');
175
176           m = ((c >> 4) & 0x0F) + '0';
177           if (m > '9')
178             m += 'A' - '9' - 1;
179           error_char (m);
180
181           m = (c & 0x0F) + '0';
182           if (m > '9')
183             m += 'A' - '9' - 1;
184           error_char (m);
185         }
186     }
187
188   error_char ('\n');
189 }
190
191
192 /* As part of printing an error, we show the source lines that caused
193    the problem.  We show at least one, possibly two loci.  If we're
194    showing two loci and they both refer to the same file and line, we
195    only print the line once.  */
196
197 static void
198 show_loci (locus * l1, locus * l2)
199 {
200   int offset, flag, i, m, c1, c2, cmax;
201
202   if (l1 == NULL)
203     {
204       error_printf ("<During initialization>\n");
205       return;
206     }
207
208   c1 = l1->nextc - l1->lb->line;
209   c2 = 0;
210   if (l2 == NULL)
211     goto separate;
212
213   c2 = l2->nextc - l2->lb->line;
214
215   if (c1 < c2)
216     m = c2 - c1;
217   else
218     m = c1 - c2;
219
220
221   if (l1->lb != l2->lb || m > terminal_width - 10)
222     goto separate;
223
224   offset = 0;
225   cmax = (c1 < c2) ? c2 : c1;
226   if (cmax > terminal_width - 5)
227     offset = cmax - terminal_width + 5;
228
229   if (offset < 0)
230     offset = 0;
231
232   c1 -= offset;
233   c2 -= offset;
234
235   show_locus (offset, l1);
236
237   /* Arrange that '1' and '2' will show up even if the two columns are equal.  */
238   for (i = 1; i <= cmax; i++)
239     {
240       flag = 0;
241       if (i == c1)
242         {
243           error_char ('1');
244           flag = 1;
245         }
246       if (i == c2)
247         {
248           error_char ('2');
249           flag = 1;
250         }
251       if (flag == 0)
252         error_char (' ');
253     }
254
255   error_char ('\n');
256
257   return;
258
259 separate:
260   offset = 0;
261
262   if (c1 > terminal_width - 5)
263     {
264       offset = c1 - 5;
265       if (offset < 0)
266         offset = 0;
267       c1 = c1 - offset;
268     }
269
270   show_locus (offset, l1);
271   for (i = 1; i < c1; i++)
272     error_char (' ');
273
274   error_char ('1');
275   error_char ('\n');
276
277   if (l2 != NULL)
278     {
279       offset = 0;
280
281       if (c2 > terminal_width - 20)
282         {
283           offset = c2 - 20;
284           if (offset < 0)
285             offset = 0;
286           c2 = c2 - offset;
287         }
288
289       show_locus (offset, l2);
290
291       for (i = 1; i < c2; i++)
292         error_char (' ');
293
294       error_char ('2');
295       error_char ('\n');
296     }
297 }
298
299
300 /* Workhorse for the error printing subroutines.  This subroutine is
301    inspired by g77's error handling and is similar to printf() with
302    the following %-codes:
303
304    %c Character, %d Integer, %s String, %% Percent
305    %L  Takes locus argument
306    %C  Current locus (no argument)
307
308    If a locus pointer is given, the actual source line is printed out
309    and the column is indicated.  Since we want the error message at
310    the bottom of any source file information, we must scan the
311    argument list twice.  A maximum of two locus arguments are
312    permitted.  */
313
314 #define IBUF_LEN 30
315 #define MAX_ARGS 10
316
317 static void
318 error_print (const char *type, const char *format0, va_list argp)
319 {
320   char c, *p, int_buf[IBUF_LEN], c_arg[MAX_ARGS], *cp_arg[MAX_ARGS];
321   int i, n, have_l1, i_arg[MAX_ARGS];
322   locus *l1, *l2, *loc;
323   const char *format;
324
325   l1 = l2 = loc = NULL;
326
327   have_l1 = 0;
328
329   n = 0;
330   format = format0;
331
332   while (*format)
333     {
334       c = *format++;
335       if (c == '%')
336         {
337           c = *format++;
338
339           switch (c)
340             {
341             case '%':
342               break;
343
344             case 'L':
345               loc = va_arg (argp, locus *);
346               /* Fall through */
347
348             case 'C':
349               if (c == 'C')
350                 loc = &gfc_current_locus;
351
352               if (have_l1)
353                 {
354                   l2 = loc;
355                 }
356               else
357                 {
358                   l1 = loc;
359                   have_l1 = 1;
360                 }
361               break;
362
363             case 'd':
364             case 'i':
365               i_arg[n++] = va_arg (argp, int);
366               break;
367
368             case 'c':
369               c_arg[n++] = va_arg (argp, int);
370               break;
371
372             case 's':
373               cp_arg[n++] = va_arg (argp, char *);
374               break;
375             }
376         }
377     }
378
379   /* Show the current loci if we have to.  */
380   if (have_l1)
381     show_loci (l1, l2);
382   error_string (type);
383   error_char (' ');
384
385   have_l1 = 0;
386   format = format0;
387   n = 0;
388
389   for (; *format; format++)
390     {
391       if (*format != '%')
392         {
393           error_char (*format);
394           continue;
395         }
396
397       format++;
398       switch (*format)
399         {
400         case '%':
401           error_char ('%');
402           break;
403
404         case 'c':
405           error_char (c_arg[n++]);
406           break;
407
408         case 's':
409           error_string (cp_arg[n++]);
410           break;
411
412         case 'i':
413         case 'd':
414           i = i_arg[n++];
415
416           if (i < 0)
417             {
418               i = -i;
419               error_char ('-');
420             }
421
422           p = int_buf + IBUF_LEN - 1;
423           *p-- = '\0';
424
425           if (i == 0)
426             *p-- = '0';
427
428           while (i > 0)
429             {
430               *p-- = i % 10 + '0';
431               i = i / 10;
432             }
433
434           error_string (p + 1);
435           break;
436
437         case 'C':               /* Current locus */
438         case 'L':               /* Specified locus */
439           error_string (have_l1 ? "(2)" : "(1)");
440           have_l1 = 1;
441           break;
442         }
443     }
444
445   error_char ('\n');
446 }
447
448
449 /* Wrapper for error_print().  */
450
451 static void
452 error_printf (const char *format, ...)
453 {
454   va_list argp;
455
456   va_start (argp, format);
457   error_print ("", format, argp);
458   va_end (argp);
459 }
460
461
462 /* Issue a warning.  */
463
464 void
465 gfc_warning (const char *format, ...)
466 {
467   va_list argp;
468
469   if (inhibit_warnings)
470     return;
471
472   warning_buffer.flag = 1;
473   warning_ptr = warning_buffer.message;
474   use_warning_buffer = 1;
475
476   va_start (argp, format);
477   if (buffer_flag == 0)
478     warnings++;
479   error_print ("Warning:", format, argp);
480   va_end (argp);
481
482   error_char ('\0');
483 }
484
485
486 /* Possibly issue a warning/error about use of a nonstandard (or deleted)
487    feature.  An error/warning will be issued if the currently selected
488    standard does not contain the requested bits.  Return FAILURE if
489    and error is generated.  */
490
491 try
492 gfc_notify_std (int std, const char *format, ...)
493 {
494   va_list argp;
495   bool warning;
496
497   warning = ((gfc_option.warn_std & std) != 0)
498             && !inhibit_warnings;
499   if ((gfc_option.allow_std & std) != 0
500       && !warning)
501     return SUCCESS;
502
503   if (gfc_suppress_error)
504     return warning ? SUCCESS : FAILURE;
505   
506   if (warning)
507     {
508       warning_buffer.flag = 1;
509       warning_ptr = warning_buffer.message;
510       use_warning_buffer = 1;
511     }
512   else
513     {
514       error_buffer.flag = 1;
515       error_ptr = error_buffer.message;
516       use_warning_buffer = 0;
517     }
518
519   if (buffer_flag == 0)
520     {
521       if (warning)
522         warnings++;
523       else
524         errors++;
525     }
526   va_start (argp, format);
527   if (warning)
528     error_print ("Warning:", format, argp);
529   else
530     error_print ("Error:", format, argp);
531   va_end (argp);
532
533   error_char ('\0');
534   return warning ? SUCCESS : FAILURE;
535 }
536
537
538 /* Immediate warning (i.e. do not buffer the warning).  */
539
540 void
541 gfc_warning_now (const char *format, ...)
542 {
543   va_list argp;
544   int i;
545
546   if (inhibit_warnings)
547     return;
548
549   i = buffer_flag;
550   buffer_flag = 0;
551   warnings++;
552
553   va_start (argp, format);
554   error_print ("Warning:", format, argp);
555   va_end (argp);
556
557   error_char ('\0');
558   buffer_flag = i;
559 }
560
561
562 /* Clear the warning flag.  */
563
564 void
565 gfc_clear_warning (void)
566 {
567   warning_buffer.flag = 0;
568 }
569
570
571 /* Check to see if any warnings have been saved.
572    If so, print the warning.  */
573
574 void
575 gfc_warning_check (void)
576 {
577   if (warning_buffer.flag)
578     {
579       warnings++;
580       fputs (warning_buffer.message, stderr);
581       warning_buffer.flag = 0;
582     }
583 }
584
585
586 /* Issue an error.  */
587
588 void
589 gfc_error (const char *format, ...)
590 {
591   va_list argp;
592
593   if (gfc_suppress_error)
594     return;
595
596   error_buffer.flag = 1;
597   error_ptr = error_buffer.message;
598   use_warning_buffer = 0;
599
600   va_start (argp, format);
601   if (buffer_flag == 0)
602     errors++;
603   error_print ("Error:", format, argp);
604   va_end (argp);
605
606   error_char ('\0');
607 }
608
609
610 /* Immediate error.  */
611
612 void
613 gfc_error_now (const char *format, ...)
614 {
615   va_list argp;
616   int i;
617
618   error_buffer.flag = 1;
619   error_ptr = error_buffer.message;
620
621   i = buffer_flag;
622   buffer_flag = 0;
623   errors++;
624
625   va_start (argp, format);
626   error_print ("Error:", format, argp);
627   va_end (argp);
628
629   error_char ('\0');
630   buffer_flag = i;
631 }
632
633
634 /* Fatal error, never returns.  */
635
636 void
637 gfc_fatal_error (const char *format, ...)
638 {
639   va_list argp;
640
641   buffer_flag = 0;
642
643   va_start (argp, format);
644   error_print ("Fatal Error:", format, argp);
645   va_end (argp);
646
647   exit (3);
648 }
649
650
651 /* This shouldn't happen... but sometimes does.  */
652
653 void
654 gfc_internal_error (const char *format, ...)
655 {
656   va_list argp;
657
658   buffer_flag = 0;
659
660   va_start (argp, format);
661
662   show_loci (&gfc_current_locus, NULL);
663   error_printf ("Internal Error at (1):");
664
665   error_print ("", format, argp);
666   va_end (argp);
667
668   exit (4);
669 }
670
671
672 /* Clear the error flag when we start to compile a source line.  */
673
674 void
675 gfc_clear_error (void)
676 {
677   error_buffer.flag = 0;
678 }
679
680
681 /* Check to see if any errors have been saved.
682    If so, print the error.  Returns the state of error_flag.  */
683
684 int
685 gfc_error_check (void)
686 {
687   int rc;
688
689   rc = error_buffer.flag;
690
691   if (error_buffer.flag)
692     {
693       errors++;
694       fputs (error_buffer.message, stderr);
695       error_buffer.flag = 0;
696     }
697
698   return rc;
699 }
700
701
702 /* Save the existing error state.  */
703
704 void
705 gfc_push_error (gfc_error_buf * err)
706 {
707   err->flag = error_buffer.flag;
708   if (error_buffer.flag)
709     strcpy (err->message, error_buffer.message);
710
711   error_buffer.flag = 0;
712 }
713
714
715 /* Restore a previous pushed error state.  */
716
717 void
718 gfc_pop_error (gfc_error_buf * err)
719 {
720   error_buffer.flag = err->flag;
721   if (error_buffer.flag)
722     strcpy (error_buffer.message, err->message);
723 }
724
725
726 /* Debug wrapper for printf.  */
727
728 void
729 gfc_status (const char *format, ...)
730 {
731   va_list argp;
732
733   va_start (argp, format);
734
735   vprintf (format, argp);
736
737   va_end (argp);
738 }
739
740
741 /* Subroutine for outputting a single char so that we don't have to go
742    around creating a lot of 1-character strings.  */
743
744 void
745 gfc_status_char (char c)
746 {
747   putchar (c);
748 }
749
750
751 /* Report the number of warnings and errors that occurred to the caller.  */
752
753 void
754 gfc_get_errors (int *w, int *e)
755 {
756   if (w != NULL)
757     *w = warnings;
758   if (e != NULL)
759     *e = errors;
760 }