1 /*****************************************************************************/
5 /* Symbol table for the ca65 macroassembler */
9 /* (C) 1998 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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 /*****************************************************************************/
38 #include "../common/symdefs.h"
39 #include "../common/hashstr.h"
40 #include "../common/xmalloc.h"
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* Bits for the Flags value in SymEntry */
57 #define SF_USER 0x0001 /* User bit */
58 #define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
59 #define SF_EXPORT 0x0004 /* Export this symbol */
60 #define SF_IMPORT 0x0008 /* Import this symbol */
61 #define SF_GLOBAL 0x0010 /* Global symbol */
62 #define SF_ZP 0x0020 /* Declared as zeropage symbol */
63 #define SF_ABS 0x0040 /* Declared as absolute symbol */
64 #define SF_INDEXED 0x0800 /* Index is valid */
65 #define SF_CONST 0x1000 /* The symbol has a constant value */
66 #define SF_MULTDEF 0x2000 /* Multiply defined symbol */
67 #define SF_DEFINED 0x4000 /* Defined */
68 #define SF_REFERENCED 0x8000 /* Referenced */
71 #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
72 #define SF_UNDEFVAL (SF_REFERENCED)
73 #define SF_IMPMASK (SF_TRAMPOLINE | SF_IMPORT | SF_REFERENCED)
74 #define SF_IMPVAL (SF_IMPORT | SF_REFERENCED)
75 #define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT)
76 #define SF_EXPVAL (SF_EXPORT)
77 #define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
78 #define SF_DBGINFOVAL (SF_DEFINED)
82 /* Structure of a symbol table entry */
84 SymEntry* Left; /* Lexically smaller entry */
85 SymEntry* Right; /* Lexically larger entry */
86 SymEntry* List; /* List of all entries */
87 SymEntry* Locals; /* Root of subtree for local symbols */
88 struct SymTable_* SymTab; /* Table this symbol is in, 0 for locals */
89 FilePos Pos; /* File position for this symbol */
90 unsigned Flags; /* Symbol flags */
91 unsigned Index; /* Index of import/export entries */
93 struct ExprNode_* Expr; /* Expression if CONST not set */
94 long Val; /* Value (if CONST set) */
95 SymEntry* Sym; /* Symbol (if trampoline entry) */
97 char Name [1]; /* Dynamic allocation */
102 /* Definitions for the hash table */
103 #define MAIN_HASHTAB_SIZE 213
104 #define SUB_HASHTAB_SIZE 53
105 typedef struct SymTable_ SymTable;
107 unsigned TableSlots; /* Number of hash table slots */
108 unsigned TableEntries; /* Number of entries in the table */
109 SymTable* BackLink; /* Link to enclosing scope if any */
110 SymEntry* Table [1]; /* Dynamic allocation */
115 /* Symbol table variables */
116 static SymEntry* SymList = 0; /* List of all symbol table entries */
117 static SymEntry* SymLast = 0; /* Pointer to last defined symbol */
118 static SymTable* SymTab = 0; /* Pointer to current symbol table */
119 static SymTable* RootTab = 0; /* Root symbol table */
120 static unsigned ImportCount = 0;/* Counter for import symbols */
121 static unsigned ExportCount = 0;/* Counter for export symbols */
125 /*****************************************************************************/
126 /* Internally used functions */
127 /*****************************************************************************/
131 static int IsLocal (const char* Name)
132 /* Return true if Name is the name of a local symbol */
134 return (*Name == LocalStart);
139 static SymEntry* NewSymEntry (const char* Name)
140 /* Allocate a symbol table entry, initialize and return it */
145 /* Get the length of the name */
148 /* Allocate memory */
149 S = xmalloc (sizeof (SymEntry) + Len);
151 /* Initialize the entry */
159 memcpy (S->Name, Name, Len+1);
161 /* Insert it into the list of all entries */
165 /* Return the initialized entry */
171 static SymTable* NewSymTable (unsigned Size)
172 /* Allocate a symbol table on the heap and return it */
176 /* Allocate memory */
177 S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*));
179 /* Set variables and clear hash table entries */
180 S->TableSlots = Size;
187 /* Return the prepared struct */
193 static int SearchSymTab (SymEntry* T, const char* Name, SymEntry** E)
194 /* Search in the given table for a name (Hash is the hash value of Name and
195 * is given as parameter so that it will not get calculated twice if we search
196 * in more than one table). If we find the symbol, the function will return 0
197 * and put the entry pointer into E. If we did not find the symbol, and the
198 * tree is empty, E is set to NULL. If the tree is not empty, E will be set to
199 * the last entry, and the result of the function is <0 if the entry should
200 * be inserted on the left side, and >0 if it should get inserted on the right
206 /* Is there a tree? */
212 /* We have a table, search it */
214 /* Choose next entry */
215 Cmp = strcmp (Name, T->Name);
216 if (Cmp < 0 && T->Left) {
218 } else if (Cmp > 0 && T->Right) {
221 /* Found or end of search */
226 /* Return the search result */
233 /*****************************************************************************/
235 /*****************************************************************************/
239 static SymEntry* SymFind (SymTable* Tab, const char* Name, int AllocNew)
240 /* Find a new symbol table entry in the given table. If AllocNew is given and
241 * the entry is not found, create a new one. Return the entry found, or the
242 * new entry created, or - in case AllocNew is zero - return 0.
249 if (IsLocal (Name)) {
251 /* Local symbol, get the table */
253 /* No last global, so there's no local table */
254 Error (ERR_ILLEGAL_LOCAL_USE);
256 return NewSymEntry (Name);
262 /* Search for the symbol if we have a table */
263 Cmp = SearchSymTab (SymLast->Locals, Name, &S);
265 /* If we found an entry, return it */
272 /* Otherwise create a new entry, insert and return it */
273 SymEntry* N = NewSymEntry (Name);
276 } else if (Cmp < 0) {
286 /* Global symbol: Get the hash value for the name */
287 Hash = HashStr (Name) % Tab->TableSlots;
289 /* Search for the entry */
290 Cmp = SearchSymTab (Tab->Table [Hash], Name, &S);
292 /* If we found an entry, return it */
294 /* Check for a trampoline entry, in this case return the real
297 if (S->Flags & SF_TRAMPOLINE) {
306 /* Otherwise create a new entry, insert and return it */
307 SymEntry* N = NewSymEntry (Name);
309 Tab->Table [Hash] = N;
310 } else if (Cmp < 0) {
322 /* We did not find the entry and AllocNew is false. */
328 static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
329 /* Find a symbol in any table */
333 /* Search in the current table */
334 Sym = SymFind (Tab, Name, 0);
336 /* Found, return it */
339 /* Not found, search in the backlink, if we have one */
342 } while (Sym == 0 && Tab != 0);
350 static SymEntry* SymRefInternal (SymTable* Table, const char* Name)
351 /* Search for the symbol in the given table and return it */
355 /* Try to find the symbol, create a new one if the symbol does not exist */
356 S = SymFind (Table, Name, 1);
358 /* Mark the symbol as referenced */
359 S->Flags |= SF_REFERENCED;
367 void SymEnterLevel (void)
368 /* Enter a new lexical level */
371 /* Create the main symbol table */
372 RootTab = SymTab = NewSymTable (MAIN_HASHTAB_SIZE);
374 /* Create a local symbol table */
376 LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
377 LocalSyms->BackLink = SymTab;
384 void SymLeaveLevel (void)
385 /* Leave the current lexical level */
387 SymTab = SymTab->BackLink;
392 void SymDef (const char* Name, ExprNode* Expr, int ZP)
393 /* Define a new symbol */
397 /* Do we have such a symbol? */
398 S = SymFind (SymTab, Name, 1);
399 if (S->Flags & SF_IMPORT) {
400 /* Defined symbol is marked as imported external symbol */
401 Error (ERR_SYM_ALREADY_IMPORT);
404 if (S->Flags & SF_DEFINED) {
405 /* Multiple definition */
406 Error (ERR_SYM_ALREADY_DEFINED, Name);
407 S->Flags |= SF_MULTDEF;
411 /* Set the symbol data */
412 if (IsConstExpr (Expr)) {
413 /* Expression is const, store the value */
414 S->Flags |= SF_CONST;
415 S->V.Val = GetExprVal (Expr);
418 /* Not const, store the expression */
421 S->Flags |= SF_DEFINED;
426 /* If the symbol is a ZP symbol, check if the value is in correct range */
427 if (S->Flags & SF_ZP) {
428 /* Already marked as ZP symbol by some means */
429 if (!IsByteExpr (Expr)) {
434 /* If this is not a local symbol, remember it as the last global one */
435 if (!IsLocal (Name)) {
442 SymEntry* SymRef (const char* Name)
443 /* Search for the symbol and return it */
445 /* Reference the symbol in the current table */
446 return SymRefInternal (SymTab, Name);
451 SymEntry* SymRefGlobal (const char* Name)
452 /* Search for the symbol in the global namespace and return it */
454 /* Reference the symbol in the current table */
455 return SymRefInternal (RootTab, Name);
460 void SymImport (const char* Name, int ZP)
461 /* Mark the given symbol as an imported symbol */
465 /* Don't accept local symbols */
466 if (IsLocal (Name)) {
467 Error (ERR_ILLEGAL_LOCAL_USE);
471 /* Do we have such a symbol? */
472 S = SymFind (SymTab, Name, 1);
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);
484 /* If the symbol is marked as global, check the symbol size, then do
485 * silently remove the global flag
487 if (S->Flags & SF_GLOBAL) {
488 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
489 Error (ERR_SYM_REDECL_MISMATCH);
491 S->Flags &= ~SF_GLOBAL;
494 /* Set the symbol data */
495 S->Flags |= SF_IMPORT;
503 void SymExport (const char* Name, int ZP)
504 /* Mark the given symbol as an exported symbol */
508 /* Don't accept local symbols */
509 if (IsLocal (Name)) {
510 Error (ERR_ILLEGAL_LOCAL_USE);
514 /* Do we have such a symbol? */
515 S = SymFind (SymTab, Name, 1);
516 if (S->Flags & SF_IMPORT) {
517 /* The symbol is already marked as imported external symbol */
518 Error (ERR_SYM_ALREADY_IMPORT);
522 /* If the symbol is marked as global, check the symbol size, then do
523 * silently remove the global flag
525 if (S->Flags & SF_GLOBAL) {
526 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
527 Error (ERR_SYM_REDECL_MISMATCH);
529 S->Flags &= ~SF_GLOBAL;
532 /* Set the symbol data */
533 S->Flags |= SF_EXPORT | SF_REFERENCED;
541 void SymGlobal (const char* Name, int ZP)
542 /* Mark the given symbol as a global symbol, that is, as a symbol that is
543 * either imported or exported.
548 /* Don't accept local symbols */
549 if (IsLocal (Name)) {
550 Error (ERR_ILLEGAL_LOCAL_USE);
554 /* Search for this symbol, create a new entry if needed */
555 S = SymFind (SymTab, Name, 1);
557 /* If the symbol is already marked as import or export, check the
558 * size of the definition, then bail out. */
559 if (S->Flags & SF_IMPORT || S->Flags & SF_EXPORT) {
560 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
561 Error (ERR_SYM_REDECL_MISMATCH);
566 /* Mark the symbol */
567 S->Flags |= SF_GLOBAL;
575 int SymIsDef (const char* Name)
576 /* Return true if the given symbol is already defined */
578 SymEntry* S = SymFindAny (SymTab, Name);
579 return S != 0 && (S->Flags & (SF_DEFINED | SF_IMPORT)) != 0;
584 int SymIsRef (const char* Name)
585 /* Return true if the given symbol has been referenced */
587 SymEntry* S = SymFindAny (SymTab, Name);
588 return S != 0 && (S->Flags & SF_REFERENCED) != 0;
593 int SymIsConst (SymEntry* S)
594 /* Return true if the given symbol has a constant value */
596 /* Resolve trampoline entries */
597 if (S->Flags & SF_TRAMPOLINE) {
601 /* Check for constness */
602 if (S->Flags & SF_CONST) {
604 } else if ((S->Flags & SF_DEFINED) && IsConstExpr (S->V.Expr)) {
605 /* Constant expression, remember the value */
606 ExprNode* Expr = S->V.Expr;
607 S->Flags |= SF_CONST;
608 S->V.Val = GetExprVal (Expr);
617 int SymIsZP (SymEntry* S)
618 /* Return true if the symbol is explicitly marked as zeropage symbol */
620 /* Resolve trampoline entries */
621 if (S->Flags & SF_TRAMPOLINE) {
625 /* If the symbol is not a global symbol, was not defined before, check the
626 * enclosing scope for a symbol with the same name, and return the ZP
627 * attribute of this symbol if we find one.
629 if (!IsLocal (S->Name) &&
630 (S->Flags & (SF_ZP | SF_ABS | SF_DEFINED | SF_IMPORT)) == 0 &&
631 S->SymTab->BackLink != 0) {
633 /* Try to find a symbol with the same name in the enclosing scope */
634 SymEntry* E = SymFindAny (S->SymTab->BackLink, S->Name);
636 /* If we found one, use the ZP flag */
637 if (E && (E->Flags & SF_ZP) != 0) {
642 /* Check the ZP flag */
643 return (S->Flags & SF_ZP) != 0;
648 int SymIsImport (SymEntry* S)
649 /* Return true if the given symbol is marked as import */
651 /* Resolve trampoline entries */
652 if (S->Flags & SF_TRAMPOLINE) {
656 /* Check the import flag */
657 return (S->Flags & SF_IMPORT) != 0;
662 int SymHasExpr (SymEntry* S)
663 /* Return true if the given symbol has an associated expression */
665 /* Resolve trampoline entries */
666 if (S->Flags & SF_TRAMPOLINE) {
670 /* Check the expression */
671 return ((S->Flags & SF_DEFINED) != 0 &&
672 (S->Flags & SF_IMPORT) == 0 &&
673 (S->Flags & SF_CONST) == 0);
678 void SymFinalize (SymEntry* S)
679 /* Finalize a symbol expression if there is one */
681 /* Resolve trampoline entries */
682 if (S->Flags & SF_TRAMPOLINE) {
686 /* Check if we have an expression */
687 if (SymHasExpr (S)) {
688 S->V.Expr = FinalizeExpr (S->V.Expr);
694 void SymMarkUser (SymEntry* S)
695 /* Set a user mark on the specified symbol */
697 /* Resolve trampoline entries */
698 if (S->Flags & SF_TRAMPOLINE) {
708 void SymUnmarkUser (SymEntry* S)
709 /* Remove a user mark from the specified symbol */
711 /* Resolve trampoline entries */
712 if (S->Flags & SF_TRAMPOLINE) {
717 S->Flags &= ~SF_USER;
722 int SymHasUserMark (SymEntry* S)
723 /* Return the state of the user mark for the specified symbol */
725 /* Resolve trampoline entries */
726 if (S->Flags & SF_TRAMPOLINE) {
731 return (S->Flags & SF_USER) != 0;
736 long GetSymVal (SymEntry* S)
737 /* Return the symbol value */
739 /* Resolve trampoline entries */
740 if (S->Flags & SF_TRAMPOLINE) {
744 PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
750 ExprNode* GetSymExpr (SymEntry* S)
751 /* Get the expression for a non-const symbol */
753 /* Resolve trampoline entries */
754 if (S->Flags & SF_TRAMPOLINE) {
758 PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
764 const char* GetSymName (SymEntry* S)
765 /* Return the name of the symbol */
767 /* Resolve trampoline entries */
768 if (S->Flags & SF_TRAMPOLINE) {
776 unsigned GetSymIndex (SymEntry* S)
777 /* Return the symbol index for the given symbol */
779 /* Resolve trampoline entries */
780 if (S->Flags & SF_TRAMPOLINE) {
783 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
789 const FilePos* GetSymPos (SymEntry* S)
790 /* Return the position of first occurence in the source for the given symbol */
792 /* Resolve trampoline entries */
793 if (S->Flags & SF_TRAMPOLINE) {
796 PRECONDITION (S != 0);
802 static void SymCheckUndefined (SymEntry* S)
803 /* Handle an undefined symbol */
805 /* Undefined symbol. It may be...
807 * - An undefined symbol in a nested lexical level. In this
808 * case, search for the symbol in the higher levels and
809 * make the entry a trampoline entry if we find one.
811 * - If the symbol is not found, it is a real undefined symbol.
812 * If the AutoImport flag is set, make it an import. If the
813 * AutoImport flag is not set, it's an error.
817 /* It's a global symbol, get the higher level table */
818 SymTable* Tab = S->SymTab->BackLink;
820 Sym = SymFindAny (Tab, S->Name);
822 if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) {
823 /* We've found a symbol in a higher level that is
824 * either defined in the source, or an import.
828 /* The symbol found is undefined itself. Look further */
829 Tab = Sym->SymTab->BackLink;
832 /* No symbol found */
838 /* We found the symbol in a higher level. Make S a trampoline
839 * symbol. Beware: We have to transfer the symbol attributes to
840 * the real symbol and check for any conflicts.
842 S->Flags |= SF_TRAMPOLINE;
845 /* Transfer the flags. Note: S may not be imported, since in that
846 * case it wouldn't be undefined.
848 if (S->Flags & SF_EXPORT) {
849 if (Sym->Flags & SF_IMPORT) {
850 /* The symbol is already marked as imported external symbol */
851 PError (&S->Pos, ERR_SYM_ALREADY_IMPORT);
853 Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
856 /* Transfer the referenced flag */
857 Sym->Flags |= (S->Flags & SF_REFERENCED);
860 /* The symbol is definitely undefined */
861 if (S->Flags & SF_EXPORT) {
862 /* We will not auto-import an export */
863 PError (&S->Pos, ERR_EXPORT_UNDEFINED, S->Name);
866 /* Mark as import, will be indexed later */
867 S->Flags |= SF_IMPORT;
870 PError (&S->Pos, ERR_SYM_UNDEFINED, S->Name);
879 /* Run through all symbols and check for anomalies and errors */
883 /* Check for open lexical levels */
884 if (SymTab->BackLink != 0) {
885 Error (ERR_OPEN_PROC);
888 /* First pass: Walk through all symbols, checking for undefined's and
889 * changing them to trampoline symbols or make them imports.
893 /* If the symbol is marked as global, mark it as export, if it is
894 * already defined, otherwise mark it as import.
896 if (S->Flags & SF_GLOBAL) {
897 S->Flags &= ~SF_GLOBAL;
898 if (S->Flags & SF_DEFINED) {
899 S->Flags |= SF_EXPORT;
901 S->Flags |= SF_IMPORT;
905 /* Handle undefined symbols */
906 if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
907 /* This is an undefined symbol. Handle it. */
908 SymCheckUndefined (S);
915 /* Second pass: Walk again through the symbols. Ignore undefined's, since
916 * we handled them in the last pass, and ignore trampoline symbols, since
917 * we handled them in the last pass, too.
921 if ((S->Flags & SF_TRAMPOLINE) == 0 &&
922 (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
923 if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
924 /* Symbol was defined but never referenced */
925 PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, S->Name);
927 if (S->Flags & SF_IMPORT) {
928 if ((S->Flags & SF_REFERENCED) == 0) {
929 /* Imported symbol is not referenced */
930 PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, S->Name);
932 /* Give the import an index, count imports */
933 S->Index = ImportCount++;
934 S->Flags |= SF_INDEXED;
937 if (S->Flags & SF_EXPORT) {
938 /* Give the export an index, count exports */
939 S->Index = ExportCount++;
940 S->Flags |= SF_INDEXED;
951 void SymDump (FILE* F)
952 /* Dump the symbol table */
954 SymEntry* S = SymList;
957 /* Ignore trampoline symbols */
958 if ((S->Flags & SF_TRAMPOLINE) != 0) {
959 printf ("%-24s %s %s %s %s %s\n",
961 (S->Flags & SF_DEFINED)? "DEF" : "---",
962 (S->Flags & SF_REFERENCED)? "REF" : "---",
963 (S->Flags & SF_IMPORT)? "IMP" : "---",
964 (S->Flags & SF_EXPORT)? "EXP" : "---",
965 (S->Flags & SF_ZP)? "ZP" : "--");
974 void WriteImports (void)
975 /* Write the imports list to the object file */
979 /* Tell the object file module that we're about to start the imports */
982 /* Write the import count to the list */
983 ObjWrite16 (ImportCount);
985 /* Walk throught list and write all imports to the file */
988 if ((S->Flags & SF_IMPMASK) == SF_IMPVAL) {
989 if (S->Flags & SF_ZP) {
994 ObjWriteStr (S->Name);
995 ObjWritePos (&S->Pos);
1000 /* Done writing imports */
1006 void WriteExports (void)
1007 /* Write the exports list to the object file */
1011 /* Tell the object file module that we're about to start the exports */
1014 /* Write the export count to the list */
1015 ObjWrite16 (ExportCount);
1017 /* Walk throught list and write all exports to the file */
1020 if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) {
1021 unsigned char ExprMask;
1023 /* Finalize an associated expression if we have one */
1026 /* Check if the symbol is const */
1027 ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
1029 /* Write the type */
1030 if (S->Flags & SF_ZP) {
1031 ObjWrite8 (EXP_ZP | ExprMask);
1033 ObjWrite8 (EXP_ABS | ExprMask);
1035 ObjWriteStr (S->Name);
1036 if (ExprMask == EXP_CONST) {
1037 /* Constant value */
1038 ObjWrite32 (S->V.Val);
1040 /* Expression involved */
1041 WriteExpr (S->V.Expr);
1043 ObjWritePos (&S->Pos);
1048 /* Done writing exports */
1054 void WriteDbgSyms (void)
1055 /* Write a list of all symbols to the object file */
1060 /* Tell the object file module that we're about to start the debug info */
1063 /* Check if debug info is requested */
1066 /* Walk through the list and count the symbols */
1070 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1077 if (Count > 0xFFFF) {
1078 Fatal (FAT_TOO_MANY_SYMBOLS);
1081 /* Write the symbol count to the list */
1084 /* Walk through list and write all symbols to the file */
1087 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1088 unsigned char ExprMask;
1090 /* Finalize an associated expression if we have one */
1093 /* Check if the symbol is const */
1094 ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
1096 /* Write the type */
1097 if (S->Flags & SF_ZP) {
1098 ObjWrite8 (EXP_ZP | ExprMask);
1100 ObjWrite8 (EXP_ABS | ExprMask);
1102 ObjWriteStr (S->Name);
1103 if (ExprMask == EXP_CONST) {
1104 /* Constant value */
1105 ObjWrite32 (S->V.Val);
1107 /* Expression involved */
1108 WriteExpr (S->V.Expr);
1110 ObjWritePos (&S->Pos);
1117 /* No debug symbols */
1122 /* Done writing debug symbols */