]> git.sur5r.net Git - cc65/blob - src/ca65/error.c
Finished implemenation of commands to delete macros. Added the new commands to
[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(%lu): %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, 0);
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         DoneCollection (&LineInfos);
202     }
203 }
204
205
206
207 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
208 /* Print warning message giving an explicit file and position. */
209 {
210     if (Level <= WarnLevel) {
211         va_list ap;
212         va_start (ap, Format);
213         VPrintMsg (Pos, "Warning", Format, ap);
214         va_end (ap);
215
216         /* Count warnings */
217         ++WarningCount;
218     }
219 }
220
221
222
223 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
224 /* Print warning message using the given line infos */
225 {
226     if (Level <= WarnLevel) {
227         /* Output the message */
228         va_list ap;
229         va_start (ap, Format);
230         WarningMsg (LineInfos, Format, ap);
231         va_end (ap);
232     }
233 }
234
235
236
237 /*****************************************************************************/
238 /*                                  Errors                                   */
239 /*****************************************************************************/
240
241
242
243 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
244 /* Print an error message */
245 {
246     /* The first entry in the collection is that of the actual source pos */
247     const LineInfo* LI = CollConstAt (LineInfos, 0);
248
249     /* Output an error for this position */
250     VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
251
252     /* Add additional notifications if necessary */
253     AddNotifications (LineInfos);
254
255     /* Count errors */
256     ++ErrorCount;
257 }
258
259
260
261 void Error (const char* Format, ...)
262 /* Print an error message */
263 {
264     va_list ap;
265     Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
266
267     /* Get line infos for the current position */
268     GetFullLineInfo (&LineInfos, 0);
269
270     /* Output the message */
271     va_start (ap, Format);
272     ErrorMsg (&LineInfos, Format, ap);
273     va_end (ap);
274
275     /* Free the line info list */
276     DoneCollection (&LineInfos);
277 }
278
279
280
281 void LIError (const Collection* LineInfos, const char* Format, ...)
282 /* Print an error message using the given line infos. */
283 {
284     /* Output an error for this position */
285     va_list ap;
286     va_start (ap, Format);
287     ErrorMsg (LineInfos, Format, ap);
288     va_end (ap);
289 }
290
291
292
293 void ErrorSkip (const char* Format, ...)
294 /* Print an error message and skip the rest of the line */
295 {
296     va_list ap;
297     Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
298
299     /* Get line infos for the current position */
300     GetFullLineInfo (&LineInfos, 0);
301
302     /* Output the message */
303     va_start (ap, Format);
304     ErrorMsg (&LineInfos, Format, ap);
305     va_end (ap);
306
307     /* Free the line info list */
308     DoneCollection (&LineInfos);
309
310     /* Skip tokens until we reach the end of the line */
311     SkipUntilSep ();
312 }
313
314
315
316 /*****************************************************************************/
317 /*                                   Code                                    */
318 /*****************************************************************************/
319
320
321
322 void Fatal (const char* Format, ...)
323 /* Print a message about a fatal error and die */
324 {
325     va_list ap;
326     StrBuf S = STATIC_STRBUF_INITIALIZER;
327
328     va_start (ap, Format);
329     SB_VPrintf (&S, Format, ap);
330     SB_Terminate (&S);
331     va_end (ap);
332
333     fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
334
335     SB_Done (&S);
336
337     /* And die... */
338     exit (EXIT_FAILURE);
339 }
340
341
342
343 void Internal (const char* Format, ...)
344 /* Print a message about an internal assembler error and die. */
345 {
346     va_list ap;
347     StrBuf S = STATIC_STRBUF_INITIALIZER;
348
349     va_start (ap, Format);
350     SB_VPrintf (&S, Format, ap);
351     SB_Terminate (&S);
352     va_end (ap);
353
354     fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));
355
356     SB_Done (&S);
357
358     exit (EXIT_FAILURE);
359 }
360
361
362