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 (at) 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 32 bool complaint_issued; 33 static unsigned *indent_ptr = 0; 34 35 36 38 /** Report an error message. 39 * 40 * \param loc the location, defaulting to the current file, 41 * or the program name. 42 * \param prefix put before the message (e.g., "warning"). 43 * \param message the error message, a printf format string. Iff it 44 * ends with ": ", then no trailing newline is printed, 45 * and the caller should print the remaining 46 * newline-terminated message to stderr. 47 * \param args the arguments of the format string. 48 */ 49 static 50 void 51 error_message (location *loc, 52 const char *prefix, 53 const char *message, va_list args) 54 { 55 unsigned pos = 0; 56 57 if (loc) 58 pos += location_print (stderr, *loc); 59 else 60 pos += fprintf(stderr, "%s", current_file ? current_file : program_name); 61 pos += fprintf(stderr, ": "); 62 63 if (indent_ptr) 64 { 65 if (!*indent_ptr) 66 *indent_ptr = pos; 67 else if (*indent_ptr > pos) 68 fprintf (stderr, "%*s", *indent_ptr - pos, ""); 69 indent_ptr = 0; 70 } 71 72 if (prefix) 73 fprintf (stderr, "%s: ", prefix); 74 75 vfprintf (stderr, message, args); 76 { 77 size_t l = strlen (message); 78 if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ') 79 { 80 putc ('\n', stderr); 81 fflush (stderr); 82 if (loc && feature_flag & feature_caret) 83 location_caret (stderr, *loc); 84 } 85 } 86 fflush (stderr); 87 } 88 89 /** Wrap error_message() with varargs handling. */ 90 #define ERROR_MESSAGE(Loc, Prefix, Message) \ 91 { \ 92 va_list args; \ 93 va_start (args, Message); \ 94 error_message (Loc, Prefix, Message, args); \ 95 va_end (args); \ 96 } 97 98 99 /*--------------------------------. 100 | Report a warning, and proceed. | 101 `--------------------------------*/ 102 103 void 104 set_warning_issued (void) 105 { 106 static bool warning_issued = false; 107 if (!warning_issued && (warnings_flag & warnings_error)) 108 { 109 fprintf (stderr, "%s: warnings being treated as errors\n", program_name); 110 complaint_issued = true; 111 } 112 warning_issued = true; 113 } 114 115 void 116 warn_at (location loc, const char *message, ...) 117 { 118 if (!(warnings_flag & warnings_other)) 119 return; 120 set_warning_issued (); 121 ERROR_MESSAGE (&loc, _("warning"), message); 122 } 123 124 void 125 warn_at_indent (location loc, unsigned *indent, 126 const char *message, ...) 127 { 128 if (!(warnings_flag & warnings_other)) 129 return; 130 set_warning_issued (); 131 indent_ptr = indent; 132 ERROR_MESSAGE (&loc, *indent ? NULL : _("warning"), message); 133 } 134 135 void 136 warn (const char *message, ...) 137 { 138 if (!(warnings_flag & warnings_other)) 139 return; 140 set_warning_issued (); 141 ERROR_MESSAGE (NULL, _("warning"), message); 142 } 143 144 145 /*-----------------------------------------------------------. 146 | An error has occurred, but we can proceed, and die later. | 147 `-----------------------------------------------------------*/ 148 149 void 150 complain_at (location loc, const char *message, ...) 151 { 152 ERROR_MESSAGE (&loc, _("error"), message); 153 complaint_issued = true; 154 } 155 156 void 157 complain_at_indent (location loc, unsigned *indent, 158 const char *message, ...) 159 { 160 indent_ptr = indent; 161 ERROR_MESSAGE (&loc, *indent ? NULL : _("error"), message); 162 complaint_issued = true; 163 } 164 165 void 166 complain (const char *message, ...) 167 { 168 ERROR_MESSAGE (NULL, _("error"), message); 169 complaint_issued = true; 170 } 171 172 173 /*--------------------------------------------------------------. 174 | An incompatibility with POSIX Yacc: mapped either to warn* or | 175 | complain* depending on yacc_flag. | 176 `--------------------------------------------------------------*/ 177 178 void 179 yacc_at (location loc, const char *message, ...) 180 { 181 if (yacc_flag) 182 { 183 ERROR_MESSAGE (&loc, NULL, message); 184 complaint_issued = true; 185 } 186 else if (warnings_flag & warnings_yacc) 187 { 188 set_warning_issued (); 189 ERROR_MESSAGE (&loc, _("warning"), message); 190 } 191 } 192 193 void 194 midrule_value_at (location loc, const char *message, ...) 195 { 196 if (!(warnings_flag & warnings_midrule_values)) 197 return; 198 set_warning_issued (); 199 ERROR_MESSAGE (&loc, _("warning"), message); 200 } 201 202 /*-------------------------------------------------. 203 | A severe error has occurred, we cannot proceed. | 204 `-------------------------------------------------*/ 205 206 void 207 fatal_at (location loc, const char *message, ...) 208 { 209 ERROR_MESSAGE (&loc, _("fatal error"), message); 210 exit (EXIT_FAILURE); 211 } 212 213 void 214 fatal (const char *message, ...) 215 { 216 ERROR_MESSAGE (NULL, _("fatal error"), message); 217 exit (EXIT_FAILURE); 218 } 219