]> git.sur5r.net Git - cc65/blob - src/da65/labels.c
Fixed an error
[cc65] / src / da65 / labels.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 labels.c                                  */
4 /*                                                                           */
5 /*                         Label management for da65                         */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2006-2007 Ullrich von Bassewitz                                       */
10 /*               Roemerstrasse 52                                            */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <string.h>
38
39 /* common */
40 #include "xmalloc.h"
41 #include "xsprintf.h"
42
43 /* da65 */
44 #include "attrtab.h"
45 #include "code.h"
46 #include "comments.h"
47 #include "error.h"
48 #include "global.h"
49 #include "labels.h"
50 #include "output.h"
51
52
53
54 /*****************************************************************************/
55 /*                                   Data                                    */
56 /*****************************************************************************/
57
58
59
60 /* Symbol table */
61 static const char* SymTab[0x10000];
62
63
64
65 /*****************************************************************************/
66 /*                                   Code                                    */
67 /*****************************************************************************/
68
69
70
71 static const char* MakeLabelName (unsigned Addr)
72 /* Make the default label name from the given address and return it in a
73  * static buffer.
74  */
75 {
76     static char LabelBuf [32];
77     xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr);
78     return LabelBuf;
79 }
80
81
82
83 static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
84 /* Add a label */
85 {
86     /* Get an existing label attribute */
87     attr_t ExistingAttr = GetLabelAttr (Addr);
88
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?).
93          */
94         if (ExistingAttr == Attr &&
95             ((Name == 0 && SymTab[Addr] == 0) || strcmp (SymTab[Addr], Name) == 0)) {
96             return;
97         }
98         Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name);
99     }
100
101     /* Create a new label (xstrdup will return NULL if input NULL) */
102     SymTab[Addr] = xstrdup (Name);
103
104     /* Remember the attribute */
105     MarkAddr (Addr, Attr);
106 }
107
108
109
110 void AddIntLabel (unsigned Addr)
111 /* Add an internal label using the address to generate the name. */
112 {
113     AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
114 }
115
116
117
118 void AddExtLabel (unsigned Addr, const char* Name)
119 /* Add an external label */
120 {
121     AddLabel (Addr, atExtLabel, Name);
122 }
123
124
125
126 void AddUnnamedLabel (unsigned Addr)
127 /* Add an unnamed label */
128 {
129     AddLabel (Addr, atUnnamedLabel, 0);
130 }
131
132
133
134 void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs)
135 /* Add a dependent label at the given address using "basename+Offs" as the new
136  * name.
137  */
138 {
139     /* Allocate memory for the dependent label name */
140     unsigned NameLen = strlen (BaseName);
141     char*    DepName = xmalloc (NameLen + 7);   /* "+$ABCD\0" */
142
143     /* Create the new name in the buffer */
144     if (UseHexOffs) {
145         sprintf (DepName, "%s+$%02X", BaseName, Offs);
146     } else {
147         sprintf (DepName, "%s+%u", BaseName, Offs);
148     }
149
150     /* Define the labels */
151     AddLabel (Addr, Attr | atDepLabel, DepName);
152
153     /* Free the name buffer */
154     xfree (DepName);
155 }
156
157
158
159 static void AddLabelRange (unsigned Addr, attr_t Attr,
160                            const char* Name, unsigned Count)
161 /* Add a label for a range. The first entry gets the label "Name" while the
162  * others get "Name+offs".
163  */
164 {
165     /* Define the label */
166     AddLabel (Addr, Attr, Name);
167
168     /* Define dependent labels if necessary */
169     if (Count > 1) {
170         unsigned Offs;
171
172         /* Setup the format string */
173         const char* Format = UseHexOffs? "$%02X" : "%u";
174
175         /* Allocate memory for the dependent label names */
176         unsigned NameLen = strlen (Name);
177         char*    DepName = xmalloc (NameLen + 7);       /* "+$ABCD" */
178         char*    DepOffs = DepName + NameLen + 1;
179
180         /* Copy the original name into the buffer */
181         memcpy (DepName, Name, NameLen);
182         DepName[NameLen] = '+';
183
184         /* Define the labels */
185         for (Offs = 1; Offs < Count; ++Offs) {
186             sprintf (DepOffs, Format, Offs);
187             AddLabel (Addr + Offs, Attr | atDepLabel, DepName);
188         }
189
190         /* Free the name buffer */
191         xfree (DepName);
192     }
193 }
194
195
196
197 void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count)
198 /* Add an internal label for a range. The first entry gets the label "Name"
199  * while the others get "Name+offs".
200  */
201 {
202     /* Define the label range */
203     AddLabelRange (Addr, atIntLabel, Name, Count);
204 }
205
206
207
208 void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count)
209 /* Add an external label for a range. The first entry gets the label "Name"
210  * while the others get "Name+offs".
211  */
212 {
213     /* Define the label range */
214     AddLabelRange (Addr, atExtLabel, Name, Count);
215 }
216
217
218
219 int HaveLabel (unsigned Addr)
220 /* Check if there is a label for the given address */
221 {
222     /* Check for a label */
223     return (GetLabelAttr (Addr) != atNoLabel);
224 }
225
226
227
228 int MustDefLabel (unsigned Addr)
229 /* Return true if we must define a label for this address, that is, if there
230  * is a label at this address, and it is an external or internal label.
231  */
232 {
233     /* Get the label attribute */
234     attr_t A = GetLabelAttr (Addr);
235
236     /* Check for an internal, external, or unnamed label */
237     return (A == atExtLabel || A == atIntLabel || A == atUnnamedLabel);
238 }
239
240
241
242 const char* GetLabelName (unsigned Addr)
243 /* Return the label name for an address */
244 {
245     /* Get the label attribute */
246     attr_t A = GetLabelAttr (Addr);
247
248     /* Special case unnamed labels, because these don't have a named stored in
249      * the symbol table to save space.
250      */
251     if (A == atUnnamedLabel) {
252         return "";
253     } else {
254         /* Return the label if any */
255         return SymTab[Addr];
256     }
257 }
258
259
260
261 const char* GetLabel (unsigned Addr, unsigned RefFrom)
262 /* Return the label name for an address, as it is used in a label reference.
263  * RefFrom is the address the label is referenced from. This is needed in case
264  * of unnamed labels, to determine the name.
265  */
266 {
267     static const char* FwdLabels[] = {
268         ":+", ":++", ":+++", ":++++", ":+++++", ":++++++", ":+++++++",
269         ":++++++++", ":+++++++++", ":++++++++++"
270     };
271     static const char* BackLabels[] = {
272         ":-", ":--", ":---", ":----", ":-----", ":------", ":-------",
273         ":--------", ":---------", ":----------"
274     };
275
276     /* Get the label attribute */
277     attr_t A = GetLabelAttr (Addr);
278
279     /* Special case unnamed labels, because these don't have a named stored in
280      * the symbol table to save space.
281      */
282     if (A == atUnnamedLabel) {
283
284         unsigned Count = 0;
285
286         /* Search forward or backward depending in which direction the label
287          * is.
288          */
289         if (Addr <= RefFrom) {
290             /* Search backwards */
291             unsigned I = RefFrom;
292             while (Addr < I) {
293                 --I;
294                 A = GetLabelAttr (I);
295                 if (A == atUnnamedLabel) {
296                     ++Count;
297                     if (Count >= sizeof (BackLabels) / sizeof (BackLabels[0])) {
298                         Error ("Too many unnamed labels between label at "
299                                "$%04X and reference at $%04X", Addr, RefFrom);
300                     }
301                 }
302             }
303
304             /* Return the label name */
305             return BackLabels[Count-1];
306
307         } else {
308             /* Search forwards */
309             unsigned I = RefFrom;
310             while (Addr > I) {
311                 ++I;
312                 A = GetLabelAttr (I);
313                 if (A == atUnnamedLabel) {
314                     ++Count;
315                     if (Count >= sizeof (FwdLabels) / sizeof (FwdLabels[0])) {
316                         Error ("Too many unnamed labels between label at "
317                                "$%04X and reference at $%04X", Addr, RefFrom);
318                     }
319                 }
320             }
321
322             /* Return the label name */
323             return FwdLabels[Count-1];
324         }
325
326     } else {
327         /* Return the label if any */
328         return SymTab[Addr];
329     }
330 }
331
332
333
334 void ForwardLabel (unsigned Offs)
335 /* If necessary, output a forward label, one that is within the next few
336  * bytes and is therefore output as "label = * + x".
337  */
338 {
339     /* Calculate the actual address */
340     unsigned long Addr = PC + Offs;
341
342     /* Get the type of the label */
343     attr_t A = GetLabelAttr (Addr);
344
345     /* If there is no label, or just a dependent one, bail out */
346     if (A == atNoLabel || (A & atDepLabel) != 0) {
347         return;
348     }
349
350     /* An unnamed label cannot be output as a forward declaration, so this is
351      * an error.
352      */
353     if (A == atUnnamedLabel) {
354         Error ("Cannot define unnamed label at address $%04lX", Addr);
355     }
356
357     /* Output the label */
358     DefForward (GetLabelName (Addr), GetComment (Addr), Offs);
359 }
360
361
362
363 static void DefOutOfRangeLabel (unsigned long Addr)
364 /* Define one label that is outside code range. */
365 {
366     switch (GetLabelAttr (Addr)) {
367
368         case atIntLabel:
369         case atExtLabel:
370             DefConst (SymTab[Addr], GetComment (Addr), Addr);
371             break;
372
373         case atUnnamedLabel:
374             Error ("Cannot define unnamed label at address $%04lX", Addr);
375             break;
376
377         default:
378             break;
379
380     }
381 }
382
383
384
385 void DefOutOfRangeLabels (void)
386 /* Output any labels that are out of the loaded code range */
387 {
388     unsigned long Addr;
389
390     SeparatorLine ();
391
392     /* Low range */
393     Addr = 0;
394     while (Addr < CodeStart) {
395         DefOutOfRangeLabel (Addr++);
396     }
397
398     /* Skip areas in code range */
399     while (Addr <= CodeEnd) {
400         if (GetStyleAttr (Addr) == atSkip) {
401             DefOutOfRangeLabel (Addr);
402         }
403         ++Addr;
404     }
405
406     /* High range */
407     while (Addr < 0x10000) {
408         DefOutOfRangeLabel (Addr++);
409     }
410
411     SeparatorLine ();
412 }
413
414
415