]> git.sur5r.net Git - cc65/commitdiff
Fixed a bug in the handling of ranges where the granularity is not one: An
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 29 Apr 2004 14:00:28 +0000 (14:00 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 29 Apr 2004 14:00:28 +0000 (14:00 +0000)
internally generated label could disrupt the output of such a range by
adding an offset not equal to the granularity. The solution is to only
add dependent labels within such a range on all addresses that do not
match the granularity (odd addresses for a .word table for example).

git-svn-id: svn://svn.cc65.org/cc65/trunk@3002 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/da65/attrtab.c
src/da65/attrtab.h
src/da65/data.c
src/da65/handler.c
src/da65/infofile.c

index 69efa282a75fa9879feb81c9634d5fbfcc225a41..4cce152fd81e2c5452c7d95455837103f4b6cd41 100644 (file)
@@ -79,6 +79,30 @@ static void AddrCheck (unsigned Addr)
 
 
 
+unsigned GetGranularity (attr_t Style)
+/* Get the granularity for the given style */
+{
+    switch (Style) {
+       case atDefault:  return 1;
+       case atCode:     return 1;
+       case atIllegal:  return 1;
+       case atByteTab:  return 1;
+       case atDByteTab: return 2;
+       case atWordTab:  return 2;
+       case atDWordTab: return 4;
+       case atAddrTab:  return 2;
+       case atRtsTab:   return 2;
+       case atTextTab:  return 1;
+
+       case atSkip:
+       default:
+           Internal ("GetGraularity called for style = %d", Style);
+           return 0;
+    }
+}
+
+
+
 void MarkRange (unsigned Start, unsigned End, attr_t Attr)
 /* Mark a range with the given attribute */
 {
@@ -129,11 +153,11 @@ void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
 
     /* Must not have two symbols for one address */
     if (ExistingAttr != atNoLabel) {
-       /* Allow redefinition if identical */
+       /* Allow redefinition if identical */
                if (ExistingAttr == Attr && strcmp (SymTab[Addr], Name) == 0) {
-           return;
-       }
-       Error ("Duplicate label for address %04X: %s/%s", Addr, SymTab[Addr], Name);
+           return;
+       }
+       Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name);
     }
 
     /* Create a new label */
@@ -145,43 +169,90 @@ void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
 
 
 
-void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
-/* Add an external label for a range. The first entry gets the label "Name"
- * while the others get "Name+offs".
+void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs)
+/* Add a dependent label at the given address using "base name+Offs" as the new
+ * name.
+ */
+{
+    /* Allocate memory for the dependent label name */
+    unsigned NameLen = strlen (BaseName);
+    char*    DepName = xmalloc (NameLen + 7);  /* "+$ABCD" */
+
+    /* Create the new name in the buffer */
+    if (UseHexOffs) {
+       sprintf (DepName, "%s+$%02X", BaseName, Offs);
+    } else {
+       sprintf (DepName, "%s+%u", BaseName, Offs);
+    }
+
+    /* Define the labels */
+    AddLabel (Addr, Attr | atDepLabel, DepName);
+
+    /* Free the name buffer */
+    xfree (DepName);
+}
+
+
+
+static void AddLabelRange (unsigned Addr, attr_t Attr, const char* Name, unsigned Count)
+/* Add a label for a range. The first entry gets the label "Name" while the
+ * others get "Name+offs".
  */
 {
     /* Define the label */
-    AddLabel (Addr, atExtLabel, Name);
+    AddLabel (Addr, Attr, Name);
 
     /* Define dependent labels if necessary */
     if (Count > 1) {
-       unsigned Offs;
+       unsigned Offs;
 
         /* Setup the format string */
         const char* Format = UseHexOffs? "$%02X" : "%u";
 
-       /* Allocate memory for the dependent label names */
-       unsigned NameLen = strlen (Name);
-       char*    DepName = xmalloc (NameLen + 7);
-       char*    DepOffs = DepName + NameLen + 1;
+       /* Allocate memory for the dependent label names */
+       unsigned NameLen = strlen (Name);
+       char*    DepName = xmalloc (NameLen + 7);       /* "+$ABCD" */
+       char*    DepOffs = DepName + NameLen + 1;
 
-       /* Copy the original name into the buffer */
-       memcpy (DepName, Name, NameLen);
-       DepName[NameLen] = '+';
+       /* Copy the original name into the buffer */
+       memcpy (DepName, Name, NameLen);
+       DepName[NameLen] = '+';
 
-       /* Define the labels */
-       for (Offs = 1; Offs < Count; ++Offs) {
-           sprintf (DepOffs, Format, Offs);
-           AddLabel (Addr + Offs, atDepLabel, DepName);
-       }
+       /* Define the labels */
+               for (Offs = 1; Offs < Count; ++Offs) {
+           sprintf (DepOffs, Format, Offs);
+           AddLabel (Addr + Offs, Attr | atDepLabel, DepName);
+       }
 
-       /* Free the name buffer */
-       xfree (DepName);
+       /* Free the name buffer */
+       xfree (DepName);
     }
 }
 
 
 
+void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count)
+/* Add an internal label for a range. The first entry gets the label "Name"
+ * while the others get "Name+offs".
+ */
+{
+    /* Define the label range */
+    AddLabelRange (Addr, atIntLabel, Name, Count);
+}
+
+
+
+void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
+/* Add an external label for a range. The first entry gets the label "Name"
+ * while the others get "Name+offs".
+ */
+{
+    /* Define the label range */
+    AddLabelRange (Addr, atExtLabel, Name, Count);
+}
+
+
+
 int HaveLabel (unsigned Addr)
 /* Check if there is a label for the given address */
 {
@@ -267,7 +338,7 @@ void DefOutOfRangeLabels (void)
     while (Addr < CodeStart) {
        if (MustDefLabel (Addr)) {
            DefineConst (Addr);
-       }
+       }
         ++Addr;
     }
 
index 69c8ee2981993a73b955ca00ab14686a81c4cefc..2e64be0678154f630ceeeac12187e5d2e3edac63 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
+/* (C) 2000-2004 Ullrich von Bassewitz                                       */
 /*               Römerstrasse 52                                             */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
@@ -63,10 +63,10 @@ typedef enum attr_t {
     atNoLabel  = 0x00,         /* No label for this address */
     atExtLabel = 0x10,         /* External label */
     atIntLabel  = 0x20,                /* Internally generated label */
-    atDepLabel = 0x30,         /* Dependent label (always extern) */
+    atDepLabel         = 0x40,         /* Dependent label */
 
     atStyleMask = 0x0F,                /* Output style */
-    atLabelMask = 0x30         /* Label information */
+    atLabelMask = 0x70         /* Label information */
 } attr_t;
 
 
@@ -77,6 +77,9 @@ typedef enum attr_t {
 
 
 
+unsigned GetGranularity (attr_t Style);
+/* Get the granularity for the given style */
+
 void MarkRange (unsigned Start, unsigned End, attr_t Attr);
 /* Mark a range with the given attribute */
 
@@ -91,6 +94,16 @@ const char* MakeLabelName (unsigned Addr);
 void AddLabel (unsigned Addr, attr_t Attr, const char* Name);
 /* Add a label */
 
+void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs);
+/* Add a dependent label at the given address using "base name+Offs" as the new
+ * name.
+ */
+
+void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count);
+/* Add an internal label for a range. The first entry gets the label "Name"
+ * while the others get "Name+offs".
+ */
+
 void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count);
 /* Add an external label for a range. The first entry gets the label "Name"
  * while the others get "Name+offs".
index e16336860fecfb7258bc960ae9ba27cf27b02edd..2056ab8227e4ea0b389f67d05c2a4b14ceb35117 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
+/* (C) 2000-2004 Ullrich von Bassewitz                                       */
 /*               Römerstrasse 52                                             */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
@@ -189,7 +189,7 @@ unsigned AddrTable (void)
            const char* Label = GetLabel (Addr);
            if (Label == 0) {
                /* OOPS! Should not happen */
-               Internal ("OOPS - Label for address %04X disappeard!", Addr);
+               Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
            }
            Indent (MIndent);
            Output (".addr");
@@ -249,7 +249,7 @@ unsigned RtsTable (void)
            const char* Label = GetLabel (Addr);
            if (Label == 0) {
                /* OOPS! Should not happen */
-               Internal ("OOPS - Label for address %04X disappeard!", Addr);
+               Internal ("OOPS - Label for address 0x%06X disappeard!", Addr);
            }
            Indent (MIndent);
            Output (".word");
index d9967c2e62f850cd7b8b3920bf971df606c149e1..fe0b019e04122509015f836f92a47b615758fee7 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
+/* (C) 2000-2004 Ullrich von Bassewitz                                       */
 /*               Römerstrasse 52                                             */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
@@ -129,10 +129,57 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
 static void GenerateLabel (unsigned Flags, unsigned Addr)
 /* Generate a label in pass one if requested */
 {
-    if (Pass == 1 && !HaveLabel (Addr)) {
-               if ((Flags & flGenLabel) != 0 ||
-                   ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd)) {
+    /* Generate labels in pass #1, and only if we don't have a label already */
+    if (Pass == 1 && !HaveLabel (Addr) &&
+       /* Check if we must create a label */
+               ((Flags & flGenLabel) != 0 ||
+                ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
+
+       /* As a special case, handle ranges with tables or similar. Within
+        * such a range with a granularity > 1, do only generate dependent
+        * labels for all addresses but the first one. Be sure to generate
+        * a label for the start of the range, however.
+        */
+       attr_t Style         = GetStyleAttr (Addr);
+       unsigned Granularity = GetGranularity (Style);
+
+       if (Granularity == 1) {
+           /* Just add the label */
            AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
+       } else {
+           /* Search for the start of the range or the last non dependent
+            * label in the range.
+            */
+           unsigned Offs;
+           attr_t LabelAttr;
+           unsigned LabelAddr = Addr;
+           while (LabelAddr > CodeStart) {
+
+               if (Style != GetStyleAttr (LabelAddr-1)) {
+                   /* End of range reached */
+                   break;
+               }
+               --LabelAddr;
+               LabelAttr = GetLabelAttr (LabelAddr);
+               if ((LabelAttr & (atIntLabel|atExtLabel)) != 0 &&
+                   (LabelAttr & atDepLabel) == 0) {
+                   /* The address has an internal or external label */
+                   break;
+               }
+           }
+
+           /* If the proposed label address doesn't have a label, define one */
+           if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
+               AddLabel (LabelAddr, atIntLabel, MakeLabelName (LabelAddr));
+           }
+
+           /* Create the label */
+           Offs = Addr - LabelAddr;
+           if (Offs == 0) {
+               AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
+           } else {
+               AddDepLabel (Addr, atIntLabel, GetLabel (LabelAddr), Offs);
+           }
        }
     }
 }
index 7c94186747fd2de6e103d258102b877ca57a865e..493054f4561aa8e847720864323bb3d6792df670 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
+/* (C) 2000-2004 Ullrich von Bassewitz                                       */
 /*               Römerstrasse 52                                             */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
@@ -239,6 +239,8 @@ static void RangeSection (void)
     unsigned End       = 0;
     unsigned char Type = 0;
     char* Name          = 0;
+    unsigned MemberSize = 0;
+
 
     /* Skip the token */
     InfoNextTok ();
@@ -290,15 +292,15 @@ static void RangeSection (void)
                InfoNextTok ();
                InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE");
                switch (InfoTok) {
-                   case INFOTOK_ADDRTAB:       Type = atAddrTab;       break;
-                   case INFOTOK_BYTETAB:       Type = atByteTab;       break;
-                   case INFOTOK_CODE:          Type = atCode;          break;
-                    case INFOTOK_DBYTETAB:      Type = atDByteTab;      break;
-                   case INFOTOK_DWORDTAB:      Type = atDWordTab;      break;
-                           case INFOTOK_RTSTAB:        Type = atRtsTab;        break;
-                    case INFOTOK_SKIP:          Type = atSkip;          break;
-                   case INFOTOK_TEXTTAB:       Type = atTextTab;       break;
-                   case INFOTOK_WORDTAB:       Type = atWordTab;       break;
+                   case INFOTOK_ADDRTAB:  Type = atAddrTab;  MemberSize = 2; break;
+                   case INFOTOK_BYTETAB:  Type = atByteTab;  MemberSize = 1; break;
+                   case INFOTOK_CODE:     Type = atCode;     MemberSize = 1; break;
+                    case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break;
+                   case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break;
+                           case INFOTOK_RTSTAB:   Type = atRtsTab;   MemberSize = 2; break;
+                    case INFOTOK_SKIP:     Type = atSkip;     MemberSize = 1; break;
+                   case INFOTOK_TEXTTAB:  Type = atTextTab;  MemberSize = 1; break;
+                   case INFOTOK_WORDTAB:  Type = atWordTab;  MemberSize = 2; break;
                }
                InfoNextTok ();
                break;
@@ -319,6 +321,11 @@ static void RangeSection (void)
        InfoError ("Start value must not be greater than end value");
     }
 
+    /* Check the granularity */
+    if (((End - Start + 1) % MemberSize) != 0) {
+       InfoError ("Type of range needs a granularity of %u", MemberSize);
+    }
+
     /* Set the range */
     MarkRange (Start, End, Type);