OSDN Git Service

* errfn.c (cp_thing): Handle the `%%' formatting sequence.
[pf3gnuchains/gcc-fork.git] / gcc / cp / errfn.c
1 /* Provide a call-back mechanism for handling error output.
2    Copyright (C) 1993, 1994, 1995 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 "toplev.h"
26
27 #ifdef __STDC__
28 #include <stdarg.h>
29 #else
30 #include <varargs.h>
31 #endif
32
33 /* cp_printer is the type of a function which converts an argument into
34    a string for digestion by printf.  The cp_printer function should deal
35    with all memory management; the functions in this file will not free
36    the char*s returned.  See error.c for an example use of this code.  */
37
38 typedef char* cp_printer PROTO((tree, int));
39 extern cp_printer * cp_printers[256];
40
41 /* Whether or not we should try to be quiet for errors and warnings; this is
42    used to avoid being too talkative about problems with tentative choices
43    when we're computing the conversion costs for a method call.  */
44 int cp_silent = 0;
45
46 typedef void errorfn ();        /* deliberately vague */
47
48 extern char* cp_file_of PROTO((tree));
49 extern int   cp_line_of PROTO((tree));
50
51 #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
52
53 /* This function supports only `%s', `%d', `%%', and the C++ print
54    codes.  */
55
56 #ifdef __STDC__
57 static void
58 cp_thing (errorfn *errfn, int atarg1, const char *format, va_list ap)
59 #else
60 static void
61 cp_thing (errfn, atarg1, format, ap)
62      errorfn *errfn;
63      int atarg1;
64      const char *format;
65      va_list ap;
66 #endif
67 {
68   static char *buf;
69   static long buflen;
70   int nargs = 0;
71   long len;
72   long offset;
73   const char *f;
74   tree atarg = 0;
75
76   len = strlen (format) + 1;
77   if (len > buflen)
78     {
79       buflen = len;
80       buf = xrealloc (buf, buflen);
81     }
82   offset = 0;
83
84   for (f = format; *f; ++f)
85     {
86       cp_printer * function;
87       int alternate;
88       int maybe_here;
89       
90       /* ignore text */
91       if (*f != '%')
92         {
93           buf[offset++] = *f;
94           continue;
95         }
96
97       ++f;
98
99       alternate = 0;
100       maybe_here = 0;
101
102       /* Check for '+' and '#' (in that order). */
103       if (*f == '+')
104         {
105           maybe_here = 1;
106           ++f;
107         }
108       if (*f == '#')
109         {
110           alternate = 1;
111           ++f;
112         }
113
114       /* no field width or precision */
115
116       function = cp_printers[(int)*f];
117
118       if (function || *f == 's')
119         {
120           char *p;
121           int plen;
122
123           if (*f == 's')
124             {
125               p = va_arg (ap, char *);
126               nargs++;
127             }
128           else
129             {
130               tree t = va_arg (ap, tree);
131               nargs++;
132
133               /* This indicates that ATARG comes from a different
134                  location than normal.  */
135               if (maybe_here && atarg1)
136                 atarg = t;
137
138               /* If atarg1 is set and this is the first argument, then
139                  set ATARG appropriately.  */
140               if (atarg1 && nargs == 1)
141                 atarg = t;
142
143               p = (*function) (t, alternate);
144             }
145
146           plen = strlen (p);
147           len += plen;
148           if (len > buflen)
149             {
150               buflen = len;
151               buf = xrealloc (buf, len);
152             }
153           strcpy (buf + offset, p);
154           offset += plen;
155         }
156       else if (*f == '%')
157         {
158           /* A `%%' has occurred in the input string.  Since the
159              string we produce here will be passed to vprintf we must
160              preserve both `%' characters.  */
161
162           len += 2;
163           if (len > buflen)
164             {
165               buflen = len;
166               buf = xrealloc (buf, len);
167             }
168           strcpy (buf + offset, "%%");
169           offset += 2;
170         }
171       else
172         {
173           if (*f != 'd')
174             abort ();
175           len += HOST_BITS_PER_INT / 2;
176           if (len > buflen)
177             {
178               buflen = len;
179               buf = xrealloc (buf, len);
180             }
181           sprintf (buf + offset, "%d", va_arg (ap, int));
182           nargs++;
183           offset += strlen (buf + offset);
184           /* With an ANSI C library one could write
185              out += sprintf (...); */
186         }
187     }
188   buf[offset] = '\0';
189
190   /* If ATARG1 is set, but we haven't extracted any arguments, then
191      extract one tree argument for ATARG.  */  
192   if (nargs == 0 && atarg1)
193     atarg = va_arg (ap, tree);
194
195   if (atarg)
196     {
197       char *file = cp_file_of (atarg);
198       int   line = cp_line_of (atarg);
199       (*errfn) (file, line, buf);
200     }
201   else
202     (*errfn) (buf);
203
204 }
205
206 #ifdef __STDC__
207 #define DECLARE(name) void name (const char *format, ...)
208 #define INIT va_start (ap, format)
209 #else
210 #define DECLARE(name) void name (format, va_alist) char *format; va_dcl
211 #define INIT va_start (ap)
212 #endif
213
214 DECLARE (cp_error)
215 {
216   va_list ap;
217   INIT;
218   if (! cp_silent)
219     cp_thing ((errorfn *) error, 0, format, ap);
220   va_end (ap);
221 }
222
223 DECLARE (cp_warning)
224 {
225   va_list ap;
226   INIT;
227   if (! cp_silent)
228     cp_thing ((errorfn *) warning, 0, format, ap);
229   va_end (ap);
230 }
231
232 DECLARE (cp_pedwarn)
233 {
234   va_list ap;
235   INIT;
236   if (! cp_silent)
237     cp_thing ((errorfn *) pedwarn, 0, format, ap);
238   va_end (ap);
239 }
240
241 DECLARE (cp_compiler_error)
242 {
243   extern errorfn compiler_error;
244   va_list ap;
245   INIT;
246   if (! cp_silent)
247     cp_thing (compiler_error, 0, format, ap);
248   va_end (ap);
249 }
250
251 DECLARE (cp_sprintf)
252 {
253   va_list ap;
254   INIT;
255   cp_thing ((errorfn *) sprintf, 0, format, ap);
256   va_end (ap);
257 }
258
259 DECLARE (cp_error_at)
260 {
261   va_list ap;
262   INIT;
263   if (! cp_silent)
264     cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
265   va_end (ap);
266 }
267
268 DECLARE (cp_warning_at)
269 {
270   va_list ap;
271   INIT;
272   if (! cp_silent)
273     cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
274   va_end (ap);
275 }
276
277 DECLARE (cp_pedwarn_at)
278 {
279   va_list ap;
280   INIT;
281   if (! cp_silent)
282     cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, format, ap);
283   va_end (ap);
284 }