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(%lu): %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, 0);
195 /* Output the message */
196 va_start (ap, Format);
197 WarningMsg (&LineInfos, Format, ap);
200 /* Free the line info list */
201 DoneCollection (&LineInfos);
207 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
208 /* Print warning message giving an explicit file and position. */
210 if (Level <= WarnLevel) {
212 va_start (ap, Format);
213 VPrintMsg (Pos, "Warning", Format, ap);
223 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
224 /* Print warning message using the given line infos */
226 if (Level <= WarnLevel) {
227 /* Output the message */
229 va_start (ap, Format);
230 WarningMsg (LineInfos, Format, ap);
237 /*****************************************************************************/
239 /*****************************************************************************/
243 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
244 /* Print an error message */
246 /* The first entry in the collection is that of the actual source pos */
247 const LineInfo* LI = CollConstAt (LineInfos, 0);
249 /* Output an error for this position */
250 VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
252 /* Add additional notifications if necessary */
253 AddNotifications (LineInfos);
261 void Error (const char* Format, ...)
262 /* Print an error message */
265 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
267 /* Get line infos for the current position */
268 GetFullLineInfo (&LineInfos, 0);
270 /* Output the message */
271 va_start (ap, Format);
272 ErrorMsg (&LineInfos, Format, ap);
275 /* Free the line info list */
276 DoneCollection (&LineInfos);
281 void LIError (const Collection* LineInfos, const char* Format, ...)
282 /* Print an error message using the given line infos. */
284 /* Output an error for this position */
286 va_start (ap, Format);
287 ErrorMsg (LineInfos, Format, ap);
293 void ErrorSkip (const char* Format, ...)
294 /* Print an error message and skip the rest of the line */
297 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
299 /* Get line infos for the current position */
300 GetFullLineInfo (&LineInfos, 0);
302 /* Output the message */
303 va_start (ap, Format);
304 ErrorMsg (&LineInfos, Format, ap);
307 /* Free the line info list */
308 DoneCollection (&LineInfos);
310 /* Skip tokens until we reach the end of the line */
316 /*****************************************************************************/
318 /*****************************************************************************/
322 void Fatal (const char* Format, ...)
323 /* Print a message about a fatal error and die */
326 StrBuf S = STATIC_STRBUF_INITIALIZER;
328 va_start (ap, Format);
329 SB_VPrintf (&S, Format, ap);
333 fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
343 void Internal (const char* Format, ...)
344 /* Print a message about an internal assembler error and die. */
347 StrBuf S = STATIC_STRBUF_INITIALIZER;
349 va_start (ap, Format);
350 SB_VPrintf (&S, Format, ap);
354 fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));