]> git.sur5r.net Git - cc65/blobdiff - src/ld65/config.c
Another warning.
[cc65] / src / ld65 / config.c
index 5959067b221d570d7bea928c2e76993ae1759174..73eee1caac57255b715d353eb401b2a578a6950e 100644 (file)
@@ -653,6 +653,7 @@ static void ParseSegments (void)
         {   "RW",               CFGTOK_RW               },
         {   "BSS",              CFGTOK_BSS              },
         {   "ZP",               CFGTOK_ZP               },
+        {   "OVERWRITE",        CFGTOK_OVERWRITE        },
     };
 
     unsigned Count;
@@ -753,11 +754,12 @@ static void ParseSegments (void)
                     FlagAttr (&S->Attr, SA_TYPE, "TYPE");
                     CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
                     switch (CfgTok) {
-                        case CFGTOK_RO:    S->Flags |= SF_RO;               break;
-                        case CFGTOK_RW:    /* Default */                    break;
-                        case CFGTOK_BSS:   S->Flags |= SF_BSS;              break;
-                        case CFGTOK_ZP:    S->Flags |= (SF_BSS | SF_ZP);    break;
-                        default:           Internal ("Unexpected token: %d", CfgTok);
+                        case CFGTOK_RO:        S->Flags |= SF_RO;                  break;
+                        case CFGTOK_RW:        /* Default */                       break;
+                        case CFGTOK_BSS:       S->Flags |= SF_BSS;                 break;
+                        case CFGTOK_ZP:        S->Flags |= (SF_BSS | SF_ZP);       break;
+                        case CFGTOK_OVERWRITE: S->Flags |= (SF_OVERWRITE | SF_RO); break;
+                        default:               Internal ("Unexpected token: %d", CfgTok);
                     }
                     CfgNextTok ();
                     break;
@@ -1795,6 +1797,7 @@ unsigned CfgProcess (void)
     for (I = 0; I < CollCount (&MemoryAreas); ++I) {
         unsigned J;
         unsigned long Addr;
+        unsigned Overwrites = 0;
 
         /* Get the next memory area */
         MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
@@ -1848,6 +1851,27 @@ unsigned CfgProcess (void)
             /* Remember the start address before handling this segment */
             unsigned long StartAddr = Addr;
 
+            /* Take note of "overwrite" segments and make sure there are no
+            ** other segment types following them in current memory region.
+            */
+            if (S->Flags & SF_OVERWRITE) {
+                if (S->Flags & (SF_OFFSET | SF_START)) {
+                    ++Overwrites;
+                } else {
+                    CfgError (GetSourcePos (M->LI),
+                              "Segment `%s' of type `overwrite' requires either"
+                              " `Start' or `Offset' attribute to be specified",
+                              GetString (S->Name));
+                }
+            } else {
+                if (Overwrites > 0) {
+                    CfgError (GetSourcePos (M->LI),
+                              "Segment `%s' is preceded by at least one segment"
+                              " of type `overwrite'",
+                              GetString (S->Name));
+                }
+            }
+
             /* Some actions depend on whether this is the load or run memory
             ** area.
             */
@@ -1896,22 +1920,33 @@ unsigned CfgProcess (void)
                         /* An offset was given, no address, make an address */
                         NewAddr += M->Start;
                     }
-                    if (NewAddr < Addr) {
-                        /* Offset already too large */
-                        ++Overflows;
-                        if (S->Flags & SF_OFFSET) {
-                            CfgWarning (GetSourcePos (S->LI),
-                                        "Segment `%s' offset is too small in `%s' by %lu byte%c",
-                                        GetString (S->Name), GetString (M->Name),
-                                        Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+
+                    if (S->Flags & SF_OVERWRITE) {
+                        if (NewAddr < M->Start) {
+                            CfgError (GetSourcePos (S->LI),
+                                      "Segment `%s' begins before memory area `%s'",
+                                      GetString (S->Name), GetString (M->Name));
                         } else {
-                            CfgWarning (GetSourcePos (S->LI),
-                                        "Segment `%s' start address is too low in `%s' by %lu byte%c",
-                                        GetString (S->Name), GetString (M->Name),
-                                        Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+                            Addr = NewAddr;
                         }
                     } else {
-                        Addr = NewAddr;
+                        if (NewAddr < Addr) {
+                            /* Offset already too large */
+                            ++Overflows;
+                            if (S->Flags & SF_OFFSET) {
+                                CfgWarning (GetSourcePos (S->LI),
+                                            "Segment `%s' offset is too small in `%s' by %lu byte%c",
+                                            GetString (S->Name), GetString (M->Name),
+                                            Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+                            } else {
+                                CfgWarning (GetSourcePos (S->LI),
+                                            "Segment `%s' start address is too low in `%s' by %lu byte%c",
+                                            GetString (S->Name), GetString (M->Name),
+                                            Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+                            }
+                        } else {
+                            Addr = NewAddr;
+                        }
                     }
                 }