]> git.sur5r.net Git - cc65/blob - src/ca65/symentry.c
Add translation from PETSCII to screen codes.
[cc65] / src / ca65 / symentry.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                symentry.c                                 */
4 /*                                                                           */
5 /*              Symbol table entry for the ca65 macroassembler               */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 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 "symdefs.h"
41 #include "xmalloc.h"
42
43 /* ca65 */
44 #include "error.h"
45 #include "expr.h"
46 #include "global.h"
47 #include "scanner.h"
48 #include "segment.h"
49 #include "spool.h"
50 #include "studyexpr.h"          /* ### */
51 #include "symentry.h"
52 #include "symtab.h"
53
54
55
56 /*****************************************************************************/
57 /*                                   Data                                    */
58 /*****************************************************************************/
59
60
61
62 /* List of all symbol table entries */
63 SymEntry* SymList = 0;
64
65 /* Pointer to last defined symbol */
66 SymEntry* SymLast = 0;
67
68
69
70 /*****************************************************************************/
71 /*                                   Code                                    */
72 /*****************************************************************************/
73
74
75
76 SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
77 /* Allocate a symbol table entry, initialize and return it */
78 {
79     unsigned I;
80
81     /* Allocate memory */
82     SymEntry* S = xmalloc (sizeof (SymEntry));
83
84     /* Initialize the entry */
85     S->Left       = 0;
86     S->Right      = 0;
87     S->Locals     = 0;
88     S->Sym.Tab    = 0;
89     S->DefLines   = EmptyCollection;
90     S->RefLines   = EmptyCollection;
91     for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
92         S->GuessedUse[I] = 0;
93     }
94     S->HLLSym     = 0;
95     S->Flags      = Flags;
96     S->DebugSymId = ~0U;
97     S->ImportId   = ~0U;
98     S->ExportId   = ~0U;
99     S->Expr       = 0;
100     S->ExprRefs   = AUTO_COLLECTION_INITIALIZER;
101     S->ExportSize = ADDR_SIZE_DEFAULT;
102     S->AddrSize   = ADDR_SIZE_DEFAULT;
103     memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
104     S->Name       = GetStrBufId (Name);
105
106     /* Insert it into the list of all entries */
107     S->List = SymList;
108     SymList = S;
109
110     /* Return the initialized entry */
111     return S;
112 }
113
114
115
116 int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
117 /* Search in the given tree for a name. If we find the symbol, the function
118 ** will return 0 and put the entry pointer into E. If we did not find the
119 ** symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
120 ** E will be set to the last entry, and the result of the function is <0 if
121 ** the entry should be inserted on the left side, and >0 if it should get
122 ** inserted on the right side.
123 */
124 {
125     /* Is there a tree? */
126     if (T == 0) {
127         *E = 0;
128         return 1;
129     }
130
131     /* We have a table, search it */
132     while (1) {
133
134         /* Get the symbol name */
135         const StrBuf* SymName = GetStrBuf (T->Name);
136
137         /* Choose next entry */
138         int Cmp = SB_Compare (Name, SymName);
139         if (Cmp < 0 && T->Left) {
140             T = T->Left;
141         } else if (Cmp > 0 && T->Right) {
142             T = T->Right;
143         } else {
144             /* Found or end of search, return the result */
145             *E = T;
146             return Cmp;
147         }
148     }
149 }
150
151
152
153 void SymTransferExprRefs (SymEntry* From, SymEntry* To)
154 /* Transfer all expression references from one symbol to another. */
155 {
156     unsigned I;
157
158     for (I = 0; I < CollCount (&From->ExprRefs); ++I) {
159
160         /* Get the expression node */
161         ExprNode* E = CollAtUnchecked (&From->ExprRefs, I);
162
163         /* Safety */
164         CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == From);
165
166         /* Replace the symbol reference */
167         E->V.Sym = To;
168
169         /* Add the expression reference */
170         SymAddExprRef (To, E);
171     }
172
173     /* Remove all symbol references from the old symbol */
174     CollDeleteAll (&From->ExprRefs);
175 }
176
177
178
179 static void SymReplaceExprRefs (SymEntry* S)
180 /* Replace the references to this symbol by a copy of the symbol expression */
181 {
182     unsigned I;
183     long     Val;
184
185     /* Check if the expression is const and get its value */
186     int IsConst = IsConstExpr (S->Expr, &Val);
187     CHECK (IsConst);
188
189     /* Loop over all references */
190     for (I = 0; I < CollCount (&S->ExprRefs); ++I) {
191
192         /* Get the expression node */
193         ExprNode* E = CollAtUnchecked (&S->ExprRefs, I);
194
195         /* Safety */
196         CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S);
197
198         /* We cannot touch the root node, since there are pointers to it.
199         ** Replace it by a literal node.
200         */
201         E->Op = EXPR_LITERAL;
202         E->V.IVal = Val;
203     }
204
205     /* Remove all symbol references from the symbol */
206     CollDeleteAll (&S->ExprRefs);
207 }
208
209
210
211 void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
212 /* Define a new symbol */
213 {
214     if (S->Flags & SF_IMPORT) {
215         /* Defined symbol is marked as imported external symbol */
216         Error ("Symbol '%m%p' is already an import", GetSymName (S));
217         return;
218     }
219     if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
220         /* Variable symbols cannot be exports or globals */
221         Error ("Var symbol '%m%p' cannot be an export or global symbol", GetSymName (S));
222         return;
223     }
224     if (S->Flags & SF_DEFINED) {
225         /* Multiple definition. In case of a variable, this is legal. */
226         if ((S->Flags & SF_VAR) == 0) {
227             Error ("Symbol '%m%p' is already defined", GetSymName (S));
228             S->Flags |= SF_MULTDEF;
229             return;
230         } else {
231             /* Redefinition must also be a variable symbol */
232             if ((Flags & SF_VAR) == 0) {
233                 Error ("Symbol '%m%p' is already different kind", GetSymName (S));
234                 return;
235             }
236             /* Delete the current symbol expression, since it will get
237             ** replaced
238             */
239             FreeExpr (S->Expr);
240             S->Expr = 0;
241         }
242     }
243
244     /* Map a default address size to a real value */
245     if (AddrSize == ADDR_SIZE_DEFAULT) {
246         /* ### Must go! Delay address size calculation until end of assembly! */
247         ExprDesc ED;
248         ED_Init (&ED);
249         StudyExpr (Expr, &ED);
250         AddrSize = ED.AddrSize;
251         ED_Done (&ED);
252     }
253
254     /* Set the symbol value */
255     S->Expr = Expr;
256
257     /* In case of a variable symbol, walk over all expressions containing
258     ** this symbol and replace the (sub-)expression by the literal value of
259     ** the tree. Be sure to replace the expression node in place, since there
260     ** may be pointers to it.
261     */
262     if (Flags & SF_VAR) {
263         SymReplaceExprRefs (S);
264     }
265
266     /* If the symbol is marked as global, export it. Address size is checked
267     ** below.
268     */
269     if (S->Flags & SF_GLOBAL) {
270         S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
271         ReleaseFullLineInfo (&S->DefLines);
272     }
273
274     /* Mark the symbol as defined and use the given address size */
275     S->Flags |= (SF_DEFINED | Flags);
276     S->AddrSize = AddrSize;
277
278     /* Remember the line info of the symbol definition */
279     GetFullLineInfo (&S->DefLines);
280
281     /* If the symbol is exported, check the address sizes */
282     if (S->Flags & SF_EXPORT) {
283         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
284             /* Use the real size of the symbol */
285             S->ExportSize = S->AddrSize;
286         } else if (S->AddrSize > S->ExportSize) {
287             /* We're exporting a symbol smaller than it actually is */
288             Warning (1, "Symbol '%m%p' is %s but exported %s",
289                      GetSymName (S), AddrSizeToStr (S->AddrSize),
290                      AddrSizeToStr (S->ExportSize));
291         }
292     }
293
294     /* If this is not a local symbol, remember it as the last global one */
295     if ((S->Flags & SF_LOCAL) == 0) {
296         SymLast = S;
297     }
298 }
299
300
301
302 void SymRef (SymEntry* S)
303 /* Mark the given symbol as referenced */
304 {
305     /* Mark the symbol as referenced */
306     S->Flags |= SF_REFERENCED;
307
308     /* Remember the current location */
309     CollAppend (&S->RefLines, GetAsmLineInfo ());
310 }
311
312
313
314 void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
315 /* Mark the given symbol as an imported symbol */
316 {
317     if (S->Flags & SF_DEFINED) {
318         Error ("Symbol '%m%p' is already defined", GetSymName (S));
319         S->Flags |= SF_MULTDEF;
320         return;
321     }
322     if (S->Flags & SF_EXPORT) {
323         /* The symbol is already marked as exported symbol */
324         Error ("Cannot import exported symbol '%m%p'", GetSymName (S));
325         return;
326     }
327
328     /* If no address size is given, use the address size of the enclosing
329     ** segment.
330     */
331     if (AddrSize == ADDR_SIZE_DEFAULT) {
332         AddrSize = GetCurrentSegAddrSize ();
333     }
334
335     /* If the symbol is marked as import or global, check the address size,
336     ** then do silently remove the global flag.
337     */
338     if (S->Flags & SF_IMPORT) {
339         if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) {
340             Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
341         }
342         if (AddrSize != S->AddrSize) {
343             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
344         }
345     }
346     if (S->Flags & SF_GLOBAL) {
347         S->Flags &= ~SF_GLOBAL;
348         if (AddrSize != S->AddrSize) {
349             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
350         }
351     }
352
353     /* Set the symbol data */
354     S->Flags |= (SF_IMPORT | Flags);
355     S->AddrSize = AddrSize;
356
357     /* Mark the position of the import as the position of the definition.
358     ** Please note: In case of multiple .global or .import statements, the line
359     ** infos add up.
360     */
361     GetFullLineInfo (&S->DefLines);
362 }
363
364
365
366 void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
367 /* Mark the given symbol as an exported symbol */
368 {
369     /* Check if it's ok to export the symbol */
370     if (S->Flags & SF_IMPORT) {
371         /* The symbol is already marked as imported external symbol */
372         Error ("Symbol '%m%p' is already an import", GetSymName (S));
373         return;
374     }
375     if (S->Flags & SF_VAR) {
376         /* Variable symbols cannot be exported */
377         Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
378         return;
379     }
380
381     /* If the symbol was marked as global before, remove the global flag and
382     ** proceed, but check the address size.
383     */
384     if (S->Flags & SF_GLOBAL) {
385         if (AddrSize != S->ExportSize) {
386             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
387         }
388         S->Flags &= ~SF_GLOBAL;
389
390         /* .GLOBAL remembers line infos in case an .IMPORT follows. We have
391         ** to remove these here.
392         */
393         ReleaseFullLineInfo (&S->DefLines);
394     }
395
396     /* If the symbol was already marked as an export, but wasn't defined
397     ** before, the address sizes in both definitions must match.
398     */
399     if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
400         if (S->ExportSize != AddrSize) {
401             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
402         }
403     }
404     S->ExportSize = AddrSize;
405
406     /* If the symbol is already defined, check symbol size against the
407     ** exported size.
408     */
409     if (S->Flags & SF_DEFINED) {
410         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
411             /* No export size given, use the real size of the symbol */
412             S->ExportSize = S->AddrSize;
413         } else if (S->AddrSize > S->ExportSize) {
414             /* We're exporting a symbol smaller than it actually is */
415             Warning (1, "Symbol '%m%p' is %s but exported %s",
416                      GetSymName (S), AddrSizeToStr (S->AddrSize),
417                      AddrSizeToStr (S->ExportSize));
418         }
419     }
420
421     /* Set the symbol data */
422     S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
423
424     /* Remember line info for this reference */
425     CollAppend (&S->RefLines, GetAsmLineInfo ());
426 }
427
428
429
430 void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
431 /* Mark the given symbol as a global symbol, that is, as a symbol that is
432 ** either imported or exported.
433 */
434 {
435     if (S->Flags & SF_VAR) {
436         /* Variable symbols cannot be exported or imported */
437         Error ("Var symbol '%m%p' cannot be made global", GetSymName (S));
438         return;
439     }
440
441     /* If the symbol is already marked as import, the address size must match.
442     ** Apart from that, ignore the global declaration.
443     */
444     if (S->Flags & SF_IMPORT) {
445         if (AddrSize == ADDR_SIZE_DEFAULT) {
446             /* Use the size of the current segment */
447             AddrSize = GetCurrentSegAddrSize ();
448         }
449         if (AddrSize != S->AddrSize) {
450             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
451         }
452         return;
453     }
454
455     /* If the symbol is already an export: If it is not defined, the address
456     ** sizes must match.
457     */
458     if (S->Flags & SF_EXPORT) {
459         if ((S->Flags & SF_DEFINED) == 0) {
460             /* Symbol is undefined */
461             if (AddrSize != S->ExportSize) {
462                 Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
463             }
464         } else if (AddrSize != ADDR_SIZE_DEFAULT) {
465             /* Symbol is defined and address size given */
466             if (AddrSize != S->ExportSize) {
467                 Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
468             }
469         }
470         return;
471     }
472
473     /* If the symbol is already marked as global, the address size must match.
474     ** Use the ExportSize here, since it contains the actual address size
475     ** passed to this function.
476     */
477     if (S->Flags & SF_GLOBAL) {
478         if (AddrSize != S->ExportSize) {
479             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
480         }
481         return;
482     }
483
484     /* If we come here, the symbol was neither declared as export, import or
485     ** global before. Check if it is already defined, in which case it will
486     ** become an export. If it is not defined, mark it as global and remember
487     ** the given address sizes.
488     */
489     if (S->Flags & SF_DEFINED) {
490         /* The symbol is defined, export it */
491         S->ExportSize = AddrSize;
492         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
493             /* No export size given, use the real size of the symbol */
494             S->ExportSize = S->AddrSize;
495         } else if (S->AddrSize > S->ExportSize) {
496             /* We're exporting a symbol smaller than it actually is */
497             Warning (1, "Symbol '%m%p' is %s but exported %s",
498                      GetSymName (S), AddrSizeToStr (S->AddrSize),
499                      AddrSizeToStr (S->ExportSize));
500         }
501         S->Flags |= (SF_EXPORT | Flags);
502     } else {
503         /* Since we don't know if the symbol will get exported or imported,
504         ** remember two different address sizes: One for an import in AddrSize,
505         ** and the other one for an export in ExportSize.
506         */
507         S->AddrSize = AddrSize;
508         if (S->AddrSize == ADDR_SIZE_DEFAULT) {
509             /* Use the size of the current segment */
510             S->AddrSize = GetCurrentSegAddrSize ();
511         }
512         S->ExportSize = AddrSize;
513         S->Flags |= (SF_GLOBAL | Flags);
514
515         /* Remember the current location as location of definition in case
516         ** an .IMPORT follows later.
517         */
518         GetFullLineInfo (&S->DefLines);
519     }
520 }
521
522
523
524 void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
525 /* Mark the given symbol as a module constructor/destructor. This will also
526 ** mark the symbol as an export. Initializers may never be zero page symbols.
527 */
528 {
529     /* Check the parameters */
530 #if (CD_TYPE_MIN != 0)
531     CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
532 #else
533     CHECK (Type <= CD_TYPE_MAX);
534 #endif
535     CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
536
537     /* Check for errors */
538     if (S->Flags & SF_IMPORT) {
539         /* The symbol is already marked as imported external symbol */
540         Error ("Symbol '%m%p' is already an import", GetSymName (S));
541         return;
542     }
543     if (S->Flags & SF_VAR) {
544         /* Variable symbols cannot be exported or imported */
545         Error ("Var symbol '%m%p' cannot be exported", GetSymName (S));
546         return;
547     }
548
549     /* If the symbol was already marked as an export or global, check if
550     ** this was done specifiying the same address size. In case of a global
551     ** declaration, silently remove the global flag.
552     */
553     if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
554         if (S->ExportSize != AddrSize) {
555             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
556         }
557         S->Flags &= ~SF_GLOBAL;
558     }
559     S->ExportSize = AddrSize;
560
561     /* If the symbol is already defined, check symbol size against the
562     ** exported size.
563     */
564     if (S->Flags & SF_DEFINED) {
565         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
566             /* Use the real size of the symbol */
567             S->ExportSize = S->AddrSize;
568         } else if (S->AddrSize != S->ExportSize) {
569             Error ("Address size mismatch for symbol '%m%p'", GetSymName (S));
570         }
571     }
572
573     /* If the symbol already was declared as a condes of this type,
574     ** check if the new priority value is the same as the old one.
575     */
576     if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
577         if (S->ConDesPrio[Type] != Prio) {
578             Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S));
579         }
580     }
581     S->ConDesPrio[Type] = Prio;
582
583     /* Set the symbol data */
584     S->Flags |= (SF_EXPORT | SF_REFERENCED);
585
586     /* Remember the line info for this reference */
587     CollAppend (&S->RefLines, GetAsmLineInfo ());
588 }
589
590
591
592 void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
593 /* Mark the address size of the given symbol as guessed. The address size
594 ** passed as argument is the one NOT used, because the actual address size
595 ** wasn't known. Example: Zero page addressing was not used because symbol
596 ** is undefined, and absolute addressing was available.
597 */
598 {
599     /* We must have a valid address size passed */
600     PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT);
601
602     /* We do not support all address sizes currently */
603     if (AddrSize > sizeof (Sym->GuessedUse) / sizeof (Sym->GuessedUse[0])) {
604         return;
605     }
606
607     /* We can only remember one such occurance */
608     if (Sym->GuessedUse[AddrSize-1]) {
609         return;
610     }
611
612     /* Ok, remember the file position */
613     Sym->GuessedUse[AddrSize-1] = xdup (&CurTok.Pos, sizeof (CurTok.Pos));
614 }
615
616
617
618 void SymExportFromGlobal (SymEntry* S)
619 /* Called at the end of assembly. Converts a global symbol that is defined
620 ** into an export.
621 */
622 {
623     /* Remove the global flag and make the symbol an export */
624     S->Flags &= ~SF_GLOBAL;
625     S->Flags |= SF_EXPORT;
626 }
627
628
629
630 void SymImportFromGlobal (SymEntry* S)
631 /* Called at the end of assembly. Converts a global symbol that is undefined
632 ** into an import.
633 */
634 {
635     /* Remove the global flag and make it an import */
636     S->Flags &= ~SF_GLOBAL;
637     S->Flags |= SF_IMPORT;
638 }
639
640
641
642 int SymIsConst (const SymEntry* S, long* Val)
643 /* Return true if the given symbol has a constant value. If Val is not NULL
644 ** and the symbol has a constant value, store it's value there.
645 */
646 {
647     /* Check for constness */
648     return (SymHasExpr (S) && IsConstExpr (S->Expr, Val));
649 }
650
651
652
653 SymTable* GetSymParentScope (SymEntry* S)
654 /* Get the parent scope of the symbol (not the one it is defined in). Return
655 ** NULL if the symbol is a cheap local, or defined on global level.
656 */
657 {
658     if ((S->Flags & SF_LOCAL) != 0) {
659         /* This is a cheap local symbol */
660         return 0;
661     } else if (S->Sym.Tab == 0) {
662         /* Symbol not in a table. This may happen if there have been errors
663         ** before. Return NULL in this case to avoid further errors.
664         */
665         return 0;
666     } else {
667         /* This is a global symbol */
668         return S->Sym.Tab->Parent;
669     }
670 }
671
672
673
674 struct ExprNode* GetSymExpr (SymEntry* S)
675 /* Get the expression for a non-const symbol */
676 {
677     PRECONDITION (S != 0 && SymHasExpr (S));
678     return S->Expr;
679 }
680
681
682
683 const struct ExprNode* SymResolve (const SymEntry* S)
684 /* Helper function for DumpExpr. Resolves a symbol into an expression or return
685 ** NULL. Do not call in other contexts!
686 */
687 {
688     return SymHasExpr (S)? S->Expr : 0;
689 }
690
691
692
693 long GetSymVal (SymEntry* S)
694 /* Return the value of a symbol assuming it's constant. FAIL will be called
695 ** in case the symbol is undefined or not constant.
696 */
697 {
698     long Val;
699     CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val));
700     return Val;
701 }
702
703
704
705 unsigned GetSymImportId (const SymEntry* S)
706 /* Return the import id for the given symbol */
707 {
708     PRECONDITION (S != 0 && (S->Flags & SF_IMPORT) && S->ImportId != ~0U);
709     return S->ImportId;
710 }
711
712
713
714 unsigned GetSymExportId (const SymEntry* S)
715 /* Return the export id for the given symbol */
716 {
717     PRECONDITION (S != 0 && (S->Flags & SF_EXPORT) && S->ExportId != ~0U);
718     return S->ExportId;
719 }
720
721
722
723 unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
724 /* Return a set of flags used when writing symbol information into a file.
725 ** If the SYM_CONST bit is set, ConstVal will contain the constant value
726 ** of the symbol. The result does not include the condes count.
727 ** See common/symdefs.h for more information.
728 */
729 {
730     /* Setup info flags */
731     unsigned Flags = 0;
732     Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR;
733     Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE;
734     Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD;
735     if (S->Flags & SF_EXPORT) {
736         Flags |= SYM_EXPORT;
737     }
738     if (S->Flags & SF_IMPORT) {
739         Flags |= SYM_IMPORT;
740     }
741
742     /* Return the result */
743     return Flags;
744 }