#include <stdio.h>
#include <string.h>
#include <errno.h>
-
+
/* common */
#include "xmalloc.h"
-
+
/* ld65 */
#include "global.h"
#include "error.h"
* in the linker.
*/
Warning ("Segment `%s' in module `%s' requires larger alignment",
- S->Name, S->Seg->AlignObj->Name);
+ S->Name, GetObjFileName (S->Seg->AlignObj));
}
/* Handle ALIGN and OFFSET/START */
+#include <string.h>
+
/* common */
#include "check.h"
#include "coll.h"
+#include "segdefs.h"
#include "xmalloc.h"
/* ld65 */
#include "exports.h"
+#include "fragment.h"
#include "segments.h"
#include "condes.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
typedef struct ConDesDesc ConDesDesc;
struct ConDesDesc {
Collection ExpList; /* List of exported symbols */
- char* Label; /* Name of table label */
char* SegName; /* Name of segment the table is in */
- unsigned char Enable; /* Table enabled */
+ char* Label; /* Name of table label */
+ char* CountSym; /* Name of symbol for entry count */
+ unsigned char Order; /* Table order (increasing/decreasing) */
};
/* Array for all types */
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
- { STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
+ { STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
};
+/*****************************************************************************/
+/* Internally used function to create the condes tables */
+/*****************************************************************************/
+
+
+
+static int ConDesCompare (void* Data, const void* E1, const void* E2)
+/* Compare function to sort the exports */
+{
+ int Cmp;
+
+ /* Data is actually a pointer to a ConDesDesc from the table, E1 and
+ * E2 are exports from the collection. Get the condes type and cast
+ * the void pointers to object pointers.
+ */
+ ConDesDesc* CD = ((ConDesDesc*) Data);
+ int Type = CD - ConDes;
+ const Export* Exp1 = (const Export*) E1;
+ const Export* Exp2 = (const Export*) E2;
+
+ /* Get the priorities of the two exports */
+ unsigned Prio1 = Exp1->ConDes[Type];
+ unsigned Prio2 = Exp2->ConDes[Type];
+
+ /* Compare the priorities for this condes type */
+ if (Prio1 < Prio2) {
+ Cmp = -1;
+ } else if (Prio1 > Prio2) {
+ Cmp = 1;
+ } else {
+ /* Use the name in this case */
+ Cmp = strcmp (Exp1->Name, Exp2->Name);
+ }
+
+ /* Reverse the result for decreasing order */
+ if (CD->Order == cdIncreasing) {
+ return Cmp;
+ } else {
+ return -Cmp;
+ }
+}
+
+
+
+static void ConDesCreateOne (ConDesDesc* CD)
+/* Create one table if requested */
+{
+ Segment* Seg; /* Segment for table */
+ Section* Sec; /* Section for table */
+ unsigned Count; /* Number of exports */
+ unsigned I;
+
+ /* Check if this table has a segment and table label defined. If not,
+ * creation was not requested in the config file - ignore it.
+ */
+ if (CD->SegName == 0 || CD->Label == 0) {
+ return;
+ }
+
+ /* Check if there is an import for the table label. If not, there is no
+ * reference to the table and we would just waste memory creating the
+ * table.
+ */
+ if (!IsUnresolved (CD->Label)) {
+ return;
+ }
+
+ /* Sort the collection of exports according to priority */
+ CollSort (&CD->ExpList, ConDesCompare, CD);
+
+ /* Get the segment for the table, create it if needed */
+ Seg = GetSegment (CD->SegName, SEGTYPE_ABS, 0);
+
+ /* Create a new section for the table */
+ Sec = NewSection (Seg, 1, SEGTYPE_ABS);
+
+ /* Walk over the exports and create a fragment for each one. We will use
+ * the exported expression without copying it, since it's cheap and there
+ * is currently no place where it gets changed (hope this will not hunt
+ * me later...).
+ */
+ Count = CollCount (&CD->ExpList);
+ for (I = 0; I < Count; ++I) {
+
+ /* Get the export */
+ Export* E = CollAt (&CD->ExpList, I);
+
+ /* Create the fragment */
+ Fragment* F = NewFragment (FRAG_EXPR, 2, Sec);
+
+ /* Set the expression pointer */
+ F->Expr = E->Expr;
+ }
+
+ /* Define the table start as an export, offset into section is zero
+ * (the section only contains the table).
+ */
+ CreateSegExport (CD->Label, Sec, 0);
+
+ /* If we have a CountSym name given AND if it is referenced, define it
+ * with the number of elements in the table.
+ */
+ if (CD->CountSym) {
+ CreateConstExport (CD->CountSym, Count);
+ }
+}
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* Insert the export into all tables for which declarations exist */
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
- unsigned Prio = E->ConDes[Type];
- if (Prio != CD_PRIO_NONE) {
+ unsigned Prio = E->ConDes[Type];
+ if (Prio != CD_PRIO_NONE) {
CollAppend (&ConDes[Type].ExpList, E);
}
}
-const char* ConDesGetSegName (unsigned Type)
-/* Return the segment name for the given ConDes type */
+void ConDesSetCountSym (unsigned Type, const char* Name)
+/* Set the name for the given ConDes count symbol */
{
/* Check the parameters */
- PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+ PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && Name != 0);
- /* Return the name */
- return ConDes[Type].SegName;
+ /* Setting the symbol twice is bad */
+ CHECK (ConDes[Type].CountSym == 0);
+
+ /* Set the name */
+ ConDes[Type].CountSym = xstrdup (Name);
}
-const char* ConDesGetLabel (unsigned Type)
-/* Return the label for the given ConDes type */
+void ConDesSetOrder (unsigned Type, ConDesOrder Order)
+/* Set the sorting oder for the given ConDes table */
{
/* Check the parameters */
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
- /* Return the name */
- return ConDes[Type].Label;
+ /* Set the order */
+ ConDes[Type].Order = Order;
}
int ConDesHasSegName (unsigned Type)
/* Return true if a segment name is already defined for this ConDes type */
{
- return (ConDesGetSegName(Type) != 0);
+ /* Check the parameters */
+ PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+
+ return (ConDes[Type].SegName != 0);
}
int ConDesHasLabel (unsigned Type)
/* Return true if a label is already defined for this ConDes type */
{
- return (ConDesGetLabel(Type) != 0);
+ /* Check the parameters */
+ PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
+
+ return (ConDes[Type].Label != 0);
}
void ConDesCreate (void)
/* Create the condes tables if requested */
{
+ unsigned Type;
+
+ /* Walk over the descriptor array and create a table for each entry */
+ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
+ ConDesCreateOne (ConDes + Type);
+ }
}
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Order of the tables */
+typedef enum {
+ cdIncreasing, /* Increasing priority - default */
+ cdDecreasing /* Decreasing priority */
+} ConDesOrder;
+
+
+
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void ConDesSetLabel (unsigned Type, const char* Name);
/* Set the label for the given ConDes type */
-const char* ConDesGetSegName (unsigned Type);
-/* Return the segment name for the given ConDes type */
+void ConDesSetCountSym (unsigned Type, const char* Name);
+/* Set the name for the given ConDes count symbol */
-const char* ConDesGetLabel (unsigned Type);
-/* Return the label for the given ConDes type */
+void ConDesSetOrder (unsigned Type, ConDesOrder Order);
+/* Set the sorting oder for the given ConDes table */
int ConDesHasSegName (unsigned Type);
/* Return true if a segment name is already defined for this ConDes type */
static const IdentTok Attributes [] = {
{ "SEGMENT", CFGTOK_SEGMENT },
{ "LABEL", CFGTOK_LABEL },
+ { "COUNT", CFGTOK_COUNT },
{ "TYPE", CFGTOK_TYPE },
+ { "ORDER", CFGTOK_ORDER },
};
static const IdentTok Types [] = {
{ "DESTRUCTOR", CFGTOK_DESTRUCTOR },
};
+ static const IdentTok Orders [] = {
+ { "DECREASING", CFGTOK_DECREASING },
+ { "INCREASING", CFGTOK_INCREASING },
+ };
+
/* Attribute values. */
char SegName[sizeof (CfgSVal)];
char Label[sizeof (CfgSVal)];
- int Type = -1; /* Initialize to avoid gcc warnings */
+ char Count[sizeof (CfgSVal)];
+ /* Initialize to avoid gcc warnings: */
+ int Type = -1;
+ ConDesOrder Order = cdIncreasing;
/* Bitmask to remember the attributes we got already */
enum {
atNone = 0x0000,
atSegName = 0x0001,
atLabel = 0x0002,
- atType = 0x0004
+ atCount = 0x0004,
+ atType = 0x0008,
+ atOrder = 0x0010
};
unsigned AttrFlags = atNone;
strcpy (Label, CfgSVal);
break;
+ case CFGTOK_COUNT:
+ /* Don't allow this twice */
+ FlagAttr (&AttrFlags, atCount, "COUNT");
+ /* We expect an identifier */
+ CfgAssureIdent ();
+ /* Remember the value for later */
+ strcpy (Count, CfgSVal);
+ break;
case CFGTOK_TYPE:
/* Don't allow this twice */
}
break;
+ case CFGTOK_ORDER:
+ /* Don't allow this twice */
+ FlagAttr (&AttrFlags, atOrder, "ORDER");
+ CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
+ switch (CfgTok) {
+ case CFGTOK_DECREASING: Order = cdDecreasing; break;
+ case CFGTOK_INCREASING: Order = cdIncreasing; break;
+ default: FAIL ("Unexpected order token");
+ }
+ break;
+
default:
FAIL ("Unexpected attribute token");
/* Define the attributes */
ConDesSetSegName (Type, SegName);
ConDesSetLabel (Type, Label);
+ if (AttrFlags & atCount) {
+ ConDesSetCountSym (Type, Count);
+ }
+ if (AttrFlags & atOrder) {
+ ConDesSetOrder (Type, Order);
+ }
}
/* Read the import type and check it */
unsigned char Type = Read8 (F);
if (Type != IMP_ZP && Type != IMP_ABS) {
- Error ("Unknown import type in module `%s': %02X", Obj->Name, Type);
+ Error ("Unknown import type in module `%s': %02X",
+ GetObjFileName (Obj), Type);
}
/* Create a new import */
/* Create an export for a literal date */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS, Name, 0);
+ Export* E = NewExport (EXP_ABS | EXP_CONST, Name, 0);
/* Assign the value */
E->Expr = LiteralExpr (Value, 0);
/* Create an relative export for a memory area offset */
{
/* Create a new export */
- Export* E = NewExport (EXP_ABS, Name, 0);
+ Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
/* Assign the value */
E->Expr = MemExpr (Mem, Offs, 0);
+Export* CreateSegExport (const char* Name, Section* Sec, unsigned long Offs)
+/* Create a relative export to a segment (section) */
+{
+ /* Create a new export */
+ Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
+
+ /* Assign the value */
+ E->Expr = SegExpr (Sec, Offs, 0);
+
+ /* Insert the export */
+ InsertExport (E);
+
+ /* Return the new export */
+ return E;
+}
+
+
+
static Export* FindExport (const char* Name)
/* Check for an identifier in the list. Return 0 if not found, otherwise
* return a pointer to the export.
/* User defined export */
Warning ("Type mismatch for `%s', export in "
"%s(%lu), import in %s(%lu)",
- E->Name, E->Obj->Files [Imp->Pos.Name],
- E->Pos.Line, Imp->Obj->Files [Imp->Pos.Name],
+ E->Name, GetSourceFileName (E->Obj, Imp->Pos.Name),
+ E->Pos.Line, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
} else {
/* Export created by the linker */
Warning ("Type mismatch for `%s', imported from %s(%lu)",
- E->Name, Imp->Obj->Files [Imp->Pos.Name],
+ E->Name, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
}
}
"Unresolved external `%s' referenced in:\n",
E->Name);
while (Imp) {
- const char* Name = Imp->Obj->Files [Imp->Pos.Name];
+ const char* Name = GetSourceFileName (Imp->Obj, Imp->Pos.Name);
fprintf (stderr, " %s(%lu)\n", Name, Imp->Pos.Line);
Imp = Imp->Next;
}
const Export* E = ExpPool [I];
/* Print unreferenced symbols only if explictly requested */
- if (VerboseMap || E->ImpCount > 0) {
+ if (VerboseMap || E->ImpCount > 0 || IS_EXP_CONDES (E->Type)) {
fprintf (F,
"%-25s %06lX %c%c%c ",
E->Name,
*/
if (VerboseMap || Exp->ImpCount > 0) {
- /* Get the name of the object file that exports the symbol.
- * Beware: There may be no object file if the symbol is a linker
- * generated symbol.
- */
- const char* ObjName = (Exp->Obj != 0)? Exp->Obj->Name : "linker generated";
-
/* Print the export */
fprintf (F,
"%s (%s):\n",
Exp->Name,
- ObjName);
+ GetObjFileName (Exp->Obj));
/* Print all imports for this symbol */
Imp = Exp->ImpList;
/* Print the import */
fprintf (F,
" %-25s %s(%lu)\n",
- Imp->Obj->Name,
- Imp->Obj->Files [Imp->Pos.Name],
+ GetObjFileName (Imp->Obj),
+ GetSourceFileName (Imp->Obj, Imp->Pos.Name),
Imp->Pos.Line);
/* Next import */
/* Print an error about a circular reference using to define the given export */
{
Error ("Circular reference for symbol `%s', %s(%lu)",
- E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
+ E->Name, GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line);
}
Import* ImpList; /* List of imports for this symbol */
FilePos Pos; /* File position of definition */
ExprNode* Expr; /* Expression (0 if not def'd) */
- unsigned char Type; /* Type of export */
+ unsigned char Type; /* Type of export */
unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */
char* Name; /* Name - dynamically allocated */
};
Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
/* Create an relative export for a memory area offset */
+Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
+/* Create a relative export to a segment (section) */
+
int IsUnresolved (const char* Name);
/* Check if this symbol is an unresolved export */
*/
if (ExportHasMark (E)) {
Error ("Circular reference for symbol `%s', %s(%lu)",
- E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
+ E->Name, GetSourceFileName (E->Obj, E->Pos.Name),
+ E->Pos.Line);
Const = 0;
} else {
MarkExport (E);
/* Check that this is really a segment node */
PRECONDITION (Expr->Op == EXPR_SEGMENT);
- /* Return the export */
- return Expr->Obj->Sections [Expr->V.SegNum];
+ /* If we have an object file, get the section from it, otherwise
+ * (internally generated expressions), get the section from the
+ * section pointer.
+ */
+ if (Expr->Obj) {
+ /* Return the export */
+ return Expr->Obj->Sections [Expr->V.SegNum];
+ } else {
+ return Expr->V.Sec;
+ }
}
+ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O)
+/* Return an expression tree that encodes an offset into a segment */
+{
+ ExprNode* Root;
+
+ ExprNode* Expr = NewExprNode (O);
+ Expr->Op = EXPR_SEGMENT;
+ Expr->V.Sec = Sec;
+
+ Root = NewExprNode (O);
+ Root->Op = EXPR_PLUS;
+ Root->Left = Expr;
+ Root->Right = LiteralExpr (Offs, O);
+
+ return Root;
+}
+
+
+
ExprNode* ReadExpr (FILE* F, ObjData* O)
/* Read an expression from the given file */
{
return (E1->V.ImpNum == E2->V.ImpNum);
case EXPR_SEGMENT:
- /* Segment number must be identical */
- return (E1->V.SegNum == E2->V.SegNum);
+ /* Section must be identical */
+ return (GetExprSection (E1) == GetExprSection (E2));
case EXPR_MEMAREA:
/* Memory area must be identical */
/* common */
#include "exprdefs.h"
-
+
/* ld65 */
#include "objdata.h"
#include "exports.h"
ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O);
/* Return an expression tree that encodes an offset into the memory area */
+ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O);
+/* Return an expression tree that encodes an offset into a segment */
+
void DumpExpr (const ExprNode* Expr);
/* Dump an expression tree to stdout */
/* */
/*****************************************************************************/
-
+
/* common */
#include "xmalloc.h"
F->Obj = 0;
F->Size = Size;
F->Expr = 0;
+ InitFilePos (&F->Pos);
F->Type = Type;
- /* Insert the code fragment into the segment */
+ /* Insert the code fragment into the section */
if (S->FragRoot == 0) {
/* First fragment */
S->FragRoot = F;
S->FragLast->Next = F;
}
S->FragLast = F;
+
+ /* Increment the size of the section by the size of the fragment */
S->Size += Size;
+ /* Increment the size of the segment that contains the section */
+ S->Seg->Size += Size;
+
/* Return the new fragment */
return F;
}
{
O->Header.Magic = Read32 (Lib);
if (O->Header.Magic != OBJ_MAGIC) {
- Error ("Object file `%s' in library `%s' is invalid", O->Name, LibName);
+ Error ("Object file `%s' in library `%s' is invalid",
+ GetObjFileName (O), LibName);
}
O->Header.Version = Read16 (Lib);
if (O->Header.Version != OBJ_VERSION) {
Error ("Object file `%s' in library `%s' has wrong version",
- O->Name, LibName);
+ GetObjFileName (O), LibName);
}
O->Header.Flags = Read16 (Lib);
O->Header.OptionOffs = Read32 (Lib);
-
-
-
-
/* We've linked this module */
if (O->LibName) {
/* The file is from a library */
- fprintf (F, "%s(%s):\n", O->LibName, O->Name);
+ fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O));
} else {
- fprintf (F, "%s:\n", O->Name);
+ fprintf (F, "%s:\n", GetObjFileName (O));
}
for (I = 0; I < O->SectionCount; ++I) {
const Section* S = O->Sections [I];
/* */
/* */
/* */
-/* (C) 1998 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <string.h>
-#include "../common/xmalloc.h"
+/* common */
+#include "check.h"
+#include "xmalloc.h"
+/* ld65 */
#include "error.h"
#include "objdata.h"
+const char* GetObjFileName (const ObjData* O)
+/* Get the name of the object file. Return "(linker generated)" if the object
+ * file is NULL.
+ */
+{
+ return O? O->Name : "(linker generated)";
+}
+
+
+
+const char* GetSourceFileName (const ObjData* O, unsigned Index)
+/* Get the name of the source file with the given index. If O is NULL, return
+ * "(linker generated)" as the file name.
+ */
+{
+ /* Check if we have an object file */
+ if (O == 0) {
+
+ /* No object file */
+ return "(linker generated)";
+
+ } else {
+
+ /* Check the parameter */
+ PRECONDITION (Index < O->FileCount);
+
+ /* Return the name */
+ return O->Files[Index];
+
+ }
+}
+
+
+
+
void FreeObjData (ObjData* O);
/* Free a complete struct */
+const char* GetObjFileName (const ObjData* O);
+/* Get the name of the object file. Return "(linker generated)" if the object
+ * file is NULL.
+ */
+
+const char* GetSourceFileName (const ObjData* O, unsigned Index);
+/* Get the name of the source file with the given index. If O is NULL, return
+ * "(linker generated)" as the file name.
+ */
+
/* End of objdata.h */
CFGTOK_CONDES,
CFGTOK_SEGMENT,
CFGTOK_LABEL,
+ CFGTOK_COUNT,
+ CFGTOK_ORDER,
+
CFGTOK_CONSTRUCTOR,
- CFGTOK_DESTRUCTOR
+ CFGTOK_DESTRUCTOR,
+
+ CFGTOK_DECREASING,
+ CFGTOK_INCREASING
} cfgtok_t;
-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 */
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;
S->Seg = Seg;
S->FragRoot = 0;
S->FragLast = 0;
- S->Size = 0;
+ S->Size = 0;
S->Align = Align;
S->Type = 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;
-}
-
-
-
Section* ReadSection (FILE* F, ObjData* O)
/* Read a section from a file */
{
- unsigned HashVal;
char* Name;
unsigned long Size;
unsigned char Align;
/* 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);
+ 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);
/* 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 */
default:
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
- O->Name, S->Name, Type);
+ GetObjFileName (O), S->Name, Type);
/* NOTREACHED */
return 0;
}
Size -= Frag->Size;
}
- /* Increment the segment size by the section size */
- S->Size += Sec->Size;
-
/* Return the section */
return Sec;
}
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:
+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.
+ */
+
+Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type);
+/* Create a new section for the given segment */
+
Section* ReadSection (FILE* F, struct ObjData* O);
/* Read a section from a file */