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