/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2003 Ullrich von Bassewitz */
+/* Römerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+#include <string.h>
+
/* common */
+#include "addrsize.h"
#include "check.h"
#include "coll.h"
+#include "fragdefs.h"
+#include "segdefs.h"
#include "xmalloc.h"
/* ld65 */
+#include "condes.h"
#include "exports.h"
+#include "fragment.h"
#include "segments.h"
-#include "condes.h"
+#include "spool.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Struct describing one condes type */
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 */
+ Collection ExpList; /* List of exported symbols */
+ unsigned SegName; /* Name of segment the table is in */
+ unsigned Label; /* Name of table label */
+ unsigned 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, 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 },
};
+/*****************************************************************************/
+/* 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 (GetString (Exp1->Name), GetString (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 == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) {
+ 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, ADDR_SIZE_ABS, 0);
+
+ /* Create a new section for the table */
+ Sec = NewSection (Seg, 1, ADDR_SIZE_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).
+ */
+ CreateSectionExport (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);
}
}
-void ConDesSetSegName (unsigned Type, const char* SegName)
+void ConDesSetSegName (unsigned Type, unsigned SegName)
/* Set the segment name where the table should go */
{
/* Check the parameters */
- PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && SegName != 0);
+ PRECONDITION (Type <= CD_TYPE_MAX && SegName != 0);
/* Setting the segment name twice is bad */
- CHECK (ConDes[Type].SegName == 0);
+ CHECK (ConDes[Type].SegName == INVALID_STRING_ID);
/* Set the name */
- ConDes[Type].SegName = xstrdup (SegName);
+ ConDes[Type].SegName = SegName;
}
-void ConDesSetLabel (unsigned Type, const char* Name)
+void ConDesSetLabel (unsigned Type, unsigned Name)
/* Set the label for the given ConDes type */
{
/* Check the parameters */
- PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && Name != 0);
+ PRECONDITION (Type <= CD_TYPE_MAX && Name != 0);
/* Setting the label twice is bad */
- CHECK (ConDes[Type].Label == 0);
+ CHECK (ConDes[Type].Label == INVALID_STRING_ID);
/* Set the name */
- ConDes[Type].Label = xstrdup (Name);
+ ConDes[Type].Label = Name;
}
-const char* ConDesGetSegName (unsigned Type)
-/* Return the segment name for the given ConDes type */
+void ConDesSetCountSym (unsigned Type, unsigned 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_MAX && Name != 0);
+
+ /* Setting the symbol twice is bad */
+ CHECK (ConDes[Type].CountSym == INVALID_STRING_ID);
- /* Return the name */
- return ConDes[Type].SegName;
+ /* Set the name */
+ ConDes[Type].CountSym = 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);
+ PRECONDITION (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_MAX);
+
+ return (ConDes[Type].SegName != INVALID_STRING_ID);
}
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_MAX);
+
+ return (ConDes[Type].Label != INVALID_STRING_ID);
}
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);
+ }
}
-
-