X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=0ae19b6d6398e8db36dd3ca5bf96f884cbf96656;hb=3e887bd9dd06b89177bff864b50fc58c8dadc8bf;hp=ea3dec3cc11baa0f83cf20875ad737372c56bd40;hpb=18840117ec255797f7685ca82f493750a7812e35;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index ea3dec3cc..0ae19b6d6 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ +/* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,6 +40,7 @@ #include "check.h" #include "exprdefs.h" #include "hashstr.h" +#include "print.h" #include "segdefs.h" #include "symdefs.h" #include "xmalloc.h" @@ -50,6 +51,7 @@ #include "fileio.h" #include "fragment.h" #include "global.h" +#include "lineinfo.h" #include "segments.h" @@ -75,7 +77,26 @@ static Segment* SegRoot = 0; /* List of all segments */ -static Segment* NewSegment (const char* Name, unsigned char Type) +static Segment* SegFindInternal (const char* Name, unsigned HashVal) +/* Try to find the segment with the given name, return a pointer to the + * segment structure, or 0 if not found. + */ +{ + Segment* S = HashTab [HashVal]; + while (S) { + if (strcmp (Name, S->Name) == 0) { + /* Found */ + break; + } + S = S->Next; + } + /* Not found */ + return S; +} + + + +static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type) /* Create a new segment and initialize it */ { /* Get the length of the symbol name */ @@ -103,13 +124,50 @@ static Segment* NewSegment (const char* Name, unsigned char Type) SegRoot = S; ++SegCount; + /* Insert the segment into the segment hash list */ + S->Next = HashTab [HashVal]; + HashTab [HashVal] = S; + /* Return the new entry */ return S; } -static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) +Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName) +/* Search for a segment and return an existing one. If the segment does not + * exist, create a new one and return that. ObjName is only used for the error + * message and may be NULL if the segment is linker generated. + */ +{ + /* Create a hash over the name and try to locate the segment in the table */ + unsigned HashVal = HashStr (Name) % HASHTAB_SIZE; + Segment* S = SegFindInternal (Name, HashVal); + + /* If we don't have that segment already, allocate it using the type of + * the first section. + */ + if (S == 0) { + /* Create a new segment */ + S = NewSegment (Name, HashVal, Type); + } else { + /* Check if the existing segment has the requested type */ + if (S->Type != Type) { + /* Allow an empty object name */ + if (ObjName == 0) { + ObjName = "[linker generated]"; + } + Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name); + } + } + + /* Return the segment */ + return S; +} + + + +Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) /* Create a new section for the given segment */ { unsigned long V; @@ -123,7 +181,7 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ S->Seg = Seg; S->FragRoot = 0; S->FragLast = 0; - S->Size = 0; + S->Size = 0; S->Align = Align; S->Type = Type; @@ -150,29 +208,9 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ -static Segment* SegFindInternal (const char* Name, unsigned HashVal) -/* Try to find the segment with the given name, return a pointer to the - * segment structure, or 0 if not found. - */ -{ - Segment* S = HashTab [HashVal]; - while (S) { - if (strcmp (Name, S->Name) == 0) { - /* Found */ - break; - } - S = S->Next; - } - /* Not found */ - return S; -} - - - Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { - unsigned HashVal; char* Name; unsigned long Size; unsigned char Align; @@ -193,24 +231,11 @@ Section* ReadSection (FILE* F, ObjData* O) Type = Read8 (F); /* Print some data */ - if (Verbose > 1) { - printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", - O->Name, Name, Size, Align, Type); - } + Print (stdout, 2, "Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", + GetObjFileName (O), Name, Size, Align, Type); - /* Create a hash over the name and try to locate the segment in the table */ - HashVal = HashStr (Name) % HASHTAB_SIZE; - S = SegFindInternal (Name, HashVal); - - /* If we don't have that segment already, allocate it using the type of - * the first section. - */ - if (S == 0) { - /* Create a new segment and insert it */ - S = NewSegment (Name, Type); - S->Next = HashTab [HashVal]; - HashTab [HashVal] = S; - } + /* Get the segment for this section */ + S = GetSegment (Name, Type, GetObjFileName (O)); /* We have the segment and don't need the name any longer */ xfree (Name); @@ -218,12 +243,6 @@ Section* ReadSection (FILE* F, ObjData* O) /* Allocate the section we will return later */ Sec = NewSection (S, Align, Type); - /* Check if the section has the same type as the segment */ - if (Sec->Type != S->Type) { - /* OOPS */ - Error ("Module `%s': Type mismatch for segment `%s'", O->Name, S->Name); - } - /* Set up the minimum segment alignment */ if (Sec->Align > S->Align) { /* Section needs larger alignment, use this one */ @@ -235,6 +254,7 @@ Section* ReadSection (FILE* F, ObjData* O) while (Size) { Fragment* Frag; + unsigned LineInfoIndex; /* Read the fragment type */ unsigned char Type = Read8 (F); @@ -264,7 +284,7 @@ Section* ReadSection (FILE* F, ObjData* O) default: Error ("Unknown fragment type in module `%s', segment `%s': %02X", - O->Name, S->Name, Type); + GetObjFileName (O), S->Name, Type); /* NOTREACHED */ return 0; } @@ -281,13 +301,30 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_SEXPR: /* An expression */ Frag->Expr = ReadExpr (F, O); - break; + break; } /* Read the file position of the fragment */ ReadFilePos (F, &Frag->Pos); + /* Read the additional line info and resolve it */ + LineInfoIndex = ReadVar (F); + if (LineInfoIndex) { + --LineInfoIndex; + 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, O->LineInfoCount); + } + /* Point from the fragment to the line info... */ + Frag->LI = O->LineInfos[LineInfoIndex]; + /* ...and back from the line info to the fragment */ + CollAppend (&Frag->LI->Fragments, Frag); + } + /* Remember the module we had this fragment from */ Frag->Obj = O; @@ -296,9 +333,6 @@ Section* ReadSection (FILE* F, ObjData* O) Size -= Frag->Size; } - /* Increment the segment size by the section size */ - S->Size += Sec->Size; - /* Return the section */ return Sec; } @@ -467,6 +501,7 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* If we have fill bytes, write them now */ WriteMult (Tgt, S->FillVal, Sec->Fill); + Offs += Sec->Fill; /* Loop over all fragments in this section */ Frag = Sec->FragRoot; @@ -489,12 +524,14 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) case SEG_EXPR_RANGE_ERROR: Error ("Range error in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; case SEG_EXPR_TOO_COMPLEX: Error ("Expression too complex in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; default: