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 7GNU CC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GNU CC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GNU CC; see the file COPYING. If not, write to 19the Free Software Foundation, 59 Temple Place - Suite 330, 20Boston, 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 33typedef char* cp_printer PROTO((tree, int)); 34extern 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. */ 39int cp_silent = 0; 40 41typedef void errorfn (); /* deliberately vague */ 42 43static 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 50static void 51cp_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 192void 193cp_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 211void 212cp_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 230void 231cp_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 249void 250cp_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 268void 269cp_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 279void 280cp_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 297void 298cp_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 316void 317cp_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 335void 336cp_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} 353