mirror of
https://github.com/cc65/cc65.git
synced 2024-09-28 10:55:43 +00:00
757b400aa1
there weren't any more line infos to display, because they had the wrong type. git-svn-id: svn://svn.cc65.org/cc65/trunk@5882 b7a2c559-68d2-44c3-8de9-860c34a00d81
398 lines
11 KiB
C
398 lines
11 KiB
C
/*****************************************************************************/
|
|
/* */
|
|
/* error.c */
|
|
/* */
|
|
/* Error handling for the ca65 macroassembler */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
|
/* Roemerstrasse 52 */
|
|
/* D-70794 Filderstadt */
|
|
/* EMail: uz@cc65.org */
|
|
/* */
|
|
/* */
|
|
/* This software is provided 'as-is', without any expressed or implied */
|
|
/* warranty. In no event will the authors be held liable for any damages */
|
|
/* arising from the use of this software. */
|
|
/* */
|
|
/* Permission is granted to anyone to use this software for any purpose, */
|
|
/* including commercial applications, and to alter it and redistribute it */
|
|
/* freely, subject to the following restrictions: */
|
|
/* */
|
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
|
/* claim that you wrote the original software. If you use this software */
|
|
/* in a product, an acknowledgment in the product documentation would be */
|
|
/* appreciated but is not required. */
|
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
|
/* be misrepresented as being the original software. */
|
|
/* 3. This notice may not be removed or altered from any source */
|
|
/* distribution. */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
|
|
/* common */
|
|
#include "strbuf.h"
|
|
|
|
/* ca65 */
|
|
#include "error.h"
|
|
#include "filetab.h"
|
|
#include "lineinfo.h"
|
|
#include "nexttok.h"
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Data */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
/* Warning level */
|
|
unsigned WarnLevel = 1;
|
|
|
|
/* Statistics */
|
|
unsigned ErrorCount = 0;
|
|
unsigned WarningCount = 0;
|
|
|
|
/* Maximum number of additional notifications */
|
|
#define MAX_NOTES 6
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Helper functions */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
static void VPrintMsg (const FilePos* Pos, const char* Desc,
|
|
const char* Format, va_list ap)
|
|
/* Format and output an error/warning message. */
|
|
{
|
|
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
|
|
|
/* Format the actual message */
|
|
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
|
|
SB_VPrintf (&Msg, Format, ap);
|
|
SB_Terminate (&Msg);
|
|
|
|
/* Format the message header */
|
|
SB_Printf (&S, "%s(%u): %s: ",
|
|
SB_GetConstBuf (GetFileName (Pos->Name)),
|
|
Pos->Line,
|
|
Desc);
|
|
|
|
/* Append the message to the message header */
|
|
SB_Append (&S, &Msg);
|
|
|
|
/* Delete the formatted message */
|
|
SB_Done (&Msg);
|
|
|
|
/* Add a new line and terminate the generated full message */
|
|
SB_AppendChar (&S, '\n');
|
|
SB_Terminate (&S);
|
|
|
|
/* Output the full message */
|
|
fputs (SB_GetConstBuf (&S), stderr);
|
|
|
|
/* Delete the buffer for the full message */
|
|
SB_Done (&S);
|
|
}
|
|
|
|
|
|
|
|
static void PrintMsg (const FilePos* Pos, const char* Desc,
|
|
const char* Format, ...)
|
|
/* Format and output an error/warning message. */
|
|
{
|
|
va_list ap;
|
|
va_start (ap, Format);
|
|
VPrintMsg (Pos, Desc, Format, ap);
|
|
va_end (ap);
|
|
}
|
|
|
|
|
|
|
|
static void AddNotifications (const Collection* LineInfos)
|
|
/* Output additional notifications for an error or warning */
|
|
{
|
|
unsigned I;
|
|
unsigned Output;
|
|
unsigned Skipped;
|
|
|
|
/* The basic line info is always in slot zero. It has been used to
|
|
* output the actual error or warning. The following slots may contain
|
|
* more information. Check them and print additional notifications if
|
|
* they're present, but limit the number to a reasonable value.
|
|
*/
|
|
for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) {
|
|
/* Get next line info */
|
|
const LineInfo* LI = CollConstAt (LineInfos, I);
|
|
/* Check the type and output an appropriate note */
|
|
const char* Msg;
|
|
switch (GetLineInfoType (LI)) {
|
|
|
|
case LI_TYPE_EXT:
|
|
Msg = "Assembler code generated from this line";
|
|
break;
|
|
|
|
case LI_TYPE_MACRO:
|
|
Msg = "Macro was defined here";
|
|
break;
|
|
|
|
default:
|
|
/* No output */
|
|
Msg = 0;
|
|
break;
|
|
|
|
}
|
|
|
|
/* Output until an upper limit of messages is reached */
|
|
if (Msg) {
|
|
if (Output < MAX_NOTES) {
|
|
PrintMsg (GetSourcePos (LI), "Note", "%s", Msg);
|
|
++Output;
|
|
} else {
|
|
++Skipped;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Add a note if we have more stuff that we won't output */
|
|
if (Skipped > 0) {
|
|
const LineInfo* LI = CollConstAt (LineInfos, 0);
|
|
PrintMsg (GetSourcePos (LI), "Note",
|
|
"Dropping %u additional line infos", Skipped);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Warnings */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
|
|
/* Print warning message. */
|
|
{
|
|
/* The first entry in the collection is that of the actual source pos */
|
|
const LineInfo* LI = CollConstAt (LineInfos, 0);
|
|
|
|
/* Output a warning for this position */
|
|
VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
|
|
|
|
/* Add additional notifications if necessary */
|
|
AddNotifications (LineInfos);
|
|
|
|
/* Count warnings */
|
|
++WarningCount;
|
|
}
|
|
|
|
|
|
|
|
void Warning (unsigned Level, const char* Format, ...)
|
|
/* Print warning message. */
|
|
{
|
|
if (Level <= WarnLevel) {
|
|
|
|
va_list ap;
|
|
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
|
|
|
|
/* Get line infos for the current position */
|
|
GetFullLineInfo (&LineInfos);
|
|
|
|
/* Output the message */
|
|
va_start (ap, Format);
|
|
WarningMsg (&LineInfos, Format, ap);
|
|
va_end (ap);
|
|
|
|
/* Free the line info list */
|
|
ReleaseFullLineInfo (&LineInfos);
|
|
DoneCollection (&LineInfos);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
|
|
/* Print warning message giving an explicit file and position. */
|
|
{
|
|
if (Level <= WarnLevel) {
|
|
va_list ap;
|
|
va_start (ap, Format);
|
|
VPrintMsg (Pos, "Warning", Format, ap);
|
|
va_end (ap);
|
|
|
|
/* Count warnings */
|
|
++WarningCount;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
|
|
/* Print warning message using the given line infos */
|
|
{
|
|
if (Level <= WarnLevel) {
|
|
/* Output the message */
|
|
va_list ap;
|
|
va_start (ap, Format);
|
|
WarningMsg (LineInfos, Format, ap);
|
|
va_end (ap);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Errors */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
|
|
/* Print an error message */
|
|
{
|
|
/* The first entry in the collection is that of the actual source pos */
|
|
const LineInfo* LI = CollConstAt (LineInfos, 0);
|
|
|
|
/* Output an error for this position */
|
|
VPrintMsg (GetSourcePos (LI), "Error", Format, ap);
|
|
|
|
/* Add additional notifications if necessary */
|
|
AddNotifications (LineInfos);
|
|
|
|
/* Count errors */
|
|
++ErrorCount;
|
|
}
|
|
|
|
|
|
|
|
void Error (const char* Format, ...)
|
|
/* Print an error message */
|
|
{
|
|
va_list ap;
|
|
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
|
|
|
|
/* Get line infos for the current position */
|
|
GetFullLineInfo (&LineInfos);
|
|
|
|
/* Output the message */
|
|
va_start (ap, Format);
|
|
ErrorMsg (&LineInfos, Format, ap);
|
|
va_end (ap);
|
|
|
|
/* Free the line info list */
|
|
ReleaseFullLineInfo (&LineInfos);
|
|
DoneCollection (&LineInfos);
|
|
}
|
|
|
|
|
|
|
|
void PError (const FilePos* Pos, const char* Format, ...)
|
|
/* Print an error message giving an explicit file and position. */
|
|
{
|
|
va_list ap;
|
|
va_start (ap, Format);
|
|
VPrintMsg (Pos, "Error", Format, ap);
|
|
va_end (ap);
|
|
|
|
/* Count errors */
|
|
++ErrorCount;
|
|
}
|
|
|
|
|
|
|
|
void LIError (const Collection* LineInfos, const char* Format, ...)
|
|
/* Print an error message using the given line infos. */
|
|
{
|
|
/* Output an error for this position */
|
|
va_list ap;
|
|
va_start (ap, Format);
|
|
ErrorMsg (LineInfos, Format, ap);
|
|
va_end (ap);
|
|
}
|
|
|
|
|
|
|
|
void ErrorSkip (const char* Format, ...)
|
|
/* Print an error message and skip the rest of the line */
|
|
{
|
|
va_list ap;
|
|
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
|
|
|
|
/* Get line infos for the current position */
|
|
GetFullLineInfo (&LineInfos);
|
|
|
|
/* Output the message */
|
|
va_start (ap, Format);
|
|
ErrorMsg (&LineInfos, Format, ap);
|
|
va_end (ap);
|
|
|
|
/* Free the line info list */
|
|
ReleaseFullLineInfo (&LineInfos);
|
|
DoneCollection (&LineInfos);
|
|
|
|
/* Skip tokens until we reach the end of the line */
|
|
SkipUntilSep ();
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Code */
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
void Fatal (const char* Format, ...)
|
|
/* Print a message about a fatal error and die */
|
|
{
|
|
va_list ap;
|
|
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
|
|
|
va_start (ap, Format);
|
|
SB_VPrintf (&S, Format, ap);
|
|
SB_Terminate (&S);
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S));
|
|
|
|
SB_Done (&S);
|
|
|
|
/* And die... */
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
|
|
void Internal (const char* Format, ...)
|
|
/* Print a message about an internal assembler error and die. */
|
|
{
|
|
va_list ap;
|
|
StrBuf S = STATIC_STRBUF_INITIALIZER;
|
|
|
|
va_start (ap, Format);
|
|
SB_VPrintf (&S, Format, ap);
|
|
SB_Terminate (&S);
|
|
va_end (ap);
|
|
|
|
fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));
|
|
|
|
SB_Done (&S);
|
|
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
|
|
|