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