1/* Declaration for error-reporting function for Bison. 2 3 Copyright (C) 2000-2002, 2004-2006, 2009-2012 Free Software 4 Foundation, Inc. 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19/* Based on error.c and error.h, 20 written by David MacKenzie <djm@gnu.ai.mit.edu>. */ 21 22#include <config.h> 23#include "system.h" 24 25#include <stdarg.h> 26#include <progname.h> 27 28#include "complain.h" 29#include "files.h" 30#include "getargs.h" 31 32bool complaint_issued; 33static unsigned *indent_ptr = 0; 34 35 36 37/** Report an error message. 38 * 39 * \param loc the location, defaulting to the current file, 40 * or the program name. 41 * \param prefix put before the message (e.g., "warning"). 42 * \param message the error message, a printf format string. Iff it 43 * ends with ": ", then no trailing newline is printed, 44 * and the caller should print the remaining 45 * newline-terminated message to stderr. 46 * \param args the arguments of the format string. 47 */ 48static 49void 50error_message (location *loc, 51 const char *prefix, 52 const char *message, va_list args) 53{ 54 unsigned pos = 0; 55 56 if (loc) 57 pos += location_print (stderr, *loc); 58 else 59 pos += fprintf(stderr, "%s", current_file ? current_file : program_name); 60 pos += fprintf(stderr, ": "); 61 62 if (indent_ptr) 63 { 64 if (!*indent_ptr) 65 *indent_ptr = pos; 66 else if (*indent_ptr > pos) 67 fprintf (stderr, "%*s", *indent_ptr - pos, ""); 68 indent_ptr = 0; 69 } 70 71 if (prefix) 72 fprintf (stderr, "%s: ", prefix); 73 74 vfprintf (stderr, message, args); 75 { 76 size_t l = strlen (message); 77 if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ') 78 { 79 putc ('\n', stderr); 80 fflush (stderr); 81 if (loc && feature_flag & feature_caret) 82 location_caret (stderr, *loc); 83 } 84 } 85 fflush (stderr); 86} 87 88/** Wrap error_message() with varargs handling. */ 89#define ERROR_MESSAGE(Loc, Prefix, Message) \ 90{ \ 91 va_list args; \ 92 va_start (args, Message); \ 93 error_message (Loc, Prefix, Message, args); \ 94 va_end (args); \ 95} 96 97 98/*--------------------------------. 99| Report a warning, and proceed. | 100`--------------------------------*/ 101 102void 103set_warning_issued (void) 104{ 105 static bool warning_issued = false; 106 if (!warning_issued && (warnings_flag & warnings_error)) 107 { 108 fprintf (stderr, "%s: warnings being treated as errors\n", program_name); 109 complaint_issued = true; 110 } 111 warning_issued = true; 112} 113 114void 115warn_at (location loc, const char *message, ...) 116{ 117 if (!(warnings_flag & warnings_other)) 118 return; 119 set_warning_issued (); 120 ERROR_MESSAGE (&loc, _("warning"), message); 121} 122 123void 124warn_at_indent (location loc, unsigned *indent, 125 const char *message, ...) 126{ 127 if (!(warnings_flag & warnings_other)) 128 return; 129 set_warning_issued (); 130 indent_ptr = indent; 131 ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message); 132} 133 134void 135warn (const char *message, ...) 136{ 137 if (!(warnings_flag & warnings_other)) 138 return; 139 set_warning_issued (); 140 ERROR_MESSAGE (NULL, _("warning"), message); 141} 142 143 144/*-----------------------------------------------------------. 145| An error has occurred, but we can proceed, and die later. | 146`-----------------------------------------------------------*/ 147 148void 149complain_at (location loc, const char *message, ...) 150{ 151 ERROR_MESSAGE (&loc, _("error"), message); 152 complaint_issued = true; 153} 154 155void 156complain_at_indent (location loc, unsigned *indent, 157 const char *message, ...) 158{ 159 indent_ptr = indent; 160 ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message); 161 complaint_issued = true; 162} 163 164void 165complain (const char *message, ...) 166{ 167 ERROR_MESSAGE (NULL, _("error"), message); 168 complaint_issued = true; 169} 170 171 172/*--------------------------------------------------------------. 173| An incompatibility with POSIX Yacc: mapped either to warn* or | 174| complain* depending on yacc_flag. | 175`--------------------------------------------------------------*/ 176 177void 178yacc_at (location loc, const char *message, ...) 179{ 180 if (yacc_flag) 181 { 182 ERROR_MESSAGE (&loc, NULL, message); 183 complaint_issued = true; 184 } 185 else if (warnings_flag & warnings_yacc) 186 { 187 set_warning_issued (); 188 ERROR_MESSAGE (&loc, _("warning"), message); 189 } 190} 191 192void 193midrule_value_at (location loc, const char *message, ...) 194{ 195 if (!(warnings_flag & warnings_midrule_values)) 196 return; 197 set_warning_issued (); 198 ERROR_MESSAGE (&loc, _("warning"), message); 199} 200 201/*-------------------------------------------------. 202| A severe error has occurred, we cannot proceed. | 203`-------------------------------------------------*/ 204 205void 206fatal_at (location loc, const char *message, ...) 207{ 208 ERROR_MESSAGE (&loc, _("fatal error"), message); 209 exit (EXIT_FAILURE); 210} 211 212void 213fatal (const char *message, ...) 214{ 215 ERROR_MESSAGE (NULL, _("fatal error"), message); 216 exit (EXIT_FAILURE); 217} 218