1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 22:29:35 +00:00

First finished implementation of the condes feature

git-svn-id: svn://svn.cc65.org/cc65/trunk@456 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-11-20 21:56:48 +00:00
parent 7646787a6e
commit 518220f9cf
16 changed files with 433 additions and 122 deletions

View File

@ -36,10 +36,10 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* 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 */

View File

@ -33,20 +33,24 @@
#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 */
/*****************************************************************************/
@ -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);
}
}

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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)

View File

@ -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];

View File

@ -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 <string.h>
#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];
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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:

View File

@ -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 */