1 /*****************************************************************************/
5 /* Symbol table 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 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
61 /* Combined symbol entry flags used within this module */
62 #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
63 #define SF_UNDEFVAL (SF_REFERENCED)
64 #define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT)
65 #define SF_EXPVAL (SF_EXPORT)
66 #define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
67 #define SF_DBGINFOVAL (SF_DEFINED)
69 /* Definitions for the hash table */
70 #define MAIN_HASHTAB_SIZE 213
71 #define SUB_HASHTAB_SIZE 53
72 typedef struct SymTable SymTable;
74 SymTable* Left; /* Pointer to smaller entry */
75 SymTable* Right; /* Pointer to greater entry */
76 SymTable* Parent; /* Link to enclosing scope if any */
77 SymTable* Childs; /* Pointer to child scopes */
78 unsigned Level; /* Lexical level */
79 unsigned TableSlots; /* Number of hash table slots */
80 unsigned TableEntries; /* Number of entries in the table */
81 unsigned Name; /* Name of the scope */
82 SymEntry* Table [1]; /* Dynamic allocation */
85 /* Arguments for SymFind */
86 #define SF_FIND_EXISTING 0
87 #define SF_ALLOC_NEW 1
89 /* Symbol table variables */
90 static SymEntry* SymLast = 0; /* Pointer to last defined symbol */
91 static SymTable* SymTab = 0; /* Pointer to current symbol table */
92 static SymTable* RootTab = 0; /* Root symbol table */
93 static unsigned ImportCount = 0;/* Counter for import symbols */
94 static unsigned ExportCount = 0;/* Counter for export symbols */
98 /*****************************************************************************/
99 /* Internally used functions */
100 /*****************************************************************************/
104 static int IsLocalName (const char* Name)
105 /* Return true if Name is the name of a local symbol */
107 return (*Name == LocalStart);
112 static int IsLocalNameId (unsigned Name)
113 /* Return true if Name is the name of a local symbol */
115 return (*GetString (Name) == LocalStart);
120 static unsigned SymTableSize (unsigned Level)
121 /* Get the size of a table for the given lexical level */
132 static SymTable* NewSymTable (SymTable* Parent, unsigned Name)
133 /* Allocate a symbol table on the heap and return it */
135 /* Determine the lexical level and the number of table slots */
136 unsigned Level = Parent? Parent->Level + 1 : 0;
137 unsigned Slots = SymTableSize (Level);
139 /* Allocate memory */
140 SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
142 /* Set variables and clear hash table entries */
147 S->TableSlots = Slots;
155 /* Insert the symbol table into the child tree of the parent */
157 SymTable* T = Parent->Childs;
163 /* Choose next entry */
164 if (S->Name < T->Name) {
171 } else if (S->Name > T->Name) {
179 /* Duplicate scope name */
180 Internal ("Duplicate scope name: `%s'", GetString (S->Name));
185 /* This is the root table */
189 /* Return the prepared struct */
195 static int SearchSymTree (SymEntry* T, unsigned Name, SymEntry** E)
196 /* Search in the given tree for a name. If we find the symbol, the function
197 * will return 0 and put the entry pointer into E. If we did not find the
198 * symbol, and the tree is empty, E is set to NULL. If the tree is not empty,
199 * E will be set to the last entry, and the result of the function is <0 if
200 * the entry should be inserted on the left side, and >0 if it should get
201 * inserted on the right side.
206 /* Is there a tree? */
212 /* We have a table, search it */
214 /* Choose next entry */
215 if (Name < T->Name) {
217 } else if (Name > T->Name) {
222 if (Name < T->Name && T->Left) {
224 } else if (Name > T->Name && T->Right) {
227 /* Found or end of search, return the result */
236 /*****************************************************************************/
238 /*****************************************************************************/
242 static SymEntry* SymFind (SymTable* Tab, unsigned Name, int AllocNew)
243 /* Find a new symbol table entry in the given table. If AllocNew is given and
244 * the entry is not found, create a new one. Return the entry found, or the
245 * new entry created, or - in case AllocNew is zero - return 0.
252 if (IsLocalNameId (Name)) {
254 /* Local symbol, get the table */
256 /* No last global, so there's no local table */
257 Error (ERR_ILLEGAL_LOCAL_USE);
259 return NewSymEntry (Name);
265 /* Search for the symbol if we have a table */
266 Cmp = SearchSymTree (SymLast->Locals, Name, &S);
268 /* If we found an entry, return it */
275 /* Otherwise create a new entry, insert and return it */
276 SymEntry* N = NewSymEntry (Name);
279 } else if (Cmp < 0) {
289 /* Global symbol: Get the hash value for the name */
290 Hash = Name % Tab->TableSlots;
292 /* Search for the entry */
293 Cmp = SearchSymTree (Tab->Table[Hash], Name, &S);
295 /* If we found an entry, return it */
297 /* Check for a trampoline entry, in this case return the real
300 while (S->Flags & SF_TRAMPOLINE) {
308 /* Otherwise create a new entry, insert and return it */
309 SymEntry* N = NewSymEntry (Name);
311 Tab->Table[Hash] = N;
312 } else if (Cmp < 0) {
324 /* We did not find the entry and AllocNew is false. */
330 static SymEntry* SymFindAny (SymTable* Tab, unsigned Name)
331 /* Find a symbol in any table */
335 /* Search in the current table */
336 Sym = SymFind (Tab, Name, SF_FIND_EXISTING);
338 /* Found, return it */
341 /* Not found, search in the parent scope, if we have one */
344 } while (Sym == 0 && Tab != 0);
352 void SymEnterLevel (const char* ScopeName)
353 /* Enter a new lexical level */
355 /* Accept NULL pointers for the scope name */
356 if (ScopeName == 0) {
360 /* Create the new table */
361 SymTab = NewSymTable (SymTab, GetStringId (ScopeName));
366 void SymLeaveLevel (void)
367 /* Leave the current lexical level */
369 SymTab = SymTab->Parent;
374 int SymIsLocalLevel (void)
375 /* Return true if we are on a local symbol table level. */
377 return (SymTab != RootTab);
382 void SymDef (const char* Name, ExprNode* Expr, unsigned Flags)
383 /* Define a new symbol */
385 /* Do we have such a symbol? */
386 SymEntry* S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
387 if (S->Flags & SF_IMPORT) {
388 /* Defined symbol is marked as imported external symbol */
389 Error (ERR_SYM_ALREADY_IMPORT, Name);
392 if (S->Flags & SF_DEFINED) {
393 /* Multiple definition */
394 Error (ERR_SYM_ALREADY_DEFINED, Name);
395 S->Flags |= SF_MULTDEF;
399 /* Set the symbol data */
400 if (IsConstExpr (Expr)) {
401 /* Expression is const, store the value */
402 S->Flags |= SF_CONST;
403 S->V.Val = GetExprVal (Expr);
406 /* Not const, store the expression */
409 S->Flags |= SF_DEFINED;
410 if (Flags & SYM_ZP) {
413 if (Flags & SYM_LABEL) {
414 S->Flags |= SF_LABEL;
417 /* If the symbol is a ZP symbol, check if the value is in correct range */
418 if (S->Flags & SF_ZP) {
419 /* Already marked as ZP symbol by some means */
420 if (!IsByteExpr (Expr)) {
425 /* If this is not a local symbol, remember it as the last global one */
426 if (!IsLocalName (Name)) {
433 SymEntry* SymRef (const char* Name, int Scope)
434 /* Search for the symbol and return it */
437 unsigned NameId = GetStringId (Name);
440 case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_ALLOC_NEW); break;
441 case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_ALLOC_NEW); break;
443 /* Others are not allowed */
446 Internal ("Invalid scope in SymRef: %d", Scope);
451 /* Mark the symbol as referenced */
452 S->Flags |= SF_REFERENCED;
460 static void SymImportInternal (const char* Name, unsigned Flags)
461 /* Mark the given symbol as an imported symbol */
465 /* Don't accept local symbols */
466 if (IsLocalName (Name)) {
467 Error (ERR_ILLEGAL_LOCAL_USE);
471 /* Do we have such a symbol? */
472 S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
473 if (S->Flags & SF_DEFINED) {
474 Error (ERR_SYM_ALREADY_DEFINED, Name);
475 S->Flags |= SF_MULTDEF;
478 if (S->Flags & SF_EXPORT) {
479 /* The symbol is already marked as exported symbol */
480 Error (ERR_SYM_ALREADY_EXPORT, Name);
484 /* If the symbol is marked as global, check the symbol flags, then do
485 * silently remove the global flag
487 if (S->Flags & SF_GLOBAL) {
488 if ((Flags & (SF_ZP | SF_FORCED)) != (S->Flags & (SF_ZP | SF_FORCED))) {
489 Error (ERR_SYM_REDECL_MISMATCH, Name);
491 S->Flags &= ~SF_GLOBAL;
494 /* Set the symbol data */
495 S->Flags |= (SF_IMPORT | Flags);
500 void SymImport (const char* Name)
501 /* Mark the given symbol as an imported symbol */
503 SymImportInternal (Name, SF_NONE);
508 void SymImportZP (const char* Name)
509 /* Mark the given symbol as a forced imported symbol */
511 SymImportInternal (Name, SF_ZP);
516 void SymImportForced (const char* Name)
517 /* Mark the given symbol as a forced imported symbol */
519 SymImportInternal (Name, SF_FORCED);
524 static void SymExportInternal (const char* Name, unsigned Flags)
525 /* Mark the given symbol as an exported symbol */
529 /* Don't accept local symbols */
530 if (IsLocalName (Name)) {
531 Error (ERR_ILLEGAL_LOCAL_USE);
535 /* Do we have such a symbol? */
536 S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
537 if (S->Flags & SF_IMPORT) {
538 /* The symbol is already marked as imported external symbol */
539 Error (ERR_SYM_ALREADY_IMPORT, Name);
543 /* If the symbol is marked as global, check the symbol size, then do
544 * silently remove the global flag
546 if (S->Flags & SF_GLOBAL) {
547 if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) {
548 Error (ERR_SYM_REDECL_MISMATCH, Name);
550 S->Flags &= ~SF_GLOBAL;
553 /* Set the symbol data */
554 S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);
559 void SymExport (const char* Name)
560 /* Mark the given symbol as an exported symbol */
562 SymExportInternal (Name, SF_NONE);
567 void SymExportZP (const char* Name)
568 /* Mark the given symbol as an exported zeropage symbol */
570 SymExportInternal (Name, SF_ZP);
575 static void SymGlobalInternal (const char* Name, unsigned Flags)
576 /* Mark the given symbol as a global symbol, that is, as a symbol that is
577 * either imported or exported.
582 /* Don't accept local symbols */
583 if (IsLocalName (Name)) {
584 Error (ERR_ILLEGAL_LOCAL_USE);
588 /* Search for this symbol, create a new entry if needed */
589 S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
591 /* If the symbol is already marked as import or export, check the
592 * size of the definition, then bail out. */
593 if (S->Flags & SF_IMPORT || S->Flags & SF_EXPORT) {
594 if ((Flags & SF_ZP) != (S->Flags & SF_ZP)) {
595 Error (ERR_SYM_REDECL_MISMATCH, Name);
600 /* Mark the symbol */
601 S->Flags |= (SF_GLOBAL | Flags);
606 void SymGlobal (const char* Name)
607 /* Mark the given symbol as a global symbol, that is, as a symbol that is
608 * either imported or exported.
611 SymGlobalInternal (Name, SF_NONE);
616 void SymGlobalZP (const char* Name)
617 /* Mark the given symbol as a global zeropage symbol, that is, as a symbol
618 * that is either imported or exported.
621 SymGlobalInternal (Name, SF_ZP);
626 void SymConDes (const char* Name, unsigned Type, unsigned Prio)
627 /* Mark the given symbol as a module constructor/destructor. This will also
628 * mark the symbol as an export. Initializers may never be zero page symbols.
633 /* Check the parameters */
634 #if (CD_TYPE_MIN != 0)
635 CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
637 CHECK (Type <= CD_TYPE_MAX);
639 CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);
641 /* Don't accept local symbols */
642 if (IsLocalName (Name)) {
643 Error (ERR_ILLEGAL_LOCAL_USE);
647 /* Do we have such a symbol? */
648 S = SymFind (SymTab, GetStringId (Name), SF_ALLOC_NEW);
649 if (S->Flags & SF_IMPORT) {
650 /* The symbol is already marked as imported external symbol */
651 Error (ERR_SYM_ALREADY_IMPORT, Name);
655 /* If the symbol is marked as global, silently remove the global flag */
656 if (S->Flags & SF_GLOBAL) {
657 S->Flags &= ~SF_GLOBAL;
660 /* Check if the symbol was not already defined as ZP symbol */
661 if ((S->Flags & SF_ZP) != 0) {
662 Error (ERR_SYM_REDECL_MISMATCH, Name);
665 /* If the symbol was already declared as a condes, check if the new
666 * priority value is the same as the old one.
668 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
669 if (S->ConDesPrio[Type] != Prio) {
670 Error (ERR_SYM_REDECL_MISMATCH, Name);
673 S->ConDesPrio[Type] = Prio;
675 /* Set the symbol data */
676 S->Flags |= SF_EXPORT | SF_REFERENCED;
681 int SymIsDef (const char* Name, int Scope)
682 /* Return true if the given symbol is already defined */
686 /* Get the string pool index for the name */
687 unsigned NameId = GetStringId (Name);
689 /* Search for the symbol */
691 case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
692 case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
693 case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
694 default: Internal ("Invalid scope in SymIsDef: %d", Scope);
697 /* Check if it's defined */
698 return S != 0 && (S->Flags & SF_DEFINED) != 0;
703 int SymIsRef (const char* Name, int Scope)
704 /* Return true if the given symbol has been referenced */
708 /* Get the string pool index for the name */
709 unsigned NameId = GetStringId (Name);
711 /* Search for the symbol */
713 case SCOPE_ANY: S = SymFindAny (SymTab, NameId); break;
714 case SCOPE_GLOBAL: S = SymFind (RootTab, NameId, SF_FIND_EXISTING); break;
715 case SCOPE_LOCAL: S = SymFind (SymTab, NameId, SF_FIND_EXISTING); break;
716 default: Internal ("Invalid scope in SymIsRef: %d", Scope);
719 /* Check if it's defined */
720 return S != 0 && (S->Flags & SF_REFERENCED) != 0;
725 int SymIsConst (SymEntry* S)
726 /* Return true if the given symbol has a constant value */
728 /* Resolve trampoline entries */
729 if (S->Flags & SF_TRAMPOLINE) {
733 /* Check for constness */
734 if (S->Flags & SF_CONST) {
736 } else if ((S->Flags & SF_DEFINED) && IsConstExpr (S->V.Expr)) {
737 /* Constant expression, remember the value */
738 ExprNode* Expr = S->V.Expr;
739 S->Flags |= SF_CONST;
740 S->V.Val = GetExprVal (Expr);
749 int SymIsZP (SymEntry* S)
750 /* Return true if the symbol is explicitly marked as zeropage symbol */
752 /* Resolve trampoline entries */
753 if (S->Flags & SF_TRAMPOLINE) {
757 /* If the symbol is not a global symbol, was not defined before, check the
758 * enclosing scope for a symbol with the same name, and return the ZP
759 * attribute of this symbol if we find one.
761 if (!IsLocalNameId (S->Name) &&
762 (S->Flags & (SF_ZP | SF_ABS | SF_DEFINED | SF_IMPORT)) == 0 &&
763 S->SymTab->Parent != 0) {
765 /* Try to find a symbol with the same name in the enclosing scope */
766 SymEntry* E = SymFindAny (S->SymTab->Parent, S->Name);
768 /* If we found one, use the ZP flag */
769 if (E && (E->Flags & SF_ZP) != 0) {
774 /* Check the ZP flag */
775 return (S->Flags & SF_ZP) != 0;
780 int SymIsImport (SymEntry* S)
781 /* Return true if the given symbol is marked as import */
783 /* Resolve trampoline entries */
784 if (S->Flags & SF_TRAMPOLINE) {
788 /* Check the import flag */
789 return (S->Flags & SF_IMPORT) != 0;
794 int SymHasExpr (SymEntry* S)
795 /* Return true if the given symbol has an associated expression */
797 /* Resolve trampoline entries */
798 if (S->Flags & SF_TRAMPOLINE) {
802 /* Check the expression */
803 return ((S->Flags & SF_DEFINED) != 0 &&
804 (S->Flags & SF_IMPORT) == 0 &&
805 (S->Flags & SF_CONST) == 0);
810 void SymFinalize (SymEntry* S)
811 /* Finalize a symbol expression if there is one */
813 /* Resolve trampoline entries */
814 if (S->Flags & SF_TRAMPOLINE) {
818 /* Check if we have an expression */
819 if ((S->Flags & SF_FINALIZED) == 0 && SymHasExpr (S)) {
820 S->V.Expr = FinalizeExpr (S->V.Expr);
821 S->Flags |= SF_FINALIZED;
827 void SymMarkUser (SymEntry* S)
828 /* Set a user mark on the specified symbol */
830 /* Resolve trampoline entries */
831 if (S->Flags & SF_TRAMPOLINE) {
841 void SymUnmarkUser (SymEntry* S)
842 /* Remove a user mark from the specified symbol */
844 /* Resolve trampoline entries */
845 if (S->Flags & SF_TRAMPOLINE) {
850 S->Flags &= ~SF_USER;
855 int SymHasUserMark (SymEntry* S)
856 /* Return the state of the user mark for the specified symbol */
858 /* Resolve trampoline entries */
859 if (S->Flags & SF_TRAMPOLINE) {
864 return (S->Flags & SF_USER) != 0;
869 long GetSymVal (SymEntry* S)
870 /* Return the symbol value */
872 /* Resolve trampoline entries */
873 if (S->Flags & SF_TRAMPOLINE) {
877 PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
883 ExprNode* GetSymExpr (SymEntry* S)
884 /* Get the expression for a non-const symbol */
886 /* Resolve trampoline entries */
887 if (S->Flags & SF_TRAMPOLINE) {
891 PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
897 const char* GetSymName (SymEntry* S)
898 /* Return the name of the symbol */
900 /* Resolve trampoline entries */
901 if (S->Flags & SF_TRAMPOLINE) {
904 return GetString (S->Name);
909 unsigned GetSymIndex (SymEntry* S)
910 /* Return the symbol index for the given symbol */
912 /* Resolve trampoline entries */
913 if (S->Flags & SF_TRAMPOLINE) {
916 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
922 const FilePos* GetSymPos (SymEntry* S)
923 /* Return the position of first occurence in the source for the given symbol */
925 /* Resolve trampoline entries */
926 if (S->Flags & SF_TRAMPOLINE) {
929 PRECONDITION (S != 0);
935 static void SymCheckUndefined (SymEntry* S)
936 /* Handle an undefined symbol */
938 /* Undefined symbol. It may be...
940 * - An undefined symbol in a nested lexical level. In this
941 * case, search for the symbol in the higher levels and
942 * make the entry a trampoline entry if we find one.
944 * - If the symbol is not found, it is a real undefined symbol.
945 * If the AutoImport flag is set, make it an import. If the
946 * AutoImport flag is not set, it's an error.
950 /* It's a global symbol, get the higher level table */
951 SymTable* Tab = S->SymTab->Parent;
953 Sym = SymFindAny (Tab, S->Name);
955 if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) {
956 /* We've found a symbol in a higher level that is
957 * either defined in the source, or an import.
961 /* The symbol found is undefined itself. Look further */
962 Tab = Sym->SymTab->Parent;
965 /* No symbol found */
971 /* We found the symbol in a higher level. Make S a trampoline
972 * symbol. Beware: We have to transfer the symbol attributes to
973 * the real symbol and check for any conflicts.
975 S->Flags |= SF_TRAMPOLINE;
978 /* Transfer the flags. Note: S may not be imported, since in that
979 * case it wouldn't be undefined.
981 if (S->Flags & SF_EXPORT) {
982 if (Sym->Flags & SF_IMPORT) {
983 /* The symbol is already marked as imported external symbol */
984 PError (&S->Pos, ERR_SYM_ALREADY_IMPORT, GetString (S->Name));
986 Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
989 /* Transfer the referenced flag */
990 Sym->Flags |= (S->Flags & SF_REFERENCED);
993 /* The symbol is definitely undefined */
994 if (S->Flags & SF_EXPORT) {
995 /* We will not auto-import an export */
996 PError (&S->Pos, ERR_EXPORT_UNDEFINED, GetString (S->Name));
999 /* Mark as import, will be indexed later */
1000 S->Flags |= SF_IMPORT;
1003 PError (&S->Pos, ERR_SYM_UNDEFINED, GetString (S->Name));
1011 void SymCheck (void)
1012 /* Run through all symbols and check for anomalies and errors */
1016 /* Check for open lexical levels */
1017 if (SymTab->Parent != 0) {
1018 Error (ERR_OPEN_PROC);
1021 /* First pass: Walk through all symbols, checking for undefined's and
1022 * changing them to trampoline symbols or make them imports.
1026 /* If the symbol is marked as global, mark it as export, if it is
1027 * already defined, otherwise mark it as import.
1029 if (S->Flags & SF_GLOBAL) {
1030 S->Flags &= ~SF_GLOBAL;
1031 if (S->Flags & SF_DEFINED) {
1032 S->Flags |= SF_EXPORT;
1034 S->Flags |= SF_IMPORT;
1038 /* Handle undefined symbols */
1039 if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
1040 /* This is an undefined symbol. Handle it. */
1041 SymCheckUndefined (S);
1048 /* Second pass: Walk again through the symbols. Ignore undefined's, since
1049 * we handled them in the last pass, and ignore trampoline symbols, since
1050 * we handled them in the last pass, too.
1054 if ((S->Flags & SF_TRAMPOLINE) == 0 &&
1055 (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
1056 if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
1057 /* Symbol was defined but never referenced */
1058 PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, GetString (S->Name));
1060 if (S->Flags & SF_IMPORT) {
1061 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
1062 /* Imported symbol is not referenced */
1063 PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, GetString (S->Name));
1065 /* Give the import an index, count imports */
1066 S->Index = ImportCount++;
1067 S->Flags |= SF_INDEXED;
1070 if (S->Flags & SF_EXPORT) {
1071 /* Give the export an index, count exports */
1072 S->Index = ExportCount++;
1073 S->Flags |= SF_INDEXED;
1084 void SymDump (FILE* F)
1085 /* Dump the symbol table */
1087 SymEntry* S = SymList;
1090 /* Ignore trampoline symbols */
1091 if ((S->Flags & SF_TRAMPOLINE) != 0) {
1093 "%-24s %s %s %s %s %s\n",
1094 GetString (S->Name),
1095 (S->Flags & SF_DEFINED)? "DEF" : "---",
1096 (S->Flags & SF_REFERENCED)? "REF" : "---",
1097 (S->Flags & SF_IMPORT)? "IMP" : "---",
1098 (S->Flags & SF_EXPORT)? "EXP" : "---",
1099 (S->Flags & SF_ZP)? "ZP" : "--");
1108 void WriteImports (void)
1109 /* Write the imports list to the object file */
1113 /* Tell the object file module that we're about to start the imports */
1116 /* Write the import count to the list */
1117 ObjWriteVar (ImportCount);
1119 /* Walk throught list and write all valid imports to the file. An import
1120 * is considered valid, if it is either referenced, or the forced bit is
1121 * set. Otherwise, the import is ignored (no need to link in something
1126 if ((S->Flags & (SF_TRAMPOLINE | SF_IMPORT)) == SF_IMPORT &&
1127 (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
1129 if (S->Flags & SF_ZP) {
1132 ObjWrite8 (IMP_ABS);
1134 ObjWriteVar (S->Name);
1135 ObjWritePos (&S->Pos);
1140 /* Done writing imports */
1146 static unsigned char GetExprMask (SymEntry* S)
1147 /* Return the expression bits for the given symbol table entry */
1149 unsigned char ExprMask;
1151 /* Check if the symbol is const */
1152 ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
1154 /* Add zeropage/abs bits */
1155 ExprMask |= (S->Flags & SF_ZP)? EXP_ZP : EXP_ABS;
1157 /* Add the label/equate bits */
1158 ExprMask |= (S->Flags & SF_LABEL)? EXP_LABEL : EXP_EQUATE;
1160 /* Return the mask */
1166 void WriteExports (void)
1167 /* Write the exports list to the object file */
1172 /* Tell the object file module that we're about to start the exports */
1175 /* Write the export count to the list */
1176 ObjWriteVar (ExportCount);
1178 /* Walk throught list and write all exports to the file */
1181 if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) {
1182 unsigned char ExprMask;
1184 /* Finalize an associated expression if we have one */
1187 /* Get the expression bits */
1188 ExprMask = GetExprMask (S);
1190 /* Count the number of ConDes types */
1191 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
1192 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
1193 INC_EXP_CONDES_COUNT (ExprMask);
1197 /* Write the type */
1198 ObjWrite8 (ExprMask);
1200 /* Write any ConDes declarations */
1201 if (GET_EXP_CONDES_COUNT (ExprMask) > 0) {
1202 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
1203 unsigned char Prio = S->ConDesPrio[Type];
1204 if (Prio != CD_PRIO_NONE) {
1205 ObjWrite8 (CD_BUILD (Type, Prio));
1210 /* Write the name */
1211 ObjWriteVar (S->Name);
1213 /* Write the value */
1214 if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
1215 /* Constant value */
1216 ObjWrite32 (S->V.Val);
1218 /* Expression involved */
1219 WriteExpr (S->V.Expr);
1222 /* Write the source file position */
1223 ObjWritePos (&S->Pos);
1228 /* Done writing exports */
1234 void WriteDbgSyms (void)
1235 /* Write a list of all symbols to the object file */
1240 /* Tell the object file module that we're about to start the debug info */
1243 /* Check if debug info is requested */
1246 /* Walk through the list and count the symbols */
1250 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1256 /* Write the symbol count to the list */
1257 ObjWriteVar (Count);
1259 /* Walk through list and write all symbols to the file */
1262 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1263 unsigned char ExprMask;
1265 /* Finalize an associated expression if we have one */
1268 /* Get the expression bits */
1269 ExprMask = GetExprMask (S);
1271 /* Write the type */
1272 ObjWrite8 (ExprMask);
1274 /* Write the name */
1275 ObjWriteVar (S->Name);
1277 /* Write the value */
1278 if ((ExprMask & EXP_MASK_VAL) == EXP_CONST) {
1279 /* Constant value */
1280 ObjWrite32 (S->V.Val);
1282 /* Expression involved */
1283 WriteExpr (S->V.Expr);
1286 /* Write the source file position */
1287 ObjWritePos (&S->Pos);
1294 /* No debug symbols */
1299 /* Done writing debug symbols */