Started to generalize line info handling. Remove separate FilePos fields and
try to manage all and everything with LineInfos. git-svn-id: svn://svn.cc65.org/cc65/trunk@4914 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -41,8 +41,8 @@
|
|||||||
#include "asserts.h"
|
#include "asserts.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "objfile.h"
|
#include "objfile.h"
|
||||||
#include "scanner.h"
|
|
||||||
#include "spool.h"
|
#include "spool.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ struct Assertion {
|
|||||||
ExprNode* Expr; /* Expression to evaluate */
|
ExprNode* Expr; /* Expression to evaluate */
|
||||||
AssertAction Action; /* Action to take */
|
AssertAction Action; /* Action to take */
|
||||||
unsigned Msg; /* Message to print (if any) */
|
unsigned Msg; /* Message to print (if any) */
|
||||||
FilePos Pos; /* File position of assertion */
|
Collection LI; /* Line infos for the assertion */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Collection with all assertions for a module */
|
/* Collection with all assertions for a module */
|
||||||
@@ -83,7 +83,8 @@ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Ms
|
|||||||
A->Expr = Expr;
|
A->Expr = Expr;
|
||||||
A->Action = Action;
|
A->Action = Action;
|
||||||
A->Msg = Msg;
|
A->Msg = Msg;
|
||||||
A->Pos = CurTok.Pos;
|
A->LI = EmptyCollection;
|
||||||
|
GetFullLineInfo (&A->LI);
|
||||||
|
|
||||||
/* Return the new struct */
|
/* Return the new struct */
|
||||||
return A;
|
return A;
|
||||||
@@ -128,11 +129,11 @@ void CheckAssertions (void)
|
|||||||
switch (A->Action) {
|
switch (A->Action) {
|
||||||
|
|
||||||
case ASSERT_ACT_WARN:
|
case ASSERT_ACT_WARN:
|
||||||
PWarning (&A->Pos, 0, "%s", Msg);
|
LIWarning (&A->LI, 0, "%s", Msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASSERT_ACT_ERROR:
|
case ASSERT_ACT_ERROR:
|
||||||
PError (&A->Pos, "%s", Msg);
|
LIError (&A->LI, "%s", Msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -169,7 +170,7 @@ void WriteAssertions (void)
|
|||||||
WriteExpr (A->Expr);
|
WriteExpr (A->Expr);
|
||||||
ObjWriteVar ((unsigned) A->Action);
|
ObjWriteVar ((unsigned) A->Action);
|
||||||
ObjWriteVar (A->Msg);
|
ObjWriteVar (A->Msg);
|
||||||
ObjWritePos (&A->Pos);
|
WriteLineInfo (&A->LI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Done writing the assertions */
|
/* Done writing the assertions */
|
||||||
@@ -179,4 +180,4 @@ void WriteAssertions (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The line info slot used */
|
||||||
|
static unsigned LineInfoSlot;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -103,7 +114,7 @@ void DbgInfoLine (void)
|
|||||||
* follow, the last line info is terminated.
|
* follow, the last line info is terminated.
|
||||||
*/
|
*/
|
||||||
if (CurTok.Tok == TOK_SEP) {
|
if (CurTok.Tok == TOK_SEP) {
|
||||||
ClearLineInfo ();
|
ClearLineInfo (LineInfoSlot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +144,7 @@ void DbgInfoLine (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the line info */
|
/* Remember the line info */
|
||||||
GenLineInfo (Index, LineNum, 0);
|
GenLineInfo (LineInfoSlot, Index, LineNum, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,5 +157,3 @@ void DbgInfoSym (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2001 Ullrich von Bassewitz */
|
/* (C) 2000-2011, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "filetab.h"
|
#include "filetab.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "nexttok.h"
|
#include "nexttok.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +63,32 @@ unsigned WarningCount = 0;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Helper functions */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int FindAsmEntry (const Collection* LineInfos)
|
||||||
|
/* Return the last entry of type LI_TYPE_ASM in the given line infos. If none
|
||||||
|
* was found, return -1.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I = CollCount (LineInfos);
|
||||||
|
while (I > 0) {
|
||||||
|
const LineInfo* LI = CollConstAt (LineInfos, --I);
|
||||||
|
if ((LI->Type & LI_MASK_TYPE) == LI_TYPE_ASM) {
|
||||||
|
/* Found */
|
||||||
|
return (int) I;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Warnings */
|
/* Warnings */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -111,6 +138,29 @@ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...)
|
||||||
|
/* Print warning message using the given line infos */
|
||||||
|
{
|
||||||
|
const LineInfo* LI;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/* Search backwards in LI for the first entry of type LI_TYPE_ASM. */
|
||||||
|
int I = FindAsmEntry (LineInfos);
|
||||||
|
|
||||||
|
/* We must have such an entry */
|
||||||
|
CHECK (I >= 0);
|
||||||
|
|
||||||
|
/* Get the position for this entry */
|
||||||
|
LI = CollConstAt (LineInfos, I);
|
||||||
|
|
||||||
|
/* Output a warning for this position */
|
||||||
|
va_start (ap, Format);
|
||||||
|
WarningMsg (&LI->Pos, Level, Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Errors */
|
/* Errors */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -157,6 +207,29 @@ 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. */
|
||||||
|
{
|
||||||
|
const LineInfo* LI;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/* Search backwards in LI for the first entry of type LI_TYPE_ASM. */
|
||||||
|
int I = FindAsmEntry (LineInfos);
|
||||||
|
|
||||||
|
/* We must have such an entry */
|
||||||
|
CHECK (I >= 0);
|
||||||
|
|
||||||
|
/* Get the position for this entry */
|
||||||
|
LI = CollConstAt (LineInfos, I);
|
||||||
|
|
||||||
|
/* Output an error for this position */
|
||||||
|
va_start (ap, Format);
|
||||||
|
ErrorMsg (&LI->Pos, Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ErrorSkip (const char* Format, ...)
|
void ErrorSkip (const char* Format, ...)
|
||||||
/* Print an error message and skip the rest of the line */
|
/* Print an error message and skip the rest of the line */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -40,12 +40,13 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
|
#include "coll.h"
|
||||||
#include "filepos.h"
|
#include "filepos.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -71,12 +72,18 @@ void Warning (unsigned Level, const char* Format, ...) attribute ((format (print
|
|||||||
void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
||||||
/* Print warning message giving an explicit file and position. */
|
/* Print warning message giving an explicit file and position. */
|
||||||
|
|
||||||
|
void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
||||||
|
/* Print warning message using the given line infos */
|
||||||
|
|
||||||
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
/* Print an error message */
|
/* Print an error message */
|
||||||
|
|
||||||
void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
|
void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3)));
|
||||||
/* Print an error message giving an explicit file and position. */
|
/* 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. */
|
||||||
|
|
||||||
void ErrorSkip (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void ErrorSkip (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
/* Print an error message and skip the rest of the line */
|
/* Print an error message and skip the rest of the line */
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,6 @@
|
|||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "fragment.h"
|
#include "fragment.h"
|
||||||
#include "lineinfo.h"
|
|
||||||
#include "scanner.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -60,8 +58,8 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
|
|||||||
/* Initialize it */
|
/* Initialize it */
|
||||||
F->Next = 0;
|
F->Next = 0;
|
||||||
F->LineList = 0;
|
F->LineList = 0;
|
||||||
F->Pos = CurTok.Pos;
|
F->LI = EmptyCollection;
|
||||||
F->LI = UseLineInfo (CurLineInfo);
|
GetFullLineInfo (&F->LI);
|
||||||
F->Len = Len;
|
F->Len = Len;
|
||||||
F->Type = Type;
|
F->Type = Type;
|
||||||
|
|
||||||
@@ -71,4 +69,3 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* R<EFBFBD>merstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -40,27 +40,29 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "exprdefs.h"
|
#include "exprdefs.h"
|
||||||
#include "filepos.h"
|
#include "coll.h"
|
||||||
|
|
||||||
|
/* ca65 */
|
||||||
|
#include "lineinfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* struct Fragment */
|
/* struct Fragment */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct Fragment Fragment;
|
typedef struct Fragment Fragment;
|
||||||
struct Fragment {
|
struct Fragment {
|
||||||
Fragment* Next; /* Pointer to next fragment in segment */
|
Fragment* Next; /* Pointer to next fragment in segment */
|
||||||
Fragment* LineList; /* List of fragments for one src line */
|
Fragment* LineList; /* List of fragments for one src line */
|
||||||
FilePos Pos; /* File position for this fragment */
|
Collection LI; /* Line info for this fragment */
|
||||||
struct LineInfo* LI; /* Extra line info */
|
unsigned short Len; /* Length for this fragment */
|
||||||
unsigned short Len; /* Length for this fragment */
|
unsigned char Type; /* Fragment type */
|
||||||
unsigned char Type; /* Fragment type */
|
|
||||||
union {
|
union {
|
||||||
unsigned char Data[4]; /* Literal values */
|
unsigned char Data[4]; /* Literal values */
|
||||||
ExprNode* Expr; /* Expression */
|
ExprNode* Expr; /* Expression */
|
||||||
} V;
|
} V;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -43,28 +43,90 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
#include "objfile.h"
|
#include "global.h"
|
||||||
#include "lineinfo.h"
|
#include "lineinfo.h"
|
||||||
|
#include "objfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* An invalid line info index */
|
||||||
|
#define INV_LINEINFO_INDEX UINT_MAX
|
||||||
|
|
||||||
/* Collection containing all line infos */
|
/* Collection containing all line infos */
|
||||||
Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
|
static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
|
||||||
unsigned LineInfoValid = 0; /* Valid, that is, used entries */
|
|
||||||
|
|
||||||
/* Static pointer to last line info or NULL if not active */
|
/* Number of valid (=used) line infos in LineInfoColl */
|
||||||
LineInfo* CurLineInfo = 0;
|
static unsigned UsedLineInfoCount;
|
||||||
|
|
||||||
|
/* Entry in CurLineInfo */
|
||||||
|
typedef struct LineInfoSlot LineInfoSlot;
|
||||||
|
struct LineInfoSlot {
|
||||||
|
unsigned Type;
|
||||||
|
LineInfo* Info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Dynamically allocated array of LineInfoSlots */
|
||||||
|
static LineInfoSlot* CurLineInfo;
|
||||||
|
static unsigned AllocatedSlots;
|
||||||
|
static unsigned UsedSlots;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* struct LineInfo */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static LineInfo* NewLineInfo (unsigned Type, unsigned File,
|
||||||
|
unsigned long Line, unsigned Col)
|
||||||
|
/* Create and return a new line info. Usage will be zero. */
|
||||||
|
{
|
||||||
|
/* Allocate memory */
|
||||||
|
LineInfo* LI = xmalloc (sizeof (LineInfo));
|
||||||
|
|
||||||
|
/* Initialize the fields */
|
||||||
|
LI->Usage = 0;
|
||||||
|
LI->Type = Type;
|
||||||
|
LI->Index = INV_LINEINFO_INDEX;
|
||||||
|
LI->Pos.Name = File;
|
||||||
|
LI->Pos.Line = Line;
|
||||||
|
LI->Pos.Col = Col;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -74,24 +136,131 @@ LineInfo* CurLineInfo = 0;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static LineInfo* NewLineInfo (unsigned File, unsigned long Line, unsigned Col)
|
void InitLineInfo (void)
|
||||||
/* Create and return a new line info. Usage will be zero. */
|
/* Initialize the line infos */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate 8 slots */
|
||||||
LineInfo* LI = xmalloc (sizeof (LineInfo));
|
AllocatedSlots = 8;
|
||||||
|
CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initalize the predefined slots */
|
||||||
LI->Usage = 0;
|
UsedSlots = 2;
|
||||||
LI->Index = 0; /* Currently invalid */
|
CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM;
|
||||||
LI->Pos.Line = Line;
|
CurLineInfo[LI_SLOT_ASM].Info = 0;
|
||||||
LI->Pos.Col = Col;
|
CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT;
|
||||||
LI->Pos.Name = File;
|
CurLineInfo[LI_SLOT_EXT].Info = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Insert this structure into the collection */
|
|
||||||
CollAppend (&LineInfoColl, LI);
|
|
||||||
|
|
||||||
/* Return the new struct */
|
|
||||||
return LI;
|
unsigned AllocLineInfoSlot (unsigned Type)
|
||||||
|
/* Allocate a line info slot of the given type and return the slot index */
|
||||||
|
{
|
||||||
|
/* Grow the array if necessary */
|
||||||
|
if (UsedSlots >= AllocatedSlots) {
|
||||||
|
LineInfoSlot* NewLineInfo;
|
||||||
|
AllocatedSlots *= 2;
|
||||||
|
NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
|
||||||
|
memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
|
||||||
|
xfree (CurLineInfo);
|
||||||
|
CurLineInfo = NewLineInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Array is now big enough, add the new data */
|
||||||
|
CurLineInfo[UsedSlots].Type = Type;
|
||||||
|
CurLineInfo[UsedSlots].Info = 0;
|
||||||
|
|
||||||
|
/* Increment the count and return the index of the new slot */
|
||||||
|
return UsedSlots++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FreeLineInfoSlot (unsigned Slot)
|
||||||
|
/* Free the line info in the given slot. Note: Alloc/Free must be used in
|
||||||
|
* FIFO order.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Check the parameter */
|
||||||
|
PRECONDITION (Slot == UsedSlots - 1);
|
||||||
|
|
||||||
|
/* Free the last entry */
|
||||||
|
FreeLineInfo (CurLineInfo[Slot].Info);
|
||||||
|
--UsedSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GenLineInfo (unsigned Slot, unsigned File, unsigned long Line, unsigned Col)
|
||||||
|
/* Generate a new line info in the given slot */
|
||||||
|
{
|
||||||
|
/* 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 (S->Info->Pos.Col == Col &&
|
||||||
|
S->Info->Pos.Line == Line &&
|
||||||
|
S->Info->Pos.Name == File) {
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate new data */
|
||||||
|
S->Info = NewLineInfo (S->Type, File, Line, Col);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LineInfo* GetLineInfo (unsigned Slot)
|
||||||
|
/* Get the line info from the given slot */
|
||||||
|
{
|
||||||
|
PRECONDITION (Slot < UsedSlots);
|
||||||
|
return CurLineInfo[Slot].Info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GetFullLineInfo (Collection* LineInfos)
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Copy all valid line infos to the collection */
|
||||||
|
for (I = 0; I < UsedSlots; ++I) {
|
||||||
|
|
||||||
|
/* Get the slot */
|
||||||
|
LineInfoSlot* S = CurLineInfo + I;
|
||||||
|
|
||||||
|
/* Ignore empty slots */
|
||||||
|
if (S->Info) {
|
||||||
|
++S->Info->Usage;
|
||||||
|
CollAppend (LineInfos, S->Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -102,35 +271,30 @@ LineInfo* UseLineInfo (LineInfo* LI)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (LI) {
|
if (LI) {
|
||||||
if (LI->Usage++ == 0) {
|
++LI->Usage;
|
||||||
/* One more valid line info */
|
|
||||||
++LineInfoValid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return LI;
|
return LI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GenLineInfo (unsigned FileIndex, unsigned long LineNum, unsigned ColNum)
|
LineInfo* ReleaseLineInfo (LineInfo* LI)
|
||||||
/* Generate a new line info */
|
/* Decrease the reference count of the given line info and return it. The
|
||||||
|
* function will gracefully accept NULL pointers and do nothing in this case.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
/* Create a new line info and make it current */
|
if (LI) {
|
||||||
CurLineInfo = NewLineInfo (FileIndex, LineNum, ColNum);
|
/* Cannot decrease below zero */
|
||||||
}
|
CHECK (LI->Usage != 0);
|
||||||
|
--LI->Usage;
|
||||||
|
}
|
||||||
|
return LI;
|
||||||
void ClearLineInfo (void)
|
|
||||||
/* Clear the current line info */
|
|
||||||
{
|
|
||||||
CurLineInfo = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int CmpLineInfo (void* Data attribute ((unused)),
|
static int CmpLineInfo (void* Data attribute ((unused)),
|
||||||
const void* LI1_, const void* LI2_)
|
const void* LI1_, const void* LI2_)
|
||||||
/* Compare function for the sort */
|
/* Compare function for the sort */
|
||||||
{
|
{
|
||||||
/* Cast the pointers */
|
/* Cast the pointers */
|
||||||
@@ -138,21 +302,11 @@ static int CmpLineInfo (void* Data attribute ((unused)),
|
|||||||
const LineInfo* LI2 = LI2_;
|
const LineInfo* LI2 = LI2_;
|
||||||
|
|
||||||
/* Unreferenced line infos are always larger, otherwise sort by file,
|
/* Unreferenced line infos are always larger, otherwise sort by file,
|
||||||
* then by line.
|
* then by line, then by column.
|
||||||
*/
|
*/
|
||||||
if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
|
if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
|
||||||
/* Both are either referenced or unreferenced */
|
/* Both are either referenced or unreferenced */
|
||||||
if (LI1->Pos.Name< LI2->Pos.Name) {
|
return CompareFilePos (&LI1->Pos, &LI2->Pos);
|
||||||
return -1;
|
|
||||||
} else if (LI1->Pos.Name > LI2->Pos.Name) {
|
|
||||||
return 1;
|
|
||||||
} else if (LI1->Pos.Line < LI2->Pos.Line) {
|
|
||||||
return -1;
|
|
||||||
} else if (LI1->Pos.Line > LI2->Pos.Line) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (LI1->Usage > 0) {
|
if (LI1->Usage > 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -164,25 +318,54 @@ static int CmpLineInfo (void* Data attribute ((unused)),
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WriteLineInfo (const Collection* LineInfos)
|
||||||
|
/* Write a list of line infos to the object file. MakeLineInfoIndex has to
|
||||||
|
* be called before!
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Write the count */
|
||||||
|
ObjWriteVar (CollCount (LineInfos));
|
||||||
|
|
||||||
|
/* Write the line info indices */
|
||||||
|
for (I = 0; I < CollCount (LineInfos); ++I) {
|
||||||
|
ObjWriteVar (((const LineInfo*) CollConstAt (LineInfos, I))->Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MakeLineInfoIndex (void)
|
void MakeLineInfoIndex (void)
|
||||||
/* Sort the line infos and drop all unreferenced ones */
|
/* Index the line infos */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
/* Sort the collection */
|
/* Sort the collection */
|
||||||
CollSort (&LineInfoColl, CmpLineInfo, 0);
|
CollSort (&LineInfoColl, CmpLineInfo, 0);
|
||||||
|
|
||||||
/* Walk over the list and index the line infos. */
|
/* Walk over the list, index the line infos and count the used ones */
|
||||||
for (I = 0; I < LineInfoValid; ++I) {
|
UsedLineInfoCount = 0;
|
||||||
|
for (I = 0; I < CollCount (&LineInfoColl); ++I) {
|
||||||
/* Get a pointer to this line info */
|
/* Get a pointer to this line info */
|
||||||
LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
|
LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
|
||||||
LI->Index = I;
|
|
||||||
|
/* If it is invalid, terminate the loop. All unused line infos were
|
||||||
|
* placed at the end of the collection by the sort.
|
||||||
|
*/
|
||||||
|
if (LI->Usage == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Index and count this one */
|
||||||
|
LI->Index = I;
|
||||||
|
++UsedLineInfoCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void WriteLineInfo (void)
|
void WriteLineInfos (void)
|
||||||
/* Write a list of all line infos to the object file. */
|
/* Write a list of all line infos to the object file. */
|
||||||
{
|
{
|
||||||
/* Tell the object file module that we're about to write line infos */
|
/* Tell the object file module that we're about to write line infos */
|
||||||
@@ -194,15 +377,12 @@ void WriteLineInfo (void)
|
|||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
/* Write the line info count to the list */
|
/* Write the line info count to the list */
|
||||||
ObjWriteVar (LineInfoValid);
|
ObjWriteVar (UsedLineInfoCount);
|
||||||
|
|
||||||
/* Walk through list and write all line infos that have references.
|
/* Walk over the list and write all line infos */
|
||||||
* Because of the sort, this are exactly the first LineInfoValid
|
for (I = 0; I < UsedLineInfoCount; ++I) {
|
||||||
* ones.
|
|
||||||
*/
|
|
||||||
for (I = 0; I < LineInfoValid; ++I) {
|
|
||||||
/* Get a pointer to this line info */
|
/* Get a pointer to this line info */
|
||||||
LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
|
LineInfo* LI = CollAt (&LineInfoColl, I);
|
||||||
/* Write the source file position */
|
/* Write the source file position */
|
||||||
ObjWritePos (&LI->Pos);
|
ObjWritePos (&LI->Pos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,34 +52,46 @@
|
|||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
#include "filepos.h"
|
#include "filepos.h"
|
||||||
|
|
||||||
/* ca65 */
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Predefined line info slots. These are allocated when initializing the
|
||||||
|
* module. Beware: Some code relies on the fact that slot zero is the basic
|
||||||
|
* standard line info. It is assumed to be always there.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
LI_SLOT_ASM = 0, /* Normal assembler source */
|
||||||
|
LI_SLOT_EXT = 1, /* Externally supplied line info */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Types of line infos. The low byte may be used for some sort of depth
|
||||||
|
* counter.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
LI_MASK_COUNT = 0x00FF, /* Mask to extract the count */
|
||||||
|
|
||||||
|
LI_TYPE_EXT = 0x0100, /* Externally supplied line info */
|
||||||
|
LI_TYPE_ASM = 0x0200, /* Normal assembler source */
|
||||||
|
LI_TYPE_MACRO = 0x0300, /* Macro expansion */
|
||||||
|
LI_MASK_TYPE = 0x7F00, /* Mask to extract the type */
|
||||||
|
};
|
||||||
|
|
||||||
/* The LineInfo structure is shared between several fragments, so we need a
|
/* The LineInfo structure is shared between several fragments, so we need a
|
||||||
* reference counter.
|
* reference counter.
|
||||||
*/
|
*/
|
||||||
typedef struct LineInfo LineInfo;
|
typedef struct LineInfo LineInfo;
|
||||||
struct LineInfo {
|
struct LineInfo {
|
||||||
unsigned Usage; /* Usage counter */
|
unsigned Usage; /* Usage counter */
|
||||||
unsigned Index; /* Index */
|
unsigned Type; /* Type of line info */
|
||||||
FilePos Pos; /* File position */
|
unsigned Index; /* Index */
|
||||||
|
FilePos Pos; /* File position */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Collection containing all line infos */
|
|
||||||
extern Collection LineInfoColl;
|
|
||||||
extern unsigned LineInfoValid; /* Valid, that is, used entries */
|
|
||||||
|
|
||||||
/* Global pointer to last line info or NULL if not active */
|
|
||||||
extern LineInfo* CurLineInfo;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -88,23 +100,50 @@ extern LineInfo* CurLineInfo;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void InitLineInfo (void);
|
||||||
|
/* Initialize the line infos */
|
||||||
|
|
||||||
|
unsigned AllocLineInfoSlot (unsigned Type);
|
||||||
|
/* Allocate a line info slot of the given type and return the slot index */
|
||||||
|
|
||||||
|
void FreeLineInfoSlot (unsigned Slot);
|
||||||
|
/* Free the line info in the given slot. Note: Alloc/Free must be used in
|
||||||
|
* FIFO order.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void GenLineInfo (unsigned Slot, unsigned File, unsigned long Line, unsigned Col);
|
||||||
|
/* Generate a new line info in the given slot */
|
||||||
|
|
||||||
|
void ClearLineInfo (unsigned Slot);
|
||||||
|
/* Clear the line info in the given slot */
|
||||||
|
|
||||||
|
LineInfo* GetLineInfo (unsigned Slot);
|
||||||
|
/* Get the line info from the given slot */
|
||||||
|
|
||||||
|
void GetFullLineInfo (Collection* LineInfos);
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
LineInfo* UseLineInfo (LineInfo* LI);
|
LineInfo* UseLineInfo (LineInfo* LI);
|
||||||
/* Increase the reference count of the given line info and return it. The
|
/* Increase the reference count of the given line info and return it. The
|
||||||
* function will gracefully accept NULL pointers and do nothing in this case.
|
* function will gracefully accept NULL pointers and do nothing in this case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void GenLineInfo (unsigned FileIndex, unsigned long LineNum, unsigned ColNum);
|
LineInfo* ReleaseLineInfo (LineInfo* LI);
|
||||||
/* Generate a new line info */
|
/* Decrease the reference count of the given line info and return it. The
|
||||||
|
* function will gracefully accept NULL pointers and do nothing in this case.
|
||||||
void ClearLineInfo (void);
|
|
||||||
/* Clear the current line info */
|
|
||||||
|
|
||||||
void MakeLineInfoIndex (void);
|
|
||||||
/* Walk over the line info list and make an index of all entries ignoring
|
|
||||||
* those with a usage count of zero.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void WriteLineInfo (void);
|
void WriteLineInfo (const Collection* LineInfos);
|
||||||
|
/* Write a list of line infos to the object file. MakeLineInfoIndex has to
|
||||||
|
* be called before!
|
||||||
|
*/
|
||||||
|
|
||||||
|
void MakeLineInfoIndex (void);
|
||||||
|
/* Index the line infos */
|
||||||
|
|
||||||
|
void WriteLineInfos (void);
|
||||||
/* Write a list of all line infos to the object file. */
|
/* Write a list of all line infos to the object file. */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -805,7 +805,7 @@ static void CreateObjFile (void)
|
|||||||
WriteDbgSyms ();
|
WriteDbgSyms ();
|
||||||
|
|
||||||
/* Write line infos if requested */
|
/* Write line infos if requested */
|
||||||
WriteLineInfo ();
|
WriteLineInfos ();
|
||||||
|
|
||||||
/* Write the string pool */
|
/* Write the string pool */
|
||||||
WriteStrPool ();
|
WriteStrPool ();
|
||||||
@@ -902,7 +902,7 @@ int main (int argc, char* argv [])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
OutFile = GetArg (&I, 2);
|
OutFile = GetArg (&I, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
@@ -926,7 +926,7 @@ int main (int argc, char* argv [])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
OptAutoImport (Arg, 0);
|
OptAutoImport (Arg, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
@@ -980,6 +980,9 @@ int main (int argc, char* argv [])
|
|||||||
/* Initialize the segments */
|
/* Initialize the segments */
|
||||||
InitSegments ();
|
InitSegments ();
|
||||||
|
|
||||||
|
/* Initialize the line infos */
|
||||||
|
InitLineInfo ();
|
||||||
|
|
||||||
/* Initialize the scanner, open the input file */
|
/* Initialize the scanner, open the input file */
|
||||||
InitScanner (InFile);
|
InitScanner (InFile);
|
||||||
|
|
||||||
|
|||||||
@@ -371,24 +371,24 @@ void SegCheck (void)
|
|||||||
if (Abs) {
|
if (Abs) {
|
||||||
/* Absolute value */
|
/* Absolute value */
|
||||||
if (Val > 255) {
|
if (Val > 255) {
|
||||||
PError (&F->Pos, "Range error (%ld not in [0..255])", Val);
|
LIError (&F->LI, "Range error (%ld not in [0..255])", Val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* PC relative value */
|
/* PC relative value */
|
||||||
if (Val < -128 || Val > 127) {
|
if (Val < -128 || Val > 127) {
|
||||||
PError (&F->Pos, "Range error (%ld not in [-128..127])", Val);
|
LIError (&F->LI, "Range error (%ld not in [-128..127])", Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (F->Len == 2) {
|
} else if (F->Len == 2) {
|
||||||
if (Abs) {
|
if (Abs) {
|
||||||
/* Absolute value */
|
/* Absolute value */
|
||||||
if (Val > 65535) {
|
if (Val > 65535) {
|
||||||
PError (&F->Pos, "Range error (%ld not in [0..65535])", Val);
|
LIError (&F->LI, "Range error (%ld not in [0..65535])", Val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* PC relative value */
|
/* PC relative value */
|
||||||
if (Val < -32768 || Val > 32767) {
|
if (Val < -32768 || Val > 32767) {
|
||||||
PError (&F->Pos, "Range error (%ld not in [-32768..32767])", Val);
|
LIError (&F->LI, "Range error (%ld not in [-32768..32767])", Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,7 +412,7 @@ void SegCheck (void)
|
|||||||
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
|
if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) ||
|
||||||
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
|
(F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
|
||||||
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
|
(F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
|
||||||
PError (&F->Pos, "Range error");
|
LIError (&F->LI, "Range error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +477,6 @@ static void WriteOneSeg (Segment* Seg)
|
|||||||
/* Write one segment to the object file */
|
/* Write one segment to the object file */
|
||||||
{
|
{
|
||||||
Fragment* Frag;
|
Fragment* Frag;
|
||||||
unsigned LineInfoIndex;
|
|
||||||
unsigned long DataSize;
|
unsigned long DataSize;
|
||||||
unsigned long EndPos;
|
unsigned long EndPos;
|
||||||
|
|
||||||
@@ -541,14 +540,8 @@ static void WriteOneSeg (Segment* Seg)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the file position of this fragment */
|
/* Write the line infos for this fragment */
|
||||||
ObjWritePos (&Frag->Pos);
|
WriteLineInfo (&Frag->LI);
|
||||||
|
|
||||||
/* Write extra line info for this fragment. Zero is considered
|
|
||||||
* "no line info", so add one to the value.
|
|
||||||
*/
|
|
||||||
LineInfoIndex = Frag->LI? Frag->LI->Index + 1 : 0;
|
|
||||||
ObjWriteVar (LineInfoIndex);
|
|
||||||
|
|
||||||
/* Next fragment */
|
/* Next fragment */
|
||||||
Frag = Frag->Next;
|
Frag = Frag->Next;
|
||||||
@@ -620,3 +613,4 @@ void WriteSegments (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user