xref: /openbsd/gnu/gcc/libcpp/errors.c (revision 76d0caae)
1 /* Default error handlers for CPP Library.
2    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
3    2001, 2002, 2004 Free Software Foundation, Inc.
4    Written by Per Bothner, 1994.
5    Based on CCCP program by Paul Rubin, June 1986
6    Adapted to ANSI C, Richard Stallman, Jan 1987
7 
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 
22  In other words, you are welcome to use, share and improve this program.
23  You are forbidden to forbid anyone else to use, share and improve
24  what you give them.   Help stamp out software-hoarding!  */
25 
26 #include "config.h"
27 #include "system.h"
28 #include "cpplib.h"
29 #include "internal.h"
30 
31 static void print_location (cpp_reader *, source_location, unsigned int);
32 
33 /* Print the logical file location (LINE, COL) in preparation for a
34    diagnostic.  Outputs the #include chain if it has changed.  A line
35    of zero suppresses the include stack, and outputs the program name
36    instead.  */
37 static void
38 print_location (cpp_reader *pfile, source_location line, unsigned int col)
39 {
40   if (line == 0)
41     fprintf (stderr, "%s: ", progname);
42   else
43     {
44       const struct line_map *map;
45       unsigned int lin;
46 
47       map = linemap_lookup (pfile->line_table, line);
48       linemap_print_containing_files (pfile->line_table, map);
49 
50       lin = SOURCE_LINE (map, line);
51       if (col == 0)
52 	{
53 	  col = SOURCE_COLUMN (map, line);
54 	  if (col == 0)
55 	    col = 1;
56 	}
57 
58       if (lin == 0)
59 	fprintf (stderr, "%s:", map->to_file);
60       else if (CPP_OPTION (pfile, show_column) == 0)
61 	fprintf (stderr, "%s:%u:", map->to_file, lin);
62       else
63 	fprintf (stderr, "%s:%u:%u:", map->to_file, lin, col);
64 
65       fputc (' ', stderr);
66     }
67 }
68 
69 /* Set up for a diagnostic: print the file and line, bump the error
70    counter, etc.  SRC_LOC is the logical line number; zero means to print
71    at the location of the previously lexed token, which tends to be
72    the correct place by default.  The column number can be specified either
73    using COLUMN or (if COLUMN==0) extracting SOURCE_COLUMN from SRC_LOC.
74    (This may seem redundant, but is useful when pre-scanning (cleaning) a line,
75    when we haven't yet verified whether the current line_map has a
76    big enough max_column_hint.)
77 
78    Returns 0 if the error has been suppressed.  */
79 int
80 _cpp_begin_message (cpp_reader *pfile, int code,
81 		    source_location src_loc, unsigned int column)
82 {
83   int level = CPP_DL_EXTRACT (code);
84 
85   switch (level)
86     {
87     case CPP_DL_WARNING:
88     case CPP_DL_PEDWARN:
89       if (cpp_in_system_header (pfile)
90 	  && ! CPP_OPTION (pfile, warn_system_headers))
91 	return 0;
92       /* Fall through.  */
93 
94     case CPP_DL_WARNING_SYSHDR:
95       if (CPP_OPTION (pfile, warnings_are_errors)
96 	  || (level == CPP_DL_PEDWARN && CPP_OPTION (pfile, pedantic_errors)))
97 	{
98 	  if (CPP_OPTION (pfile, inhibit_errors))
99 	    return 0;
100 	  level = CPP_DL_ERROR;
101 	  pfile->errors++;
102 	}
103       else if (CPP_OPTION (pfile, inhibit_warnings))
104 	return 0;
105       break;
106 
107     case CPP_DL_ERROR:
108       if (CPP_OPTION (pfile, inhibit_errors))
109 	return 0;
110       /* ICEs cannot be inhibited.  */
111     case CPP_DL_ICE:
112       pfile->errors++;
113       break;
114     }
115 
116   print_location (pfile, src_loc, column);
117   if (CPP_DL_WARNING_P (level))
118     fputs (_("warning: "), stderr);
119   else if (level == CPP_DL_ICE)
120     fputs (_("internal error: "), stderr);
121   else
122     fputs (_("error: "), stderr);
123 
124   return 1;
125 }
126 
127 /* Don't remove the blank before do, as otherwise the exgettext
128    script will mistake this as a function definition */
129 #define v_message(msgid, ap) \
130  do { vfprintf (stderr, _(msgid), ap); putc ('\n', stderr); } while (0)
131 
132 /* Exported interface.  */
133 
134 /* Print an error at the location of the previously lexed token.  */
135 void
136 cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
137 {
138   source_location src_loc;
139   va_list ap;
140 
141   va_start (ap, msgid);
142 
143   if (CPP_OPTION (pfile, client_diagnostic))
144     pfile->cb.error (pfile, level, _(msgid), &ap);
145   else
146     {
147       if (CPP_OPTION (pfile, traditional))
148 	{
149 	  if (pfile->state.in_directive)
150 	    src_loc = pfile->directive_line;
151 	  else
152 	    src_loc = pfile->line_table->highest_line;
153 	}
154       else
155 	{
156 	  /* Find actual previous token.  */
157 	  cpp_token *t;
158 
159 	  if (pfile->cur_token != pfile->cur_run->base)
160 	    t = pfile->cur_token - 1;
161 	  else
162 	    {
163 	      if (pfile->cur_run->prev != NULL)
164 	        t = pfile->cur_run->prev->limit;
165 	      else
166 	        t = NULL;
167 	    }
168 	  /* Retrieve corresponding source location, unless we failed.  */
169 	  src_loc = t ? t->src_loc : 0;
170 	}
171 
172       if (_cpp_begin_message (pfile, level, src_loc, 0))
173 	v_message (msgid, ap);
174     }
175 
176   va_end (ap);
177 }
178 
179 /* Print an error at a specific location.  */
180 void
181 cpp_error_with_line (cpp_reader *pfile, int level,
182 		     source_location src_loc, unsigned int column,
183 		     const char *msgid, ...)
184 {
185   va_list ap;
186 
187   va_start (ap, msgid);
188 
189   if (_cpp_begin_message (pfile, level, src_loc, column))
190     v_message (msgid, ap);
191 
192   va_end (ap);
193 }
194 
195 void
196 cpp_errno (cpp_reader *pfile, int level, const char *msgid)
197 {
198   if (msgid[0] == '\0')
199     msgid = _("stdout");
200 
201   cpp_error (pfile, level, "%s: %s", msgid, xstrerror (errno));
202 }
203