/*****************************************************************************/
/* */
-/* condes.h */
+/* condes.c */
/* */
/* Module constructor/destructor support */
/* */
/* */
/* */
-/* (C) 2000-2008 Ullrich von Bassewitz */
-/* Roemerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include "addrsize.h"
#include "check.h"
#include "coll.h"
+#include "filepos.h"
#include "fragdefs.h"
#include "xmalloc.h"
struct ConDesDesc {
Collection ExpList; /* List of exported symbols */
unsigned SegName; /* Name of segment the table is in */
- unsigned Label; /* Name of table label */
+ unsigned Label; /* Name of table label */
unsigned CountSym; /* Name of symbol for entry count */
- unsigned char Order; /* Table order (increasing/decreasing) */
+ unsigned char Order; /* Table order (increasing/decreasing) */
+ ConDesImport Import; /* Forced import if any */
};
/* Array for all types */
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
- { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing },
+ {
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },{
+ STATIC_COLLECTION_INITIALIZER,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ INVALID_STRING_ID,
+ cdIncreasing,
+ { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT },
+ },
};
+const ConDesImport* ConDesGetImport (unsigned Type)
+/* Get the forced import for the given ConDes type. Returns NULL if there is
+ * no forced import for this type.
+ */
+{
+ const ConDesImport* Import;
+
+ /* Check the parameters */
+ PRECONDITION (Type <= CD_TYPE_MAX);
+
+ /* Return the import */
+ Import = &ConDes[Type].Import;
+ return (Import->Name != INVALID_STRING_ID)? Import : 0;
+}
+
+
+
+void ConDesSetImport (unsigned Type, const ConDesImport* Import)
+/* Set the forced import for the given ConDes type */
+{
+ /* Check the parameters */
+ PRECONDITION (Type <= CD_TYPE_MAX && Import != 0);
+
+ /* Setting the import twice is bad */
+ CHECK (ConDes[Type].Import.Name == INVALID_STRING_ID);
+
+ /* Set the import and its position */
+ ConDes[Type].Import = *Import;
+}
+
+
+
void ConDesSetLabel (unsigned Type, unsigned Name)
/* Set the label for the given ConDes type */
{
/* */
/* */
/* */
-/* (C) 2000-2003 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2012, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+/* common */
+#include "filepos.h"
+
+
+
/*****************************************************************************/
/* Forwards */
/*****************************************************************************/
cdDecreasing /* Decreasing priority */
} ConDesOrder;
+/* Data for a forced condes import */
+typedef struct ConDesImport ConDesImport;
+struct ConDesImport {
+ unsigned Name; /* Name of the import */
+ FilePos Pos; /* Position of import in the config file */
+ unsigned AddrSize; /* Address size of the symbol */
+};
+
/*****************************************************************************/
void ConDesSetSegName (unsigned Type, unsigned SegName);
/* Set the segment name where the table should go */
+const ConDesImport* ConDesGetImport (unsigned Type);
+/* Get the forced import for the given ConDes type. Returns NULL if there is
+ * no forced import for this type.
+ */
+
+void ConDesSetImport (unsigned Type, const ConDesImport* Import);
+/* Set the forced import for the given ConDes type */
+
void ConDesSetLabel (unsigned Type, unsigned Name);
/* Set the label for the given ConDes type */
/* Parse the CONDES feature */
{
static const IdentTok Attributes [] = {
- { "SEGMENT", CFGTOK_SEGMENT },
- { "LABEL", CFGTOK_LABEL },
{ "COUNT", CFGTOK_COUNT },
- { "TYPE", CFGTOK_TYPE },
+ { "IMPORT", CFGTOK_IMPORT },
+ { "LABEL", CFGTOK_LABEL },
{ "ORDER", CFGTOK_ORDER },
+ { "SEGMENT", CFGTOK_SEGMENT },
+ { "TYPE", CFGTOK_TYPE },
};
static const IdentTok Types [] = {
};
/* Attribute values. */
- unsigned SegName = INVALID_STRING_ID;
- unsigned Label = INVALID_STRING_ID;
unsigned Count = INVALID_STRING_ID;
+ unsigned Label = INVALID_STRING_ID;
+ unsigned SegName = INVALID_STRING_ID;
+ ConDesImport Import;
/* 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,
- atCount = 0x0004,
- atType = 0x0008,
- atOrder = 0x0010
+ atCount = 0x0001,
+ atImport = 0x0002,
+ atLabel = 0x0004,
+ atOrder = 0x0008,
+ atSegName = 0x0010,
+ atType = 0x0020,
};
unsigned AttrFlags = atNone;
/* Check which attribute was given */
switch (AttrTok) {
- case CFGTOK_SEGMENT:
- /* Don't allow this twice */
- FlagAttr (&AttrFlags, atSegName, "SEGMENT");
+ case CFGTOK_COUNT:
+ /* Don't allow this twice */
+ FlagAttr (&AttrFlags, atCount, "COUNT");
/* We expect an identifier */
- CfgAssureIdent ();
- /* Remember the value for later */
- SegName = GetStrBufId (&CfgSVal);
+ CfgAssureIdent ();
+ /* Remember the value for later */
+ Count = GetStrBufId (&CfgSVal);
break;
- case CFGTOK_LABEL:
+ case CFGTOK_IMPORT:
/* Don't allow this twice */
- FlagAttr (&AttrFlags, atLabel, "LABEL");
+ FlagAttr (&AttrFlags, atImport, "IMPORT");
/* We expect an identifier */
- CfgAssureIdent ();
- /* Remember the value for later */
- Label = GetStrBufId (&CfgSVal);
- break;
+ CfgAssureIdent ();
+ /* Remember value and position for later */
+ Import.Name = GetStrBufId (&CfgSVal);
+ Import.Pos = CfgErrorPos;
+ Import.AddrSize = ADDR_SIZE_ABS;
+ break;
- case CFGTOK_COUNT:
+ case CFGTOK_LABEL:
/* Don't allow this twice */
- FlagAttr (&AttrFlags, atCount, "COUNT");
+ FlagAttr (&AttrFlags, atLabel, "LABEL");
/* We expect an identifier */
- CfgAssureIdent ();
- /* Remember the value for later */
- Count = GetStrBufId (&CfgSVal);
- break;
-
- case CFGTOK_TYPE:
- /* Don't allow this twice */
- FlagAttr (&AttrFlags, atType, "TYPE");
- /* The type may be given as id or numerical */
- if (CfgTok == CFGTOK_INTCON) {
- CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
- Type = (int) CfgIVal;
- } else {
- CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
- switch (CfgTok) {
- case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
- case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
- case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break;
- default: FAIL ("Unexpected type token");
- }
- }
- break;
+ CfgAssureIdent ();
+ /* Remember the value for later */
+ Label = GetStrBufId (&CfgSVal);
+ break;
case CFGTOK_ORDER:
/* Don't allow this twice */
}
break;
+ case CFGTOK_SEGMENT:
+ /* Don't allow this twice */
+ FlagAttr (&AttrFlags, atSegName, "SEGMENT");
+ /* We expect an identifier */
+ CfgAssureIdent ();
+ /* Remember the value for later */
+ SegName = GetStrBufId (&CfgSVal);
+ break;
+
+ case CFGTOK_TYPE:
+ /* Don't allow this twice */
+ FlagAttr (&AttrFlags, atType, "TYPE");
+ /* The type may be given as id or numerical */
+ if (CfgTok == CFGTOK_INTCON) {
+ CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX);
+ Type = (int) CfgIVal;
+ } else {
+ CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
+ switch (CfgTok) {
+ case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break;
+ case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break;
+ case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break;
+ default: FAIL ("Unexpected type token");
+ }
+ }
+ break;
+
default:
FAIL ("Unexpected attribute token");
if (AttrFlags & atCount) {
ConDesSetCountSym (Type, Count);
}
+ if (AttrFlags & atImport) {
+ ConDesSetImport (Type, &Import);
+ }
if (AttrFlags & atOrder) {
ConDesSetOrder (Type, Order);
}
unsigned Name, ObjData* Obj)
/* Create a new export and initialize it */
{
+ unsigned I;
+
/* Allocate memory */
Export* E = xmalloc (sizeof (Export));
E->DbgSymId = ~0U;
E->Type = Type | SYM_EXPORT;
E->AddrSize = AddrSize;
- memset (E->ConDes, 0, sizeof (E->ConDes));
+ for (I = 0; I < sizeof (E->ConDes) / sizeof (E->ConDes[0]); ++I) {
+ E->ConDes[I] = CD_PRIO_NONE;
+ }
/* Return the new entry */
return E;
Export* ReadExport (FILE* F, ObjData* O)
/* Read an export from a file */
{
- unsigned ConDesCount;
- Export* E;
+ unsigned ConDesCount;
+ unsigned I;
+ Export* E;
/* Read the type */
unsigned Type = ReadVar (F);
ConDesCount = SYM_GET_CONDES_COUNT (Type);
if (ConDesCount > 0) {
- unsigned char ConDes[CD_TYPE_COUNT];
- unsigned I;
+ unsigned char ConDes[CD_TYPE_COUNT];
- /* Read the data into temp storage */
- ReadData (F, ConDes, ConDesCount);
+ /* Read the data into temp storage */
+ ReadData (F, ConDes, ConDesCount);
- /* Re-order the data. In the file, each decl is encoded into a byte
- * which contains the type and the priority. In memory, we will use
- * an array of types which contain the priority. This array was
- * cleared by the constructor (NewExport), so we must only set the
- * fields that contain values.
- */
- for (I = 0; I < ConDesCount; ++I) {
- unsigned ConDesType = CD_GET_TYPE (ConDes[I]);
- unsigned ConDesPrio = CD_GET_PRIO (ConDes[I]);
- E->ConDes[ConDesType] = ConDesPrio;
- }
+ /* Re-order the data. In the file, each decl is encoded into a byte
+ * which contains the type and the priority. In memory, we will use
+ * an array of types which contain the priority.
+ */
+ for (I = 0; I < ConDesCount; ++I) {
+ E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]);
+ }
}
/* Read the name */
if (SYM_IS_EXPR (Type)) {
E->Expr = ReadExpr (F, O);
} else {
- E->Expr = LiteralExpr (Read32 (F), O);
+ E->Expr = LiteralExpr (Read32 (F), O);
}
/* Read the size */
ReadLineInfoList (F, O, &E->DefLines);
ReadLineInfoList (F, O, &E->RefLines);
+ /* If this symbol is exported as a condes, and the condes type declares a
+ * forced import, add this import to the object module.
+ */
+ for (I = 0; I < CD_TYPE_COUNT; ++I) {
+ const ConDesImport* CDI;
+ if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) {
+
+ unsigned J;
+
+ /* Generate a new import and insert it */
+ Import* Imp = InsertImport (GenImport (CDI->Name, CDI->AddrSize));
+
+ /* Add line info for the config file and for the export that is
+ * actually the condes that forces the import.
+ */
+ CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos));
+ for (J = 0; J < CollCount (&E->DefLines); ++J) {
+ CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J)));
+ }
+ }
+ }
+
/* Return the new export */
return E;
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+LineInfo* DupLineInfo (const LineInfo* LI)
+/* Creates a duplicate of a line info structure */
+{
+ /* Allocate memory */
+ LineInfo* New = xmalloc (sizeof (LineInfo));
+
+ /* Copy the fields (leave id invalid) */
+ New->Id = LI->Id;
+ New->File = LI->File;
+ New->Type = LI->Type;
+ New->Pos = LI->Pos;
+ New->Spans = DupSpanList (LI->Spans);
+
+ /* Return the copy */
+ return New;
+}
+
+
+
LineInfo* GenLineInfo (const FilePos* Pos)
/* Generate a new (internally used) line info with the given information */
{
void FreeLineInfo (LineInfo* LI);
/* Free a LineInfo structure. */
+LineInfo* DupLineInfo (const LineInfo* LI);
+/* Creates a duplicate of a line info structure */
+
void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos);
/* Read a list of line infos stored as a list of indices in the object file,
* make real line infos from them and place them into the passed collection.
+unsigned* DupSpanList (const unsigned* S)
+/* Duplicate a span list */
+{
+ unsigned Size;
+
+ /* The list may be empty */
+ if (S == 0) {
+ return 0;
+ }
+
+ /* Allocate memory, copy and return the new list */
+ Size = (*S + 1) * sizeof (*S);
+ return memcpy (xmalloc (Size), S, Size);
+}
+
+
+
void FreeSpan (Span* S)
/* Free a span structure */
{
* the span ids. If the number of spans is zero, NULL is returned.
*/
+unsigned* DupSpanList (const unsigned* S);
+/* Duplicate a span list */
+
void FreeSpan (Span* S);
/* Free a span structure */