1 /*****************************************************************************/
5 /* Error handling for the ca65 macroassembler */
9 /* (C) 1998-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
58 unsigned WarnLevel = 1;
61 unsigned ErrorCount = 0;
62 unsigned WarningCount = 0;
64 /* Maximum number of additional notifications */
69 /*****************************************************************************/
70 /* Helper functions */
71 /*****************************************************************************/
75 static void VPrintMsg (const FilePos* Pos, const char* Desc,
76 const char* Format, va_list ap)
77 /* Format and output an error/warning message. */
79 StrBuf S = STATIC_STRBUF_INITIALIZER;
81 /* Format the actual message */
82 StrBuf Msg = STATIC_STRBUF_INITIALIZER;
83 SB_VPrintf (&Msg, Format, ap);
86 /* Format the message header */
87 SB_Printf (&S, "%s(%u): %s: ",
88 SB_GetConstBuf (GetFileName (Pos->Name)),
92 /* Append the message to the message header */
95 /* Delete the formatted message */
98 /* Add a new line and terminate the generated full message */
99 SB_AppendChar (&S, '\n');
102 /* Output the full message */
103 fputs (SB_GetConstBuf (&S), stderr);
105 /* Delete the buffer for the full message */
111 static void PrintMsg (const FilePos* Pos, const char* Desc,
112 const char* Format, ...)
113 /* Format and output an error/warning message. */
116 va_start (ap, Format);
117 VPrintMsg (Pos, Desc, Format, ap);
123 static void AddNotifications (const Collection* LineInfos)
124 /* Output additional notifications for an error or warning */
130 /* The basic line info is always in slot zero. It has been used to
131 * output the actual error or warning. The following slots may contain
132 * more information. Check them and print additional notifications if
133 * they're present, but limit the number to a reasonable value.
135 for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) {
136 /* Get next line info */
137 const LineInfo* LI = CollConstAt (LineInfos, I);
138 /* Check the type and output an appropriate note */
140 switch (GetLineInfoType (LI)) {
143 Msg = "Expanded from here";
147 Msg = "Assembler code generated from this line";
151 Msg = "Macro was defined here";
154 case LI_TYPE_MACPARAM:
155 Msg = "Macro parameter came from here";
165 /* Output until an upper limit of messages is reached */
167 if (Output < MAX_NOTES) {
168 PrintMsg (GetSourcePos (LI), "Note", "%s", Msg);
176 /* Add a note if we have more stuff that we won't output */
178 const LineInfo* LI = CollConstAt (LineInfos, 0);
179 PrintMsg (GetSourcePos (LI), "Note",
180 "Dropping %u additional line infos", Skipped);
186 /*****************************************************************************/
188 /*****************************************************************************/
192 static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
193 /* Print warning message. */
195 /* The first entry in the collection is that of the actual source pos */
196 const LineInfo* LI = CollConstAt (LineInfos, 0);
198 /* Output a warning for this position */
199 VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
201 /* Add additional notifications if necessary */
202 AddNotifications (LineInfos);
210 void Warning (unsigned Level, const char* Format, ...)
211 /* Print warning message. */
213 if (Level <= WarnLevel) {
216 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
218 /* Get line infos for the current position */
219 GetFullLineInfo (&LineInfos);
221 /* Output the message */
222 va_start (ap, Format);
223 WarningMsg (&LineInfos, Format, ap);
226 /* Free the line info list */
227 ReleaseFullLineInfo (&LineInfos);
228 DoneCollection (&LineInfos);
234 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
235 /* Print warning message giving an explicit file and position. */
237 if (Level <= WarnLevel) {
239 va_start (ap, Format);
240 VPrintMsg (Pos, "Warning", Format, ap);
250 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
251 /* Print warning message using the given line infos */
253 if (Level <= WarnLevel) {
254 /* Output the message */
256 va_start (ap, Format);
257 WarningMsg (LineInfos, Format, ap);
264 /*****************************************************************************/
266 /*****************************************************************************/
270 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
271 /* Print an error message */
273 /* The first entry in the collection is that of the actual source pos */
274 const LineInfo* LI = CollConstAt (LineInfos, 0);
276 /* Output an error for this position */
277 VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
279 /* Add additional notifications if necessary */
280 AddNotifications (LineInfos);
288 void Error (const char* Format, ...)
289 /* Print an error message */
292 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
294 /* Get line infos for the current position */
295 GetFullLineInfo (&LineInfos);
297 /* Output the message */
298 va_start (ap, Format);
299 ErrorMsg (&LineInfos, Format, ap);
302 /* Free the line info list */
303 ReleaseFullLineInfo (&LineInfos);
304 DoneCollection (&LineInfos);
309 void PError (const FilePos* Pos, const char* Format, ...)
310 /* Print an error message giving an explicit file and position. */
313 va_start (ap, Format);
314 VPrintMsg (Pos, "Error", Format, ap);
323 void LIError (const Collection* LineInfos, const char* Format, ...)
324 /* Print an error message using the given line infos. */
326 /* Output an error for this position */
328 va_start (ap, Format);
329 ErrorMsg (LineInfos, Format, ap);
335 void ErrorSkip (const char* Format, ...)
336 /* Print an error message and skip the rest of the line */
339 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
341 /* Get line infos for the current position */
342 GetFullLineInfo (&LineInfos);
344 /* Output the message */
345 va_start (ap, Format);
346 ErrorMsg (&LineInfos, Format, ap);
349 /* Free the line info list */
350 ReleaseFullLineInfo (&LineInfos);
351 DoneCollection (&LineInfos);
353 /* Skip tokens until we reach the end of the line */
359 /*****************************************************************************/
361 /*****************************************************************************/
365 void Fatal (const char* Format, ...)
366 /* Print a message about a fatal error and die */
369 StrBuf S = STATIC_STRBUF_INITIALIZER;
371 va_start (ap, Format);
372 SB_VPrintf (&S, Format, ap);
376 fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
386 void Internal (const char* Format, ...)
387 /* Print a message about an internal assembler error and die. */
390 StrBuf S = STATIC_STRBUF_INITIALIZER;
392 va_start (ap, Format);
393 SB_VPrintf (&S, Format, ap);
397 fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));