1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-24 00:29:32 +00:00

Use line infos to output more verbose error and warning messages whenever

possible.


git-svn-id: svn://svn.cc65.org/cc65/trunk@4950 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2011-01-29 18:43:36 +00:00
parent 1dcba5c24e
commit 1072edb0d8
11 changed files with 148 additions and 152 deletions

View File

@ -84,7 +84,7 @@ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Ms
A->Action = Action;
A->Msg = Msg;
A->LI = EmptyCollection;
GetFullLineInfo (&A->LI);
GetFullLineInfo (&A->LI, 1);
/* Return the new struct */
return A;

View File

@ -37,6 +37,7 @@
#include "error.h"
#include "expr.h"
#include "instr.h"
#include "lineinfo.h"
#include "nexttok.h"
#include "symbol.h"
#include "symtab.h"
@ -73,7 +74,7 @@ enum {
typedef struct IfDesc IfDesc;
struct IfDesc {
unsigned Flags; /* Bitmapped flags, see above */
FilePos Pos; /* File position of the .IF */
Collection LineInfos; /* File position of the .IF */
const char* Name; /* Name of the directive */
};
@ -97,9 +98,10 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm)
ID = &IfStack [IfCount++];
/* Initialize elements */
ID->Flags = NeedTerm? ifNeedTerm : ifNone;
ID->Pos = CurTok.Pos;
ID->Name = Directive;
ID->Flags = NeedTerm? ifNeedTerm : ifNone;
ID->LineInfos = EmptyCollection;
GetFullLineInfo (&ID->LineInfos, 0);
ID->Name = Directive;
/* Return the result */
return ID;
@ -218,7 +220,7 @@ void DoConditionals (void)
/* Allow an .ELSE */
InvertIfCond (D);
SetElse (D, 1);
D->Pos = CurTok.Pos;
GetFullLineInfo (&D->LineInfos, 0);
D->Name = ".ELSE";
IfCond = GetCurrentIfCond ();
}
@ -464,6 +466,8 @@ void CheckOpenIfs (void)
* open .ifs in this file.
*/
{
const LineInfo* LI;
while (1) {
/* Get the current file number and check if the topmost entry on the
* .IF stack was inserted with this file number
@ -474,13 +478,14 @@ void CheckOpenIfs (void)
break;
}
if (D->Pos.Name != CurTok.Pos.Name) {
LI = CollConstAt (&D->LineInfos, 0);
if (LI->Pos.Name != CurTok.Pos.Name) {
/* The .if is from another file, bail out */
break;
}
/* Start of .if is in the file we're about to leave */
PError (&D->Pos, "Conditional assembly branch was never closed");
LIError (&D->LineInfos, "Conditional assembly branch was never closed");
FreeIf ();
}
}

View File

@ -69,45 +69,49 @@ unsigned WarningCount = 0;
static void FormatVMsg (StrBuf* S, const FilePos* Pos, const char* Desc,
const char* Format, va_list ap)
/* Format an error/warning message into S. A trailing newline and a NUL
* terminator will be added to S.
*/
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(%lu): %s: ",
SB_Printf (&S, "%s(%lu): %s: ",
SB_GetConstBuf (GetFileName (Pos->Name)),
Pos->Line,
Desc);
/* Append the message to the message header */
SB_Append (S, &Msg);
SB_Append (&S, &Msg);
/* Delete the formatted message */
SB_Done (&Msg);
/* Add a new line and terminate the generated message */
SB_AppendChar (S, '\n');
SB_Terminate (S);
/* 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 FormatMsg (StrBuf* S, const FilePos* Pos, const char* Desc,
const char* Format, ...)
/* Format an error/warning message into S. A trailing newline and a NUL
* terminator will be added to 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);
FormatVMsg (S, Pos, Desc, Format, ap);
VPrintMsg (Pos, Desc, Format, ap);
va_end (ap);
}
@ -116,8 +120,6 @@ static void FormatMsg (StrBuf* S, const FilePos* Pos, const char* Desc,
static void AddNotifications (const Collection* LineInfos)
/* Output additional notifications for an error or warning */
{
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
/* 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 additional notifications if they're
@ -130,38 +132,37 @@ static void AddNotifications (const Collection* LineInfos)
/* Check the type and output an appropriate note */
unsigned Type = GetLineInfoType (LI);
if (Type == LI_TYPE_EXT) {
FormatMsg (&Msg, GetSourcePos (LI), "Note",
"Assembler code generated from this line");
fputs (SB_GetConstBuf (&Msg), stderr);
PrintMsg (GetSourcePos (LI), "Note",
"Assembler code generated from this line");
} else if (Type == LI_TYPE_MACRO) {
PrintMsg (GetSourcePos (LI), "Note",
"Macro expansion was here");
}
}
SB_Done (&Msg);
}
/*****************************************************************************/
/* Warnings */
/* Warnings */
/*****************************************************************************/
void WarningMsg (const FilePos* Pos, unsigned Level, const char* Format, va_list ap)
static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap)
/* Print warning message. */
{
if (Level <= WarnLevel) {
/* The first entry in the collection is that of the actual source pos */
const LineInfo* LI = CollConstAt (LineInfos, 0);
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
FormatVMsg (&Msg, Pos, "Warning", Format, ap);
fputs (SB_GetConstBuf (&Msg), stderr);
SB_Done (&Msg);
/* Output a warning for this position */
VPrintMsg (GetSourcePos (LI), "Warning", Format, ap);
++WarningCount;
}
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
/* Count warnings */
++WarningCount;
}
@ -169,10 +170,22 @@ void WarningMsg (const FilePos* Pos, unsigned Level, const char* Format, va_list
void Warning (unsigned Level, const char* Format, ...)
/* Print warning message. */
{
va_list ap;
va_start (ap, Format);
WarningMsg (&CurTok.Pos, Level, Format, ap);
va_end (ap);
if (Level <= WarnLevel) {
va_list ap;
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */
GetFullLineInfo (&LineInfos, 0);
/* Output the message */
va_start (ap, Format);
WarningMsg (&LineInfos, Format, ap);
va_end (ap);
/* Free the line info list */
DoneCollection (&LineInfos);
}
}
@ -180,10 +193,15 @@ void Warning (unsigned Level, const char* Format, ...)
void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
/* Print warning message giving an explicit file and position. */
{
va_list ap;
va_start (ap, Format);
WarningMsg (Pos, Level, Format, ap);
va_end (ap);
if (Level <= WarnLevel) {
va_list ap;
va_start (ap, Format);
VPrintMsg (Pos, "Warning", Format, ap);
va_end (ap);
/* Count warnings */
++WarningCount;
}
}
@ -192,19 +210,11 @@ 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;
/* 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 */
va_start (ap, Format);
WarningMsg (GetSourcePos (LI), Level, Format, ap);
WarningMsg (LineInfos, Format, ap);
va_end (ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
}
}
@ -216,14 +226,19 @@ void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format,
void ErrorMsg (const FilePos* Pos, const char* Format, va_list ap)
void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap)
/* Print an error message */
{
StrBuf Msg = STATIC_STRBUF_INITIALIZER;
FormatVMsg (&Msg, Pos, "Error", Format, ap);
fputs (SB_GetConstBuf (&Msg), stderr);
SB_Done (&Msg);
/* 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;
}
@ -233,20 +248,18 @@ 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, 0);
/* Output the message */
va_start (ap, Format);
ErrorMsg (&CurTok.Pos, Format, ap);
ErrorMsg (&LineInfos, Format, ap);
va_end (ap);
}
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);
ErrorMsg (Pos, Format, ap);
va_end (ap);
/* Free the line info list */
DoneCollection (&LineInfos);
}
@ -254,18 +267,11 @@ void PError (const FilePos* Pos, const char* Format, ...)
void LIError (const Collection* LineInfos, const char* Format, ...)
/* Print an error message using the given line infos. */
{
va_list ap;
/* 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 */
va_list ap;
va_start (ap, Format);
ErrorMsg (GetSourcePos (LI), Format, ap);
ErrorMsg (LineInfos, Format, ap);
va_end (ap);
/* Add additional notifications if necessary */
AddNotifications (LineInfos);
}
@ -274,10 +280,20 @@ 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, 0);
/* Output the message */
va_start (ap, Format);
ErrorMsg (&CurTok.Pos, Format, ap);
ErrorMsg (&LineInfos, Format, ap);
va_end (ap);
/* Free the line info list */
DoneCollection (&LineInfos);
/* Skip tokens until we reach the end of the line */
SkipUntilSep ();
}

View File

@ -78,9 +78,6 @@ void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format,
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
/* Print an error message */
void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print an error message giving an explicit file and position. */
void LIError (const Collection* LineInfos, const char* Format, ...) attribute ((format (printf, 2, 3)));
/* Print an error message using the given line infos. */

View File

@ -59,7 +59,7 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
F->Next = 0;
F->LineList = 0;
F->LI = EmptyCollection;
GetFullLineInfo (&F->LI);
GetFullLineInfo (&F->LI, 1);
F->Len = Len;
F->Type = Type;

View File

@ -94,29 +94,15 @@ static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
LI->Index = INV_LINEINFO_INDEX;
LI->Pos = *Pos;
/* Add the line info to the list of all line infos */
CollAppend (&LineInfoColl, LI);
/* Return the new struct */
return LI;
}
static void FreeLineInfo (LineInfo* LI)
/* "Free" line info. If the usage counter is non zero, move it to the
* collection that contains all line infos, otherwise delete it.
* The function handles a NULL pointer transparently.
*/
{
if (LI) {
if (LI->Usage > 0) {
CollAppend (&LineInfoColl, LI);
} else {
xfree (LI);
}
}
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@ -128,6 +114,9 @@ void InitLineInfo (void)
{
static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
/* Increase the initial count of the line info collection */
CollGrow (&LineInfoColl, 200);
/* Allocate 8 slots */
AllocatedSlots = 8;
CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
@ -177,7 +166,7 @@ void FreeLineInfoSlot (unsigned Slot)
PRECONDITION (Slot == UsedSlots - 1);
/* Free the last entry */
FreeLineInfo (CurLineInfo[Slot].Info);
CurLineInfo[Slot].Info = 0;
--UsedSlots;
}
@ -189,19 +178,10 @@ void GenLineInfo (unsigned Slot, const FilePos* Pos)
/* Get a pointer to the slot */
LineInfoSlot* S = CurLineInfo + Slot;
/* Check if we already have data */
if (S->Info) {
/* Generate new data only if it is different from the existing. */
if (CompareFilePos (&S->Info->Pos, Pos) == 0) {
/* Already there */
return;
}
/* We have data, but it's not identical. If it is in use, copy it to
* line info collection, otherwise delete it.
*/
FreeLineInfo (S->Info);
/* Generate new data only if it is different from the existing. */
if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) {
/* Already there */
return;
}
/* Allocate new data */
@ -213,33 +193,33 @@ void GenLineInfo (unsigned Slot, const FilePos* Pos)
void ClearLineInfo (unsigned Slot)
/* Clear the line info in the given slot */
{
/* Get a pointer to the slot */
LineInfoSlot* S = CurLineInfo + Slot;
/* Free the struct and zero the pointer */
FreeLineInfo (S->Info);
S->Info = 0;
/* Zero the pointer */
CurLineInfo[Slot].Info = 0;
}
void GetFullLineInfo (Collection* LineInfos)
void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
/* Return full line infos, that is line infos for all slots in LineInfos. The
* function does also increase the usage counter for all line infos returned.
* function will clear LineInfos before usage and will increment the usage
* counter by IncUsage for all line infos returned.
*/
{
unsigned I;
unsigned I;
/* Clear the collection */
CollDeleteAll (LineInfos);
/* Copy all valid line infos to the collection */
for (I = 0; I < UsedSlots; ++I) {
/* Get the slot */
LineInfoSlot* S = CurLineInfo + I;
/* Get the line info from the slot */
LineInfo* LI = CurLineInfo[I].Info;
/* Ignore empty slots */
if (S->Info) {
++S->Info->Usage;
CollAppend (LineInfos, S->Info);
if (LI) {
LI->Usage += IncUsage;
CollAppend (LineInfos, LI);
}
}
}
@ -330,12 +310,7 @@ void MakeLineInfoIndex (void)
{
unsigned I;
/* Be sure to move pending line infos to the global list */
for (I = 0; I < UsedSlots; ++I) {
FreeLineInfo (CurLineInfo[I].Info);
}
/* Sort the collection */
/* Sort the line info list */
CollSort (&LineInfoColl, CmpLineInfo, 0);
/* Walk over the list, index the line infos and count the used ones */

View File

@ -107,9 +107,10 @@ void GenLineInfo (unsigned Slot, const FilePos* Pos);
void ClearLineInfo (unsigned Slot);
/* Clear the line info in the given slot */
void GetFullLineInfo (Collection* LineInfos);
void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage);
/* Return full line infos, that is line infos for all slots in LineInfos. The
* function does also increase the usage counter for all line infos returned.
* function will clear LineInfos before usage and will increment the usage
* counter by IncUsage for all line infos returned.
*/
LineInfo* UseLineInfo (LineInfo* LI);

View File

@ -1103,12 +1103,14 @@ CharAgain:
CurTok.Tok = TOK_DIV;
} else if (CComments) {
/* Remember the position, then skip the '*' */
FilePos Pos = CurTok.Pos;
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
GetFullLineInfo (&LineInfos, 0);
NextChar ();
do {
while (C != '*') {
if (C == EOF) {
PError (&Pos, "Unterminated comment");
LIError (&LineInfos, "Unterminated comment");
DoneCollection (&LineInfos);
goto CharAgain;
}
NextChar ();
@ -1116,6 +1118,7 @@ CharAgain:
NextChar ();
} while (C != '/');
NextChar ();
DoneCollection (&LineInfos);
goto Again;
}
return;

View File

@ -510,9 +510,9 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
if (Verbosity > 0) {
DumpExpr (Expr, SymResolve);
}
PError (GetSymPos (Sym),
"Circular reference in definition of symbol `%m%p'",
GetSymName (Sym));
LIError (&Sym->LineInfos,
"Circular reference in definition of symbol `%m%p'",
GetSymName (Sym));
ED_Invalidate (D);
} else {

View File

@ -87,7 +87,7 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
S->Locals = 0;
S->Sym.Tab = 0;
S->LineInfos = EmptyCollection;
GetFullLineInfo (&S->LineInfos);
GetFullLineInfo (&S->LineInfos, 1);
for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
S->GuessedUse[I] = 0;
}

View File

@ -83,7 +83,7 @@ static ULabel* NewULabel (ExprNode* Val)
/* Initialize the fields */
L->LineInfos = EmptyCollection;
GetFullLineInfo (&L->LineInfos);
GetFullLineInfo (&L->LineInfos, 0);
L->Val = Val;
L->Ref = 0;
@ -161,8 +161,7 @@ void ULabDef (void)
ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
CHECK (L->Val == 0);
L->Val = GenCurrentPC ();
CollDeleteAll (&L->LineInfos);
GetFullLineInfo (&L->LineInfos);
GetFullLineInfo (&L->LineInfos, 0);
} else {
/* There is no such label, create it */
NewULabel (GenCurrentPC ());