Initial import from FreeBSD RELENG_4:
[games.git] / contrib / gcc / cp / errfn.c
1 /* Provide a call-back mechanism for handling error output.
2    Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc.
3    Contributed by Jason Merrill (jason@cygnus.com)
4
5    This file is part of GNU CC.
6
7 GNU CC 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 CC 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 CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21    
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "cp-tree.h"
26 #include "toplev.h"
27
28 /* cp_printer is the type of a function which converts an argument into
29    a string for digestion by printf.  The cp_printer function should deal
30    with all memory management; the functions in this file will not free
31    the char*s returned.  See error.c for an example use of this code.  */
32
33 typedef char* cp_printer PROTO((tree, int));
34 extern cp_printer * cp_printers[256];
35
36 /* Whether or not we should try to be quiet for errors and warnings; this is
37    used to avoid being too talkative about problems with tentative choices
38    when we're computing the conversion costs for a method call.  */
39 int cp_silent = 0;
40
41 typedef void errorfn ();        /* deliberately vague */
42
43 static void cp_thing PROTO ((errorfn *, int, const char *, va_list));
44
45 #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
46
47 /* This function supports only `%s', `%d', `%%', and the C++ print
48    codes.  */
49
50 static void
51 cp_thing (errfn, atarg1, format, ap)
52      errorfn *errfn;
53      int atarg1;
54      const char *format;
55      va_list ap;
56 {
57   static char *buf;
58   static long buflen;
59   int nargs = 0;
60   long len;
61   long offset;
62   const char *f;
63   tree atarg = 0;
64
65   len = strlen (format) + 1;
66   if (len > buflen)
67     {
68       buflen = len;
69       buf = xrealloc (buf, buflen);
70     }
71   offset = 0;
72
73   for (f = format; *f; ++f)
74     {
75       cp_printer * function;
76       int alternate;
77       int maybe_here;
78       
79       /* ignore text */
80       if (*f != '%')
81         {
82           buf[offset++] = *f;
83           continue;
84         }
85
86       ++f;
87
88       alternate = 0;
89       maybe_here = 0;
90
91       /* Check for '+' and '#' (in that order). */
92       if (*f == '+')
93         {
94           maybe_here = 1;
95           ++f;
96         }
97       if (*f == '#')
98         {
99           alternate = 1;
100           ++f;
101         }
102
103       /* no field width or precision */
104
105       function = cp_printers[(int)*f];
106
107       if (function || *f == 's')
108         {
109           char *p;
110           int plen;
111
112           if (*f == 's')
113             {
114               p = va_arg (ap, char *);
115               nargs++;
116             }
117           else
118             {
119               tree t = va_arg (ap, tree);
120               nargs++;
121
122               /* This indicates that ATARG comes from a different
123                  location than normal.  */
124               if (maybe_here && atarg1)
125                 atarg = t;
126
127               /* If atarg1 is set and this is the first argument, then
128                  set ATARG appropriately.  */
129               if (atarg1 && nargs == 1)
130                 atarg = t;
131
132               p = (*function) (t, alternate);
133             }
134
135           plen = strlen (p);
136           len += plen;
137           if (len > buflen)
138             {
139               buflen = len;
140               buf = xrealloc (buf, len);
141             }
142           strcpy (buf + offset, p);
143           offset += plen;
144         }
145       else if (*f == '%')
146         {
147           /* A `%%' has occurred in the input string. Replace it with
148              a `%' in the formatted message buf. */
149
150           if (++len > buflen)
151             {
152               buflen = len;
153               buf = xrealloc (buf, len);
154             }
155           buf[offset++] = '%';
156         }
157       else
158         {
159           if (*f != 'd')
160             abort ();
161           len += HOST_BITS_PER_INT / 2;
162           if (len > buflen)
163             {
164               buflen = len;
165               buf = xrealloc (buf, len);
166             }
167           sprintf (buf + offset, "%d", va_arg (ap, int));
168           nargs++;
169           offset += strlen (buf + offset);
170           /* With an ANSI C library one could write
171              out += sprintf (...); */
172         }
173     }
174   buf[offset] = '\0';
175
176   /* If ATARG1 is set, but we haven't extracted any arguments, then
177      extract one tree argument for ATARG.  */  
178   if (nargs == 0 && atarg1)
179     atarg = va_arg (ap, tree);
180
181   if (atarg)
182     {
183       char *file = cp_file_of (atarg);
184       int   line = cp_line_of (atarg);
185       (*errfn) (file, line, "%s", buf);
186     }
187   else
188     (*errfn) ("%s", buf);
189
190 }
191
192 void
193 cp_error VPROTO((const char *format, ...))
194 {
195 #ifndef ANSI_PROTOTYPES
196   char *format;
197 #endif
198   va_list ap;
199
200   VA_START (ap, format);
201
202 #ifndef ANSI_PROTOTYPES
203   format = va_arg (ap, char *);
204 #endif
205
206   if (! cp_silent)
207     cp_thing ((errorfn *) error, 0, format, ap);
208   va_end (ap);
209 }
210
211 void
212 cp_warning VPROTO((const char *format, ...))
213 {
214 #ifndef ANSI_PROTOTYPES
215   char *format;
216 #endif
217   va_list ap;
218
219   VA_START (ap, format);
220
221 #ifndef ANSI_PROTOTYPES
222   format = va_arg (ap, char *);
223 #endif
224
225   if (! cp_silent)
226     cp_thing ((errorfn *) warning, 0, format, ap);
227   va_end (ap);
228 }
229
230 void
231 cp_pedwarn VPROTO((const char *format, ...))
232 {
233 #ifndef ANSI_PROTOTYPES
234   char *format;
235 #endif
236   va_list ap;
237
238   VA_START (ap, format);
239
240 #ifndef ANSI_PROTOTYPES
241   format = va_arg (ap, char *);
242 #endif
243
244   if (! cp_silent)
245     cp_thing ((errorfn *) pedwarn, 0, format, ap);
246   va_end (ap);
247 }
248
249 void
250 cp_compiler_error VPROTO((const char *format, ...))
251 {
252 #ifndef ANSI_PROTOTYPES
253   char *format;
254 #endif
255   va_list ap;
256
257   VA_START (ap, format);
258
259 #ifndef ANSI_PROTOTYPES
260   format = va_arg (ap, char *);
261 #endif
262
263   if (! cp_silent)
264     cp_thing ((errorfn *) compiler_error, 0, format, ap);
265   va_end (ap);
266 }
267
268 void
269 cp_deprecated (msg)
270   const char *msg;
271 {
272   extern int warn_deprecated;
273   if (!warn_deprecated)
274     return;
275   cp_warning ("%s is deprecated.", msg);
276   cp_warning ("Please see the documentation for details.");
277 }
278
279 void
280 cp_sprintf VPROTO((const char *format, ...))
281 {
282 #ifndef ANSI_PROTOTYPES
283   char *format;
284 #endif
285   va_list ap;
286
287   VA_START (ap, format);
288
289 #ifndef ANSI_PROTOTYPES
290   format = va_arg (ap, char *);
291 #endif
292
293   cp_thing ((errorfn *) sprintf, 0, format, ap);
294   va_end (ap);
295 }
296
297 void
298 cp_error_at VPROTO((const char *format, ...))
299 {
300 #ifndef ANSI_PROTOTYPES
301   char *format;
302 #endif
303   va_list ap;
304
305   VA_START (ap, format);
306
307 #ifndef ANSI_PROTOTYPES
308   format = va_arg (ap, char *);
309 #endif
310
311   if (! cp_silent)
312     cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
313   va_end (ap);
314 }
315
316 void
317 cp_warning_at VPROTO((const char *format, ...))
318 {
319 #ifndef ANSI_PROTOTYPES
320   char *format;
321 #endif
322   va_list ap;
323
324   VA_START (ap, format);
325
326 #ifndef ANSI_PROTOTYPES
327   format = va_arg (ap, char *);
328 #endif
329
330   if (! cp_silent)
331     cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
332   va_end (ap);
333 }
334
335 void
336 cp_pedwarn_at VPROTO((const char *format, ...))
337 {
338 #ifndef ANSI_PROTOTYPES
339   char *format;
340 #endif
341   va_list ap;
342
343   VA_START (ap, format);
344
345 #ifndef ANSI_PROTOTYPES
346   format = va_arg (ap, char *);
347 #endif
348
349   if (! cp_silent)
350     cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, format, ap);
351   va_end (ap);
352 }