]> git.sur5r.net Git - cc65/blob - src/cc65/symtab.c
Added flexible array members for structs
[cc65] / src / cc65 / symtab.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 symtab.c                                  */
4 /*                                                                           */
5 /*              Symbol table management for the cc65 C compiler              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 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 <stdio.h>
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <string.h>
40
41 /* common */
42 #include "check.h"
43 #include "debugflag.h"
44 #include "hashstr.h"
45 #include "xmalloc.h"
46
47 /* cc65 */
48 #include "asmcode.h"
49 #include "asmlabel.h"
50 #include "codegen.h"
51 #include "datatype.h"
52 #include "declare.h"
53 #include "error.h"
54 #include "funcdesc.h"
55 #include "global.h"
56 #include "symentry.h"
57 #include "typecmp.h"
58 #include "symtab.h"
59
60
61
62 /*****************************************************************************/
63 /*                                   Data                                    */
64 /*****************************************************************************/
65
66
67
68 /* An empty symbol table */
69 SymTable        EmptySymTab = {
70     0,          /* PrevTab */
71     0,          /* SymHead */
72     0,          /* SymTail */
73     0,          /* SymCount */
74     1,          /* Size */
75     { 0 }       /* Tab[1] */
76 };
77
78 /* Symbol table sizes */
79 #define SYMTAB_SIZE_GLOBAL      211U
80 #define SYMTAB_SIZE_FUNCTION     29U
81 #define SYMTAB_SIZE_BLOCK        13U
82 #define SYMTAB_SIZE_STRUCT       19U
83 #define SYMTAB_SIZE_LABEL         7U
84
85 /* The current and root symbol tables */
86 static unsigned         LexicalLevel    = 0;    /* For safety checks */
87 static SymTable*        SymTab0         = 0;
88 static SymTable*        SymTab          = 0;
89 static SymTable*        TagTab0         = 0;
90 static SymTable*        TagTab          = 0;
91 static SymTable*        LabelTab        = 0;
92
93
94
95 /*****************************************************************************/
96 /*                              struct SymTable                              */
97 /*****************************************************************************/
98
99
100
101 static SymTable* NewSymTable (unsigned Size)
102 /* Create and return a symbol table for the given lexical level */
103 {
104     unsigned I;
105
106     /* Allocate memory for the table */
107     SymTable* S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*));
108
109     /* Initialize the symbol table structure */
110     S->PrevTab  = 0;
111     S->SymHead  = 0;
112     S->SymTail  = 0;
113     S->SymCount = 0;
114     S->Size     = Size;
115     for (I = 0; I < Size; ++I) {
116         S->Tab[I] = 0;
117     }
118
119     /* Return the symbol table */
120     return S;
121 }
122
123
124
125 static void FreeSymTable (SymTable* S)
126 /* Free the given symbo table including all symbols */
127 {
128     /* Free all symbols */
129     SymEntry* Sym = S->SymHead;
130     while (Sym) {
131         SymEntry* NextSym = Sym->NextSym;
132         FreeSymEntry (Sym);
133         Sym = NextSym;
134     }
135
136     /* Free the table itself */
137     xfree (S);
138 }
139
140
141
142 /*****************************************************************************/
143 /*                         Check symbols in a table                          */
144 /*****************************************************************************/
145
146
147
148 static void CheckSymTable (SymTable* Tab)
149 /* Check a symbol table for open references, unused symbols ... */
150 {
151     SymEntry* Entry = Tab->SymHead;
152     while (Entry) {
153
154         /* Get the storage flags for tne entry */
155         unsigned Flags = Entry->Flags;
156
157         /* Ignore typedef entries */
158         if ((Flags & SC_TYPEDEF) != SC_TYPEDEF) {
159
160             /* Check if the symbol is one with storage, and it if it was
161              * defined but not used.
162              */
163             if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
164                 if (SymIsDef (Entry) && !SymIsRef (Entry)) {
165                     if (Flags & SC_PARAM) {
166                         Warning ("Parameter `%s' is never used", Entry->Name);
167                     } else {
168                         Warning ("`%s' is defined but never used", Entry->Name);
169                     }
170                 }
171             }
172
173             /* If the entry is a label, check if it was defined in the function */
174             if (Flags & SC_LABEL) {
175                 if (!SymIsDef (Entry)) {
176                     /* Undefined label */
177                     Error ("Undefined label: `%s'", Entry->Name);
178                 } else if (!SymIsRef (Entry)) {
179                     /* Defined but not used */
180                     Warning ("`%s' is defined but never used", Entry->Name);
181                 }
182             }
183
184         }
185
186         /* Next entry */
187         Entry = Entry->NextSym;
188     }
189 }
190
191
192
193 /*****************************************************************************/
194 /*                        Handling of lexical levels                         */
195 /*****************************************************************************/
196
197
198
199 unsigned GetLexicalLevel (void)
200 /* Return the current lexical level */
201 {
202     return LexicalLevel;
203 }
204
205
206
207 void EnterGlobalLevel (void)
208 /* Enter the program global lexical level */
209 {
210     /* Safety */
211     PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL);
212
213     /* Create and assign the symbol table */
214     SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
215
216     /* Create and assign the tag table */
217     TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
218 }
219
220
221
222 void LeaveGlobalLevel (void)
223 /* Leave the program global lexical level */
224 {
225     /* Safety */
226     PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL);
227
228     /* Check the tables */
229     CheckSymTable (SymTab0);
230
231     /* Dump the tables if requested */
232     if (Debug) {
233         PrintSymTable (SymTab0, stdout, "Global symbol table");
234         PrintSymTable (TagTab0, stdout, "Global tag table");
235     }
236
237     /* Don't delete the symbol and struct tables! */
238     SymTab = 0;
239     TagTab = 0;
240 }
241
242
243
244 void EnterFunctionLevel (void)
245 /* Enter function lexical level */
246 {
247     SymTable* S;
248
249     /* New lexical level */
250     ++LexicalLevel;
251
252     /* Get a new symbol table and make it current */
253     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
254     S->PrevTab = SymTab;
255     SymTab     = S;
256
257     /* Get a new tag table and make it current */
258     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
259     S->PrevTab = TagTab;
260     TagTab  = S;
261
262     /* Create and assign a new label table */
263     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
264 }
265
266
267
268 void RememberFunctionLevel (struct FuncDesc* F)
269 /* Remember the symbol tables for the level and leave the level without checks */
270 {
271     /* Leave the lexical level */
272     --LexicalLevel;
273
274     /* Remember the tables */
275     F->SymTab = SymTab;
276     F->TagTab = TagTab;
277
278     /* Don't delete the tables */
279     SymTab = SymTab->PrevTab;
280     TagTab = TagTab->PrevTab;
281 }
282
283
284
285 void ReenterFunctionLevel (struct FuncDesc* F)
286 /* Reenter the function lexical level using the existing tables from F */
287 {
288     /* New lexical level */
289     ++LexicalLevel;
290
291     /* Make the tables current again */
292     F->SymTab->PrevTab = SymTab;
293     SymTab = F->SymTab;
294
295     F->TagTab->PrevTab = TagTab;
296     TagTab = F->TagTab;
297
298     /* Create and assign a new label table */
299     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
300 }
301
302
303
304 void LeaveFunctionLevel (void)
305 /* Leave function lexical level */
306 {
307     /* Leave the lexical level */
308     --LexicalLevel;
309
310     /* Check the tables */
311     CheckSymTable (SymTab);
312     CheckSymTable (LabelTab);
313
314     /* Drop the label table if it is empty */
315     if (LabelTab->SymCount == 0) {
316         FreeSymTable (LabelTab);
317     }
318
319     /* Don't delete the tables */
320     SymTab = SymTab->PrevTab;
321     TagTab = TagTab->PrevTab;
322     LabelTab  = 0;
323 }
324
325
326
327 void EnterBlockLevel (void)
328 /* Enter a nested block in a function */
329 {
330     SymTable* S;
331
332     /* New lexical level */
333     ++LexicalLevel;
334
335     /* Get a new symbol table and make it current */
336     S = NewSymTable (SYMTAB_SIZE_BLOCK);
337     S->PrevTab  = SymTab;
338     SymTab      = S;
339
340     /* Get a new tag table and make it current */
341     S = NewSymTable (SYMTAB_SIZE_BLOCK);
342     S->PrevTab = TagTab;
343     TagTab     = S;
344 }
345
346
347
348 void LeaveBlockLevel (void)
349 /* Leave a nested block in a function */
350 {
351     /* Leave the lexical level */
352     --LexicalLevel;
353
354     /* Check the tables */
355     CheckSymTable (SymTab);
356
357     /* Don't delete the tables */
358     SymTab = SymTab->PrevTab;
359     TagTab = TagTab->PrevTab;
360 }
361
362
363
364 void EnterStructLevel (void)
365 /* Enter a nested block for a struct definition */
366 {
367     SymTable* S;
368
369     /* Get a new symbol table and make it current. Note: Structs and enums
370      * nested in struct scope are NOT local to the struct but visible in the
371      * outside scope. So we will NOT create a new struct or enum table.
372      */
373     S = NewSymTable (SYMTAB_SIZE_BLOCK);
374     S->PrevTab  = SymTab;
375     SymTab      = S;
376 }
377
378
379
380 void LeaveStructLevel (void)
381 /* Leave a nested block for a struct definition */
382 {
383     /* Don't delete the table */
384     SymTab = SymTab->PrevTab;
385 }
386
387
388
389 /*****************************************************************************/
390 /*                              Find functions                               */
391 /*****************************************************************************/
392
393
394
395 static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
396 /* Search for an entry in one table */
397 {
398     /* Get the start of the hash chain */
399     SymEntry* E = T->Tab [Hash % T->Size];
400     while (E) {
401         /* Compare the name */
402         if (strcmp (E->Name, Name) == 0) {
403             /* Found */
404             return E;
405         }
406         /* Not found, next entry in hash chain */
407         E = E->NextHash;
408     }
409
410     /* Not found */
411     return 0;
412 }
413
414
415
416 static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
417 /* Find the symbol with the given name in the table tree that starts with T */
418 {
419     /* Get the hash over the name */
420     unsigned Hash = HashStr (Name);
421
422     /* Check all symbol tables for the symbol */
423     while (Tab) {
424         /* Try to find the symbol in this table */
425         SymEntry* E = FindSymInTable (Tab, Name, Hash);
426
427         /* Bail out if we found it */
428         if (E != 0) {
429             return E;
430         }
431
432         /* Repeat the search in the next higher lexical level */
433         Tab = Tab->PrevTab;
434     }
435
436     /* Not found */
437     return 0;
438 }
439
440
441
442 SymEntry* FindSym (const char* Name)
443 /* Find the symbol with the given name */
444 {
445     return FindSymInTree (SymTab, Name);
446 }
447
448
449
450 SymEntry* FindGlobalSym (const char* Name)
451 /* Find the symbol with the given name in the global symbol table only */
452 {
453     return FindSymInTable (SymTab0, Name, HashStr (Name));
454 }
455
456
457
458 SymEntry* FindLocalSym (const char* Name)
459 /* Find the symbol with the given name in the current symbol table only */
460 {
461     return FindSymInTable (SymTab, Name, HashStr (Name));
462 }
463
464
465
466 SymEntry* FindTagSym (const char* Name)
467 /* Find the symbol with the given name in the tag table */
468 {
469     return FindSymInTree (TagTab, Name);
470 }
471
472
473
474 SymEntry* FindStructField (const type* Type, const char* Name)
475 /* Find a struct field in the fields list */
476 {
477     SymEntry* Field = 0;
478
479     /* The given type may actually be a pointer to struct */
480     if (Type[0] == T_PTR) {
481         ++Type;
482     }
483
484     /* Non-structs do not have any struct fields... */
485     if (IsClassStruct (Type)) {
486
487         const SymTable* Tab;
488
489         /* Get a pointer to the struct/union type */
490         const SymEntry* Struct = (const SymEntry*) Decode (Type+1);
491         CHECK (Struct != 0);
492
493         /* Get the field symbol table from the struct entry.
494          * Beware: The table may not exist.
495          */
496         Tab = Struct->V.S.SymTab;
497
498         /* Now search in the struct symbol table */
499         if (Tab) {
500             Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
501         }
502     }
503
504     return Field;
505 }
506
507
508
509 /*****************************************************************************/
510 /*                       Add stuff to the symbol table                       */
511 /*****************************************************************************/
512
513
514
515 static void AddSymEntry (SymTable* T, SymEntry* S)
516 /* Add a symbol to a symbol table */
517 {
518     /* Get the hash value for the name */
519     unsigned Hash = HashStr (S->Name) % T->Size;
520
521     /* Insert the symbol into the list of all symbols in this level */
522     if (T->SymTail) {
523         T->SymTail->NextSym = S;
524     }
525     S->PrevSym = T->SymTail;
526     T->SymTail = S;
527     if (T->SymHead == 0) {
528         /* First symbol */
529         T->SymHead = S;
530     }
531     T->SymCount++;
532
533     /* Insert the symbol into the hash chain */
534     S->NextHash  = T->Tab[Hash];
535     T->Tab[Hash] = S;
536
537     /* Tell the symbol in which table it is */
538     S->Owner = T;
539 }
540
541
542
543 SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab)
544 /* Add a struct/union entry and return it */
545 {
546     /* Do we have an entry with this name already? */
547     SymEntry* Entry = FindSymInTable (TagTab, Name, HashStr (Name));
548     if (Entry) {
549
550         /* We do have an entry. This may be a forward, so check it. */
551         if ((Entry->Flags & SC_STRUCT) == 0) {
552             /* Existing symbol is not a struct */
553             Error ("Symbol `%s' is already different kind", Name);
554         } else if (Size > 0 && Entry->V.S.Size > 0) {
555             /* Both structs are definitions. */
556             Error ("Multiple definition for `%s'", Name);
557         } else {
558             /* Define the struct size if it is given */
559             if (Size > 0) {
560                 Entry->V.S.SymTab = Tab;
561                 Entry->V.S.Size   = Size;
562             }
563         }
564
565     } else {
566
567         /* Create a new entry */
568         Entry = NewSymEntry (Name, SC_STRUCT);
569
570         /* Set the struct data */
571         Entry->V.S.SymTab = Tab;
572         Entry->V.S.Size   = Size;
573
574         /* Add it to the current table */
575         AddSymEntry (TagTab, Entry);
576     }
577
578     /* Return the entry */
579     return Entry;
580 }
581
582
583
584 SymEntry* AddConstSym (const char* Name, const type* Type, unsigned Flags, long Val)
585 /* Add an constant symbol to the symbol table and return it */
586 {
587     /* Do we have an entry with this name already? */
588     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
589     if (Entry) {
590         if ((Entry->Flags & SC_CONST) != SC_CONST) {
591             Error ("Symbol `%s' is already different kind", Name);
592         } else {
593             Error ("Multiple definition for `%s'", Name);
594         }
595         return Entry;
596     }
597
598     /* Create a new entry */
599     Entry = NewSymEntry (Name, Flags);
600
601     /* Enum values are ints */
602     Entry->Type = TypeDup (Type);
603
604     /* Set the enum data */
605     Entry->V.ConstVal = Val;
606
607     /* Add the entry to the symbol table */
608     AddSymEntry (SymTab, Entry);
609
610     /* Return the entry */
611     return Entry;
612 }
613
614
615
616 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
617 /* Add a goto label to the label table */
618 {
619     /* Do we have an entry with this name already? */
620     SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
621     if (Entry) {
622
623         if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) {
624             /* Trying to define the label more than once */
625             Error ("Label `%s' is defined more than once", Name);
626         }
627         Entry->Flags |= Flags;
628
629     } else {
630
631         /* Create a new entry */
632         Entry = NewSymEntry (Name, SC_LABEL | Flags);
633
634         /* Set a new label number */
635         Entry->V.Label = GetLocalLabel ();
636
637         /* Add the entry to the label table */
638         AddSymEntry (LabelTab, Entry);
639
640     }
641
642     /* Return the entry */
643     return Entry;
644 }
645
646
647
648 SymEntry* AddLocalSym (const char* Name, const type* Type, unsigned Flags, int Offs)
649 /* Add a local symbol and return the symbol entry */
650 {
651     /* Do we have an entry with this name already? */
652     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
653     if (Entry) {
654
655         /* We have a symbol with this name already */
656         Error ("Multiple definition for `%s'", Name);
657
658     } else {
659
660         /* Create a new entry */
661         Entry = NewSymEntry (Name, Flags);
662
663         /* Set the symbol attributes */
664         Entry->Type   = TypeDup (Type);
665         if ((Flags & SC_AUTO) == SC_AUTO) {
666             Entry->V.Offs = Offs;
667         } else if ((Flags & SC_REGISTER) == SC_REGISTER) {
668             Entry->V.R.RegOffs  = Offs;
669             Entry->V.R.SaveOffs = oursp;        /* ### Cleaner! */
670         } else if ((Flags & SC_STATIC) == SC_STATIC) {
671             Entry->V.Label = Offs;
672         } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
673             Entry->V.Offs = Offs;
674         } else {
675             Internal ("Invalid flags in AddLocalSym: %04X", Flags);
676         }
677
678         /* Add the entry to the symbol table */
679         AddSymEntry (SymTab, Entry);
680
681     }
682
683     /* Return the entry */
684     return Entry;
685 }
686
687
688
689 SymEntry* AddGlobalSym (const char* Name, const type* Type, unsigned Flags)
690 /* Add an external or global symbol to the symbol table and return the entry */
691 {
692     /* There is some special handling for functions, so check if it is one */
693     int IsFunc = IsTypeFunc (Type);
694
695     /* Functions must be inserted in the global symbol table */
696     SymTable* Tab = IsFunc? SymTab0 : SymTab;
697
698     /* Do we have an entry with this name already? */
699     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
700     if (Entry) {
701
702         type* EType;
703
704         /* We have a symbol with this name already */
705         if (Entry->Flags & SC_TYPE) {
706             Error ("Multiple definition for `%s'", Name);
707             return Entry;
708         }
709
710         /* Get the type string of the existing symbol */
711         EType = Entry->Type;
712
713         /* If we are handling arrays, the old entry or the new entry may be an
714          * incomplete declaration. Accept this, and if the exsting entry is
715          * incomplete, complete it.
716          */
717         if (IsTypeArray (Type) && IsTypeArray (EType)) {
718
719             /* Get the array sizes */
720             long Size  = GetElementCount (Type);
721             long ESize = GetElementCount (EType);
722
723             if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
724                 TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) < TC_EQUAL) {
725                 /* Types not identical: Conflicting types */
726                 Error ("Conflicting types for `%s'", Name);
727                 return Entry;
728             } else {
729                 /* Check if we have a size in the existing definition */
730                 if (ESize == UNSPECIFIED) {                           
731                     /* Existing, size not given, use size from new def */
732                     Encode (EType + 1, Size);
733                 }
734             }
735
736         } else {
737             /* New type must be identical */
738             if (TypeCmp (EType, Type) < TC_EQUAL) {
739                 Error ("Conflicting types for `%s'", Name);
740                 return Entry;
741             }
742
743             /* In case of a function, use the new type descriptor, since it
744              * contains pointers to the new symbol tables that are needed if
745              * an actual function definition follows.
746              */
747             if (IsFunc) {
748                 /* Get the function descriptor from the new type */
749                 FuncDesc* F = GetFuncDesc (Type);
750                 /* Use this new function descriptor */
751                 Entry->V.F.Func = F;
752                 EncodePtr (EType+1, F);
753             }
754         }
755
756         /* Add the new flags */
757         Entry->Flags |= Flags;
758
759     } else {
760
761         /* Create a new entry */
762         Entry = NewSymEntry (Name, Flags);
763
764         /* Set the symbol attributes */
765         Entry->Type = TypeDup (Type);
766
767         /* If this is a function, set the function descriptor and clear
768          * additional fields.
769          */
770         if (IsFunc) {
771             Entry->V.F.Func = GetFuncDesc (Entry->Type);
772             Entry->V.F.Seg  = 0;
773         }
774
775         /* Add the entry to the symbol table */
776         AddSymEntry (Tab, Entry);
777     }
778
779     /* Return the entry */
780     return Entry;
781 }
782
783
784
785 /*****************************************************************************/
786 /*                                   Code                                    */
787 /*****************************************************************************/
788
789
790
791 SymTable* GetSymTab (void)
792 /* Return the current symbol table */
793 {
794     return SymTab;
795 }
796
797
798
799 SymTable* GetGlobalSymTab (void)
800 /* Return the global symbol table */
801 {
802     return SymTab0;
803 }
804
805
806
807 int SymIsLocal (SymEntry* Sym)
808 /* Return true if the symbol is defined in the highest lexical level */
809 {
810     return (Sym->Owner == SymTab || Sym->Owner == TagTab);
811 }
812
813
814
815 void MakeZPSym (const char* Name)
816 /* Mark the given symbol as zero page symbol */
817 {
818     /* Get the symbol table entry */
819     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
820
821     /* Mark the symbol as zeropage */
822     if (Entry) {
823         Entry->Flags |= SC_ZEROPAGE;
824     } else {
825         Error ("Undefined symbol: `%s'", Name);
826     }
827 }
828
829
830
831 void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...)
832 /* Write the symbol table to the given file */
833 {
834     unsigned Len;
835     const SymEntry* Entry;
836
837     /* Print the header */
838     va_list ap;
839     va_start (ap, Header);
840     fputc ('\n', F);
841     Len = vfprintf (F, Header, ap);
842     va_end (ap);
843     fputc ('\n', F);
844
845     /* Underline the header */
846     while (Len--) {
847         fputc ('=', F);
848     }
849     fputc ('\n', F);
850
851     /* Dump the table */
852     Entry = Tab->SymHead;
853     if (Entry == 0) {
854         fprintf (F, "(empty)\n");
855     } else {
856         while (Entry) {
857             DumpSymEntry (F, Entry);
858             Entry = Entry->NextSym;
859         }
860     }
861     fprintf (F, "\n\n\n");
862 }
863
864
865
866 void EmitExternals (void)
867 /* Write import/export statements for external symbols */
868 {
869     SymEntry* Entry;
870
871     Entry = SymTab->SymHead;
872     while (Entry) {
873         unsigned Flags = Entry->Flags;
874         if (Flags & SC_EXTERN) {
875             /* Only defined or referenced externs */
876             if (SymIsRef (Entry) && !SymIsDef (Entry)) {
877                 /* An import */
878                 g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
879             } else if (SymIsDef (Entry)) {
880                 /* An export */
881                 g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
882             }
883         }
884         Entry = Entry->NextSym;
885     }
886 }
887
888
889