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 /*****************************************************************************/
53 /*****************************************************************************/
55 /*****************************************************************************/
59 /* Bits for the Flags value in SymEntry */
60 #define SF_USER 0x0001 /* User bit */
61 #define SF_TRAMPOLINE 0x0002 /* Trampoline entry */
62 #define SF_EXPORT 0x0004 /* Export this symbol */
63 #define SF_IMPORT 0x0008 /* Import this symbol */
64 #define SF_GLOBAL 0x0010 /* Global symbol */
65 #define SF_ZP 0x0020 /* Declared as zeropage symbol */
66 #define SF_ABS 0x0040 /* Declared as absolute symbol */
67 #define SF_INDEXED 0x0800 /* Index is valid */
68 #define SF_CONST 0x1000 /* The symbol has a constant value */
69 #define SF_MULTDEF 0x2000 /* Multiply defined symbol */
70 #define SF_DEFINED 0x4000 /* Defined */
71 #define SF_REFERENCED 0x8000 /* Referenced */
74 #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
75 #define SF_UNDEFVAL (SF_REFERENCED)
76 #define SF_IMPMASK (SF_TRAMPOLINE | SF_IMPORT | SF_REFERENCED)
77 #define SF_IMPVAL (SF_IMPORT | SF_REFERENCED)
78 #define SF_EXPMASK (SF_TRAMPOLINE | SF_EXPORT)
79 #define SF_EXPVAL (SF_EXPORT)
80 #define SF_DBGINFOMASK (SF_TRAMPOLINE | SF_DEFINED | SF_EXPORT | SF_IMPORT)
81 #define SF_DBGINFOVAL (SF_DEFINED)
85 /* Structure of a symbol table entry */
87 SymEntry* Left; /* Lexically smaller entry */
88 SymEntry* Right; /* Lexically larger entry */
89 SymEntry* List; /* List of all entries */
90 SymEntry* Locals; /* Root of subtree for local symbols */
91 struct SymTable_* SymTab; /* Table this symbol is in, 0 for locals */
92 FilePos Pos; /* File position for this symbol */
93 unsigned Flags; /* Symbol flags */
94 unsigned Index; /* Index of import/export entries */
96 struct ExprNode_* Expr; /* Expression if CONST not set */
97 long Val; /* Value (if CONST set) */
98 SymEntry* Sym; /* Symbol (if trampoline entry) */
100 char Name [1]; /* Dynamic allocation */
105 /* Definitions for the hash table */
106 #define MAIN_HASHTAB_SIZE 213
107 #define SUB_HASHTAB_SIZE 53
108 typedef struct SymTable_ SymTable;
110 unsigned TableSlots; /* Number of hash table slots */
111 unsigned TableEntries; /* Number of entries in the table */
112 SymTable* BackLink; /* Link to enclosing scope if any */
113 SymEntry* Table [1]; /* Dynamic allocation */
118 /* Symbol table variables */
119 static SymEntry* SymList = 0; /* List of all symbol table entries */
120 static SymEntry* SymLast = 0; /* Pointer to last defined symbol */
121 static SymTable* SymTab = 0; /* Pointer to current symbol table */
122 static SymTable* RootTab = 0; /* Root symbol table */
123 static unsigned ImportCount = 0;/* Counter for import symbols */
124 static unsigned ExportCount = 0;/* Counter for export symbols */
128 /*****************************************************************************/
129 /* Internally used functions */
130 /*****************************************************************************/
134 static int IsLocal (const char* Name)
135 /* Return true if Name is the name of a local symbol */
137 return (*Name == LocalStart);
142 static SymEntry* NewSymEntry (const char* Name)
143 /* Allocate a symbol table entry, initialize and return it */
148 /* Get the length of the name */
151 /* Allocate memory */
152 S = xmalloc (sizeof (SymEntry) + Len);
154 /* Initialize the entry */
162 memcpy (S->Name, Name, Len+1);
164 /* Insert it into the list of all entries */
168 /* Return the initialized entry */
174 static SymTable* NewSymTable (unsigned Size)
175 /* Allocate a symbol table on the heap and return it */
179 /* Allocate memory */
180 S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*));
182 /* Set variables and clear hash table entries */
183 S->TableSlots = Size;
190 /* Return the prepared struct */
196 static int SearchSymTab (SymEntry* T, const char* Name, SymEntry** E)
197 /* Search in the given table for a name (Hash is the hash value of Name and
198 * is given as parameter so that it will not get calculated twice if we search
199 * in more than one table). If we find the symbol, the function will return 0
200 * and put the entry pointer into E. If we did not find the symbol, and the
201 * tree is empty, E is set to NULL. If the tree is not empty, E will be set to
202 * the last entry, and the result of the function is <0 if the entry should
203 * be inserted on the left side, and >0 if it should get inserted on the right
209 /* Is there a tree? */
215 /* We have a table, search it */
217 /* Choose next entry */
218 Cmp = strcmp (Name, T->Name);
219 if (Cmp < 0 && T->Left) {
221 } else if (Cmp > 0 && T->Right) {
224 /* Found or end of search */
229 /* Return the search result */
236 /*****************************************************************************/
238 /*****************************************************************************/
242 static SymEntry* SymFind (SymTable* Tab, const char* 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 (IsLocal (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 = SearchSymTab (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 = HashStr (Name) % Tab->TableSlots;
292 /* Search for the entry */
293 Cmp = SearchSymTab (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 if (S->Flags & SF_TRAMPOLINE) {
309 /* Otherwise create a new entry, insert and return it */
310 SymEntry* N = NewSymEntry (Name);
312 Tab->Table [Hash] = N;
313 } else if (Cmp < 0) {
325 /* We did not find the entry and AllocNew is false. */
331 static SymEntry* SymFindAny (SymTable* Tab, const char* Name)
332 /* Find a symbol in any table */
336 /* Search in the current table */
337 Sym = SymFind (Tab, Name, 0);
339 /* Found, return it */
342 /* Not found, search in the backlink, if we have one */
345 } while (Sym == 0 && Tab != 0);
353 static SymEntry* SymRefInternal (SymTable* Table, const char* Name)
354 /* Search for the symbol in the given table and return it */
358 /* Try to find the symbol, create a new one if the symbol does not exist */
359 S = SymFind (Table, Name, 1);
361 /* Mark the symbol as referenced */
362 S->Flags |= SF_REFERENCED;
370 void SymEnterLevel (void)
371 /* Enter a new lexical level */
374 /* Create the main symbol table */
375 RootTab = SymTab = NewSymTable (MAIN_HASHTAB_SIZE);
377 /* Create a local symbol table */
379 LocalSyms = NewSymTable (SUB_HASHTAB_SIZE);
380 LocalSyms->BackLink = SymTab;
387 void SymLeaveLevel (void)
388 /* Leave the current lexical level */
390 SymTab = SymTab->BackLink;
395 void SymDef (const char* Name, ExprNode* Expr, int ZP)
396 /* Define a new symbol */
400 /* Do we have such a symbol? */
401 S = SymFind (SymTab, Name, 1);
402 if (S->Flags & SF_IMPORT) {
403 /* Defined symbol is marked as imported external symbol */
404 Error (ERR_SYM_ALREADY_IMPORT);
407 if (S->Flags & SF_DEFINED) {
408 /* Multiple definition */
409 Error (ERR_SYM_ALREADY_DEFINED, Name);
410 S->Flags |= SF_MULTDEF;
414 /* Set the symbol data */
415 if (IsConstExpr (Expr)) {
416 /* Expression is const, store the value */
417 S->Flags |= SF_CONST;
418 S->V.Val = GetExprVal (Expr);
421 /* Not const, store the expression */
424 S->Flags |= SF_DEFINED;
429 /* If the symbol is a ZP symbol, check if the value is in correct range */
430 if (S->Flags & SF_ZP) {
431 /* Already marked as ZP symbol by some means */
432 if (!IsByteExpr (Expr)) {
437 /* If this is not a local symbol, remember it as the last global one */
438 if (!IsLocal (Name)) {
445 SymEntry* SymRef (const char* Name)
446 /* Search for the symbol and return it */
448 /* Reference the symbol in the current table */
449 return SymRefInternal (SymTab, Name);
454 SymEntry* SymRefGlobal (const char* Name)
455 /* Search for the symbol in the global namespace and return it */
457 /* Reference the symbol in the current table */
458 return SymRefInternal (RootTab, Name);
463 void SymImport (const char* Name, int ZP)
464 /* Mark the given symbol as an imported symbol */
468 /* Don't accept local symbols */
469 if (IsLocal (Name)) {
470 Error (ERR_ILLEGAL_LOCAL_USE);
474 /* Do we have such a symbol? */
475 S = SymFind (SymTab, Name, 1);
476 if (S->Flags & SF_DEFINED) {
477 Error (ERR_SYM_ALREADY_DEFINED, Name);
478 S->Flags |= SF_MULTDEF;
481 if (S->Flags & SF_EXPORT) {
482 /* The symbol is already marked as exported symbol */
483 Error (ERR_SYM_ALREADY_EXPORT);
487 /* If the symbol is marked as global, check the symbol size, then do
488 * silently remove the global flag
490 if (S->Flags & SF_GLOBAL) {
491 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
492 Error (ERR_SYM_REDECL_MISMATCH);
494 S->Flags &= ~SF_GLOBAL;
497 /* Set the symbol data */
498 S->Flags |= SF_IMPORT;
506 void SymExport (const char* Name, int ZP)
507 /* Mark the given symbol as an exported symbol */
511 /* Don't accept local symbols */
512 if (IsLocal (Name)) {
513 Error (ERR_ILLEGAL_LOCAL_USE);
517 /* Do we have such a symbol? */
518 S = SymFind (SymTab, Name, 1);
519 if (S->Flags & SF_IMPORT) {
520 /* The symbol is already marked as imported external symbol */
521 Error (ERR_SYM_ALREADY_IMPORT);
525 /* If the symbol is marked as global, check the symbol size, then do
526 * silently remove the global flag
528 if (S->Flags & SF_GLOBAL) {
529 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
530 Error (ERR_SYM_REDECL_MISMATCH);
532 S->Flags &= ~SF_GLOBAL;
535 /* Set the symbol data */
536 S->Flags |= SF_EXPORT | SF_REFERENCED;
544 void SymGlobal (const char* Name, int ZP)
545 /* Mark the given symbol as a global symbol, that is, as a symbol that is
546 * either imported or exported.
551 /* Don't accept local symbols */
552 if (IsLocal (Name)) {
553 Error (ERR_ILLEGAL_LOCAL_USE);
557 /* Search for this symbol, create a new entry if needed */
558 S = SymFind (SymTab, Name, 1);
560 /* If the symbol is already marked as import or export, check the
561 * size of the definition, then bail out. */
562 if (S->Flags & SF_IMPORT || S->Flags & SF_EXPORT) {
563 if ((ZP != 0) != ((S->Flags & SF_ZP) != 0)) {
564 Error (ERR_SYM_REDECL_MISMATCH);
569 /* Mark the symbol */
570 S->Flags |= SF_GLOBAL;
578 int SymIsDef (const char* Name)
579 /* Return true if the given symbol is already defined */
581 SymEntry* S = SymFindAny (SymTab, Name);
582 return S != 0 && (S->Flags & (SF_DEFINED | SF_IMPORT)) != 0;
587 int SymIsRef (const char* Name)
588 /* Return true if the given symbol has been referenced */
590 SymEntry* S = SymFindAny (SymTab, Name);
591 return S != 0 && (S->Flags & SF_REFERENCED) != 0;
596 int SymIsConst (SymEntry* S)
597 /* Return true if the given symbol has a constant value */
599 /* Resolve trampoline entries */
600 if (S->Flags & SF_TRAMPOLINE) {
604 /* Check for constness */
605 if (S->Flags & SF_CONST) {
607 } else if ((S->Flags & SF_DEFINED) && IsConstExpr (S->V.Expr)) {
608 /* Constant expression, remember the value */
609 ExprNode* Expr = S->V.Expr;
610 S->Flags |= SF_CONST;
611 S->V.Val = GetExprVal (Expr);
620 int SymIsZP (SymEntry* S)
621 /* Return true if the symbol is explicitly marked as zeropage symbol */
623 /* Resolve trampoline entries */
624 if (S->Flags & SF_TRAMPOLINE) {
628 /* If the symbol is not a global symbol, was not defined before, check the
629 * enclosing scope for a symbol with the same name, and return the ZP
630 * attribute of this symbol if we find one.
632 if (!IsLocal (S->Name) &&
633 (S->Flags & (SF_ZP | SF_ABS | SF_DEFINED | SF_IMPORT)) == 0 &&
634 S->SymTab->BackLink != 0) {
636 /* Try to find a symbol with the same name in the enclosing scope */
637 SymEntry* E = SymFindAny (S->SymTab->BackLink, S->Name);
639 /* If we found one, use the ZP flag */
640 if (E && (E->Flags & SF_ZP) != 0) {
645 /* Check the ZP flag */
646 return (S->Flags & SF_ZP) != 0;
651 int SymIsImport (SymEntry* S)
652 /* Return true if the given symbol is marked as import */
654 /* Resolve trampoline entries */
655 if (S->Flags & SF_TRAMPOLINE) {
659 /* Check the import flag */
660 return (S->Flags & SF_IMPORT) != 0;
665 int SymHasExpr (SymEntry* S)
666 /* Return true if the given symbol has an associated expression */
668 /* Resolve trampoline entries */
669 if (S->Flags & SF_TRAMPOLINE) {
673 /* Check the expression */
674 return ((S->Flags & SF_DEFINED) != 0 &&
675 (S->Flags & SF_IMPORT) == 0 &&
676 (S->Flags & SF_CONST) == 0);
681 void SymFinalize (SymEntry* S)
682 /* Finalize a symbol expression if there is one */
684 /* Resolve trampoline entries */
685 if (S->Flags & SF_TRAMPOLINE) {
689 /* Check if we have an expression */
690 if (SymHasExpr (S)) {
691 S->V.Expr = FinalizeExpr (S->V.Expr);
697 void SymMarkUser (SymEntry* S)
698 /* Set a user mark on the specified symbol */
700 /* Resolve trampoline entries */
701 if (S->Flags & SF_TRAMPOLINE) {
711 void SymUnmarkUser (SymEntry* S)
712 /* Remove a user mark from the specified symbol */
714 /* Resolve trampoline entries */
715 if (S->Flags & SF_TRAMPOLINE) {
720 S->Flags &= ~SF_USER;
725 int SymHasUserMark (SymEntry* S)
726 /* Return the state of the user mark for the specified symbol */
728 /* Resolve trampoline entries */
729 if (S->Flags & SF_TRAMPOLINE) {
734 return (S->Flags & SF_USER) != 0;
739 long GetSymVal (SymEntry* S)
740 /* Return the symbol value */
742 /* Resolve trampoline entries */
743 if (S->Flags & SF_TRAMPOLINE) {
747 PRECONDITION ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_CONST) != 0);
753 ExprNode* GetSymExpr (SymEntry* S)
754 /* Get the expression for a non-const symbol */
756 /* Resolve trampoline entries */
757 if (S->Flags & SF_TRAMPOLINE) {
761 PRECONDITION (S != 0 && (S->Flags & SF_CONST) == 0);
767 const char* GetSymName (SymEntry* S)
768 /* Return the name of the symbol */
770 /* Resolve trampoline entries */
771 if (S->Flags & SF_TRAMPOLINE) {
779 unsigned GetSymIndex (SymEntry* S)
780 /* Return the symbol index for the given symbol */
782 /* Resolve trampoline entries */
783 if (S->Flags & SF_TRAMPOLINE) {
786 PRECONDITION (S != 0 && (S->Flags & SF_INDEXED));
792 const FilePos* GetSymPos (SymEntry* S)
793 /* Return the position of first occurence in the source for the given symbol */
795 /* Resolve trampoline entries */
796 if (S->Flags & SF_TRAMPOLINE) {
799 PRECONDITION (S != 0);
805 static void SymCheckUndefined (SymEntry* S)
806 /* Handle an undefined symbol */
808 /* Undefined symbol. It may be...
810 * - An undefined symbol in a nested lexical level. In this
811 * case, search for the symbol in the higher levels and
812 * make the entry a trampoline entry if we find one.
814 * - If the symbol is not found, it is a real undefined symbol.
815 * If the AutoImport flag is set, make it an import. If the
816 * AutoImport flag is not set, it's an error.
820 /* It's a global symbol, get the higher level table */
821 SymTable* Tab = S->SymTab->BackLink;
823 Sym = SymFindAny (Tab, S->Name);
825 if (Sym->Flags & (SF_DEFINED | SF_IMPORT)) {
826 /* We've found a symbol in a higher level that is
827 * either defined in the source, or an import.
831 /* The symbol found is undefined itself. Look further */
832 Tab = Sym->SymTab->BackLink;
835 /* No symbol found */
841 /* We found the symbol in a higher level. Make S a trampoline
842 * symbol. Beware: We have to transfer the symbol attributes to
843 * the real symbol and check for any conflicts.
845 S->Flags |= SF_TRAMPOLINE;
848 /* Transfer the flags. Note: S may not be imported, since in that
849 * case it wouldn't be undefined.
851 if (S->Flags & SF_EXPORT) {
852 if (Sym->Flags & SF_IMPORT) {
853 /* The symbol is already marked as imported external symbol */
854 PError (&S->Pos, ERR_SYM_ALREADY_IMPORT);
856 Sym->Flags |= S->Flags & (SF_EXPORT | SF_ZP);
859 /* Transfer the referenced flag */
860 Sym->Flags |= (S->Flags & SF_REFERENCED);
863 /* The symbol is definitely undefined */
864 if (S->Flags & SF_EXPORT) {
865 /* We will not auto-import an export */
866 PError (&S->Pos, ERR_EXPORT_UNDEFINED, S->Name);
869 /* Mark as import, will be indexed later */
870 S->Flags |= SF_IMPORT;
873 PError (&S->Pos, ERR_SYM_UNDEFINED, S->Name);
882 /* Run through all symbols and check for anomalies and errors */
886 /* Check for open lexical levels */
887 if (SymTab->BackLink != 0) {
888 Error (ERR_OPEN_PROC);
891 /* First pass: Walk through all symbols, checking for undefined's and
892 * changing them to trampoline symbols or make them imports.
896 /* If the symbol is marked as global, mark it as export, if it is
897 * already defined, otherwise mark it as import.
899 if (S->Flags & SF_GLOBAL) {
900 S->Flags &= ~SF_GLOBAL;
901 if (S->Flags & SF_DEFINED) {
902 S->Flags |= SF_EXPORT;
904 S->Flags |= SF_IMPORT;
908 /* Handle undefined symbols */
909 if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
910 /* This is an undefined symbol. Handle it. */
911 SymCheckUndefined (S);
918 /* Second pass: Walk again through the symbols. Ignore undefined's, since
919 * we handled them in the last pass, and ignore trampoline symbols, since
920 * we handled them in the last pass, too.
924 if ((S->Flags & SF_TRAMPOLINE) == 0 &&
925 (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
926 if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
927 /* Symbol was defined but never referenced */
928 PWarning (&S->Pos, WARN_SYM_NOT_REFERENCED, S->Name);
930 if (S->Flags & SF_IMPORT) {
931 if ((S->Flags & SF_REFERENCED) == 0) {
932 /* Imported symbol is not referenced */
933 PWarning (&S->Pos, WARN_IMPORT_NOT_REFERENCED, S->Name);
935 /* Give the import an index, count imports */
936 S->Index = ImportCount++;
937 S->Flags |= SF_INDEXED;
940 if (S->Flags & SF_EXPORT) {
941 /* Give the export an index, count exports */
942 S->Index = ExportCount++;
943 S->Flags |= SF_INDEXED;
954 void SymDump (FILE* F)
955 /* Dump the symbol table */
957 SymEntry* S = SymList;
960 /* Ignore trampoline symbols */
961 if ((S->Flags & SF_TRAMPOLINE) != 0) {
962 printf ("%-24s %s %s %s %s %s\n",
964 (S->Flags & SF_DEFINED)? "DEF" : "---",
965 (S->Flags & SF_REFERENCED)? "REF" : "---",
966 (S->Flags & SF_IMPORT)? "IMP" : "---",
967 (S->Flags & SF_EXPORT)? "EXP" : "---",
968 (S->Flags & SF_ZP)? "ZP" : "--");
977 void WriteImports (void)
978 /* Write the imports list to the object file */
982 /* Tell the object file module that we're about to start the imports */
985 /* Write the import count to the list */
986 ObjWrite16 (ImportCount);
988 /* Walk throught list and write all imports to the file */
991 if ((S->Flags & SF_IMPMASK) == SF_IMPVAL) {
992 if (S->Flags & SF_ZP) {
997 ObjWriteStr (S->Name);
998 ObjWritePos (&S->Pos);
1003 /* Done writing imports */
1009 void WriteExports (void)
1010 /* Write the exports list to the object file */
1014 /* Tell the object file module that we're about to start the exports */
1017 /* Write the export count to the list */
1018 ObjWrite16 (ExportCount);
1020 /* Walk throught list and write all exports to the file */
1023 if ((S->Flags & SF_EXPMASK) == SF_EXPVAL) {
1024 unsigned char ExprMask;
1026 /* Finalize an associated expression if we have one */
1029 /* Check if the symbol is const */
1030 ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
1032 /* Write the type */
1033 if (S->Flags & SF_ZP) {
1034 ObjWrite8 (EXP_ZP | ExprMask);
1036 ObjWrite8 (EXP_ABS | ExprMask);
1038 ObjWriteStr (S->Name);
1039 if (ExprMask == EXP_CONST) {
1040 /* Constant value */
1041 ObjWrite32 (S->V.Val);
1043 /* Expression involved */
1044 WriteExpr (S->V.Expr);
1046 ObjWritePos (&S->Pos);
1051 /* Done writing exports */
1057 void WriteDbgSyms (void)
1058 /* Write a list of all symbols to the object file */
1063 /* Tell the object file module that we're about to start the debug info */
1066 /* Check if debug info is requested */
1069 /* Walk through the list and count the symbols */
1073 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1080 if (Count > 0xFFFF) {
1081 Fatal (FAT_TOO_MANY_SYMBOLS);
1084 /* Write the symbol count to the list */
1087 /* Walk through list and write all symbols to the file */
1090 if ((S->Flags & SF_DBGINFOMASK) == SF_DBGINFOVAL) {
1091 unsigned char ExprMask;
1093 /* Finalize an associated expression if we have one */
1096 /* Check if the symbol is const */
1097 ExprMask = (SymIsConst (S))? EXP_CONST : EXP_EXPR;
1099 /* Write the type */
1100 if (S->Flags & SF_ZP) {
1101 ObjWrite8 (EXP_ZP | ExprMask);
1103 ObjWrite8 (EXP_ABS | ExprMask);
1105 ObjWriteStr (S->Name);
1106 if (ExprMask == EXP_CONST) {
1107 /* Constant value */
1108 ObjWrite32 (S->V.Val);
1110 /* Expression involved */
1111 WriteExpr (S->V.Expr);
1113 ObjWritePos (&S->Pos);
1120 /* No debug symbols */
1125 /* Done writing debug symbols */