From: uz Date: Sun, 14 Aug 2011 19:23:16 +0000 (+0000) Subject: Complete redesign of line info generation. Uses spans instead of a fragment X-Git-Tag: V2.13.3~300 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=b8549f0af8513bcb305b4746f438c4ebcc874cd0;p=cc65 Complete redesign of line info generation. Uses spans instead of a fragment list as before. git-svn-id: svn://svn.cc65.org/cc65/trunk@5162 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index fc0e0ba77..274b1a1d9 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -487,7 +487,7 @@ void CheckOpenIfs (void) } LI = CollConstAt (&D->LineInfos, 0); - if (LI->Pos.Name != CurTok.Pos.Name) { + if (GetSourcePos (LI)->Name != CurTok.Pos.Name) { /* The .if is from another file, bail out */ break; } diff --git a/src/ca65/dbginfo.c b/src/ca65/dbginfo.c index 59390cc62..86a470d6c 100644 --- a/src/ca65/dbginfo.c +++ b/src/ca65/dbginfo.c @@ -49,7 +49,18 @@ /*****************************************************************************/ -/* Code */ +/* Data */ +/*****************************************************************************/ + + + +/* The current line info */ +static LineInfo* CurLineInfo = 0; + + + +/*****************************************************************************/ +/* Code */ /*****************************************************************************/ @@ -99,11 +110,16 @@ void DbgInfoLine (void) long Line; FilePos Pos = STATIC_FILEPOS_INITIALIZER; + /* Any new line info terminates the last one */ + if (CurLineInfo) { + EndLine (CurLineInfo); + CurLineInfo = 0; + } + /* If a parameters follow, this is actual line info. If no parameters * follow, the last line info is terminated. */ if (CurTok.Tok == TOK_SEP) { - ClearLineInfo (LI_SLOT_EXT); return; } @@ -133,8 +149,8 @@ void DbgInfoLine (void) } Pos.Line = Line; - /* Remember the line info */ - GenLineInfo (LI_SLOT_EXT, &Pos); + /* Generate a new external line info */ + CurLineInfo = StartLine (&Pos, LI_TYPE_EXT, 0); } diff --git a/src/ca65/filetab.c b/src/ca65/filetab.c index ad760988f..84282296b 100644 --- a/src/ca65/filetab.c +++ b/src/ca65/filetab.c @@ -61,7 +61,7 @@ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ -static const void* HT_GetKey (void* Entry); +static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key. */ static int HT_Compare (const void* Key1, const void* Key2); @@ -122,7 +122,7 @@ static unsigned HT_GenHash (const void* Key) -static const void* HT_GetKey (void* Entry) +static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the index */ { return &((FileEntry*) Entry)->Name; @@ -134,7 +134,7 @@ static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if * Key1 is smaller than Key2, zero if both are equal, and a value greater * than zero if Key1 is greater then Key2. - */ + */ { return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2; } diff --git a/src/ca65/lineinfo.c b/src/ca65/lineinfo.c index d1faa21a2..7c8bf68fe 100644 --- a/src/ca65/lineinfo.c +++ b/src/ca65/lineinfo.c @@ -34,16 +34,38 @@ #include -#include /* common */ #include "coll.h" +#include "hashfunc.h" #include "xmalloc.h" /* ca65 */ #include "global.h" #include "lineinfo.h" #include "objfile.h" +#include "scanner.h" +#include "span.h" + + + +/*****************************************************************************/ +/* Forwards */ +/*****************************************************************************/ + + + +static unsigned HT_GenHash (const void* Key); +/* Generate the hash over a key. */ + +static const void* HT_GetKey (const void* Entry); +/* Given a pointer to the user entry data, return a pointer to the key */ + +static int HT_Compare (const void* Key1, const void* Key2); +/* Compare two keys. The function must return a value less than zero if + * Key1 is smaller than Key2, zero if both are equal, and a value greater + * than zero if Key1 is greater then Key2. + */ @@ -53,26 +75,99 @@ -/* An invalid line info index */ -#define INV_LINEINFO_INDEX UINT_MAX +/* Structure that holds the key for a line info */ +typedef struct LineInfoKey LineInfoKey; +struct LineInfoKey { + FilePos Pos; /* File position */ + unsigned short Type; /* Type of line info */ + unsigned short Count; /* Recursion counter */ +}; + +/* Structure that holds line info */ +struct LineInfo { + HashNode Node; /* Hash table node */ + unsigned Id; /* Index */ + LineInfoKey Key; /* Key for this line info */ + unsigned char Hashed; /* True if in hash list */ + unsigned char Referenced; /* Force reference even if no spans */ + Collection Spans; /* Segment spans for this line info */ + Collection OpenSpans; /* List of currently open spans */ +}; + + /* Collection containing all line infos */ -static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER; +static Collection LineInfoList = STATIC_COLLECTION_INITIALIZER; -/* Number of valid (=used) line infos in LineInfoColl */ -static unsigned UsedLineInfoCount; +/* Collection with currently active line infos */ +static Collection CurLineInfo = STATIC_COLLECTION_INITIALIZER; -/* Entry in CurLineInfo */ -typedef struct LineInfoSlot LineInfoSlot; -struct LineInfoSlot { - unsigned Type; - LineInfo* Info; +/* Hash table functions */ +static const HashFunctions HashFunc = { + HT_GenHash, + HT_GetKey, + HT_Compare }; -/* Dynamically allocated array of LineInfoSlots */ -static LineInfoSlot* CurLineInfo; -static unsigned AllocatedSlots; -static unsigned UsedSlots; +/* Line info hash table */ +static HashTable LineInfoTab = STATIC_HASHTABLE_INITIALIZER (1051, &HashFunc); + +/* The current assembler input line */ +static LineInfo* AsmLineInfo = 0; + + + +/*****************************************************************************/ +/* Hash table functions */ +/*****************************************************************************/ + + + +static unsigned HT_GenHash (const void* Key) +/* Generate the hash over a key. */ +{ + /* Key is a LineInfoKey pointer */ + const LineInfoKey* K = Key; + + /* Hash over a combination of type, file and line */ + return HashInt ((K->Type << 18) ^ (K->Pos.Name << 14) ^ K->Pos.Line); +} + + + +static const void* HT_GetKey (const void* Entry) +/* Given a pointer to the user entry data, return a pointer to the key */ +{ + return &((const LineInfo*)Entry)->Key; +} + + + +static int HT_Compare (const void* Key1, const void* Key2) +/* Compare two keys. The function must return a value less than zero if + * Key1 is smaller than Key2, zero if both are equal, and a value greater + * than zero if Key1 is greater then Key2. + */ +{ + /* Convert both parameters to FileInfoKey pointers */ + const LineInfoKey* K1 = Key1; + const LineInfoKey* K2 = Key2; + + /* Compare line number, then file and type, then count */ + int Res = (int)K2->Pos.Line - (int)K1->Pos.Line; + if (Res == 0) { + Res = (int)K2->Pos.Name - (int)K1->Pos.Name; + if (Res == 0) { + Res = (int)K2->Type - (int)K1->Type; + if (Res == 0) { + Res = (int)K2->Count - (int)K1->Count; + } + } + } + + /* Done */ + return Res; +} @@ -82,20 +177,20 @@ static unsigned UsedSlots; -static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos) +static LineInfo* NewLineInfo (const LineInfoKey* Key) /* 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 = *Pos; - - /* Add the line info to the list of all line infos */ - CollAppend (&LineInfoColl, LI); + InitHashNode (&LI->Node); + LI->Id = ~0U; + LI->Key = *Key; + LI->Hashed = 0; + LI->Referenced= 0; + InitCollection (&LI->Spans); + InitCollection (&LI->OpenSpans); /* Return the new struct */ return LI; @@ -103,6 +198,40 @@ static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos) +static void FreeLineInfo (LineInfo* LI) +/* Free a LineInfo structure */ +{ + /* Free the Spans collection. It is supposed to be empty */ + CHECK (CollCount (&LI->Spans) == 0); + DoneCollection (&LI->Spans); + DoneCollection (&LI->OpenSpans); + + /* Free the structure itself */ + xfree (LI); +} + + + +static void RememberLineInfo (LineInfo* LI) +/* Remember a LineInfo by adding it to the hash table and the global list. + * This will also assign the id which is actually the list position. + */ +{ + /* Assign the id */ + LI->Id = CollCount (&LineInfoList); + + /* Remember it in the global list */ + CollAppend (&LineInfoList, LI); + + /* Add it to the hash table, so we will find it if necessary */ + HT_InsertEntry (&LineInfoTab, LI); + + /* Remember that we have it */ + LI->Hashed = 1; +} + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -115,94 +244,128 @@ 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)); + CollGrow (&LineInfoList, 200); - /* Initalize the predefined slots. Be sure to create a new LineInfo for - * the default source. This is necessary to allow error message to be - * generated without any input file open. + /* Create a LineInfo for the default source. This is necessary to allow + * error message to be generated without any input file open. */ - UsedSlots = 2; - CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM; /* Count = 0 */ - CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos); - CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT; /* Count = 0 */ - CurLineInfo[LI_SLOT_EXT].Info = 0; + AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0); } -int AllocLineInfoSlot (unsigned Type, unsigned Count) -/* Allocate a line info slot of the given type and return the slot index */ +void DoneLineInfo (void) +/* Close down line infos */ { - /* 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; + /* Close all current line infos */ + unsigned Count = CollCount (&CurLineInfo); + while (Count) { + EndLine (CollAt (&CurLineInfo, --Count)); } - - /* Array is now big enough, add the new data */ - CurLineInfo[UsedSlots].Type = LI_MAKE_TYPE(Type, Count); - CurLineInfo[UsedSlots].Info = 0; - - /* Increment the count and return the index of the new slot */ - return (int) UsedSlots++; } -void FreeLineInfoSlot (int Slot) -/* Free the line info in the given slot. Note: Alloc/Free must be used in - * FIFO order. - */ +void EndLine (LineInfo* LI) +/* End a line that is tracked by the given LineInfo structure */ { - /* Check the parameter */ - PRECONDITION (Slot == (int) UsedSlots - 1); + unsigned I; + + /* Close the spans for the line */ + CloseSpans (&LI->OpenSpans); + + /* Move the spans to the list of all spans for this line, then clear the + * list of open spans. + */ + for (I = 0; I < CollCount (&LI->OpenSpans); ++I) { + CollAppend (&LI->Spans, CollAtUnchecked (&LI->OpenSpans, I)); + } + CollDeleteAll (&LI->OpenSpans); + + /* Line info is no longer active - remove it from the list of current + * line infos. + */ + CollDeleteItem (&CurLineInfo, LI); - /* Free the last entry */ - CurLineInfo[Slot].Info = 0; - --UsedSlots; + /* If this line info is already hashed, we're done. Otherwise, if it is + * marked as referenced or has non empty spans, remember it. It it is not + * referenced or doesn't have open spans, delete it. + */ + if (!LI->Hashed) { + if (LI->Referenced || CollCount (&LI->Spans) > 0) { + RememberLineInfo (LI); + } else { + FreeLineInfo (LI); + } + } } -void GenLineInfo (int Slot, const FilePos* Pos) -/* Generate a new line info in the given slot */ +LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count) +/* Start line info for a new line */ { - /* Get a pointer to the slot */ - LineInfoSlot* S = CurLineInfo + Slot; + LineInfoKey Key; + LineInfo* LI; + + /* Prepare the key struct */ + Key.Pos = *Pos; + Key.Type = Type; + Key.Count = Count; - /* Generate new data only if it is different from the existing. */ - if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) { - /* Already there */ - return; + /* Try to find a line info with this position and type in the hash table. + * If so, reuse it. Otherwise create a new one. + */ + LI = HT_FindEntry (&LineInfoTab, &Key); + if (LI == 0) { + /* Allocate a new LineInfo */ + LI = NewLineInfo (&Key); + } else { + Key.Count = 2; } - /* Allocate new data */ - S->Info = NewLineInfo (S->Type, Pos); + /* Open the spans for this line info */ + OpenSpans (&LI->OpenSpans); + + /* Add the line info to the list of current line infos */ + CollAppend (&CurLineInfo, LI); + + /* Return the new info */ + return LI; } -void ClearLineInfo (int Slot) -/* Clear the line info in the given slot */ +void NewAsmLine (void) +/* Start a new assembler input line. Use this function when generating new + * line of LI_TYPE_ASM. It will check if line and/or file have actually + * changed, end the old and start the new line as necessary. + */ { - /* Zero the pointer */ - CurLineInfo[Slot].Info = 0; + /* Check if we can reuse the old line */ + if (AsmLineInfo) { + if (AsmLineInfo->Key.Pos.Line == CurTok.Pos.Line && + AsmLineInfo->Key.Pos.Name == CurTok.Pos.Name) { + /* We do already have line info for this line */ + return; + } + + /* Line has changed -> end the old line */ + EndLine (AsmLineInfo); + } + + /* Start a new line using the current line info */ + AsmLineInfo = StartLine (&CurTok.Pos, LI_TYPE_ASM, 0); } -void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage) -/* Return full line infos, that is line infos for all slots in LineInfos. The - * function will clear LineInfos before usage and will increment the usage - * counter by IncUsage for all line infos returned. +void GetFullLineInfo (Collection* LineInfos, int ForceRef) +/* Return full line infos, that is line infos for currently active Slots. The + * function will clear LineInfos before usage. If ForceRef is not zero, a + * forced reference will be added to all line infos, with the consequence that + * they won't get deleted, even if there is no code or data generated for these + * lines. */ { unsigned I; @@ -210,66 +373,45 @@ void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage) /* Clear the collection */ CollDeleteAll (LineInfos); + /* Grow the collection as necessary */ + CollGrow (LineInfos, CollCount (&CurLineInfo)); + /* Copy all valid line infos to the collection */ - for (I = 0; I < UsedSlots; ++I) { + for (I = 0; I < CollCount (&CurLineInfo); ++I) { /* Get the line info from the slot */ - LineInfo* LI = CurLineInfo[I].Info; + LineInfo* LI = CollAt (&CurLineInfo, I); - /* Ignore empty slots */ - if (LI) { - LI->Usage += IncUsage; - CollAppend (LineInfos, LI); + /* Mark it as referenced */ + if (ForceRef) { + LI->Referenced = 1; } + + /* Return it to the caller */ + CollAppend (LineInfos, LI); } } -LineInfo* ReleaseLineInfo (LineInfo* LI) -/* 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. - */ +const FilePos* GetSourcePos (const LineInfo* LI) +/* Return the source file position from the given line info */ { - if (LI) { - /* Cannot decrease below zero */ - CHECK (LI->Usage != 0); - --LI->Usage; - } - return LI; + return &LI->Key.Pos; } -static int CmpLineInfo (void* Data attribute ((unused)), - const void* LI1_, const void* LI2_) -/* Compare function for the sort */ +unsigned GetLineInfoType (const LineInfo* LI) +/* Return the type of a line info */ { - /* Cast the pointers */ - const LineInfo* LI1 = LI1_; - const LineInfo* LI2 = LI2_; - - /* Unreferenced line infos are always larger, otherwise sort by file, - * then by line, then by column. - */ - if ((LI1->Usage == 0) == (LI2->Usage == 0)) { - /* Both are either referenced or unreferenced */ - return CompareFilePos (&LI1->Pos, &LI2->Pos); - } else { - if (LI1->Usage > 0) { - return -1; - } else { - return 1; - } - } + return LI_GET_TYPE (LI->Key.Type); } void WriteLineInfo (const Collection* LineInfos) -/* Write a list of line infos to the object file. MakeLineInfoIndex has to - * be called before! - */ +/* Write a list of line infos to the object file. */ { unsigned I; @@ -282,40 +424,10 @@ void WriteLineInfo (const Collection* LineInfos) /* Get a pointer to the line info */ const LineInfo* LI = CollConstAt (LineInfos, I); - /* Check the index */ - CHECK (LI->Index != INV_LINEINFO_INDEX); + CHECK (LI->Id != ~0U); /* Write the index to the file */ - ObjWriteVar (LI->Index); - } -} - - - -void MakeLineInfoIndex (void) -/* Index the line infos */ -{ - unsigned I; - - /* Sort the line info list */ - CollSort (&LineInfoColl, CmpLineInfo, 0); - - /* Walk over the list, index the line infos and count the used ones */ - UsedLineInfoCount = 0; - for (I = 0; I < CollCount (&LineInfoColl); ++I) { - /* Get a pointer to this line info */ - LineInfo* LI = CollAtUnchecked (&LineInfoColl, 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; + ObjWriteVar (LI->Id); } } @@ -330,18 +442,22 @@ void WriteLineInfos (void) ObjStartLineInfos (); /* Write the line info count to the list */ - ObjWriteVar (UsedLineInfoCount); + ObjWriteVar (CollCount (&LineInfoList)); /* Walk over the list and write all line infos */ - for (I = 0; I < UsedLineInfoCount; ++I) { + for (I = 0; I < CollCount (&LineInfoList); ++I) { + /* Get a pointer to this line info */ - LineInfo* LI = CollAt (&LineInfoColl, I); + LineInfo* LI = CollAt (&LineInfoList, I); + + /* Write the source file position */ + ObjWritePos (&LI->Key.Pos); /* Write the type and count of the line info */ - ObjWriteVar (LI->Type); + ObjWriteVar (LI_MAKE_TYPE (LI->Key.Type, LI->Key.Count)); - /* Write the source file position */ - ObjWritePos (&LI->Pos); + /* Write the spans for this line */ + WriteSpans (&LI->Spans); } /* End of line infos */ diff --git a/src/ca65/lineinfo.h b/src/ca65/lineinfo.h index 14ca35f81..17d2dfd43 100644 --- a/src/ca65/lineinfo.h +++ b/src/ca65/lineinfo.h @@ -41,6 +41,7 @@ /* common */ #include "coll.h" #include "filepos.h" +#include "hashtab.h" #include "lidefs.h" @@ -51,26 +52,8 @@ -/* 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_INV = -1, /* Use to mark invalid slots */ - LI_SLOT_ASM = 0, /* Normal assembler source */ - LI_SLOT_EXT = 1, /* Externally supplied line info */ -}; - -/* The LineInfo structure is shared between several fragments, so we need a - * reference counter. - */ +/* Opaque structure used to handle line information */ typedef struct LineInfo LineInfo; -struct LineInfo { - unsigned Usage; /* Usage counter */ - unsigned Type; /* Type of line info */ - unsigned Index; /* Index */ - FilePos Pos; /* File position */ -}; @@ -83,58 +66,37 @@ struct LineInfo { void InitLineInfo (void); /* Initialize the line infos */ -int AllocLineInfoSlot (unsigned Type, unsigned Count); -/* Allocate a line info slot of the given type and return the slot index */ - -void FreeLineInfoSlot (int Slot); -/* Free the line info in the given slot. Note: Alloc/Free must be used in - * FIFO order. - */ +void DoneLineInfo (void); +/* Close down line infos */ -void GenLineInfo (int Slot, const FilePos* Pos); -/* Generate a new line info in the given slot */ +void EndLine (LineInfo* LI); +/* End a line that is tracked by the given LineInfo structure */ -void ClearLineInfo (int Slot); -/* Clear the line info in the given slot */ +LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count); +/* Start line info for a new line */ -void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage); -/* Return full line infos, that is line infos for all slots in LineInfos. The - * function will clear LineInfos before usage and will increment the usage - * counter by IncUsage for all line infos returned. +void NewAsmLine (void); +/* Start a new assembler input line. Use this function when generating new + * line of LI_TYPE_ASM. It will check if line and/or file have actually + * changed, end the old and start the new line as necessary. */ -LineInfo* ReleaseLineInfo (LineInfo* LI); -/* 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 GetFullLineInfo (Collection* LineInfos, int ForceRef); +/* Return full line infos, that is line infos for currently active Slots. The + * function will clear LineInfos before usage. If ForceRef is not zero, a + * forced reference will be added to all line infos, with the consequence that + * they won't get deleted, even if there is no code or data generated for these + * lines. */ -#if defined(HAVE_INLINE) -INLINE const FilePos* GetSourcePos (const LineInfo* LI) +const FilePos* GetSourcePos (const LineInfo* LI); /* Return the source file position from the given line info */ -{ - return &LI->Pos; -} -#else -# define GetSourcePos(LI) (&(LI)->Pos) -#endif -#if defined(HAVE_INLINE) -INLINE unsigned GetLineInfoType (const LineInfo* LI) +unsigned GetLineInfoType (const LineInfo* LI); /* Return the type of a line info */ -{ - return LI_GET_TYPE (LI->Type); -} -#else -# define GetLineInfoType(LI) LI_GET_TYPE ((LI)->Type) -#endif 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 */ +/* Write a list of line infos to the object file. */ void WriteLineInfos (void); /* Write a list of all line infos to the object file. */ diff --git a/src/ca65/macro.c b/src/ca65/macro.c index 34d7eaeb7..b2fdaeaf7 100644 --- a/src/ca65/macro.c +++ b/src/ca65/macro.c @@ -65,7 +65,7 @@ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ -static const void* HT_GetKey (void* Entry); +static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ static int HT_Compare (const void* Key1, const void* Key2); @@ -130,7 +130,7 @@ struct MacExp { unsigned ParamCount; /* Number of actual parameters */ TokNode** Params; /* List of actual parameters */ TokNode* ParamExp; /* Node for expanding parameters */ - int LISlot; /* Slot for additional line infos */ + LineInfo* LI; /* Line info for the expansion */ }; /* Maximum number of nested macro expansions */ @@ -164,7 +164,7 @@ static unsigned HT_GenHash (const void* Key) -static const void* HT_GetKey (void* Entry) +static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the index */ { return &((Macro*) Entry)->Name; @@ -307,7 +307,7 @@ static MacExp* NewMacExp (Macro* M) E->Params[I] = 0; } E->ParamExp = 0; - E->LISlot = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions); + E->LI = 0; /* Mark the macro as expanding */ ++M->Expansions; @@ -344,8 +344,10 @@ static void FreeMacExp (MacExp* E) } xfree (E->Params); - /* Free the additional line info slot */ - FreeLineInfoSlot (E->LISlot); + /* Free the additional line info */ + if (E->LI) { + EndLine (E->LI); + } /* Free the final token if we have one */ if (E->Final) { @@ -644,8 +646,8 @@ static int MacExpand (void* Data) ExpandParam: if (Mac->ParamExp) { - /* Ok, use token from parameter list, but don't use its line info */ - TokSet (Mac->ParamExp, LI_SLOT_INV); + /* Ok, use token from parameter list */ + TokSet (Mac->ParamExp); /* Set pointer to next token */ Mac->ParamExp = Mac->ParamExp->Next; @@ -660,7 +662,13 @@ ExpandParam: if (Mac->Exp) { /* Use next macro token */ - TokSet (Mac->Exp, Mac->LISlot); + TokSet (Mac->Exp); + + /* Create new line info for this token */ + if (Mac->LI) { + EndLine (Mac->LI); + } + Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, MacExpansions); /* Set pointer to next token */ Mac->Exp = Mac->Exp->Next; @@ -723,7 +731,7 @@ ExpandParam: if (Mac->Final) { /* Set the final token and remove it */ - TokSet (Mac->Final, LI_SLOT_INV); + TokSet (Mac->Final); FreeTokNode (Mac->Final); Mac->Final = 0; diff --git a/src/ca65/main.c b/src/ca65/main.c index 30f22da14..1104f5b68 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -1036,15 +1036,15 @@ int main (int argc, char* argv []) CheckAssertions (); } - /* If we didn't have an errors, index the line infos */ - MakeLineInfoIndex (); - /* Dump the data */ if (Verbosity >= 2) { SymDump (stdout); SegDump (); } + /* If we didn't have an errors, finish off the line infos */ + DoneLineInfo (); + /* If we didn't have any errors, create the object, listing and * dependency files */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index c921562ee..bb31799dc 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -122,8 +122,8 @@ struct CharSource { /* Current input variables */ static CharSource* Source = 0; /* Current char source */ -static unsigned FCount = 0; /* Count of input files */ -static int C = 0; /* Current input character */ +static unsigned FCount = 0; /* Count of input files */ +static int C = 0; /* Current input character */ /* Force end of assembly */ int ForcedEnd = 0; @@ -818,7 +818,7 @@ static int Sweet16Reg (const StrBuf* Id) void NextRawTok (void) /* Read the next raw token from the input stream */ { - Macro* M; + Macro* M; /* If we've a forced end of assembly, don't read further */ if (ForcedEnd) { @@ -831,7 +831,7 @@ Restart: if (InputFromStack ()) { if (CurTok.Tok == TOK_IDENT && (M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ - MacExpandStart (M); + MacExpandStart (M); goto Restart; } return; @@ -852,7 +852,7 @@ Again: SB_Clear (&CurTok.SVal); /* Generate line info for the current token */ - GenLineInfo (LI_SLOT_ASM, &CurTok.Pos); + NewAsmLine (); /* Hex number or PC symbol? */ if (C == '$') { @@ -901,7 +901,7 @@ Again: CurTok.IVal = 0; } CurTok.IVal = (CurTok.IVal << 1) + DigitVal (C); - NextChar (); + NextChar (); } /* This is an integer constant */ @@ -1097,7 +1097,7 @@ Again: break; default: - break; + break; } } else if (CPU == CPU_SWEET16 && @@ -1195,7 +1195,7 @@ CharAgain: NextChar (); switch (C) { - case ':': + case ':': NextChar (); CurTok.Tok = TOK_NAMESPACE; break; @@ -1244,7 +1244,7 @@ CharAgain: case '#': NextChar (); CurTok.Tok = TOK_HASH; - return; + return; case '(': NextChar (); @@ -1342,7 +1342,7 @@ CharAgain: } CurTok.IVal = C; CurTok.Tok = TOK_CHARCON; - NextChar (); + NextChar (); if (C != '\'') { if (!MissingCharTerm) { Error ("Illegal character constant"); diff --git a/src/ca65/span.c b/src/ca65/span.c index 69d44ca45..e7339e78c 100644 --- a/src/ca65/span.c +++ b/src/ca65/span.c @@ -165,7 +165,9 @@ void WriteSpans (const Collection* Spans) /* Get next range */ const Span* S = CollConstAt (Spans, I); - /* Write data for th span We will write the size instead of the end + CHECK (S->End > S->Start); + + /* Write data for the span We will write the size instead of the end * offset to save some bytes, since most spans are expected to be * rather small. */ diff --git a/src/ca65/toklist.c b/src/ca65/toklist.c index efd5bc105..e79f1808a 100644 --- a/src/ca65/toklist.c +++ b/src/ca65/toklist.c @@ -82,20 +82,12 @@ void FreeTokNode (TokNode* N) -void TokSet (TokNode* N, int LineInfoSlot) -/* Set the scanner token from the given token node. If the given line info - * slot is not LI_SLOT_INV, it is used to store the position of the token fed - * into the scanner. - */ +void TokSet (TokNode* N) +/* Set the scanner token from the given token node. */ { /* Set the values */ CopyToken (&CurTok, &N->T); SB_Terminate (&CurTok.SVal); - - /* Set the position if the slot is not invald */ - if (LineInfoSlot != LI_SLOT_INV) { - GenLineInfo (LineInfoSlot, &CurTok.Pos); - } } @@ -227,7 +219,10 @@ static int ReplayTokList (void* List) CHECK (L->Last != 0); /* Set the next token from the list */ - TokSet (L->Last, LI_SLOT_ASM); + TokSet (L->Last); + + /* Set the line info for the new token */ + NewAsmLine (); /* If a check function is defined, call it, so it may look at the token * just set and changed it as apropriate. diff --git a/src/ca65/toklist.h b/src/ca65/toklist.h index 145c5f25a..b449ad9a0 100644 --- a/src/ca65/toklist.h +++ b/src/ca65/toklist.h @@ -95,11 +95,8 @@ TokNode* NewTokNode (void); void FreeTokNode (TokNode* N); /* Free the given token node */ -void TokSet (TokNode* N, int LineInfoSlot); -/* Set the scanner token from the given token node. If the given line info - * slot is not LI_SLOT_INV, it is used to store the position of the token fed - * into the scanner. - */ +void TokSet (TokNode* N); +/* Set the scanner token from the given token node. */ enum TC TokCmp (const TokNode* N); /* Compare the token given as parameter against the current token */