]> git.sur5r.net Git - cc65/blob - src/cc65/symtab.c
Changed multi-line C comments into another style.
[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-2013, 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 Type, unsigned Size, SymTable* Tab)
547 /* Add a struct/union entry and return it */
548 {
549     SymEntry* Entry;
550
551     /* Type must be struct or union */
552     PRECONDITION (Type == SC_STRUCT || Type == SC_UNION);
553
554     /* Do we have an entry with this name already? */
555     Entry = FindSymInTable (TagTab, Name, HashStr (Name));
556     if (Entry) {
557
558         /* We do have an entry. This may be a forward, so check it. */
559         if ((Entry->Flags & SC_TYPEMASK) != Type) {
560             /* Existing symbol is not a struct */
561             Error ("Symbol `%s' is already different kind", Name);
562         } else if (Size > 0 && Entry->V.S.Size > 0) {
563             /* Both structs are definitions. */
564             Error ("Multiple definition for `%s'", Name);
565         } else {
566             /* Define the struct size if it is given */
567             if (Size > 0) {
568                 Entry->V.S.SymTab = Tab;
569                 Entry->V.S.Size   = Size;
570             }
571         }
572
573     } else {
574
575         /* Create a new entry */
576         Entry = NewSymEntry (Name, Type);
577
578         /* Set the struct data */
579         Entry->V.S.SymTab = Tab;
580         Entry->V.S.Size   = Size;
581
582         /* Add it to the current table */
583         AddSymEntry (TagTab, Entry);
584     }
585
586     /* Return the entry */
587     return Entry;
588 }
589
590
591
592 SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width)
593 /* Add a bit field to the local symbol table and return the symbol entry */
594 {
595     /* Do we have an entry with this name already? */
596     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
597     if (Entry) {
598
599         /* We have a symbol with this name already */
600         Error ("Multiple definition for `%s'", Name);
601
602     } else {
603
604         /* Create a new entry */
605         Entry = NewSymEntry (Name, SC_BITFIELD);
606
607         /* Set the symbol attributes. Bit-fields are always of type unsigned */
608         Entry->Type         = type_uint;
609         Entry->V.B.Offs     = Offs;
610         Entry->V.B.BitOffs  = BitOffs;
611         Entry->V.B.BitWidth = Width;
612
613         /* Add the entry to the symbol table */
614         AddSymEntry (SymTab, Entry);
615
616     }
617
618     /* Return the entry */
619     return Entry;
620 }
621
622
623
624 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
625 /* Add an constant symbol to the symbol table and return it */
626 {
627     /* Enums must be inserted in the global symbol table */
628     SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab;
629
630     /* Do we have an entry with this name already? */
631     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
632     if (Entry) {
633         if ((Entry->Flags & SC_CONST) != SC_CONST) {
634             Error ("Symbol `%s' is already different kind", Name);
635         } else {
636             Error ("Multiple definition for `%s'", Name);
637         }
638         return Entry;
639     }
640
641     /* Create a new entry */
642     Entry = NewSymEntry (Name, Flags);
643
644     /* Enum values are ints */
645     Entry->Type = TypeDup (T);
646
647     /* Set the enum data */
648     Entry->V.ConstVal = Val;
649
650     /* Add the entry to the symbol table */
651     AddSymEntry (Tab, Entry);
652
653     /* Return the entry */
654     return Entry;
655 }
656
657
658
659 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
660 /* Add a goto label to the label table */
661 {
662     /* Do we have an entry with this name already? */
663     SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
664     if (Entry) {
665
666         if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) {
667             /* Trying to define the label more than once */
668             Error ("Label `%s' is defined more than once", Name);
669         }
670         Entry->Flags |= Flags;
671
672     } else {
673
674         /* Create a new entry */
675         Entry = NewSymEntry (Name, SC_LABEL | Flags);
676
677         /* Set a new label number */
678         Entry->V.Label = GetLocalLabel ();
679
680         /* Generate the assembler name of the label */
681         Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
682
683         /* Add the entry to the label table */
684         AddSymEntry (LabelTab, Entry);
685
686     }
687
688     /* Return the entry */
689     return Entry;
690 }
691
692
693
694 SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs)
695 /* Add a local symbol and return the symbol entry */
696 {
697     /* Do we have an entry with this name already? */
698     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
699     if (Entry) {
700
701         /* We have a symbol with this name already */
702         Error ("Multiple definition for `%s'", Name);
703
704     } else {
705
706         /* Create a new entry */
707         Entry = NewSymEntry (Name, Flags);
708
709         /* Set the symbol attributes */
710         Entry->Type = TypeDup (T);
711         if ((Flags & SC_AUTO) == SC_AUTO) {
712             Entry->V.Offs = Offs;
713         } else if ((Flags & SC_REGISTER) == SC_REGISTER) {
714             Entry->V.R.RegOffs  = Offs;
715             Entry->V.R.SaveOffs = StackPtr;
716         } else if ((Flags & SC_EXTERN) == SC_EXTERN) {
717             Entry->V.Label = Offs;
718             SymSetAsmName (Entry);
719         } else if ((Flags & SC_STATIC) == SC_STATIC) {
720             /* Generate the assembler name from the label number */
721             Entry->V.Label = Offs;
722             Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
723         } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
724             Entry->V.Offs = Offs;
725         } else {
726             Internal ("Invalid flags in AddLocalSym: %04X", Flags);
727         }
728
729         /* Add the entry to the symbol table */
730         AddSymEntry (SymTab, Entry);
731
732     }
733
734     /* Return the entry */
735     return Entry;
736 }
737
738
739
740 SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
741 /* Add an external or global symbol to the symbol table and return the entry */
742 {
743     /* There is some special handling for functions, so check if it is one */
744     int IsFunc = IsTypeFunc (T);
745
746     /* Functions must be inserted in the global symbol table */
747     SymTable* Tab = IsFunc? SymTab0 : SymTab;
748
749     /* Do we have an entry with this name already? */
750     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
751     if (Entry) {
752
753         Type* EType;
754
755         /* We have a symbol with this name already */
756         if (Entry->Flags & SC_TYPE) {
757             Error ("Multiple definition for `%s'", Name);
758             return Entry;
759         }
760
761         /* Get the type string of the existing symbol */
762         EType = Entry->Type;
763
764         /* If we are handling arrays, the old entry or the new entry may be an
765         ** incomplete declaration. Accept this, and if the exsting entry is
766         ** incomplete, complete it.
767         */
768         if (IsTypeArray (T) && IsTypeArray (EType)) {
769
770             /* Get the array sizes */
771             long Size  = GetElementCount (T);
772             long ESize = GetElementCount (EType);
773
774             if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
775                 TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
776                 /* Types not identical: Conflicting types */
777                 Error ("Conflicting types for `%s'", Name);
778                 return Entry;
779             } else {
780                 /* Check if we have a size in the existing definition */
781                 if (ESize == UNSPECIFIED) {
782                     /* Existing, size not given, use size from new def */
783                     SetElementCount (EType, Size);
784                 }
785             }
786
787         } else {
788             /* New type must be identical */
789             if (TypeCmp (EType, T) < TC_EQUAL) {
790                 Error ("Conflicting types for `%s'", Name);
791                 return Entry;
792             }
793
794             /* In case of a function, use the new type descriptor, since it
795             ** contains pointers to the new symbol tables that are needed if
796             ** an actual function definition follows. Be sure not to use the
797             ** new descriptor if it contains a function declaration with an
798             ** empty parameter list.
799             */
800             if (IsFunc) {
801                 /* Get the function descriptor from the new type */
802                 FuncDesc* F = GetFuncDesc (T);
803                 /* Use this new function descriptor if it doesn't contain
804                 ** an empty parameter list.
805                 */
806                 if ((F->Flags & FD_EMPTY) == 0) {
807                     Entry->V.F.Func = F;
808                     SetFuncDesc (EType, F);
809                 }
810             }
811         }
812
813         /* Add the new flags */
814         Entry->Flags |= Flags;
815
816     } else {
817
818         /* Create a new entry */
819         Entry = NewSymEntry (Name, Flags);
820
821         /* Set the symbol attributes */
822         Entry->Type = TypeDup (T);
823
824         /* If this is a function, set the function descriptor and clear
825         ** additional fields.
826         */
827         if (IsFunc) {
828             Entry->V.F.Func = GetFuncDesc (Entry->Type);
829             Entry->V.F.Seg  = 0;
830         }
831
832         /* Add the assembler name of the symbol */
833         SymSetAsmName (Entry);
834
835         /* Add the entry to the symbol table */
836         AddSymEntry (Tab, Entry);
837     }
838
839     /* Return the entry */
840     return Entry;
841 }
842
843
844
845 /*****************************************************************************/
846 /*                                   Code                                    */
847 /*****************************************************************************/
848
849
850
851 SymTable* GetSymTab (void)
852 /* Return the current symbol table */
853 {
854     return SymTab;
855 }
856
857
858
859 SymTable* GetGlobalSymTab (void)
860 /* Return the global symbol table */
861 {
862     return SymTab0;
863 }
864
865
866
867 int SymIsLocal (SymEntry* Sym)
868 /* Return true if the symbol is defined in the highest lexical level */
869 {
870     return (Sym->Owner == SymTab || Sym->Owner == TagTab);
871 }
872
873
874
875 void MakeZPSym (const char* Name)
876 /* Mark the given symbol as zero page symbol */
877 {
878     /* Get the symbol table entry */
879     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
880
881     /* Mark the symbol as zeropage */
882     if (Entry) {
883         Entry->Flags |= SC_ZEROPAGE;
884     } else {
885         Error ("Undefined symbol: `%s'", Name);
886     }
887 }
888
889
890
891 void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...)
892 /* Write the symbol table to the given file */
893 {
894     unsigned Len;
895     const SymEntry* Entry;
896
897     /* Print the header */
898     va_list ap;
899     va_start (ap, Header);
900     fputc ('\n', F);
901     Len = vfprintf (F, Header, ap);
902     va_end (ap);
903     fputc ('\n', F);
904
905     /* Underline the header */
906     while (Len--) {
907         fputc ('=', F);
908     }
909     fputc ('\n', F);
910
911     /* Dump the table */
912     Entry = Tab->SymHead;
913     if (Entry == 0) {
914         fprintf (F, "(empty)\n");
915     } else {
916         while (Entry) {
917             DumpSymEntry (F, Entry);
918             Entry = Entry->NextSym;
919         }
920     }
921     fprintf (F, "\n\n\n");
922 }
923
924
925
926 void EmitExternals (void)
927 /* Write import/export statements for external symbols */
928 {
929     SymEntry* Entry;
930
931     Entry = SymTab->SymHead;
932     while (Entry) {
933         unsigned Flags = Entry->Flags;
934         if (Flags & SC_EXTERN) {
935             /* Only defined or referenced externs */
936             if (SymIsRef (Entry) && !SymIsDef (Entry)) {
937                 /* An import */
938                 g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
939             } else if (SymIsDef (Entry)) {
940                 /* An export */
941                 g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
942             }
943         }
944         Entry = Entry->NextSym;
945     }
946 }
947
948
949
950 void EmitDebugInfo (void)
951 /* Emit debug infos for the locals of the current scope */
952 {
953     const char* Head;
954     const SymEntry* Sym;
955
956     /* Output info for locals if enabled */
957     if (DebugInfo) {
958         /* For cosmetic reasons in the output file, we will insert two tabs
959         ** on global level and just one on local level.
960         */
961         if (LexicalLevel == LEX_LEVEL_GLOBAL) {
962             Head = "\t.dbg\t\tsym";
963         } else {
964             Head = "\t.dbg\tsym";
965         }
966         Sym = SymTab->SymHead;
967         while (Sym) {
968             if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
969                 if (Sym->Flags & SC_AUTO) {
970                     AddTextLine ("%s, \"%s\", \"00\", auto, %d",
971                                  Head, Sym->Name, Sym->V.Offs);
972                 } else if (Sym->Flags & SC_REGISTER) {
973                     AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d",
974                                  Head, Sym->Name, Sym->V.R.RegOffs);
975
976                 } else if (SymIsRef (Sym) && !SymIsDef (Sym)) {
977                     AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"",
978                                  Head, Sym->Name,
979                                  (Sym->Flags & SC_EXTERN)? "extern" : "static",
980                                  Sym->AsmName);
981                 }
982             }
983             Sym = Sym->NextSym;
984         }
985     }
986 }