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 PrintMsg (GetSourcePos (CollConstAt (LineInfos, 0)), "Note",
153 "Dropping %u additional line infos", Skipped);
159 /*****************************************************************************/
161 /*****************************************************************************/
165 static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
166 /* Print warning message. */
168 /* The first entry in the collection is that of the actual source pos */
169 const LineInfo* LI = CollConstAt (LineInfos, 0);
171 /* Output a warning for this position */
172 VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
174 /* Add additional notifications if necessary */
175 AddNotifications (LineInfos);
183 void Warning (unsigned Level, const char* Format, ...)
184 /* Print warning message. */
186 if (Level <= WarnLevel) {
189 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
191 /* Get line infos for the current position */
192 GetFullLineInfo (&LineInfos, 0);
194 /* Output the message */
195 va_start (ap, Format);
196 WarningMsg (&LineInfos, Format, ap);
199 /* Free the line info list */
200 DoneCollection (&LineInfos);
206 void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
207 /* Print warning message giving an explicit file and position. */
209 if (Level <= WarnLevel) {
211 va_start (ap, Format);
212 VPrintMsg (Pos, "Warning", Format, ap);
222 void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
223 /* Print warning message using the given line infos */
225 if (Level <= WarnLevel) {
226 /* Output the message */
228 va_start (ap, Format);
229 WarningMsg (LineInfos, Format, ap);
236 /*****************************************************************************/
238 /*****************************************************************************/
242 void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
243 /* Print an error message */
245 /* The first entry in the collection is that of the actual source pos */
246 const LineInfo* LI = CollConstAt (LineInfos, 0);
248 /* Output an error for this position */
249 VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
251 /* Add additional notifications if necessary */
252 AddNotifications (LineInfos);
260 void Error (const char* Format, ...)
261 /* Print an error message */
264 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
266 /* Get line infos for the current position */
267 GetFullLineInfo (&LineInfos, 0);
269 /* Output the message */
270 va_start (ap, Format);
271 ErrorMsg (&LineInfos, Format, ap);
274 /* Free the line info list */
275 DoneCollection (&LineInfos);
280 void LIError (const Collection* LineInfos, const char* Format, ...)
281 /* Print an error message using the given line infos. */
283 /* Output an error for this position */
285 va_start (ap, Format);
286 ErrorMsg (LineInfos, Format, ap);
292 void ErrorSkip (const char* Format, ...)
293 /* Print an error message and skip the rest of the line */
296 Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
298 /* Get line infos for the current position */
299 GetFullLineInfo (&LineInfos, 0);
301 /* Output the message */
302 va_start (ap, Format);
303 ErrorMsg (&LineInfos, Format, ap);
306 /* Free the line info list */
307 DoneCollection (&LineInfos);
309 /* Skip tokens until we reach the end of the line */
315 /*****************************************************************************/
317 /*****************************************************************************/
321 void Fatal (const char* Format, ...)
322 /* Print a message about a fatal error and die */
325 StrBuf S = STATIC_STRBUF_INITIALIZER;
327 va_start (ap, Format);
328 SB_VPrintf (&S, Format, ap);
332 fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
342 void Internal (const char* Format, ...)
343 /* Print a message about an internal assembler error and die. */
346 StrBuf S = STATIC_STRBUF_INITIALIZER;
348 va_start (ap, Format);
349 SB_VPrintf (&S, Format, ap);
353 fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));