]> git.sur5r.net Git - cc65/blobdiff - src/ld65/segments.c
Added command line response files
[cc65] / src / ld65 / segments.c
index ea3dec3cc11baa0f83cf20875ad737372c56bd40..aa0251c389a2329e8065c2942246fb0366fba04b 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: