]> git.sur5r.net Git - cc65/blob - src/ca65/error.c
More work on high level language debug symbols. They are now passed correctly
[cc65] / src / ca65 / error.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  error.c                                  */
4 /*                                                                           */
5 /*                Error handling for the ca65 macroassembler                 */
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 "strbuf.h"
42
43 /* ca65 */
44 #include "error.h"
45 #include "filetab.h"
46 #include "lineinfo.h"
47 #include "nexttok.h"
48
49
50
51 /*****************************************************************************/
52 /*                                   Data                                    */
53 /*****************************************************************************/
54
55
56
57 /* Warning level */
58 unsigned WarnLevel      = 1;
59
60 /* Statistics */
61 unsigned ErrorCount     = 0;
62 unsigned WarningCount   = 0;
63
64
65
66 /*****************************************************************************/
67 /*                             Helper functions                              */
68 /*****************************************************************************/
69
70
71
72 static void VPrintMsg (const FilePos* Pos, const char* Desc,
73                        const char* Format, va_list ap)
74 /* Format and output an error/warning message. */
75 {
76     StrBuf S = STATIC_STRBUF_INITIALIZER;
77
78     /* Format the actual message */
79     StrBuf Msg = STATIC_STRBUF_INITIALIZER;
80     SB_VPrintf (&Msg, Format, ap);
81     SB_Terminate (&Msg);
82
83     /* Format the message header */
84     SB_Printf (&S, "%s(%u): %s: ",
85                SB_GetConstBuf (GetFileName (Pos->Name)),
86                Pos->Line,
87                Desc);
88
89     /* Append the message to the message header */
90     SB_Append (&S, &Msg);
91
92     /* Delete the formatted message */
93     SB_Done (&Msg);
94
95     /* Add a new line and terminate the generated full message */
96     SB_AppendChar (&S, '\n');
97     SB_Terminate (&S);
98
99     /* Output the full message */
100     fputs (SB_GetConstBuf (&S), stderr);
101
102     /* Delete the buffer for the full message */
103     SB_Done (&S);
104 }
105
106
107
108 static void PrintMsg (const FilePos* Pos, const char* Desc,
109                       const char* Format, ...)
110 /* Format and output an error/warning message. */
111 {
112     va_list ap;
113     va_start (ap, Format);
114     VPrintMsg (Pos, Desc, Format, ap);
115     va_end (ap);
116 }
117
118
119
120 static void AddNotifications (const Collection* LineInfos)
121 /* Output additional notifications for an error or warning */
122 {
123     unsigned I;
124     unsigned Skipped;
125
126     /* The basic line info is always in slot zero. It has been used to
127      * output the actual error or warning. The following slots may contain
128      * more information. Check them and print additional notifications if
129      * they're present, but limit the number to a reasonable value.
130      */
131     unsigned MaxCount = CollCount (LineInfos);
132     if (MaxCount > 6) {
133         MaxCount = 6;
134     }
135     Skipped = CollCount (LineInfos) - MaxCount;
136     for (I = 1; I < MaxCount; ++I) {
137         /* Get next line info */
138         const LineInfo* LI = CollConstAt (LineInfos, I);
139         /* Check the type and output an appropriate note */
140         unsigned Type = GetLineInfoType (LI);
141         if (Type == LI_TYPE_EXT) {
142             PrintMsg (GetSourcePos (LI), "Note",
143                       "Assembler code generated from this line");
144         } else if (Type == LI_TYPE_MACRO) {
145             PrintMsg (GetSourcePos (LI), "Note",
146                       "Macro was defined here");
147         }
148     }
149
150     /* Add a note if we have more stuff that we won't output */
151     if (Skipped > 0) {
152         const LineInfo* LI = CollConstAt (LineInfos, 0);
153         PrintMsg (GetSourcePos (LI), "Note",
154                   "Dropping %u additional line infos", Skipped);
155     }
156 }
157
158
159
160 /*****************************************************************************/
161 /*                                 Warnings                                  */
162 /*****************************************************************************/
163
164
165
166 static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
167 /* Print warning message. */
168 {
169     /* The first entry in the collection is that of the actual source pos */
170     const LineInfo* LI = CollConstAt (LineInfos, 0);
171
172     /* Output a warning for this position */
173     VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
174
175     /* Add additional notifications if necessary */
176     AddNotifications (LineInfos);
177
178     /* Count warnings */
179     ++WarningCount;
180 }
181
182
183
184 void Warning (unsigned Level, const char* Format, ...)
185 /* Print warning message. */
186 {
187     if (Level <= WarnLevel) {
188
189         va_list ap;
190         Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
191
192         /* Get line infos for the current position */
193         GetFullLineInfo (&LineInfos);
194
195         /* Output the message */
196         va_start (ap, Format);
197         WarningMsg (&LineInfos, Format, ap);
198         va_end (ap);
199
200         /* Free the line info list */
201         ReleaseFullLineInfo (&LineInfos);
202         DoneCollection (&LineInfos);
203     }
204 }
205
206
207
208 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
209 /* Print warning message giving an explicit file and position. */
210 {
211     if (Level <= WarnLevel) {
212         va_list ap;
213         va_start (ap, Format);
214         VPrintMsg (Pos, "Warning", Format, ap);
215         va_end (ap);
216
217         /* Count warnings */
218         ++WarningCount;
219     }
220 }
221
222
223
224 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
225 /* Print warning message using the given line infos */
226 {
227     if (Level <= WarnLevel) {
228         /* Output the message */
229         va_list ap;
230         va_start (ap, Format);
231         WarningMsg (LineInfos, Format, ap);
232         va_end (ap);
233     }
234 }
235
236
237
238 /*****************************************************************************/
239 /*                                  Errors                                   */
240 /*****************************************************************************/
241
242
243
244 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
245 /* Print an error message */
246 {
247     /* The first entry in the collection is that of the actual source pos */
248     const LineInfo* LI = CollConstAt (LineInfos, 0);
249
250     /* Output an error for this position */
251     VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
252
253     /* Add additional notifications if necessary */
254     AddNotifications (LineInfos);
255
256     /* Count errors */
257     ++ErrorCount;
258 }
259
260
261
262 void Error (const char* Format, ...)
263 /* Print an error message */
264 {
265     va_list ap;
266     Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
267
268     /* Get line infos for the current position */
269     GetFullLineInfo (&LineInfos);
270
271     /* Output the message */
272     va_start (ap, Format);
273     ErrorMsg (&LineInfos, Format, ap);
274     va_end (ap);
275
276     /* Free the line info list */
277     ReleaseFullLineInfo (&LineInfos);
278     DoneCollection (&LineInfos);
279 }
280
281
282
283 void PError (const FilePos* Pos, const char* Format, ...)
284 /* Print an error message giving an explicit file and position. */
285 {
286     va_list ap;
287     va_start (ap, Format);
288     VPrintMsg (Pos, "Error", Format, ap);
289     va_end (ap);
290
291     /* Count errors */
292     ++ErrorCount;
293 }
294
295
296
297 void LIError (const Collection* LineInfos, const char* Format, ...)
298 /* Print an error message using the given line infos. */
299 {
300     /* Output an error for this position */
301     va_list ap;
302     va_start (ap, Format);
303     ErrorMsg (LineInfos, Format, ap);
304     va_end (ap);
305 }
306
307
308
309 void ErrorSkip (const char* Format, ...)
310 /* Print an error message and skip the rest of the line */
311 {
312     va_list ap;
313     Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
314
315     /* Get line infos for the current position */
316     GetFullLineInfo (&LineInfos);
317
318     /* Output the message */
319     va_start (ap, Format);
320     ErrorMsg (&LineInfos, Format, ap);
321     va_end (ap);
322
323     /* Free the line info list */
324     ReleaseFullLineInfo (&LineInfos);
325     DoneCollection (&LineInfos);
326
327     /* Skip tokens until we reach the end of the line */
328     SkipUntilSep ();
329 }
330
331
332
333 /*****************************************************************************/
334 /*                                   Code                                    */
335 /*****************************************************************************/
336
337
338
339 void Fatal (const char* Format, ...)
340 /* Print a message about a fatal error and die */
341 {
342     va_list ap;
343     StrBuf S = STATIC_STRBUF_INITIALIZER;
344
345     va_start (ap, Format);
346     SB_VPrintf (&S, Format, ap);
347     SB_Terminate (&S);
348     va_end (ap);
349
350     fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
351
352     SB_Done (&S);
353
354     /* And die... */
355     exit (EXIT_FAILURE);
356 }
357
358
359
360 void Internal (const char* Format, ...)
361 /* Print a message about an internal assembler error and die. */
362 {
363     va_list ap;
364     StrBuf S = STATIC_STRBUF_INITIALIZER;
365
366     va_start (ap, Format);
367     SB_VPrintf (&S, Format, ap);
368     SB_Terminate (&S);
369     va_end (ap);
370
371     fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));
372
373     SB_Done (&S);
374
375     exit (EXIT_FAILURE);
376 }
377
378
379