1 /*****************************************************************************/
5 /* Unnamed labels for the ca65 macroassembler */
9 /* (C) 2000-2004 Ullrich von Bassewitz */
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 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* Struct that describes an unnamed label */
57 typedef struct ULabel ULabel;
59 FilePos Pos; /* Position of the label in the source */
60 ExprNode* Val; /* The label value - may be NULL */
61 unsigned Ref; /* Number of references */
65 static Collection ULabList = STATIC_COLLECTION_INITIALIZER;
66 static unsigned ULabDefCount = 0; /* Number of defined labels */
70 /*****************************************************************************/
72 /*****************************************************************************/
76 static ULabel* NewULabel (ExprNode* Val)
77 /* Create a new ULabel and insert it into the collection. The created label
78 * structure is returned.
81 /* Allocate memory for the ULabel structure */
82 ULabel* L = xmalloc (sizeof (ULabel));
84 /* Initialize the fields */
89 /* Insert the label into the collection */
90 CollAppend (&ULabList, L);
92 /* Return the created label */
98 ExprNode* ULabRef (int Which)
99 /* Get an unnamed label. If Which is negative, it is a backreference (a
100 * reference to an already defined label), and the function will return a
101 * segment relative expression. If Which is positive, it is a forward ref,
102 * and the function will return a expression node for an unnamed label that
103 * must be resolved later.
109 /* Which can never be 0 */
110 PRECONDITION (Which != 0);
112 /* Get the index of the referenced label */
116 Index = (int) ULabDefCount + Which;
118 /* We cannot have negative label indices */
120 /* Label does not exist */
121 Error ("Undefined label");
122 /* We must return something valid */
123 return GenCurrentPC();
126 /* Check if the label exists. If not, generate enough forward labels. */
127 if (Index < (int) CollCount (&ULabList)) {
128 /* The label exists, get it. */
129 L = CollAtUnchecked (&ULabList, Index);
131 /* Generate new, undefined labels */
132 while (Index >= (int) CollCount (&ULabList)) {
137 /* Mark the label as referenced */
140 /* If the label is already defined, return its value, otherwise return
144 return CloneExpr (L->Val);
146 return GenULabelExpr (Index);
153 /* Define an unnamed label at the current PC */
155 if (ULabDefCount < CollCount (&ULabList)) {
156 /* We did already have a forward reference to this label, so has
157 * already been generated, but doesn't have a value. Use the current
158 * PC for the label value.
160 ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
162 L->Val = GenCurrentPC ();
165 /* There is no such label, create it */
166 NewULabel (GenCurrentPC ());
169 /* We have one more defined label */
175 int ULabCanResolve (void)
176 /* Return true if we can resolve arbitrary ULabels. */
178 /* We can resolve labels if we don't have any undefineds */
179 return (ULabDefCount == CollCount (&ULabList));
184 ExprNode* ULabResolve (unsigned Index)
185 /* Return a valid expression for the unnamed label with the given index. This
186 * is used to resolve unnamed labels when assembly is done, so it is an error
187 * if a label is still undefined in this phase.
190 /* Get the label and check that it is defined */
191 ULabel* L = CollAt (&ULabList, Index);
194 /* Return the label value */
195 return CloneExpr (L->Val);
200 void ULabCheck (void)
201 /* Run through all unnamed labels and check for anomalies and errors */
203 /* Check if there are undefined labels */
204 unsigned I = ULabDefCount;
205 while (I < CollCount (&ULabList)) {
206 ULabel* L = CollAtUnchecked (&ULabList, I);
207 PError (&L->Pos, "Undefined label");
211 /* Walk over all labels and emit a warning if any unreferenced ones
214 for (I = 0; I < CollCount (&ULabList); ++I) {
215 ULabel* L = CollAtUnchecked (&ULabList, I);
217 PWarning (&L->Pos, 1, "No reference to unnamed label");