1 /*****************************************************************************/
5 /* Symbol table entry forward for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 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 /*****************************************************************************/
53 /*****************************************************************************/
55 /*****************************************************************************/
59 /* List of all symbol table entries */
60 SymEntry* SymList = 0;
62 /* Pointer to last defined symbol */
63 SymEntry* SymLast = 0;
67 /*****************************************************************************/
69 /*****************************************************************************/
73 int IsLocalName (const char* Name)
74 /* Return true if Name is the name of a local symbol */
76 return (*Name == LocalStart);
81 int IsLocalNameId (unsigned Name)
82 /* Return true if Name is the name of a local symbol */
84 return (*GetString (Name) == LocalStart);
89 static unsigned SymAddrSize (const SymEntry* S)
90 /* Get the default address size for a symbol. */
92 /* Local symbols are always near (is this ok?) */
93 if (IsLocalNameId (S->Name)) {
97 /* Return the address size of the enclosing scope */
98 return S->SymTab->AddrSize;
103 SymEntry* NewSymEntry (const char* Name)
104 /* Allocate a symbol table entry, initialize and return it */
106 /* Allocate memory */
107 SymEntry* S = xmalloc (sizeof (SymEntry));
109 /* Initialize the entry */
117 S->ExprRefs = AUTO_COLLECTION_INITIALIZER;
118 S->ExportSize = ADDR_SIZE_DEFAULT;
119 S->AddrSize = ADDR_SIZE_DEFAULT;
120 memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
121 S->Name = GetStringId (Name);
123 /* Insert it into the list of all entries */
127 /* Return the initialized entry */
133 void SymRef (SymEntry* S)
134 /* Mark the given symbol as referenced */
136 /* Mark the symbol as referenced */
137 S->Flags |= SF_REFERENCED;
142 void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
143 /* Define a new symbol */
145 if (S->Flags & SF_IMPORT) {
146 /* Defined symbol is marked as imported external symbol */
147 Error ("Symbol `%s' is already an import", GetSymName (S));
150 if (S->Flags & SF_DEFINED) {
151 /* Multiple definition */
152 Error ("Symbol `%s' is already defined", GetSymName (S));
153 S->Flags |= SF_MULTDEF;
157 /* Map a default address size to a real value */
158 if (AddrSize == ADDR_SIZE_DEFAULT) {
159 AddrSize = SymAddrSize (S);
162 /* Set the symbol value */
163 if (IsConstExpr (Expr)) {
164 /* Expression is const, store the value */
165 S->Flags |= SF_CONST;
166 S->V.Val = GetExprVal (Expr);
169 /* Not const, store the expression */
173 /* If the symbol is marked as global, export it */
174 if (S->Flags & SF_GLOBAL) {
175 S->ExportSize = S->AddrSize;
176 S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
179 /* Mark the symbol as defined and use the given address size */
180 S->Flags |= (SF_DEFINED | Flags);
181 S->AddrSize = AddrSize;
183 /* If the symbol is exported, check the address sizes */
184 if (S->Flags & SF_EXPORT) {
185 if (S->AddrSize > S->ExportSize) {
186 Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
190 /* If the symbol is a ZP symbol, check if the value is in correct range */
191 if (S->AddrSize == ADDR_SIZE_ZP) {
192 /* Already marked as ZP symbol by some means */
193 if (!IsByteExpr (Expr)) {
194 Error ("Range error");
198 /* If this is not a local symbol, remember it as the last global one */
199 if (!IsLocalNameId (S->Name)) {
206 void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
207 /* Mark the given symbol as an imported symbol */
209 /* Don't accept local symbols */
210 if (IsLocalNameId (S->Name)) {
211 Error ("Illegal use of a local symbol");
215 if (S->Flags & SF_DEFINED) {
216 Error ("Symbol `%s' is already defined", GetSymName (S));
217 S->Flags |= SF_MULTDEF;
220 if (S->Flags & SF_EXPORT) {
221 /* The symbol is already marked as exported symbol */
222 Error ("Cannot import exported symbol `%s'", GetSymName (S));
226 /* Map a default address size to a real value */
227 if (AddrSize == ADDR_SIZE_DEFAULT) {
228 AddrSize = SymAddrSize (S);
231 /* If the symbol is marked as import or global, check the symbol flags,
232 * then do silently remove the global flag
234 if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
235 if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
236 AddrSize != S->AddrSize) {
237 Error ("Redeclaration mismatch for symbol `%s'", GetSymName (S));
239 S->Flags &= ~SF_GLOBAL;
242 /* Set the symbol data */
243 S->Flags |= (SF_IMPORT | Flags);
244 S->AddrSize = AddrSize;
249 void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
250 /* Mark the given symbol as an exported symbol */
252 /* Don't accept local symbols */
253 if (IsLocalNameId (S->Name)) {
254 Error ("Illegal use of a local symbol");
258 /* Check if it's ok to export the symbol */
259 if (S->Flags & SF_IMPORT) {
260 /* The symbol is already marked as imported external symbol */
261 Error ("Symbol `%s' is already an import", GetSymName (S));
265 /* Map a default address size to a real value */
266 if (AddrSize == ADDR_SIZE_DEFAULT) {
267 AddrSize = SymAddrSize (S);
270 /* If the symbol was already marked as an export or global, check if
271 * this was done specifiying the same address size. In case of a global
272 * declaration, silently remove the global flag.
274 if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
275 if (S->ExportSize != AddrSize) {
276 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
278 S->Flags &= ~SF_GLOBAL;
280 S->ExportSize = AddrSize;
282 /* If the symbol is already defined, check symbol size against the
285 if (S->Flags & SF_DEFINED) {
286 if (S->AddrSize > S->ExportSize) {
287 Warning (1, "Address size mismatch for symbol `%s'", GetSymName (S));
291 /* Set the symbol data */
292 S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
297 void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
298 /* Mark the given symbol as a global symbol, that is, as a symbol that is
299 * either imported or exported.
302 /* Don't accept local symbols */
303 if (IsLocalNameId (S->Name)) {
304 Error ("Illegal use of a local symbol");
308 /* Map a default address size to a real value */
309 if (AddrSize == ADDR_SIZE_DEFAULT) {
310 AddrSize = SymAddrSize (S);
313 /* If the symbol is already marked as import or export, check the
314 * size of the definition, then bail out.
316 if (S->Flags & SF_IMPORT) {
317 if (AddrSize != S->AddrSize) {
318 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
322 if (S->Flags & SF_EXPORT) {
323 if (AddrSize != S->ExportSize) {
324 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
329 /* If the symbol is already defined, export it. Otherwise mark it as
332 if (S->Flags & SF_DEFINED) {
333 /* The symbol is defined, export it */
334 if (S->ExportSize != AddrSize) {
335 Error ("Address size mismatch for symbol `%s'", GetSymName (S));
337 S->Flags |= (SF_EXPORT | Flags);
338 S->ExportSize = AddrSize;
340 S->Flags |= (SF_GLOBAL | Flags);
341 S->AddrSize = AddrSize;
347 int SymIsDef (const SymEntry* S)
348 /* Return true if the given symbol is already defined */
350 return (S->Flags & SF_DEFINED) != 0;
355 int SymIsRef (const SymEntry* S)
356 /* Return true if the given symbol has been referenced */
358 return (S->Flags & SF_REFERENCED) != 0;
363 int SymIsImport (const SymEntry* S)
364 /* Return true if the given symbol is marked as import */
366 /* Resolve trampoline entries */
367 if (S->Flags & SF_TRAMPOLINE) {
371 /* Check the import flag */
372 return (S->Flags & SF_IMPORT) != 0;
377 int SymHasExpr (const SymEntry* S)
378 /* Return true if the given symbol has an associated expression */
380 /* Resolve trampoline entries */
381 if (S->Flags & SF_TRAMPOLINE) {
385 /* Check the expression */
386 return ((S->Flags & SF_DEFINED) != 0 &&
387 (S->Flags & SF_IMPORT) == 0 &&
388 (S->Flags & SF_CONST) == 0);
393 void SymFinalize (SymEntry* S)
394 /* Finalize a symbol expression if there is one */
396 /* Resolve trampoline entries */
397 if (S->Flags & SF_TRAMPOLINE) {
401 /* Check if we have an expression */
402 if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
403 S->V.Expr = FinalizeExpr (S->V.Expr);
404 S->Flags |= SF_FINALIZED;
410 void SymMarkUser (SymEntry* S)
411 /* Set a user mark on the specified symbol */
413 /* Resolve trampoline entries */
414 if (S->Flags & SF_TRAMPOLINE) {
424 void SymUnmarkUser (SymEntry* S)
425 /* Remove a user mark from the specified symbol */
427 /* Resolve trampoline entries */
428 if (S->Flags & SF_TRAMPOLINE) {
433 S->Flags &= ~SF_USER;
438 int SymHasUserMark (SymEntry* S)
439 /* Return the state of the user mark for the specified symbol */
441 /* Resolve trampoline entries */
442 if (S->Flags & SF_TRAMPOLINE) {
447 return (S->Flags & SF_USER) != 0;
452 long GetSymVal (SymEntry* S)
453 /* Return the symbol value */
455 /* Resolve trampoline entries */
456 if (S->Flags & SF_TRAMPOLINE) {
460 PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
466 struct ExprNode* GetSymExpr (SymEntry* S)
467 /* Get the expression for a non-const symbol */
469 /* Resolve trampoline entries */
470 if (S->Flags & SF_TRAMPOLINE) {
474 PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
480 const char* GetSymName (SymEntry* S)
481 /* Return the name of the symbol */
483 /* Resolve trampoline entries */
484 if (S->Flags & SF_TRAMPOLINE) {
487 return GetString (S->Name);
492 unsigned GetSymIndex (SymEntry* S)
493 /* Return the symbol index for the given symbol */
495 /* Resolve trampoline entries */
496 if (S->Flags & SF_TRAMPOLINE) {
499 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
505 const FilePos* GetSymPos (SymEntry* S)
506 /* Return the position of first occurence in the source for the given symbol */
508 /* Resolve trampoline entries */
509 if (S->Flags & SF_TRAMPOLINE) {
512 PRECONDITION (S != 0);