]> git.sur5r.net Git - cc65/blob - src/ca65/ulabel.c
Added condes tables to c64 config
[cc65] / src / ca65 / ulabel.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 ulabel.c                                  */
4 /*                                                                           */
5 /*                Unnamed labels for the ca65 macroassembler                 */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
12 /* EMail:        uz@musoftware.de                                            */
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 /* common */
37 #include "check.h"
38 #include "filepos.h"
39 #include "xmalloc.h"
40           
41 /* ca65 */
42 #include "error.h"
43 #include "expr.h"
44 #include "scanner.h"
45 #include "ulabel.h"
46
47
48
49 /*****************************************************************************/
50 /*                                   Data                                    */
51 /*****************************************************************************/
52
53
54
55 /* Struct that describes an unnamed label */
56 typedef struct ULabel_ ULabel;
57 struct ULabel_ {
58     ULabel*     Prev;                   /* Pointer to previous node in list */
59     ULabel*     Next;                   /* Pointer to next node in list */
60     FilePos     Pos;                    /* Position of the label in the source */
61     ExprNode*   Val;                    /* The label value - may be NULL */
62 };
63
64 /* List management */
65 static ULabel*  ULabRoot        = 0;    /* Root of the list */
66 static ULabel*  ULabLast        = 0;    /* Last ULabel */
67 static ULabel*  ULabLastDef     = 0;    /* Last defined ULabel */
68 static unsigned ULabCount       = 0;    /* Number of labels */
69 static unsigned ULabDefCount    = 0;    /* Number of defined labels */
70 static ULabel** ULabList        = 0;    /* Array with pointers to all labels */
71
72
73
74 /*****************************************************************************/
75 /*                                   Code                                    */
76 /*****************************************************************************/
77
78
79
80 static ULabel* NewULabel (ExprNode* Val)
81 /* Create a new ULabel and insert it into the list. The function will move
82  * ULabelLast, but not ULabelLastDef. The created label structure is returned.
83  */
84 {
85     /* Allocate memory for the ULabel structure */
86     ULabel* L = xmalloc (sizeof (ULabel));
87
88     /* Initialize the fields */
89     L->Pos = CurPos;
90     L->Val = Val;
91
92     /* Insert the label into the list */
93     L->Next = 0;
94     if (ULabRoot == 0) {
95         /* First label */
96         L->Prev = 0;
97         ULabRoot = L;
98     } else {
99         ULabLast->Next = L;
100         L->Prev = ULabLast;
101     }
102     ULabLast = L;
103
104     /* One label more */
105     ++ULabCount;
106
107     /* Return the created label */
108     return L;
109 }
110
111
112
113 ExprNode* ULabRef (int Which)
114 /* Get an unnamed label. If Which is negative, it is a backreference (a
115  * reference to an already defined label), and the function will return a
116  * segment relative expression. If Which is positive, it is a forward ref,
117  * and the function will return a expression node for an unnamed label that
118  * must be resolved later.
119  */
120 {
121     ULabel* L;
122
123     /* Which can never be 0 */
124     PRECONDITION (Which != 0);
125
126     /* Which is never really big (usually -3..+3), so a linear search is
127      * the best we can do here.
128      */
129     L = ULabLastDef;
130     if (Which < 0) {
131         /* Backward reference */
132         while (Which < -1 && L != 0) {
133             L = L->Prev;
134             ++Which;
135         }
136         if (L == 0) {
137             /* Label does not exist */
138             Error (ERR_UNDEFINED_LABEL);
139             /* We must return something valid */
140             return CurrentPC();
141         } else {
142             /* Return a copy of the label value */
143             return CloneExpr (L->Val);
144         }
145     } else {
146         /* Forward reference. Create labels as needed */
147         unsigned LabelNum = ULabDefCount + Which - 1;
148         while (Which > 0) {
149             if (L->Next == 0) {
150                 NewULabel (0);
151             }
152             L = L->Next;
153             --Which;
154         }
155         /* Return an unnamed label expression */
156         return ULabelExpr (LabelNum);
157     }
158 }
159
160
161
162 void ULabDef (void)
163 /* Define an unnamed label at the current PC */
164 {
165     /* Create a new label if needed, or use an existing one */
166     if (ULabLastDef == 0 || ULabLastDef->Next == 0) {
167         /* The last label is also the last defined label, we need a new one */
168         ULabLastDef = NewULabel (CurrentPC ());
169     } else {
170         /* We do already have the label, but it's undefined until now */
171         ULabLastDef = ULabLastDef->Next;
172         ULabLastDef->Val = CurrentPC ();
173         ULabLastDef->Pos = CurPos;
174     }
175     ++ULabDefCount;
176 }
177
178
179
180 int ULabCanResolve (void)
181 /* Return true if we can resolve arbitrary ULabels. */
182 {
183     /* We can resolve labels if we have built the necessary access array */
184     return (ULabList != 0);
185 }
186
187
188
189 ExprNode* ULabResolve (unsigned Index)
190 /* Return a valid expression for the unnamed label with the given index. This
191  * is used to resolve unnamed labels when assembly is done, so it is an error
192  * if a label is still undefined in this phase.
193  */
194 {
195     ULabel* L;
196
197     /* Must be in resolve phase and the index must be valid */
198     CHECK (ULabList != 0 && Index < ULabCount);
199
200     /* Get the label */
201     L = ULabList [Index];
202
203     /* If the label is open (not defined), return some valid value */
204     if (L->Val == 0) {
205         return LiteralExpr (0);
206     } else {
207         return CloneExpr (L->Val);
208     }
209 }
210
211
212
213 void ULabCheck (void)
214 /* Run through all unnamed labels and check for anomalies and errors */
215 {
216     ULabel* L;
217
218     /* Check if there are undefined labels */
219     if (ULabLastDef) {
220         L = ULabLastDef->Next;
221         while (L) {
222             PError (&L->Pos, ERR_UNDEFINED_LABEL);
223             L = L->Next;
224         }
225     }
226
227     /* Create an array that holds pointers to all labels. This allows us to
228      * access the labels quickly by index in the resolver phase at the end of
229      * the assembly.
230      */
231     if (ULabCount) {
232         unsigned I = 0;
233         ULabList = xmalloc (ULabCount * sizeof (ULabel*));
234         L = ULabRoot;
235         while (L) {
236             ULabList[I] = L;
237             ++I;
238             L = L->Next;
239         }
240         CHECK (I == ULabCount);
241     }
242 }
243
244
245