1 /*****************************************************************************/
5 /* Label management for da65 */
9 /* (C) 2006-2007 Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
61 static const char* SymTab[0x10000];
65 /*****************************************************************************/
67 /*****************************************************************************/
71 static const char* MakeLabelName (unsigned Addr)
72 /* Make the default label name from the given address and return it in a
76 static char LabelBuf [32];
77 xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr);
83 static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
86 /* Get an existing label attribute */
87 attr_t ExistingAttr = GetLabelAttr (Addr);
89 /* Must not have two symbols for one address */
90 if (ExistingAttr != atNoLabel) {
91 /* Allow redefinition if identical. Beware: Unnamed labels don't
92 ** have a name (you guessed that, didn't you?).
94 if (ExistingAttr == Attr &&
95 ((Name == 0 && SymTab[Addr] == 0) ||
96 (Name != 0 && SymTab[Addr] != 0 &&
97 strcmp (SymTab[Addr], Name) == 0))) {
100 Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name);
103 /* Create a new label (xstrdup will return NULL if input NULL) */
104 SymTab[Addr] = xstrdup (Name);
106 /* Remember the attribute */
107 MarkAddr (Addr, Attr);
112 void AddIntLabel (unsigned Addr)
113 /* Add an internal label using the address to generate the name. */
115 AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
120 void AddExtLabel (unsigned Addr, const char* Name)
121 /* Add an external label */
123 AddLabel (Addr, atExtLabel, Name);
128 void AddUnnamedLabel (unsigned Addr)
129 /* Add an unnamed label */
131 AddLabel (Addr, atUnnamedLabel, 0);
136 void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs)
137 /* Add a dependent label at the given address using "basename+Offs" as the new
141 /* Allocate memory for the dependent label name */
142 unsigned NameLen = strlen (BaseName);
143 char* DepName = xmalloc (NameLen + 7); /* "+$ABCD\0" */
145 /* Create the new name in the buffer */
147 sprintf (DepName, "%s+$%02X", BaseName, Offs);
149 sprintf (DepName, "%s+%u", BaseName, Offs);
152 /* Define the labels */
153 AddLabel (Addr, Attr | atDepLabel, DepName);
155 /* Free the name buffer */
161 static void AddLabelRange (unsigned Addr, attr_t Attr,
162 const char* Name, unsigned Count)
163 /* Add a label for a range. The first entry gets the label "Name" while the
164 ** others get "Name+offs".
167 /* Define the label */
168 AddLabel (Addr, Attr, Name);
170 /* Define dependent labels if necessary */
174 /* Setup the format string */
175 const char* Format = UseHexOffs? "$%02X" : "%u";
177 /* Allocate memory for the dependent label names */
178 unsigned NameLen = strlen (Name);
179 char* DepName = xmalloc (NameLen + 7); /* "+$ABCD" */
180 char* DepOffs = DepName + NameLen + 1;
182 /* Copy the original name into the buffer */
183 memcpy (DepName, Name, NameLen);
184 DepName[NameLen] = '+';
186 /* Define the labels */
187 for (Offs = 1; Offs < Count; ++Offs) {
188 sprintf (DepOffs, Format, Offs);
189 AddLabel (Addr + Offs, Attr | atDepLabel, DepName);
192 /* Free the name buffer */
199 void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count)
200 /* Add an internal label for a range. The first entry gets the label "Name"
201 ** while the others get "Name+offs".
204 /* Define the label range */
205 AddLabelRange (Addr, atIntLabel, Name, Count);
210 void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
211 /* Add an external label for a range. The first entry gets the label "Name"
212 ** while the others get "Name+offs".
215 /* Define the label range */
216 AddLabelRange (Addr, atExtLabel, Name, Count);
221 int HaveLabel (unsigned Addr)
222 /* Check if there is a label for the given address */
224 /* Check for a label */
225 return (GetLabelAttr (Addr) != atNoLabel);
230 int MustDefLabel (unsigned Addr)
231 /* Return true if we must define a label for this address, that is, if there
232 ** is a label at this address, and it is an external or internal label.
235 /* Get the label attribute */
236 attr_t A = GetLabelAttr (Addr);
238 /* Check for an internal, external, or unnamed label */
239 return (A == atExtLabel || A == atIntLabel || A == atUnnamedLabel);
244 const char* GetLabelName (unsigned Addr)
245 /* Return the label name for an address */
247 /* Get the label attribute */
248 attr_t A = GetLabelAttr (Addr);
250 /* Special case unnamed labels, because these don't have a named stored in
251 ** the symbol table to save space.
253 if (A == atUnnamedLabel) {
256 /* Return the label if any */
263 const char* GetLabel (unsigned Addr, unsigned RefFrom)
264 /* Return the label name for an address, as it is used in a label reference.
265 ** RefFrom is the address the label is referenced from. This is needed in case
266 ** of unnamed labels, to determine the name.
269 static const char* const FwdLabels[] = {
270 ":+", ":++", ":+++", ":++++", ":+++++", ":++++++", ":+++++++",
271 ":++++++++", ":+++++++++", ":++++++++++"
273 static const char* const BackLabels[] = {
274 ":-", ":--", ":---", ":----", ":-----", ":------", ":-------",
275 ":--------", ":---------", ":----------"
278 /* Get the label attribute */
279 attr_t A = GetLabelAttr (Addr);
281 /* Special case unnamed labels, because these don't have a named stored in
282 ** the symbol table to save space.
284 if (A == atUnnamedLabel) {
288 /* Search forward or backward depending in which direction the label
291 if (Addr <= RefFrom) {
292 /* Search backwards */
293 unsigned I = RefFrom;
296 A = GetLabelAttr (I);
297 if (A == atUnnamedLabel) {
299 if (Count >= sizeof (BackLabels) / sizeof (BackLabels[0])) {
300 Error ("Too many unnamed labels between label at "
301 "$%04X and reference at $%04X", Addr, RefFrom);
306 /* Return the label name */
307 return BackLabels[Count-1];
310 /* Search forwards */
311 unsigned I = RefFrom;
314 A = GetLabelAttr (I);
315 if (A == atUnnamedLabel) {
317 if (Count >= sizeof (FwdLabels) / sizeof (FwdLabels[0])) {
318 Error ("Too many unnamed labels between label at "
319 "$%04X and reference at $%04X", Addr, RefFrom);
324 /* Return the label name */
325 return FwdLabels[Count-1];
329 /* Return the label if any */
336 void ForwardLabel (unsigned Offs)
337 /* If necessary, output a forward label, one that is within the next few
338 ** bytes and is therefore output as "label = * + x".
341 /* Calculate the actual address */
342 unsigned long Addr = PC + Offs;
344 /* Get the type of the label */
345 attr_t A = GetLabelAttr (Addr);
347 /* If there is no label, or just a dependent one, bail out */
348 if (A == atNoLabel || (A & atDepLabel) != 0) {
352 /* An unnamed label cannot be output as a forward declaration, so this is
355 if (A == atUnnamedLabel) {
356 Error ("Cannot define unnamed label at address $%04lX", Addr);
359 /* Output the label */
360 DefForward (GetLabelName (Addr), GetComment (Addr), Offs);
365 static void DefOutOfRangeLabel (unsigned long Addr)
366 /* Define one label that is outside code range. */
368 switch (GetLabelAttr (Addr)) {
372 DefConst (SymTab[Addr], GetComment (Addr), Addr);
376 Error ("Cannot define unnamed label at address $%04lX", Addr);
387 void DefOutOfRangeLabels (void)
388 /* Output any labels that are out of the loaded code range */
396 while (Addr < CodeStart) {
397 DefOutOfRangeLabel (Addr++);
400 /* Skip areas in code range */
401 while (Addr <= CodeEnd) {
402 if (GetStyleAttr (Addr) == atSkip) {
403 DefOutOfRangeLabel (Addr);
409 while (Addr < 0x10000) {
410 DefOutOfRangeLabel (Addr++);