]> git.sur5r.net Git - cc65/blob - src/ca65/symentry.c
fd9f195fb1ff16ebeb1585470788a9903270731d
[cc65] / src / ca65 / symentry.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                symentry.c                                 */
4 /*                                                                           */
5 /*          Symbol table entry forward for the ca65 macroassembler           */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 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 <string.h>
37
38 /* common */
39 #include "addrsize.h"
40 #include "xmalloc.h"
41
42 /* ca65 */
43 #include "error.h"
44 #include "expr.h"
45 #include "global.h"
46 #include "scanner.h"
47 #include "spool.h"
48 #include "symentry.h"
49
50
51
52 /*****************************************************************************/
53 /*                                   Data                                    */
54 /*****************************************************************************/
55
56
57
58 /* List of all symbol table entries */
59 SymEntry* SymList = 0;
60
61 /* Pointer to last defined symbol */
62 SymEntry* SymLast = 0;
63
64
65
66 /*****************************************************************************/
67 /*                                   Code                                    */
68 /*****************************************************************************/
69
70
71
72 int IsLocalName (const char* Name)
73 /* Return true if Name is the name of a local symbol */
74 {
75     return (*Name == LocalStart);
76 }
77
78
79
80 int IsLocalNameId (unsigned Name)
81 /* Return true if Name is the name of a local symbol */
82 {
83     return (*GetString (Name) == LocalStart);
84 }
85
86
87
88 static unsigned SymAddrSize (const SymEntry* S)
89 /* Get the default address size for a symbol. */
90 {
91     /* Local symbols are always near (is this ok?) */
92     if (IsLocalNameId (S->Name)) {
93         return ADDR_SIZE_ABS;
94     }
95
96     /* Return the address size of the enclosing scope */
97     return S->SymTab->AddrSize;
98 }
99
100
101
102 SymEntry* NewSymEntry (const char* Name)
103 /* Allocate a symbol table entry, initialize and return it */
104 {
105     /* Allocate memory */
106     SymEntry* S = xmalloc (sizeof (SymEntry));
107
108     /* Initialize the entry */
109     S->Left       = 0;
110     S->Right      = 0;
111     S->Locals     = 0;
112     S->SymTab     = 0;
113     S->Pos        = CurPos;
114     S->Flags      = 0;
115     S->V.Expr     = 0;
116     S->ExprRefs   = AUTO_COLLECTION_INITIALIZER;
117     S->ExportSize = ADDR_SIZE_DEFAULT;
118     S->AddrSize   = ADDR_SIZE_DEFAULT;
119     memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
120     S->Name       = GetStringId (Name);
121
122     /* Insert it into the list of all entries */
123     S->List = SymList;
124     SymList = S;
125
126     /* Return the initialized entry */
127     return S;
128 }
129
130
131
132 void SymRef (SymEntry* S)
133 /* Mark the given symbol as referenced */
134 {
135     /* Mark the symbol as referenced */
136     S->Flags |= SF_REFERENCED;
137 }
138
139
140
141 void SymDef (SymEntry* S, ExprNode* Expr, unsigned AddrSize, unsigned Flags)
142 /* Define a new symbol */
143 {
144     if (S->Flags & SF_IMPORT) {
145         /* Defined symbol is marked as imported external symbol */
146         Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
147         return;
148     }
149     if (S->Flags & SF_DEFINED) {
150         /* Multiple definition */
151         Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
152         S->Flags |= SF_MULTDEF;
153         return;
154     }
155
156     /* Map a default address size to a real value */
157     if (AddrSize == ADDR_SIZE_DEFAULT) {
158         AddrSize = SymAddrSize (S);
159     }
160
161     /* Set the symbol value */
162     if (IsConstExpr (Expr)) {
163         /* Expression is const, store the value */
164         S->Flags |= SF_CONST;
165         S->V.Val = GetExprVal (Expr);
166         FreeExpr (Expr);
167     } else {
168         /* Not const, store the expression */
169         S->V.Expr  = Expr;
170     }
171
172     /* If the symbol is marked as global, export it */
173     if (S->Flags & SF_GLOBAL) {
174         S->ExportSize = S->AddrSize;
175         S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
176     }
177
178     /* Mark the symbol as defined and use the given address size */
179     S->Flags |= (SF_DEFINED | Flags);
180     S->AddrSize = AddrSize;
181
182     /* If the symbol is exported, check the address sizes */
183     if (S->Flags & SF_EXPORT) {
184         if (S->AddrSize > S->ExportSize) {
185             Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
186         }
187     }
188
189     /* If the symbol is a ZP symbol, check if the value is in correct range */
190     if (S->AddrSize == ADDR_SIZE_ZP) {
191         /* Already marked as ZP symbol by some means */
192         if (!IsByteExpr (Expr)) {
193             Error (ERR_RANGE);
194         }
195     }
196
197     /* If this is not a local symbol, remember it as the last global one */
198     if (!IsLocalNameId (S->Name)) {
199         SymLast = S;
200     }
201 }
202
203
204
205 void SymImport (SymEntry* S, unsigned AddrSize, unsigned Flags)
206 /* Mark the given symbol as an imported symbol */
207 {
208     /* Don't accept local symbols */
209     if (IsLocalNameId (S->Name)) {
210         Error (ERR_ILLEGAL_LOCAL_USE);
211         return;
212     }
213
214     if (S->Flags & SF_DEFINED) {
215         Error (ERR_SYM_ALREADY_DEFINED, GetSymName (S));
216         S->Flags |= SF_MULTDEF;
217         return;
218     }
219     if (S->Flags & SF_EXPORT) {
220         /* The symbol is already marked as exported symbol */
221         Error (ERR_SYM_ALREADY_EXPORT, GetSymName (S));
222         return;
223     }
224
225     /* Map a default address size to a real value */
226     if (AddrSize == ADDR_SIZE_DEFAULT) {
227         AddrSize = SymAddrSize (S);
228     }
229
230     /* If the symbol is marked as import or global, check the symbol flags,
231      * then do silently remove the global flag
232      */
233     if (S->Flags & (SF_IMPORT | SF_GLOBAL)) {
234         if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED) ||
235             AddrSize != S->AddrSize) {
236             Error (ERR_SYM_REDECL_MISMATCH, GetSymName (S));
237         }
238         S->Flags &= ~SF_GLOBAL;
239     }
240
241     /* Set the symbol data */
242     S->Flags |= (SF_IMPORT | Flags);
243     S->AddrSize = AddrSize;
244 }
245
246
247
248 void SymExport (SymEntry* S, unsigned AddrSize, unsigned Flags)
249 /* Mark the given symbol as an exported symbol */
250 {
251     /* Don't accept local symbols */
252     if (IsLocalNameId (S->Name)) {
253         Error (ERR_ILLEGAL_LOCAL_USE);
254         return;
255     }
256
257     /* Check if it's ok to export the symbol */
258     if (S->Flags & SF_IMPORT) {
259         /* The symbol is already marked as imported external symbol */
260         Error (ERR_SYM_ALREADY_IMPORT, GetSymName (S));
261         return;
262     }
263
264     /* Map a default address size to a real value */
265     if (AddrSize == ADDR_SIZE_DEFAULT) {
266         AddrSize = SymAddrSize (S);
267     }
268
269     /* If the symbol was already marked as an export or global, check if
270      * this was done specifiying the same address size. In case of a global
271      * declaration, silently remove the global flag.
272      */
273     if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
274         if (S->ExportSize != AddrSize) {
275             Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
276         }
277         S->Flags &= ~SF_GLOBAL;
278     }
279     S->ExportSize = AddrSize;
280
281     /* If the symbol is already defined, check symbol size against the
282      * exported size.
283      */
284     if (S->Flags & SF_DEFINED) {
285         if (S->AddrSize > S->ExportSize) {
286             Warning (WARN_ADDR_SIZE_MISMATCH, GetSymName (S));
287         }
288     }
289
290     /* Set the symbol data */
291     S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
292 }
293
294
295
296 void SymGlobal (SymEntry* S, unsigned AddrSize, unsigned Flags)
297 /* Mark the given symbol as a global symbol, that is, as a symbol that is
298  * either imported or exported.
299  */
300 {
301     /* Don't accept local symbols */
302     if (IsLocalNameId (S->Name)) {
303         Error (ERR_ILLEGAL_LOCAL_USE);
304         return;
305     }
306
307     /* Map a default address size to a real value */
308     if (AddrSize == ADDR_SIZE_DEFAULT) {
309         AddrSize = SymAddrSize (S);
310     }
311
312     /* If the symbol is already marked as import or export, check the
313      * size of the definition, then bail out.
314      */
315     if (S->Flags & SF_IMPORT) {
316         if (AddrSize != S->AddrSize) {
317             Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
318         }
319         return;
320     }
321     if (S->Flags & SF_EXPORT) {
322         if (AddrSize != S->ExportSize) {
323             Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
324         }
325         return;
326     }
327
328     /* If the symbol is already defined, export it. Otherwise mark it as
329      * global.
330      */
331     if (S->Flags & SF_DEFINED) {
332         /* The symbol is defined, export it */
333         if (S->ExportSize != AddrSize) {
334             Error (ERR_ADDR_SIZE_MISMATCH, GetSymName (S));
335         }
336         S->Flags |= (SF_EXPORT | Flags);
337         S->ExportSize = AddrSize;
338     } else {
339         S->Flags |= (SF_GLOBAL | Flags);
340         S->AddrSize = AddrSize;
341     }
342 }
343
344
345
346 int SymIsDef (const SymEntry* S)
347 /* Return true if the given symbol is already defined */
348 {
349     return (S->Flags & SF_DEFINED) != 0;
350 }
351
352
353
354 int SymIsRef (const SymEntry* S)
355 /* Return true if the given symbol has been referenced */
356 {
357     return (S->Flags & SF_REFERENCED) != 0;
358 }
359
360
361
362 int SymIsImport (const SymEntry* S)
363 /* Return true if the given symbol is marked as import */
364 {
365     /* Resolve trampoline entries */
366     if (S->Flags & SF_TRAMPOLINE) {
367         S = S->V.Sym;
368     }
369
370     /* Check the import flag */
371     return (S->Flags & SF_IMPORT) != 0;
372 }
373
374
375
376 int SymHasExpr (const SymEntry* S)
377 /* Return true if the given symbol has an associated expression */
378 {
379     /* Resolve trampoline entries */
380     if (S->Flags & SF_TRAMPOLINE) {
381         S = S->V.Sym;
382     }
383
384     /* Check the expression */
385     return ((S->Flags & SF_DEFINED) != 0 &&
386             (S->Flags & SF_IMPORT)  == 0 &&
387             (S->Flags & SF_CONST)   == 0);
388 }
389
390
391
392 void SymFinalize (SymEntry* S)
393 /* Finalize a symbol expression if there is one */
394 {
395     /* Resolve trampoline entries */
396     if (S->Flags & SF_TRAMPOLINE) {
397         S = S->V.Sym;
398     }
399
400     /* Check if we have an expression */
401     if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
402         S->V.Expr = FinalizeExpr (S->V.Expr);
403         S->Flags |= SF_FINALIZED;
404     }
405 }
406
407
408
409 void SymMarkUser (SymEntry* S)
410 /* Set a user mark on the specified symbol */
411 {
412     /* Resolve trampoline entries */
413     if (S->Flags & SF_TRAMPOLINE) {
414         S = S->V.Sym;
415     }
416
417     /* Set the bit */
418     S->Flags |= SF_USER;
419 }
420
421
422
423 void SymUnmarkUser (SymEntry* S)
424 /* Remove a user mark from the specified symbol */
425 {
426     /* Resolve trampoline entries */
427     if (S->Flags & SF_TRAMPOLINE) {
428         S = S->V.Sym;
429     }
430
431     /* Reset the bit */
432     S->Flags &= ~SF_USER;
433 }
434
435
436
437 int SymHasUserMark (SymEntry* S)
438 /* Return the state of the user mark for the specified symbol */
439 {
440     /* Resolve trampoline entries */
441     if (S->Flags & SF_TRAMPOLINE) {
442         S = S->V.Sym;
443     }
444
445     /* Check the bit */
446     return (S->Flags & SF_USER) != 0;
447 }
448
449
450
451 long GetSymVal (SymEntry* S)
452 /* Return the symbol value */
453 {
454     /* Resolve trampoline entries */
455     if (S->Flags & SF_TRAMPOLINE) {
456         S = S->V.Sym;
457     }
458
459     PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
460     return S->V.Val;
461 }
462
463
464
465 struct ExprNode* GetSymExpr (SymEntry* S)
466 /* Get the expression for a non-const symbol */
467 {
468     /* Resolve trampoline entries */
469     if (S->Flags & SF_TRAMPOLINE) {
470         S = S->V.Sym;
471     }
472
473     PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
474     return S->V.Expr;
475 }
476
477
478
479 const char* GetSymName (SymEntry* S)
480 /* Return the name of the symbol */
481 {
482     /* Resolve trampoline entries */
483     if (S->Flags & SF_TRAMPOLINE) {
484         S = S->V.Sym;
485     }
486     return GetString (S->Name);
487 }
488
489
490
491 unsigned GetSymIndex (SymEntry* S)
492 /* Return the symbol index for the given symbol */
493 {
494     /* Resolve trampoline entries */
495     if (S->Flags & SF_TRAMPOLINE) {
496         S = S->V.Sym;
497     }
498     PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
499     return S->Index;
500 }
501
502
503
504 const FilePos* GetSymPos (SymEntry* S)
505 /* Return the position of first occurence in the source for the given symbol */
506 {
507     /* Resolve trampoline entries */
508     if (S->Flags & SF_TRAMPOLINE) {
509         S = S->V.Sym;
510     }
511     PRECONDITION (S != 0);
512     return &S->Pos;
513 }
514
515
516
517