]> git.sur5r.net Git - cc65/blobdiff - src/ld65/condes.c
Separate processing the linker config file into two phases: The config file is
[cc65] / src / ld65 / condes.c
index 7c9e7f73bf2370335e12c4e80ef8003979027db2..1e0406a648f8c2385f10baff32503f562052546a 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 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 = SB_Compare (GetStrBuf (Exp1->Name), GetStrBuf (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                                    */
 /*****************************************************************************/
@@ -86,8 +203,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);
        }
     }
@@ -95,56 +212,59 @@ void ConDesAddExport (struct Export* 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;
 }
 
 
@@ -152,7 +272,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_MAX);
+
+    return (ConDes[Type].SegName != INVALID_STRING_ID);
 }
 
 
@@ -160,7 +283,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_MAX);
+
+    return (ConDes[Type].Label != INVALID_STRING_ID);
 }
 
 
@@ -168,6 +294,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);
+    }
 }
 
 
@@ -184,5 +316,3 @@ void ConDesDump (void)
 
 
 
-
-