From 1ae117fed8725d651c7ef62bb3fe5e5fa22274eb Mon Sep 17 00:00:00 2001 From: cuz Date: Thu, 29 Apr 2004 14:00:28 +0000 Subject: [PATCH] Fixed a bug in the handling of ranges where the granularity is not one: An 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 | 119 +++++++++++++++++++++++++++++++++++--------- src/da65/attrtab.h | 19 +++++-- src/da65/data.c | 6 +-- src/da65/handler.c | 55 ++++++++++++++++++-- src/da65/infofile.c | 27 ++++++---- 5 files changed, 182 insertions(+), 44 deletions(-) diff --git a/src/da65/attrtab.c b/src/da65/attrtab.c index 69efa282a..4cce152fd 100644 --- a/src/da65/attrtab.c +++ b/src/da65/attrtab.c @@ -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; } diff --git a/src/da65/attrtab.h b/src/da65/attrtab.h index 69c8ee298..2e64be067 100644 --- a/src/da65/attrtab.h +++ b/src/da65/attrtab.h @@ -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". diff --git a/src/da65/data.c b/src/da65/data.c index e16336860..2056ab822 100644 --- a/src/da65/data.c +++ b/src/da65/data.c @@ -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"); diff --git a/src/da65/handler.c b/src/da65/handler.c index d9967c2e6..fe0b019e0 100644 --- a/src/da65/handler.c +++ b/src/da65/handler.c @@ -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); + } } } } diff --git a/src/da65/infofile.c b/src/da65/infofile.c index 7c9418674..493054f45 100644 --- a/src/da65/infofile.c +++ b/src/da65/infofile.c @@ -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); -- 2.39.5