]> git.sur5r.net Git - cc65/commitdiff
First finished implementation of the condes feature
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 20 Nov 2000 21:56:48 +0000 (21:56 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 20 Nov 2000 21:56:48 +0000 (21:56 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@456 b7a2c559-68d2-44c3-8de9-860c34a00d81

16 files changed:
src/ld65/bin.c
src/ld65/condes.c
src/ld65/condes.h
src/ld65/config.c
src/ld65/exports.c
src/ld65/exports.h
src/ld65/expr.c
src/ld65/expr.h
src/ld65/fragment.c
src/ld65/library.c
src/ld65/mapfile.c
src/ld65/objdata.c
src/ld65/objdata.h
src/ld65/scanner.h
src/ld65/segments.c
src/ld65/segments.h

index abc873e675789c90fb0253b96e2716e005365d54..5a22267e29309aded33860c22f77c7f172c09a0e 100644 (file)
 #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 */
index 7c9e7f73bf2370335e12c4e80ef8003979027db2..d8446312d9592b0555b3202e0ba394a92b595491 100644 (file)
 
 
 
+#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                                    */
 /*****************************************************************************/
 
 
 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);
+    }
 }
 
 
index 72d295acd636ff0f86cdc46e5fe9026a4e433e21..6285ac01becedb81d0debe65729040e2397398f3 100644 (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 */
index 314fc235c10c7370f2a981c81830b8292df205c8..ee963de1dd8dc94a23eccd6d78338da952d19387 100644 (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);
+    }
 }
 
 
index 515b8527d3c6e8ed5a8d8ae2c5ee364fb7ac6300..fde9bd5ecacf86ab2a71f04f0cbf81f392496ed3 100644 (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);
 }
 
 
index 8ee675f0c00758d85a091099b02d6c47c429923a..7204f8c8ece86885aa274cb0b5ca7fa4b313a1b2 100644 (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 */
 
index 3e1f01041d8f1e09f5a79c5379f3f3546df98bcf..57092d9f1613e8962fe58f18754f40e810bd812c 100644 (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 */
index 938ed34484d4e81644032e2b69ede0671261be2f..a810d0228f55204a3d8b660c6ffd83c493889ad3 100644 (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 */
 
index 22b45f8e4a1c176fc07f66f3ab8163ef2c23eb7c..991ed3565f982de80c5fa62b8757664d7644dfe8 100644 (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;
 }
index 4a9d8a7e71256eecc5632b38886db86a4b55e754..18b21b84388c51cb49b2857ddeac1f24f12ea3e3 100644 (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)
 
 
 
-
-
-
-
index 8e3582dd1c9900506f43f9ab66e2ae2c19d7b211..8d31666fda0353899b7c33ac1d9b6f7daaf947fa 100644 (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];
index 414e82990eb0e2e859b103095c25f478cad27ad8..085468da96519673480dd374411689a369b7ff50 100644 (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       */
 
 #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];
+
+    }
+}
+
+
+
+
index 4813d809dd84fe50755333852845688d69e86830..92202977fc4f8c7136a9dde9d28bfa8e07d644a5 100644 (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 */
index d5f86e3ec4024723ee862493348874327d9f585d..399efa4147194e704fd4dadf0347fccb76d5c883 100644 (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;
 
index ea3dec3cc11baa0f83cf20875ad737372c56bd40..e41dcdeac7d01e6fe611e8f788dc6bae9cb49f67 100644 (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:
index b045229ea91ed74b6391987b84ff9cd17d83cf5f..7a0a6a97454dc39dcdd8459c333eb2ce277c044c 100644 (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 */