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