1 /*****************************************************************************/
5 /* Error handling for the ca65 macroassembler */
9 /* (C) 1998-2011, 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;
66 /*****************************************************************************/
67 /* Helper functions */
68 /*****************************************************************************/
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. */
76 StrBuf S = STATIC_STRBUF_INITIALIZER;
78 /* Format the actual message */
79 StrBuf Msg = STATIC_STRBUF_INITIALIZER;
80 SB_VPrintf (&Msg, Format, ap);
83 /* Format the message header */
84 SB_Printf (&S, "%s(%u): %s: ",
85 SB_GetConstBuf (GetFileName (Pos->Name)),
89 /* Append the message to the message header */
92 /* Delete the formatted message */
95 /* Add a new line and terminate the generated full message */
96 SB_AppendChar (&S, '\n');
99 /* Output the full message */
100 fputs (SB_GetConstBuf (&S), stderr);
102 /* Delete the buffer for the full message */
108 static void PrintMsg (const FilePos* Pos, const char* Desc,
109 const char* Format, ...)
110 /* Format and output an error/warning message. */
113 va_start (ap, Format);
114 VPrintMsg (Pos, Desc, Format, ap);
120 static void AddNotifications (const Collection* LineInfos)
121 /* Output additional notifications for an error or warning */
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.
131 unsigned MaxCount = CollCount (LineInfos);
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");
150 /* Add a note if we have more stuff that we won't output */
152 const LineInfo* LI = CollConstAt (LineInfos, 0);
153 PrintMsg (GetSourcePos (LI), "Note",
154 "Dropping %u additional line infos", Skipped);
160 /*****************************************************************************/
162 /*****************************************************************************/
166 static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
167 /* Print warning message. */
169 /* The first entry in the collection is that of the actual source pos */
170 const LineInfo* LI = CollConstAt (LineInfos, 0);
172 /* Output a warning for this position */
173 VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
175 /* Add additional notifications if necessary */
176 AddNotifications (LineInfos);
184 void Warning (unsigned Level, const char* Format, ...)
185 /* Print warning message. */
187 if (Level <= WarnLevel) {
190 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
192 /* Get line infos for the current position */
193 GetFullLineInfo (&LineInfos);
195 /* Output the message */
196 va_start (ap, Format);
197 WarningMsg (&LineInfos, Format, ap);
200 /* Free the line info list */
201 ReleaseFullLineInfo (&LineInfos);
202 DoneCollection (&LineInfos);
208 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
209 /* Print warning message giving an explicit file and position. */
211 if (Level <= WarnLevel) {
213 va_start (ap, Format);
214 VPrintMsg (Pos, "Warning", Format, ap);
224 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
225 /* Print warning message using the given line infos */
227 if (Level <= WarnLevel) {
228 /* Output the message */
230 va_start (ap, Format);
231 WarningMsg (LineInfos, Format, ap);
238 /*****************************************************************************/
240 /*****************************************************************************/
244 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
245 /* Print an error message */
247 /* The first entry in the collection is that of the actual source pos */
248 const LineInfo* LI = CollConstAt (LineInfos, 0);
250 /* Output an error for this position */
251 VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
253 /* Add additional notifications if necessary */
254 AddNotifications (LineInfos);
262 void Error (const char* Format, ...)
263 /* Print an error message */
266 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
268 /* Get line infos for the current position */
269 GetFullLineInfo (&LineInfos);
271 /* Output the message */
272 va_start (ap, Format);
273 ErrorMsg (&LineInfos, Format, ap);
276 /* Free the line info list */
277 ReleaseFullLineInfo (&LineInfos);
278 DoneCollection (&LineInfos);
283 void PError (const FilePos* Pos, const char* Format, ...)
284 /* Print an error message giving an explicit file and position. */
287 va_start (ap, Format);
288 VPrintMsg (Pos, "Error", Format, ap);
297 void LIError (const Collection* LineInfos, const char* Format, ...)
298 /* Print an error message using the given line infos. */
300 /* Output an error for this position */
302 va_start (ap, Format);
303 ErrorMsg (LineInfos, Format, ap);
309 void ErrorSkip (const char* Format, ...)
310 /* Print an error message and skip the rest of the line */
313 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
315 /* Get line infos for the current position */
316 GetFullLineInfo (&LineInfos);
318 /* Output the message */
319 va_start (ap, Format);
320 ErrorMsg (&LineInfos, Format, ap);
323 /* Free the line info list */
324 ReleaseFullLineInfo (&LineInfos);
325 DoneCollection (&LineInfos);
327 /* Skip tokens until we reach the end of the line */
333 /*****************************************************************************/
335 /*****************************************************************************/
339 void Fatal (const char* Format, ...)
340 /* Print a message about a fatal error and die */
343 StrBuf S = STATIC_STRBUF_INITIALIZER;
345 va_start (ap, Format);
346 SB_VPrintf (&S, Format, ap);
350 fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
360 void Internal (const char* Format, ...)
361 /* Print a message about an internal assembler error and die. */
364 StrBuf S = STATIC_STRBUF_INITIALIZER;
366 va_start (ap, Format);
367 SB_VPrintf (&S, Format, ap);
371 fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));