A->Action = Action;
A->Msg = Msg;
A->LI = EmptyCollection;
- GetFullLineInfo (&A->LI, 1);
+ GetFullLineInfo (&A->LI);
/* Return the new struct */
return A;
ID->Flags |= ifParentCond;
}
ID->LineInfos = EmptyCollection;
- GetFullLineInfo (&ID->LineInfos, 0);
+ GetFullLineInfo (&ID->LineInfos);
ID->Name = Directive;
/* One more slot allocated */
Done = 1;
} else {
Done = (ID->Flags & ifNeedTerm) != 0;
+ ReleaseFullLineInfo (&ID->LineInfos);
DoneCollection (&ID->LineInfos);
--IfCount;
}
/* Remember the data for the .ELSE */
if (D) {
- GetFullLineInfo (&D->LineInfos, 0);
+ ReleaseFullLineInfo (&D->LineInfos);
+ GetFullLineInfo (&D->LineInfos);
D->Name = ".ELSE";
}
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */
- GetFullLineInfo (&LineInfos, 0);
+ GetFullLineInfo (&LineInfos);
/* Output the message */
va_start (ap, Format);
va_end (ap);
/* Free the line info list */
+ ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos);
}
}
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */
- GetFullLineInfo (&LineInfos, 0);
+ GetFullLineInfo (&LineInfos);
/* Output the message */
va_start (ap, Format);
va_end (ap);
/* Free the line info list */
+ ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos);
}
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */
- GetFullLineInfo (&LineInfos, 0);
+ GetFullLineInfo (&LineInfos);
/* Output the message */
va_start (ap, Format);
va_end (ap);
/* Free the line info list */
+ ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos);
/* Skip tokens until we reach the end of the line */
F->Next = 0;
F->LineList = 0;
F->LI = EmptyCollection;
- GetFullLineInfo (&F->LI, 1);
+ GetFullLineInfo (&F->LI);
F->Len = Len;
F->Type = Type;
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 */
+ unsigned RefCount; /* Reference counter */
Collection Spans; /* Segment spans for this line info */
Collection OpenSpans; /* List of currently open spans */
};
InitHashNode (&LI->Node);
LI->Id = ~0U;
LI->Key = *Key;
- LI->Hashed = 0;
- LI->Referenced= 0;
+ LI->RefCount = 0;
InitCollection (&LI->Spans);
InitCollection (&LI->OpenSpans);
+ /* Add it to the hash table, so we will find it if necessary */
+ HT_InsertEntry (&LineInfoTab, LI);
+
/* Return the new struct */
return 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.
- */
+static int CheckLineInfo (void* Entry, void* Data attribute ((unused)))
+/* Called from HT_Walk. Remembers used line infos and assigns them an id */
{
- /* 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;
+ /* Entry is actually a line info */
+ LineInfo* LI = Entry;
+
+ /* The entry is used if there are spans or the ref counter is non zero */
+ if (LI->RefCount > 0 || CollCount (&LI->Spans) > 0) {
+ LI->Id = CollCount (&LineInfoList);
+ CollAppend (&LineInfoList, LI);
+ return 0; /* Keep the entry */
+ } else {
+ FreeLineInfo (LI);
+ return 1; /* Remove entry from table */
+ }
}
while (Count) {
EndLine (CollAt (&CurLineInfo, --Count));
}
+
+ /* Walk over the entries in the hash table and sort them into used and
+ * unused ones. Add the used ones to the line info list and assign them
+ * an id.
+ */
+ HT_Walk (&LineInfoTab, CheckLineInfo, 0);
}
* line infos.
*/
CollDeleteItem (&CurLineInfo, LI);
-
- /* 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 GetFullLineInfo (Collection* LineInfos, int ForceRef)
+LineInfo* GetAsmLineInfo (void)
+/* Return the line info for the current assembler file. The function will
+ * bump the reference counter before returning the line info.
+ */
+{
+ ++AsmLineInfo->RefCount;
+ return AsmLineInfo;
+}
+
+
+
+void ReleaseLineInfo (LineInfo* LI)
+/* Decrease the reference count for a line info */
+{
+ /* Decrease the reference counter */
+ CHECK (LI->RefCount > 0);
+ ++LI->RefCount;
+}
+
+
+
+void GetFullLineInfo (Collection* LineInfos)
/* 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.
+ * infos will be added to the given collection, existing entries will be left
+ * intact. The reference count of all added entries will be increased.
*/
{
unsigned I;
- /* Clear the collection */
- CollDeleteAll (LineInfos);
-
- /* Grow the collection as necessary */
- CollGrow (LineInfos, CollCount (&CurLineInfo));
+ /* If the collection is currently empty, grow it as necessary */
+ if (CollCount (LineInfos) == 0) {
+ CollGrow (LineInfos, CollCount (&CurLineInfo));
+ }
/* Copy all valid line infos to the collection */
for (I = 0; I < CollCount (&CurLineInfo); ++I) {
/* Get the line info from the slot */
LineInfo* LI = CollAt (&CurLineInfo, I);
- /* Mark it as referenced */
- if (ForceRef) {
- LI->Referenced = 1;
- }
+ /* Bump the reference counter */
+ ++LI->RefCount;
/* Return it to the caller */
CollAppend (LineInfos, LI);
+void ReleaseFullLineInfo (Collection* LineInfos)
+/* Decrease the reference count for a collection full of LineInfos, then clear
+ * the collection.
+ */
+{
+ unsigned I;
+
+ /* Walk over all entries */
+ for (I = 0; I < CollCount (LineInfos); ++I) {
+ /* Release the the line info */
+ ReleaseLineInfo (CollAt (LineInfos, I));
+ }
+
+ /* Delete all entries */
+ CollDeleteAll (LineInfos);
+}
+
+
+
const FilePos* GetSourcePos (const LineInfo* LI)
/* Return the source file position from the given line info */
{
/* Get a pointer to the line info */
const LineInfo* LI = CollConstAt (LineInfos, I);
+ /* Safety */
CHECK (LI->Id != ~0U);
/* Write the index to the file */
* changed, end the old and start the new line as necessary.
*/
-void GetFullLineInfo (Collection* LineInfos, int ForceRef);
+LineInfo* GetAsmLineInfo (void);
+/* Return the line info for the current assembler file. The function will
+ * bump the reference counter before returning the line info.
+ */
+
+void ReleaseLineInfo (LineInfo* LI);
+/* Decrease the reference count for a line info */
+
+void GetFullLineInfo (Collection* LineInfos);
/* 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.
+ * infos will be added to the given collection, existing entries will be left
+ * intact. The reference count of all added entries will be increased.
+ */
+
+void ReleaseFullLineInfo (Collection* LineInfos);
+/* Decrease the reference count for a collection full of LineInfos, then clear
+ * the collection.
*/
const FilePos* GetSourcePos (const LineInfo* LI);
CheckPseudo ();
}
- /* If we didn't have any errors, check the unnamed labels */
+ /* If we didn't have any errors, check and cleanup the unnamed labels */
if (ErrorCount == 0) {
- ULabCheck ();
+ ULabDone ();
}
/* If we didn't have any errors, check the symbol table */
} else if (CComments) {
/* Remember the position, then skip the '*' */
Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
- GetFullLineInfo (&LineInfos, 0);
+ GetFullLineInfo (&LineInfos);
NextChar ();
do {
while (C != '*') {
if (C == EOF) {
LIError (&LineInfos, "Unterminated comment");
+ ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos);
goto CharAgain;
}
NextChar ();
} while (C != '/');
NextChar ();
+ ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos);
goto Again;
}
S->Locals = 0;
S->Sym.Tab = 0;
S->LineInfos = EmptyCollection;
- GetFullLineInfo (&S->LineInfos, 1);
+ GetFullLineInfo (&S->LineInfos);
for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
S->GuessedUse[I] = 0;
}
/* Initialize the fields */
L->LineInfos = EmptyCollection;
- GetFullLineInfo (&L->LineInfos, 0);
+ GetFullLineInfo (&L->LineInfos);
L->Val = Val;
L->Ref = 0;
*/
ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
CHECK (L->Val == 0);
- L->Val = GenCurrentPC ();
- GetFullLineInfo (&L->LineInfos, 0);
+ L->Val = GenCurrentPC ();
+ ReleaseFullLineInfo (&L->LineInfos);
+ GetFullLineInfo (&L->LineInfos);
} else {
/* There is no such label, create it */
NewULabel (GenCurrentPC ());
-void ULabCheck (void)
-/* Run through all unnamed labels and check for anomalies and errors */
+void ULabDone (void)
+/* Run through all unnamed labels, check for anomalies and errors and do
+ * necessary cleanups.
+ */
{
/* Check if there are undefined labels */
unsigned I = ULabDefCount;
}
/* Walk over all labels and emit a warning if any unreferenced ones
- * are found.
+ * are found. Remove line infos because they're no longer needed.
*/
for (I = 0; I < CollCount (&ULabList); ++I) {
ULabel* L = CollAtUnchecked (&ULabList, I);
if (L->Ref == 0) {
LIWarning (&L->LineInfos, 1, "No reference to unnamed label");
}
+ ReleaseFullLineInfo (&L->LineInfos);
}
}
/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
* if a label is still undefined in this phase.
*/
-void ULabCheck (void);
-/* Run through all unnamed labels and check for anomalies and errors */
+void ULabDone (void);
+/* Run through all unnamed labels, check for anomalies and errors and do
+ * necessary cleanups.
+ */