diff --git a/src/ld65/fragment.c b/src/ld65/fragment.c index 3f543b33d..c3f902c75 100644 --- a/src/ld65/fragment.c +++ b/src/ld65/fragment.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (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 */ @@ -40,6 +40,8 @@ /* ld65 */ #include "error.h" #include "fragment.h" +#include "lineinfo.h" +#include "objdata.h" #include "segments.h" @@ -71,8 +73,7 @@ Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S) 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 */ @@ -96,3 +97,39 @@ Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S) +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; +} + + + diff --git a/src/ld65/fragment.h b/src/ld65/fragment.h index d6a6233cb..94e40656b 100644 --- a/src/ld65/fragment.h +++ b/src/ld65/fragment.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (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 */ @@ -39,6 +39,7 @@ /* common */ +#include "coll.h" #include "filepos.h" @@ -68,8 +69,7 @@ struct Fragment { 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 */ }; @@ -85,6 +85,15 @@ struct Fragment { 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 */ diff --git a/src/ld65/lineinfo.c b/src/ld65/lineinfo.c index 2db205782..2cc4d86ac 100644 --- a/src/ld65/lineinfo.c +++ b/src/ld65/lineinfo.c @@ -40,6 +40,7 @@ /* ld65 */ #include "fileio.h" #include "fragment.h" +#include "objdata.h" #include "segments.h" #include "lineinfo.h" @@ -67,15 +68,18 @@ static CodeRange* NewCodeRange (unsigned long Offs, unsigned long Size) -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); @@ -88,18 +92,12 @@ static LineInfo* NewLineInfo (void) 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); + FilePos Pos; + ReadFilePos (F, &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); - - /* Return the new LineInfo */ - return LI; + /* Allocate a new LineInfo struct, initialize and return it */ + return NewLineInfo (O, &Pos); } @@ -168,11 +166,11 @@ void RelocLineInfo (Segment* S) 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 */ diff --git a/src/ld65/lineinfo.h b/src/ld65/lineinfo.h index 6d02504af..7ef66d6d4 100644 --- a/src/ld65/lineinfo.h +++ b/src/ld65/lineinfo.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (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 */ @@ -38,21 +38,21 @@ +#include + /* common */ #include "coll.h" #include "filepos.h" -/* ld65 */ -#include "objdata.h" - /*****************************************************************************/ -/* Forwards */ +/* Forwards */ /*****************************************************************************/ +struct ObjData; struct Segment; @@ -87,7 +87,10 @@ struct LineInfo { -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); diff --git a/src/ld65/objdata.c b/src/ld65/objdata.c index 3365b665f..ade6192a7 100644 --- a/src/ld65/objdata.c +++ b/src/ld65/objdata.c @@ -208,7 +208,7 @@ const char* GetSourceFileName (const ObjData* O, unsigned Index) } 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); diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 11943dc77..ca99e4403 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -203,6 +203,7 @@ Section* ReadSection (FILE* F, ObjData* O) unsigned FragCount; Segment* S; Section* Sec; + LineInfo* LI; /* Read the segment data */ (void) Read32 (F); /* File size of data */ @@ -231,9 +232,11 @@ Section* ReadSection (FILE* F, ObjData* O) } /* 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 */ @@ -270,24 +273,41 @@ Section* ReadSection (FILE* F, ObjData* O) } /* 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 */ @@ -499,20 +519,20 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) 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: