/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* ld65 */
#include "error.h"
#include "fragment.h"
+#include "lineinfo.h"
+#include "objdata.h"
#include "segments.h"
F->Obj = 0;
F->Size = Size;
F->Expr = 0;
- InitFilePos (&F->Pos);
- F->LI = 0;
+ F->LineInfos = EmptyCollection;
F->Type = Type;
/* Insert the code fragment into the section */
+void AddLineInfo (Fragment* F, LineInfo* LI)
+/* Add the line info to the given fragment */
+{
+ /* Point from the fragment to the line info ... */
+ CollAppend (&F->LineInfos, LI);
+
+ /* ... and back from the line info to the fragment */
+ CollAppend (&LI->Fragments, F);
+}
+
+
+
+const char* GetFragmentSourceName (const Fragment* F)
+/* Return the name of the source file for this fragment */
+{
+ /* Each fragment has the basic info in line info #0 */
+ const LineInfo* LI = CollConstAt (&F->LineInfos, 0);
+
+ /* Return the source file name */
+ return GetSourceFileName (F->Obj, LI->Pos.Name);
+}
+
+
+
+unsigned long GetFragmentSourceLine (const Fragment* F)
+/* Return the source file line for this fragment */
+{
+ /* Each fragment has the basic info in line info #0 */
+ const LineInfo* LI = CollConstAt (&F->LineInfos, 0);
+
+ /* Return the source file line */
+ return LI->Pos.Line;
+}
+
+
+
/* */
/* */
/* */
-/* (C) 1998-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 1998-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* common */
+#include "coll.h"
#include "filepos.h"
struct ObjData* Obj; /* Source of fragment */
unsigned Size; /* Size of data/expression */
struct ExprNode* Expr; /* Expression if FRAG_EXPR */
- FilePos Pos; /* File position in source */
- struct LineInfo* LI; /* Additional line info */
+ Collection LineInfos; /* Line info for this fragment */
unsigned char Type; /* Type of fragment */
unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */
};
Fragment* NewFragment (unsigned char Type, unsigned Size, struct Section* S);
/* Create a new fragment and insert it into the section S */
+void AddLineInfo (Fragment* F, struct LineInfo* LI);
+/* Add the line info to the given fragment */
+
+const char* GetFragmentSourceName (const Fragment* F);
+/* Return the name of the source file for this fragment */
+
+unsigned long GetFragmentSourceLine (const Fragment* F);
+/* Return the source file line for this fragment */
+
/* End of fragment.h */
/* ld65 */
#include "fileio.h"
#include "fragment.h"
+#include "objdata.h"
#include "segments.h"
#include "lineinfo.h"
-static LineInfo* NewLineInfo (void)
+LineInfo* NewLineInfo (ObjData* O, const FilePos* Pos)
/* Create and return a new LineInfo struct */
{
/* Allocate memory */
LineInfo* LI = xmalloc (sizeof (LineInfo));
+ /* Make sure the name index is valid */
+ CHECK (Pos->Name < CollCount (&O->Files));
+
/* Initialize the fields */
- LI->File = 0;
- InitFilePos (&LI->Pos);
+ LI->File = CollAt (&O->Files, Pos->Name);
+ LI->Pos = *Pos;
InitCollection (&LI->Fragments);
InitCollection (&LI->CodeRanges);
LineInfo* ReadLineInfo (FILE* F, ObjData* O)
/* Read a line info from a file and return it */
{
- /* Allocate a new LineInfo struct and initialize it */
- LineInfo* LI = NewLineInfo ();
-
/* Read the file position */
- ReadFilePos (F, &LI->Pos);
-
- /* Resolve the file index to a pointer to FileInfo struct */
- CHECK (LI->Pos.Name < CollCount (&O->Files));
- LI->File = CollAt (&O->Files, LI->Pos.Name);
+ FilePos Pos;
+ ReadFilePos (F, &Pos);
- /* Return the new LineInfo */
- return LI;
+ /* Allocate a new LineInfo struct, initialize and return it */
+ return NewLineInfo (O, &Pos);
}
Frag = Sec->FragRoot;
while (Frag) {
- /* Add the range for this fragment to the line info if there
- * is any
- */
- if (Frag->LI) {
- AddCodeRange (Frag->LI, Offs, Frag->Size);
+ unsigned I;
+
+ /* Add the range for this fragment to all line infos */
+ for (I = 0; I < CollCount (&Frag->LineInfos); ++I) {
+ AddCodeRange (CollAt (&Frag->LineInfos, I), Offs, Frag->Size);
}
/* Update the offset */
/* */
/* */
/* */
-/* (C) 2001 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2001-2010, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+#include <stdio.h>
+
/* common */
#include "coll.h"
#include "filepos.h"
-/* ld65 */
-#include "objdata.h"
-
/*****************************************************************************/
-/* Forwards */
+/* Forwards */
/*****************************************************************************/
+struct ObjData;
struct Segment;
-LineInfo* ReadLineInfo (FILE* F, ObjData* O);
+LineInfo* NewLineInfo (struct ObjData* O, const FilePos* Pos);
+/* Create and return a new LineInfo struct */
+
+LineInfo* ReadLineInfo (FILE* F, struct ObjData* O);
/* Read a line info from a file and return it */
void RelocLineInfo (struct Segment* S);
} else {
/* Get a pointer to the file info struct */
- const FileInfo* FI = CollAt (&O->Files, Index);
+ const FileInfo* FI = CollConstAt (&O->Files, Index);
/* Return the name */
return GetString (FI->Name);
unsigned FragCount;
Segment* S;
Section* Sec;
+ LineInfo* LI;
/* Read the segment data */
(void) Read32 (F); /* File size of data */
}
/* Start reading fragments from the file and insert them into the section . */
+ LI = 0;
while (FragCount--) {
Fragment* Frag;
+ FilePos Pos;
unsigned LineInfoIndex;
/* Read the fragment type */
}
/* Read the file position of the fragment */
- ReadFilePos (F, &Frag->Pos);
+ ReadFilePos (F, &Pos);
+
+ /* Generate a LineInfo for this fragment. First check if this fragment
+ * was generated by the same line than that before. If not, generate
+ * a new LineInfo.
+ */
+ if (LI == 0 || LI->Pos.Line != Pos.Line || LI->Pos.Col != Pos.Col ||
+ LI->Pos.Name != Pos.Name) {
+ /* We don't have a previous line info or this one is different */
+ LI = NewLineInfo (O, &Pos);
+ CollAppend (&O->LineInfos, LI);
+ }
+ AddLineInfo (Frag, LI);
/* Read the additional line info and resolve it */
LineInfoIndex = ReadVar (F);
if (LineInfoIndex) {
--LineInfoIndex;
- if (LineInfoIndex >= CollCount (&O->LineInfos)) {
+ /* The line info index was written by the assembler and must
+ * therefore be part of the line infos read from the object file.
+ * To make sure this is true, don't compare against the count
+ * of line infos in the collection (which grows) but against the
+ * count initialized when reading from the file.
+ */
+ if (LineInfoIndex >= O->LineInfoCount) {
Internal ("In module `%s', file `%s', line %lu: Invalid line "
- "info with index %u (max count %u)",
- GetObjFileName (O),
- GetSourceFileName (O, Frag->Pos.Name),
- Frag->Pos.Line, LineInfoIndex,
- CollCount (&O->LineInfos));
+ "info with index %u (max count %u)",
+ GetObjFileName (O),
+ GetFragmentSourceName (Frag),
+ GetFragmentSourceLine (Frag),
+ LineInfoIndex,
+ O->LineInfoCount);
}
- /* Point from the fragment to the line info... */
- Frag->LI = CollAt (&O->LineInfos, LineInfoIndex);
- /* ...and back from the line info to the fragment */
- CollAppend (&Frag->LI->Fragments, Frag);
+ /* Add line info to the fragment */
+ AddLineInfo (Frag, CollAt (&O->LineInfos, LineInfoIndex));
}
/* Remember the module we had this fragment from */
case SEG_EXPR_RANGE_ERROR:
Error ("Range error in module `%s', line %lu",
- GetSourceFileName (Frag->Obj, Frag->Pos.Name),
- Frag->Pos.Line);
+ GetFragmentSourceName (Frag),
+ GetFragmentSourceLine (Frag));
break;
case SEG_EXPR_TOO_COMPLEX:
Error ("Expression too complex in module `%s', line %lu",
- GetSourceFileName (Frag->Obj, Frag->Pos.Name),
- Frag->Pos.Line);
+ GetFragmentSourceName (Frag),
+ GetFragmentSourceLine (Frag));
break;
case SEG_EXPR_INVALID:
Error ("Invalid expression in module `%s', line %lu",
- GetSourceFileName (Frag->Obj, Frag->Pos.Name),
- Frag->Pos.Line);
+ GetFragmentSourceName (Frag),
+ GetFragmentSourceLine (Frag));
break;
default: