]> git.sur5r.net Git - cc65/blob - src/ca65/symtab.c
Reverted r5835 because of Olivers changes to the asm includes.
[cc65] / src / ca65 / symtab.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 symtab.c                                  */
4 /*                                                                           */
5 /*                 Symbol table 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 "check.h"
41 #include "hashfunc.h"
42 #include "mmodel.h"
43 #include "scopedefs.h"
44 #include "symdefs.h"
45 #include "xmalloc.h"
46
47 /* ca65 */
48 #include "dbginfo.h"
49 #include "error.h"
50 #include "expr.h"
51 #include "global.h"
52 #include "objfile.h"
53 #include "scanner.h"
54 #include "segment.h"
55 #include "sizeof.h"
56 #include "span.h"
57 #include "spool.h"
58 #include "studyexpr.h"
59 #include "symtab.h"
60
61
62
63 /*****************************************************************************/
64 /*                                   Data                                    */
65 /*****************************************************************************/
66
67
68
69 /* Combined symbol entry flags used within this module */
70 #define SF_UNDEFMASK    (SF_REFERENCED | SF_DEFINED | SF_IMPORT)
71 #define SF_UNDEFVAL     (SF_REFERENCED)
72
73 /* Symbol tables */
74 SymTable*           CurrentScope = 0;   /* Pointer to current symbol table */
75 SymTable*           RootScope    = 0;   /* Root symbol table */
76 static SymTable*    LastScope    = 0;   /* Pointer to last scope in list */
77 static unsigned     ScopeCount   = 0;   /* Number of scopes */
78
79 /* Symbol table variables */
80 static unsigned     ImportCount = 0;    /* Counter for import symbols */
81 static unsigned     ExportCount = 0;    /* Counter for export symbols */
82
83
84
85 /*****************************************************************************/
86 /*                         Internally used functions                         */
87 /*****************************************************************************/
88
89
90
91 static int IsDbgSym (const SymEntry* S)
92 /* Return true if this is a debug symbol */
93 {
94     if ((S->Flags & (SF_DEFINED | SF_UNUSED)) == SF_DEFINED) {
95         /* Defined symbols are debug symbols if they aren't sizes */
96         return !IsSizeOfSymbol (S);
97     } else {
98         /* Others are debug symbols if they're referenced imports */
99         return ((S->Flags & SF_REFIMP) == SF_REFIMP);
100     }
101 }
102
103
104
105 static unsigned ScopeTableSize (unsigned Level)
106 /* Get the size of a table for the given lexical level */
107 {
108     switch (Level) {
109         case 0:         return 213;
110         case 1:         return  53;
111         default:        return  29;
112     }
113 }
114
115
116
117 static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
118 /* Allocate a symbol table on the heap and return it */
119 {
120     /* Determine the lexical level and the number of table slots */
121     unsigned Level = Parent? Parent->Level + 1 : 0;
122     unsigned Slots = ScopeTableSize (Level);
123
124     /* Allocate memory */
125     SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));
126
127     /* Set variables and clear hash table entries */
128     S->Next         = 0;
129     S->Left         = 0;
130     S->Right        = 0;
131     S->Childs       = 0;
132     S->Label        = 0;
133     S->Spans        = AUTO_COLLECTION_INITIALIZER;
134     S->Id           = ScopeCount++;
135     S->Flags        = ST_NONE;
136     S->AddrSize     = ADDR_SIZE_DEFAULT;
137     S->Type         = SCOPE_UNDEF;
138     S->Level        = Level;
139     S->TableSlots   = Slots;
140     S->TableEntries = 0;
141     S->Parent       = Parent;
142     S->Name         = GetStrBufId (Name);
143     while (Slots--) {
144         S->Table[Slots] = 0;
145     }
146
147     /* Insert the symbol table into the list of all symbol tables */
148     if (RootScope == 0) {
149         RootScope = S;
150     } else {
151         LastScope->Next = S;
152     }
153     LastScope = S;
154
155     /* Insert the symbol table into the child tree of the parent */
156     if (Parent) {
157         SymTable* T = Parent->Childs;
158         if (T == 0) {
159             /* First entry */
160             Parent->Childs = S;
161         } else {
162             while (1) {
163                 /* Choose next entry */
164                 int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
165                 if (Cmp < 0) {
166                     if (T->Left) {
167                         T = T->Left;
168                     } else {
169                         T->Left = S;
170                         break;
171                     }
172                 } else if (Cmp > 0) {
173                     if (T->Right) {
174                         T = T->Right;
175                     } else {
176                         T->Right = S;
177                         break;
178                     }
179                 } else {
180                     /* Duplicate scope name */
181                     Internal ("Duplicate scope name: `%m%p'", Name);
182                 }
183             }
184         }
185     }
186
187     /* Return the prepared struct */
188     return S;
189 }
190
191
192
193 /*****************************************************************************/
194 /*                                   Code                                    */
195 /*****************************************************************************/
196
197
198
199 void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
200                     unsigned char AddrSize, SymEntry* ScopeLabel)
201 /* Enter a new lexical level */
202 {
203     /* Map a default address size to something real */
204     if (AddrSize == ADDR_SIZE_DEFAULT) {
205         /* Use the segment address size */
206         AddrSize = GetCurrentSegAddrSize ();
207     }
208
209     /* If we have a current scope, search for the given name and create a
210      * new one if it doesn't exist. If this is the root scope, just create it.
211      */
212     if (CurrentScope) {
213
214         /* Search for the scope, create a new one */
215         CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW);
216
217         /* Check if the scope has been defined before */
218         if (CurrentScope->Flags & ST_DEFINED) {
219             Error ("Duplicate scope `%m%p'", ScopeName);
220         }
221
222     } else {
223         CurrentScope = RootScope = NewSymTable (0, ScopeName);
224     }
225
226     /* Mark the scope as defined and set type, address size and owner symbol */
227     CurrentScope->Flags    |= ST_DEFINED;
228     CurrentScope->AddrSize = AddrSize;
229     CurrentScope->Type     = Type;
230     CurrentScope->Label    = ScopeLabel;
231
232     /* If this is a scope that allows to emit data into segments, add spans
233      * for all currently existing segments. Doing this for just a few scope
234      * types is not really necessary but an optimization, because it does not
235      * allocate memory for useless data (unhandled types here don't occupy
236      * space in any segment).
237      */
238     if (CurrentScope->Type <= SCOPE_HAS_DATA) {
239         OpenSpanList (&CurrentScope->Spans);
240     }
241 }
242
243
244
245 void SymLeaveLevel (void)
246 /* Leave the current lexical level */
247 {
248     /* If this is a scope that allows to emit data into segments, close the
249      * open the spans.
250      */
251     if (CurrentScope->Type <= SCOPE_HAS_DATA) {
252         CloseSpanList (&CurrentScope->Spans);
253     }
254
255     /* If we have spans, the first one is the segment that was active, when the
256      * scope was opened. Set the size of the scope to the number of data bytes
257      * emitted into this segment. If we have an owner symbol set the size of
258      * this symbol, too.
259      */
260     if (CollCount (&CurrentScope->Spans) > 0) {
261         const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0);
262         unsigned long Size = GetSpanSize (S);
263         DefSizeOfScope (CurrentScope, Size);
264         if (CurrentScope->Label) {
265             DefSizeOfSymbol (CurrentScope->Label, Size);
266         }
267     }
268
269     /* Leave the scope */
270     CurrentScope = CurrentScope->Parent;
271 }
272
273
274
275 SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, int AllocNew)
276 /* Find a scope in the given enclosing scope */
277 {
278     SymTable** T = &Parent->Childs;
279     while (*T) {
280         int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name));
281         if (Cmp < 0) {
282             T = &(*T)->Left;
283         } else if (Cmp > 0) {
284             T = &(*T)->Right;
285         } else {
286             /* Found the scope */
287             return *T;
288         }
289     }
290
291     /* Create a new scope if requested and we didn't find one */
292     if (*T == 0 && AllocNew) {
293         *T = NewSymTable (Parent, Name);
294     }
295
296     /* Return the scope */
297     return *T;
298 }
299
300
301
302 SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name)
303 /* Find a scope in the given or any of its parent scopes. The function will
304  * never create a new symbol, since this can only be done in one specific
305  * scope.
306  */
307 {
308     SymTable* Scope;
309     do {
310         /* Search in the current table */
311         Scope = SymFindScope (Parent, Name, SYM_FIND_EXISTING);
312         if (Scope == 0) {
313             /* Not found, search in the parent scope, if we have one */
314             Parent = Parent->Parent;
315         }
316     } while (Scope == 0 && Parent != 0);
317
318     return Scope;
319 }
320
321
322
323 SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, int AllocNew)
324 /* Find a cheap local symbol. If AllocNew is given and the entry is not
325  * found, create a new one. Return the entry found, or the new entry created,
326  * or - in case AllocNew is zero - return 0.
327  */
328 {
329     SymEntry* S;
330     int Cmp;
331
332     /* Local symbol, get the table */
333     if (!Parent) {
334         /* No last global, so there's no local table */
335         Error ("No preceeding global symbol");
336         if (AllocNew) {
337             return NewSymEntry (Name, SF_LOCAL);
338         } else {
339             return 0;
340         }
341     }
342
343     /* Search for the symbol if we have a table */
344     Cmp = SymSearchTree (Parent->Locals, Name, &S);
345
346     /* If we found an entry, return it */
347     if (Cmp == 0) {
348         return S;
349     }
350
351     if (AllocNew) {
352
353         /* Otherwise create a new entry, insert and return it */
354         SymEntry* N = NewSymEntry (Name, SF_LOCAL);
355         N->Sym.Entry = Parent;
356         if (S == 0) {
357             Parent->Locals = N;
358         } else if (Cmp < 0) {
359             S->Left = N;
360         } else {
361             S->Right = N;
362         }
363         return N;
364     }
365
366     /* We did not find the entry and AllocNew is false. */
367     return 0;
368 }
369
370
371
372 SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, int AllocNew)
373 /* Find a new symbol table entry in the given table. If AllocNew is given and
374  * the entry is not found, create a new one. Return the entry found, or the
375  * new entry created, or - in case AllocNew is zero - return 0.
376  */
377 {
378     SymEntry* S;
379
380     /* Global symbol: Get the hash value for the name */
381     unsigned Hash = HashBuf (Name) % Scope->TableSlots;
382
383     /* Search for the entry */
384     int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S);
385
386     /* If we found an entry, return it */
387     if (Cmp == 0) {
388         return S;
389     }
390
391     if (AllocNew) {
392
393         /* Otherwise create a new entry, insert and return it */
394         SymEntry* N = NewSymEntry (Name, SF_NONE);
395         N->Sym.Tab = Scope;
396         if (S == 0) {
397             Scope->Table[Hash] = N;
398         } else if (Cmp < 0) {
399             S->Left = N;
400         } else {
401             S->Right = N;
402         }
403         ++Scope->TableEntries;
404         return N;
405
406     }
407
408     /* We did not find the entry and AllocNew is false. */
409     return 0;
410 }
411
412
413
414 SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name)
415 /* Find a symbol in the given or any of its parent scopes. The function will
416  * never create a new symbol, since this can only be done in one specific
417  * scope.
418  */
419 {
420     SymEntry* Sym;
421     do {
422         /* Search in the current table. Ignore entries flagged with SF_UNUSED,
423          * because for such symbols there is a real entry in one of the parent
424          * scopes.
425          */
426         Sym = SymFind (Scope, Name, SYM_FIND_EXISTING);
427         if (Sym) {
428             if (Sym->Flags & SF_UNUSED) {
429                 Sym = 0;
430             } else {
431                 /* Found, return it */
432                 break;
433             }
434         }
435
436         /* Not found, search in the parent scope, if we have one */
437         Scope = Scope->Parent;
438
439     } while (Sym == 0 && Scope != 0);
440
441     /* Return the result */
442     return Sym;
443 }
444
445
446
447 static void SymCheckUndefined (SymEntry* S)
448 /* Handle an undefined symbol */
449 {
450     /* Undefined symbol. It may be...
451      *
452      *   - An undefined symbol in a nested lexical level. In this
453      *     case, search for the symbol in the higher levels and
454      *     make the entry a trampoline entry if we find one.
455      *
456      *   - If the symbol is not found, it is a real undefined symbol.
457      *     If the AutoImport flag is set, make it an import. If the
458      *     AutoImport flag is not set, it's an error.
459      */
460     SymEntry* Sym = 0;
461     SymTable* Tab = GetSymParentScope (S);
462     while (Tab) {
463         Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING);
464         if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
465             /* We've found a symbol in a higher level that is
466              * either defined in the source, or an import.
467              */
468              break;
469         }
470         /* No matching symbol found in this level. Look further */
471         Tab = Tab->Parent;
472     }
473
474     if (Sym) {
475
476         /* We found the symbol in a higher level. Transfer the flags and
477          * address size from the local symbol to that in the higher level
478          * and check for problems.
479          */
480         if (S->Flags & SF_EXPORT) {
481             if (Sym->Flags & SF_IMPORT) {
482                 /* The symbol is already marked as import */
483                 LIError (&S->RefLines,
484                          "Symbol `%s' is already an import",
485                          GetString (Sym->Name));
486             }
487             if (Sym->Flags & SF_EXPORT) {
488                 /* The symbol is already marked as an export. */
489                 if (Sym->AddrSize > S->ExportSize) {
490                     /* We're exporting a symbol smaller than it actually is */
491                     LIWarning (&S->DefLines, 1,
492                                "Symbol `%m%p' is %s but exported %s",
493                               GetSymName (Sym),
494                               AddrSizeToStr (Sym->AddrSize),
495                               AddrSizeToStr (S->ExportSize));
496                 }
497             } else {
498                 /* Mark the symbol as an export */
499                 Sym->Flags |= SF_EXPORT;
500                 Sym->ExportSize = S->ExportSize;
501                 if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
502                     /* Use the actual size of the symbol */
503                     Sym->ExportSize = Sym->AddrSize;
504                 }
505                 if (Sym->AddrSize > Sym->ExportSize) {
506                     /* We're exporting a symbol smaller than it actually is */
507                     LIWarning (&S->DefLines, 1,
508                                "Symbol `%m%p' is %s but exported %s",
509                                GetSymName (Sym),
510                                AddrSizeToStr (Sym->AddrSize),
511                                AddrSizeToStr (Sym->ExportSize));
512                 }
513             }
514         }
515         if (S->Flags & SF_REFERENCED) {
516             /* Mark as referenced and move the line info */
517             Sym->Flags |= SF_REFERENCED;
518             CollTransfer (&Sym->RefLines, &S->RefLines);
519             CollDeleteAll (&S->RefLines);
520         }
521
522         /* Transfer all expression references */
523         SymTransferExprRefs (S, Sym);
524
525         /* Mark the symbol as unused removing all other flags */
526         S->Flags = SF_UNUSED;
527
528     } else {
529         /* The symbol is definitely undefined */
530         if (S->Flags & SF_EXPORT) {
531             /* We will not auto-import an export */
532             LIError (&S->RefLines,
533                      "Exported symbol `%m%p' was never defined",
534                      GetSymName (S));
535         } else {
536             if (AutoImport) {
537                 /* Mark as import, will be indexed later */
538                 S->Flags |= SF_IMPORT;
539                 /* Use the address size for code */
540                 S->AddrSize = CodeAddrSize;
541                 /* Mark point of import */
542                 GetFullLineInfo (&S->DefLines);
543             } else {
544                 /* Error */
545                 LIError (&S->RefLines,
546                          "Symbol `%m%p' is undefined",
547                          GetSymName (S));
548             }
549         }
550     }
551 }
552
553
554
555 void SymCheck (void)
556 /* Run through all symbols and check for anomalies and errors */
557 {
558     SymEntry* S;
559
560     /* Check for open scopes */
561     if (CurrentScope->Parent != 0) {
562         Error ("Local scope was not closed");
563     }
564
565     /* First pass: Walk through all symbols, checking for undefined's and
566      * changing them to trampoline symbols or make them imports.
567      */
568     S = SymList;
569     while (S) {
570         /* If the symbol is marked as global, mark it as export, if it is
571          * already defined, otherwise mark it as import.
572          */
573         if (S->Flags & SF_GLOBAL) {
574             if (S->Flags & SF_DEFINED) {
575                 SymExportFromGlobal (S);
576             } else {
577                 SymImportFromGlobal (S);
578             }
579         }
580
581         /* Handle undefined symbols */
582         if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
583             /* This is an undefined symbol. Handle it. */
584             SymCheckUndefined (S);
585         }
586
587         /* Next symbol */
588         S = S->List;
589     }
590
591     /* Second pass: Walk again through the symbols. Count exports and imports
592      * and set address sizes where this has not happened before. Ignore
593      * undefined's, since we handled them in the last pass, and ignore unused
594      * symbols, since we handled them in the last pass, too.
595      */
596     S = SymList;
597     while (S) {
598         if ((S->Flags & SF_UNUSED) == 0 &&
599             (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {
600
601             /* Check for defined symbols that were never referenced */
602             if (IsSizeOfSymbol (S)) {
603                 /* Remove line infos, we don't need them any longer */
604                 ReleaseFullLineInfo (&S->DefLines);
605                 ReleaseFullLineInfo (&S->RefLines);
606             } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
607                 LIWarning (&S->DefLines, 2,
608                            "Symbol `%m%p' is defined but never used",
609                            GetSymName (S));
610             }
611
612             /* Assign an index to all imports */
613             if (S->Flags & SF_IMPORT) {
614                 if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
615                     /* Imported symbol is not referenced */
616                     LIWarning (&S->DefLines, 2,
617                                "Symbol `%m%p' is imported but never used",
618                                GetSymName (S));
619                 } else {
620                     /* Give the import an id, count imports */
621                     S->ImportId = ImportCount++;
622                 }
623             }
624
625             /* Count exports, assign the export ID */
626             if (S->Flags & SF_EXPORT) {
627                 S->ExportId = ExportCount++;
628             }
629
630             /* If the symbol is defined but has an unknown address size,
631              * recalculate it.
632              */
633             if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
634                 ExprDesc ED;
635                 ED_Init (&ED);
636                 StudyExpr (S->Expr, &ED);
637                 S->AddrSize = ED.AddrSize;
638                 if (SymIsExport (S)) {
639                     if (S->ExportSize == ADDR_SIZE_DEFAULT) {
640                         /* Use the real export size */
641                         S->ExportSize = S->AddrSize;
642                     } else if (S->AddrSize > S->ExportSize) {
643                         /* We're exporting a symbol smaller than it actually is */
644                         LIWarning (&S->DefLines, 1,
645                                    "Symbol `%m%p' is %s but exported %s",
646                                    GetSymName (S),
647                                    AddrSizeToStr (S->AddrSize),
648                                    AddrSizeToStr (S->ExportSize));
649                     }
650                 }
651                 ED_Done (&ED);
652             }
653
654             /* If the address size of the symbol was guessed, check the guess
655              * against the actual address size and print a warning if the two
656              * differ.
657              */
658             if (S->AddrSize != ADDR_SIZE_DEFAULT) {
659                 /* Do we have data for this address size? */
660                 if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
661                     /* Get the file position where the symbol was used */
662                     const FilePos* P = S->GuessedUse[S->AddrSize - 1];
663                     if (P) {
664                         PWarning (P, 0,
665                                   "Didn't use %s addressing for `%m%p'",
666                                   AddrSizeToStr (S->AddrSize),
667                                   GetSymName (S));
668                     }
669                 }
670             }
671
672         }
673
674         /* Next symbol */
675         S = S->List;
676     }
677 }
678
679
680
681 void SymDump (FILE* F)
682 /* Dump the symbol table */
683 {
684     SymEntry* S = SymList;
685
686     while (S) {
687         /* Ignore unused symbols */
688         if ((S->Flags & SF_UNUSED) != 0) {
689             fprintf (F,
690                      "%m%-24p %s %s %s %s %s\n",
691                      GetSymName (S),
692                      (S->Flags & SF_DEFINED)? "DEF" : "---",
693                      (S->Flags & SF_REFERENCED)? "REF" : "---",
694                      (S->Flags & SF_IMPORT)? "IMP" : "---",
695                      (S->Flags & SF_EXPORT)? "EXP" : "---",
696                      AddrSizeToStr (S->AddrSize));
697         }
698         /* Next symbol */
699         S = S->List;
700     }
701 }
702
703
704
705 void WriteImports (void)
706 /* Write the imports list to the object file */
707 {
708     SymEntry* S;
709
710     /* Tell the object file module that we're about to start the imports */
711     ObjStartImports ();
712
713     /* Write the import count to the list */
714     ObjWriteVar (ImportCount);
715
716     /* Walk throught list and write all valid imports to the file. An import
717      * is considered valid, if it is either referenced, or the forced bit is
718      * set. Otherwise, the import is ignored (no need to link in something
719      * that isn't used).
720      */
721     S = SymList;
722     while (S) {
723         if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT &&
724             (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) {
725
726             ObjWrite8 (S->AddrSize);
727             ObjWriteVar (S->Name);
728             WriteLineInfo (&S->DefLines);
729             WriteLineInfo (&S->RefLines);
730         }
731         S = S->List;
732     }
733
734     /* Done writing imports */
735     ObjEndImports ();
736 }
737
738
739
740 void WriteExports (void)
741 /* Write the exports list to the object file */
742 {
743     SymEntry* S;
744     unsigned Type;
745
746     /* Tell the object file module that we're about to start the exports */
747     ObjStartExports ();
748
749     /* Write the export count to the list */
750     ObjWriteVar (ExportCount);
751
752     /* Walk throught list and write all exports to the file */
753     S = SymList;
754     while (S) {
755         if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) {
756
757             /* Get the expression bits and the value */
758             long ConstVal;
759             unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
760
761             /* Check if this symbol has a size. If so, remember it in the
762              * flags.
763              */
764             long Size;
765             SymEntry* SizeSym = FindSizeOfSymbol (S);
766             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
767                 SymFlags |= SYM_SIZE;
768             }
769
770             /* Count the number of ConDes types */
771             for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
772                 if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
773                     SYM_INC_CONDES_COUNT (SymFlags);
774                 }
775             }
776
777             /* Write the type and the export size */
778             ObjWriteVar (SymFlags);
779             ObjWrite8 (S->ExportSize);
780
781             /* Write any ConDes declarations */
782             if (SYM_GET_CONDES_COUNT (SymFlags) > 0) {
783                 for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
784                     unsigned char Prio = S->ConDesPrio[Type];
785                     if (Prio != CD_PRIO_NONE) {
786                         ObjWrite8 (CD_BUILD (Type, Prio));
787                     }
788                 }
789             }
790
791             /* Write the name */
792             ObjWriteVar (S->Name);
793
794             /* Write the value */
795             if (SYM_IS_CONST (SymFlags)) {
796                 /* Constant value */
797                 ObjWrite32 (ConstVal);
798             } else {
799                 /* Expression involved */
800                 WriteExpr (S->Expr);
801             }
802
803             /* If the symbol has a size, write it to the file */
804             if (SYM_HAS_SIZE (SymFlags)) {
805                 ObjWriteVar (Size);
806             }
807
808             /* Write the line infos */
809             WriteLineInfo (&S->DefLines);
810             WriteLineInfo (&S->RefLines);
811         }
812         S = S->List;
813     }
814
815     /* Done writing exports */
816     ObjEndExports ();
817 }
818
819
820
821 void WriteDbgSyms (void)
822 /* Write a list of all symbols to the object file */
823 {
824     unsigned Count;
825     SymEntry* S;
826
827     /* Tell the object file module that we're about to start the debug info */
828     ObjStartDbgSyms ();
829
830     /* Check if debug info is requested */
831     if (DbgSyms) {
832
833         /* Walk through the list, give each symbol an id and count them */
834         Count = 0;
835         S = SymList;
836         while (S) {
837             if (IsDbgSym (S)) {
838                 S->DebugSymId = Count++;
839             }
840             S = S->List;
841         }
842
843         /* Write the symbol count to the list */
844         ObjWriteVar (Count);
845
846         /* Walk through list and write all symbols to the file. Ignore size
847          * symbols.
848          */
849         S = SymList;
850         while (S) {
851             if (IsDbgSym (S)) {
852
853                 /* Get the expression bits and the value */
854                 long ConstVal;
855                 unsigned SymFlags = GetSymInfoFlags (S, &ConstVal);
856
857                 /* Check if this symbol has a size. If so, remember it in the
858                  * flags.
859                  */
860                 long Size;
861                 SymEntry* SizeSym = FindSizeOfSymbol (S);
862                 if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
863                     SymFlags |= SYM_SIZE;
864                 }
865
866                 /* Write the type */
867                 ObjWriteVar (SymFlags);
868
869                 /* Write the address size */
870                 ObjWrite8 (S->AddrSize);
871
872                 /* Write the id of the parent. For normal symbols, this is a
873                  * scope (symbol table), for cheap locals, it's a symbol.
874                  */
875                 if (SYM_IS_STD (SymFlags)) {
876                     ObjWriteVar (S->Sym.Tab->Id);
877                 } else {
878                     ObjWriteVar (S->Sym.Entry->DebugSymId);
879                 }
880
881                 /* Write the name */
882                 ObjWriteVar (S->Name);
883
884                 /* Write the value */
885                 if (SYM_IS_CONST (SymFlags)) {
886                     /* Constant value */
887                     ObjWrite32 (ConstVal);
888                 } else {
889                     /* Expression involved */
890                     WriteExpr (S->Expr);
891                 }
892
893                 /* If the symbol has a size, write it to the file */
894                 if (SYM_HAS_SIZE (SymFlags)) {
895                     ObjWriteVar (Size);
896                 }
897
898                 /* If the symbol is an im- or export, write out the ids */
899                 if (SYM_IS_IMPORT (SymFlags)) {
900                     ObjWriteVar (GetSymImportId (S));
901                 }
902                 if (SYM_IS_EXPORT (SymFlags)) {
903                     ObjWriteVar (GetSymExportId (S));
904                 }
905
906                 /* Write the line infos */
907                 WriteLineInfo (&S->DefLines);
908                 WriteLineInfo (&S->RefLines);
909             }
910             S = S->List;
911         }
912
913     } else {
914
915         /* No debug symbols */
916         ObjWriteVar (0);
917
918     }
919
920     /* Write the high level symbols */
921     WriteHLLDbgSyms ();
922
923     /* Done writing debug symbols */
924     ObjEndDbgSyms ();
925 }
926
927
928
929 void WriteScopes (void)
930 /* Write the scope table to the object file */
931 {
932     /* Tell the object file module that we're about to start the scopes */
933     ObjStartScopes ();
934
935     /* We will write scopes only if debug symbols are requested */
936     if (DbgSyms) {
937
938         /* Get head of list */
939         SymTable* S = RootScope;
940
941         /* Write the scope count to the file */
942         ObjWriteVar (ScopeCount);
943
944         /* Walk through all scopes and write them to the file */
945         while (S) {
946
947             /* Flags for this scope */
948             unsigned Flags = 0;
949
950             /* Check if this scope has a size. If so, remember it in the
951              * flags.
952              */
953             long Size;
954             SymEntry* SizeSym = FindSizeOfScope (S);
955             if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) {
956                 Flags |= SCOPE_SIZE;
957             }
958
959             /* Check if the scope has a label */
960             if (S->Label) {
961                 Flags |= SCOPE_LABELED;
962             }
963
964             /* Scope must be defined */
965             CHECK (S->Type != SCOPE_UNDEF);
966
967             /* Id of parent scope */
968             if (S->Parent) {
969                 ObjWriteVar (S->Parent->Id);
970             } else {
971                 ObjWriteVar (0);
972             }
973
974             /* Lexical level */
975             ObjWriteVar (S->Level);
976
977             /* Scope flags */
978             ObjWriteVar (Flags);
979
980             /* Type of scope */
981             ObjWriteVar (S->Type);
982
983             /* Name of the scope */
984             ObjWriteVar (S->Name);
985
986             /* If the scope has a size, write it to the file */
987             if (SCOPE_HAS_SIZE (Flags)) {
988                 ObjWriteVar (Size);
989             }
990
991             /* If the scope has a label, write its id to the file */
992             if (SCOPE_HAS_LABEL (Flags)) {
993                 ObjWriteVar (S->Label->DebugSymId);
994             }
995
996             /* Spans for this scope */
997             WriteSpanList (&S->Spans);
998
999             /* Next scope */
1000             S = S->Next;
1001         }
1002
1003     } else {
1004
1005         /* No debug info requested */
1006         ObjWriteVar (0);
1007
1008     }
1009
1010     /* Done writing the scopes */
1011     ObjEndScopes ();
1012 }
1013
1014
1015