1/*****************************************************************************/
2/* */
3/* error.c */
4/* */
5/* Error handling for the cc65 C compiler */
6/* */
7/* */
8/* */
9/* (C) 1998-2011, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <stdarg.h>
39
40/* common */
41#include "print.h"
42
43/* cc65 */
44#include "global.h"
45#include "input.h"
46#include "lineinfo.h"
47#include "scanner.h"
48#include "stmt.h"
49#include "error.h"
50
51
52
53/*****************************************************************************/
54/* Data */
55/*****************************************************************************/
56
57
58
59/* Count of errors/warnings */
60unsigned ErrorCount = 0;
61unsigned WarningCount = 0;
62
63/* Warning and error options */
64IntStack WarnEnable = INTSTACK(1); /* Enable warnings */
65IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */
66 /* Warn about: */
67IntStack WarnConstComparison= INTSTACK(1); /* - constant comparison results */
68IntStack WarnNoEffect = INTSTACK(1); /* - statements without an effect */
69IntStack WarnRemapZero = INTSTACK(1); /* - remapping character code zero */
70IntStack WarnStructParam = INTSTACK(1); /* - structs passed by val */
71IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
72IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
73IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
74IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */
75
76/* Map the name of a warning to the intstack that holds its state */
77typedef struct WarnMapEntry WarnMapEntry;
78struct WarnMapEntry {
79 IntStack* Stack;
80 const char* Name;
81};
82static WarnMapEntry WarnMap[] = {
83 /* Keep names sorted, even if it isn't used for now */
84 { &WarnConstComparison, "const-comparison" },
85 { &WarningsAreErrors, "error" },
86 { &WarnNoEffect, "no-effect" },
87 { &WarnRemapZero, "remap-zero" },
88 { &WarnStructParam, "struct-param" },
89 { &WarnUnknownPragma, "unknown-pragma" },
90 { &WarnUnusedLabel, "unused-label" },
91 { &WarnUnusedParam, "unused-param" },
92 { &WarnUnusedVar, "unused-var" },
93};
94
95
96
97/*****************************************************************************/
98/* Handling of fatal errors */
99/*****************************************************************************/
100
101
102
103void Fatal (const char* Format, ...)
104/* Print a message about a fatal error and die */
105{
106 va_list ap;
107
108 const char* FileName;
109 unsigned LineNum;
110 if (CurTok.LI) {
111 FileName = GetInputName (CurTok.LI);
112 LineNum = GetInputLine (CurTok.LI);
113 } else {
114 FileName = GetCurrentFile ();
115 LineNum = GetCurrentLine ();
116 }
117
118 fprintf (stderr, "%s(%u): Fatal: ", FileName, LineNum);
119
120 va_start (ap, Format);
121 vfprintf (stderr, Format, ap);
122 va_end (ap);
123 fprintf (stderr, "\n");
124
125 if (Line) {
126 Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
127 }
128 exit (EXIT_FAILURE);
129}
130
131
132
133void Internal (const char* Format, ...)
134/* Print a message about an internal compiler error and die. */
135{
136 va_list ap;
137
138 const char* FileName;
139 unsigned LineNum;
140 if (CurTok.LI) {
141 FileName = GetInputName (CurTok.LI);
142 LineNum = GetInputLine (CurTok.LI);
143 } else {
144 FileName = GetCurrentFile ();
145 LineNum = GetCurrentLine ();
146 }
147
148 fprintf (stderr, "%s(%u): Internal compiler error:\n",
149 FileName, LineNum);
150
151 va_start (ap, Format);
152 vfprintf (stderr, Format, ap);
153 va_end (ap);
154 fprintf (stderr, "\n");
155
156 if (Line) {
157 fprintf (stderr, "\nInput: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
158 }
159
160 /* Use abort to create a core dump */
161 abort ();
162}
163
164
165
166/*****************************************************************************/
167/* Handling of errors */
168/*****************************************************************************/
169
170
171
172static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
173/* Print an error message - internal function*/
174{
175 fprintf (stderr, "%s(%u): Error: ", Filename, LineNo);
176 vfprintf (stderr, Msg, ap);
177 fprintf (stderr, "\n");
178
179 if (Line) {
180 Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
181 }
182 ++ErrorCount;
183 if (ErrorCount > 10) {
184 Fatal ("Too many errors");
185 }
186}
187
188
189
190void Error (const char* Format, ...)
191/* Print an error message */
192{
193 va_list ap;
194 va_start (ap, Format);
195 IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
196 va_end (ap);
197}
198
199
200
201void LIError (const LineInfo* LI, const char* Format, ...)
202/* Print an error message with the line info given explicitly */
203{
204 va_list ap;
205 va_start (ap, Format);
206 IntError (GetInputName (LI), GetInputLine (LI), Format, ap);
207 va_end (ap);
208}
209
210
211
212void PPError (const char* Format, ...)
213/* Print an error message. For use within the preprocessor. */
214{
215 va_list ap;
216 va_start (ap, Format);
217 IntError (GetCurrentFile(), GetCurrentLine(), Format, ap);
218 va_end (ap);
219}
220
221
222
223/*****************************************************************************/
224/* Handling of warnings */
225/*****************************************************************************/
226
227
228
229static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
230/* Print warning message - internal function. */
231{
232 if (IS_Get (&WarningsAreErrors)) {
233
234 /* Treat the warning as an error */
235 IntError (Filename, LineNo, Msg, ap);
236
237 } else if (IS_Get (&WarnEnable)) {
238
239 fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo);
240 vfprintf (stderr, Msg, ap);
241 fprintf (stderr, "\n");
242
243 if (Line) {
244 Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line));
245 }
246 ++WarningCount;
247
248 }
249}
250
251
252
253void Warning (const char* Format, ...)
254/* Print warning message. */
255{
256 va_list ap;
257 va_start (ap, Format);
258 IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
259 va_end (ap);
260}
261
262
263
264void LIWarning (const LineInfo* LI, const char* Format, ...)
265/* Print a warning message with the line info given explicitly */
266{
267 va_list ap;
268 va_start (ap, Format);
269 IntWarning (GetInputName (LI), GetInputLine (LI), Format, ap);
270 va_end (ap);
271}
272
273
274
275void PPWarning (const char* Format, ...)
276/* Print warning message. For use within the preprocessor. */
277{
278 va_list ap;
279 va_start (ap, Format);
280 IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap);
281 va_end (ap);
282}
283
284
285
286IntStack* FindWarning (const char* Name)
287/* Search for a warning in the WarnMap table and return a pointer to the
288** intstack that holds its state. Return NULL if there is no such warning.
289*/
290{
291 unsigned I;
292
293 /* For now, do a linear search */
294 for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) {
295 if (strcmp (WarnMap[I].Name, Name) == 0) {
296 return WarnMap[I].Stack;
297 }
298 }
299 return 0;
300}
301
302
303
304void ListWarnings (FILE* F)
305/* Print a list of warning types/names to the given file */
306{
307 unsigned I;
308 for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) {
309 fprintf (F, "%s\n", WarnMap[I].Name);
310 }
311}
312
313
314
315/*****************************************************************************/
316/* Code */
317/*****************************************************************************/
318
319
320
321void ErrorReport (void)
322/* Report errors (called at end of compile) */
323{
324 Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount);
325}
326