From: cuz Date: Mon, 20 Nov 2000 21:56:48 +0000 (+0000) Subject: First finished implementation of the condes feature X-Git-Tag: V2.12.0~3075 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=518220f9cf7dabb3703d4067cdb5f777cee7d697;p=cc65 First finished implementation of the condes feature git-svn-id: svn://svn.cc65.org/cc65/trunk@456 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/ld65/bin.c b/src/ld65/bin.c index abc873e67..5a22267e2 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -36,10 +36,10 @@ #include #include #include - + /* common */ #include "xmalloc.h" - + /* ld65 */ #include "global.h" #include "error.h" @@ -140,7 +140,7 @@ static void BinWriteMem (BinDesc* D, Memory* M) * 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 */ diff --git a/src/ld65/condes.c b/src/ld65/condes.c index 7c9e7f73b..d8446312d 100644 --- a/src/ld65/condes.c +++ b/src/ld65/condes.c @@ -33,20 +33,24 @@ +#include + /* 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 */ /*****************************************************************************/ @@ -55,24 +59,134 @@ 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 */ /*****************************************************************************/ @@ -86,8 +200,8 @@ void ConDesAddExport (struct Export* E) /* 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); } } @@ -125,26 +239,29 @@ void ConDesSetLabel (unsigned Type, const char* Name) -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; } @@ -152,7 +269,10 @@ const char* ConDesGetLabel (unsigned Type) 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); } @@ -160,7 +280,10 @@ int ConDesHasSegName (unsigned Type) 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); } @@ -168,6 +291,12 @@ int ConDesHasLabel (unsigned Type) 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); + } } diff --git a/src/ld65/condes.h b/src/ld65/condes.h index 72d295acd..6285ac01b 100644 --- a/src/ld65/condes.h +++ b/src/ld65/condes.h @@ -48,6 +48,20 @@ struct Export; +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Order of the tables */ +typedef enum { + cdIncreasing, /* Increasing priority - default */ + cdDecreasing /* Decreasing priority */ +} ConDesOrder; + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -63,11 +77,11 @@ void ConDesSetSegName (unsigned Type, const char* SegName); 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 */ diff --git a/src/ld65/config.c b/src/ld65/config.c index 314fc235c..ee963de1d 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -958,7 +958,9 @@ static void ParseConDes (void) static const IdentTok Attributes [] = { { "SEGMENT", CFGTOK_SEGMENT }, { "LABEL", CFGTOK_LABEL }, + { "COUNT", CFGTOK_COUNT }, { "TYPE", CFGTOK_TYPE }, + { "ORDER", CFGTOK_ORDER }, }; static const IdentTok Types [] = { @@ -966,17 +968,27 @@ static void ParseConDes (void) { "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; @@ -1013,6 +1025,14 @@ static void ParseConDes (void) 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 */ @@ -1031,6 +1051,17 @@ static void ParseConDes (void) } 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"); @@ -1060,6 +1091,12 @@ static void ParseConDes (void) /* Define the attributes */ ConDesSetSegName (Type, SegName); ConDesSetLabel (Type, Label); + if (AttrFlags & atCount) { + ConDesSetCountSym (Type, Count); + } + if (AttrFlags & atOrder) { + ConDesSetOrder (Type, Order); + } } diff --git a/src/ld65/exports.c b/src/ld65/exports.c index 515b8527d..fde9bd5ec 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -170,7 +170,8 @@ Import* ReadImport (FILE* F, ObjData* Obj) /* 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 */ @@ -349,7 +350,7 @@ Export* CreateConstExport (const char* Name, long Value) /* 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); @@ -367,7 +368,7 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs) /* 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); @@ -381,6 +382,24 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs) +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. @@ -453,13 +472,13 @@ static void CheckSymType (const Export* E) /* 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); } } @@ -503,7 +522,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data) "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; } @@ -580,7 +599,7 @@ void PrintExportMap (FILE* F) 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, @@ -616,17 +635,11 @@ void PrintImportMap (FILE* F) */ 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; @@ -635,8 +648,8 @@ void PrintImportMap (FILE* F) /* 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 */ @@ -691,7 +704,7 @@ void CircularRefError (const Export* E) /* 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); } diff --git a/src/ld65/exports.h b/src/ld65/exports.h index 8ee675f0c..7204f8c8e 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -82,7 +82,7 @@ struct Export { 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 */ }; @@ -123,6 +123,9 @@ Export* CreateConstExport (const char* Name, long Value); 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 */ diff --git a/src/ld65/expr.c b/src/ld65/expr.c index 3e1f01041..57092d9f1 100644 --- a/src/ld65/expr.c +++ b/src/ld65/expr.c @@ -119,7 +119,8 @@ int IsConstExpr (ExprNode* Root) */ 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); @@ -208,8 +209,16 @@ Section* GetExprSection (ExprNode* Expr) /* 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; + } } @@ -381,6 +390,25 @@ ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O) +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 */ { @@ -461,8 +489,8 @@ int EqualExpr (ExprNode* E1, ExprNode* E2) 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 */ diff --git a/src/ld65/expr.h b/src/ld65/expr.h index 938ed3448..a810d0228 100644 --- a/src/ld65/expr.h +++ b/src/ld65/expr.h @@ -40,7 +40,7 @@ /* common */ #include "exprdefs.h" - + /* ld65 */ #include "objdata.h" #include "exports.h" @@ -80,6 +80,9 @@ ExprNode* LiteralExpr (long Val, ObjData* O); 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 */ diff --git a/src/ld65/fragment.c b/src/ld65/fragment.c index 22b45f8e4..991ed3565 100644 --- a/src/ld65/fragment.c +++ b/src/ld65/fragment.c @@ -31,7 +31,7 @@ /* */ /*****************************************************************************/ - + /* common */ #include "xmalloc.h" @@ -59,9 +59,10 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S) 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; @@ -69,8 +70,13 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S) 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; } diff --git a/src/ld65/library.c b/src/ld65/library.c index 4a9d8a7e7..18b21b843 100644 --- a/src/ld65/library.c +++ b/src/ld65/library.c @@ -80,12 +80,13 @@ static void LibReadObjHeader (ObjData* O) { 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); @@ -281,7 +282,3 @@ void LibAdd (FILE* F, const char* Name) - - - - diff --git a/src/ld65/mapfile.c b/src/ld65/mapfile.c index 8e3582dd1..8d31666fd 100644 --- a/src/ld65/mapfile.c +++ b/src/ld65/mapfile.c @@ -75,9 +75,9 @@ void CreateMapFile (void) /* 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]; diff --git a/src/ld65/objdata.c b/src/ld65/objdata.c index 414e82990..085468da9 100644 --- a/src/ld65/objdata.c +++ b/src/ld65/objdata.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (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 */ @@ -35,8 +35,11 @@ #include -#include "../common/xmalloc.h" +/* common */ +#include "check.h" +#include "xmalloc.h" +/* ld65 */ #include "error.h" #include "objdata.h" @@ -111,3 +114,38 @@ void FreeObjData (ObjData* O) +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]; + + } +} + + + + diff --git a/src/ld65/objdata.h b/src/ld65/objdata.h index 4813d809d..92202977f 100644 --- a/src/ld65/objdata.h +++ b/src/ld65/objdata.h @@ -97,6 +97,16 @@ ObjData* NewObjData (void); 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 */ diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index d5f86e3ec..399efa414 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -104,8 +104,14 @@ typedef enum { CFGTOK_CONDES, CFGTOK_SEGMENT, CFGTOK_LABEL, + CFGTOK_COUNT, + CFGTOK_ORDER, + CFGTOK_CONSTRUCTOR, - CFGTOK_DESTRUCTOR + CFGTOK_DESTRUCTOR, + + CFGTOK_DECREASING, + CFGTOK_INCREASING } cfgtok_t; diff --git a/src/ld65/segments.c b/src/ld65/segments.c index ea3dec3cc..e41dcdeac 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -75,7 +75,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 +122,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 +179,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 +206,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; @@ -195,22 +231,11 @@ Section* ReadSection (FILE* F, ObjData* O) /* 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); @@ -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 */ @@ -264,7 +283,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; } @@ -296,9 +315,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; } @@ -489,12 +505,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: diff --git a/src/ld65/segments.h b/src/ld65/segments.h index b045229ea..7a0a6a974 100644 --- a/src/ld65/segments.h +++ b/src/ld65/segments.h @@ -107,6 +107,15 @@ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write +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 */