]> git.sur5r.net Git - cc65/blob - src/cc65/symtab.c
Renamed attribute handling functions. Added SymHasAttr().
[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-2009, 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 "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 "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         } else if ((Flags & SC_STATIC) == SC_STATIC) {
714             /* Generate the assembler name from the label number */
715             Entry->V.Label = Offs;
716             Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
717         } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
718             Entry->V.Offs = Offs;
719         } else {
720             Internal ("Invalid flags in AddLocalSym: %04X", Flags);
721         }
722
723         /* Add the entry to the symbol table */
724         AddSymEntry (SymTab, Entry);
725
726     }
727
728     /* Return the entry */
729     return Entry;
730 }
731
732
733
734 SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
735 /* Add an external or global symbol to the symbol table and return the entry */
736 {
737     /* There is some special handling for functions, so check if it is one */
738     int IsFunc = IsTypeFunc (T);
739
740     /* Functions must be inserted in the global symbol table */
741     SymTable* Tab = IsFunc? SymTab0 : SymTab;
742
743     /* Do we have an entry with this name already? */
744     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
745     if (Entry) {
746
747         Type* EType;
748
749         /* We have a symbol with this name already */
750         if (Entry->Flags & SC_TYPE) {
751             Error ("Multiple definition for `%s'", Name);
752             return Entry;
753         }
754
755         /* Get the type string of the existing symbol */
756         EType = Entry->Type;
757
758         /* If we are handling arrays, the old entry or the new entry may be an
759          * incomplete declaration. Accept this, and if the exsting entry is
760          * incomplete, complete it.
761          */
762         if (IsTypeArray (T) && IsTypeArray (EType)) {
763
764             /* Get the array sizes */
765             long Size  = GetElementCount (T);
766             long ESize = GetElementCount (EType);
767
768             if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
769                 TypeCmp (T + 1, EType + 1) < TC_EQUAL) {
770                 /* Types not identical: Conflicting types */
771                 Error ("Conflicting types for `%s'", Name);
772                 return Entry;
773             } else {
774                 /* Check if we have a size in the existing definition */
775                 if (ESize == UNSPECIFIED) {
776                     /* Existing, size not given, use size from new def */
777                     SetElementCount (EType, Size);
778                 }
779             }
780
781         } else {
782             /* New type must be identical */
783             if (TypeCmp (EType, T) < TC_EQUAL) {
784                 Error ("Conflicting types for `%s'", Name);
785                 return Entry;
786             }
787
788             /* In case of a function, use the new type descriptor, since it
789              * contains pointers to the new symbol tables that are needed if
790              * an actual function definition follows. Be sure not to use the
791              * new descriptor if it contains a function declaration with an
792              * empty parameter list.
793              */
794             if (IsFunc) {
795                 /* Get the function descriptor from the new type */
796                 FuncDesc* F = GetFuncDesc (T);
797                 /* Use this new function descriptor if it doesn't contain
798                  * an empty parameter list.
799                  */
800                 if ((F->Flags & FD_EMPTY) == 0) {
801                     Entry->V.F.Func = F;
802                     SetFuncDesc (EType, F);
803                 }
804             }
805         }
806
807         /* Add the new flags */
808         Entry->Flags |= Flags;
809
810     } else {
811
812         unsigned Len;
813
814         /* Create a new entry */
815         Entry = NewSymEntry (Name, Flags);
816
817         /* Set the symbol attributes */
818         Entry->Type = TypeDup (T);
819
820         /* If this is a function, set the function descriptor and clear
821          * additional fields.
822          */
823         if (IsFunc) {
824             Entry->V.F.Func = GetFuncDesc (Entry->Type);
825             Entry->V.F.Seg  = 0;
826         }
827
828         /* Add the assembler name of the symbol */
829         Len = strlen (Name);
830         Entry->AsmName = xmalloc (Len + 2);
831         Entry->AsmName[0] = '_';
832         memcpy (Entry->AsmName+1, Name, Len+1);
833
834         /* Add the entry to the symbol table */
835         AddSymEntry (Tab, Entry);
836     }
837
838     /* Return the entry */
839     return Entry;
840 }
841
842
843
844 /*****************************************************************************/
845 /*                                   Code                                    */
846 /*****************************************************************************/
847
848
849
850 SymTable* GetSymTab (void)
851 /* Return the current symbol table */
852 {
853     return SymTab;
854 }
855
856
857
858 SymTable* GetGlobalSymTab (void)
859 /* Return the global symbol table */
860 {
861     return SymTab0;
862 }
863
864
865
866 int SymIsLocal (SymEntry* Sym)
867 /* Return true if the symbol is defined in the highest lexical level */
868 {
869     return (Sym->Owner == SymTab || Sym->Owner == TagTab);
870 }
871
872
873
874 void MakeZPSym (const char* Name)
875 /* Mark the given symbol as zero page symbol */
876 {
877     /* Get the symbol table entry */
878     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
879
880     /* Mark the symbol as zeropage */
881     if (Entry) {
882         Entry->Flags |= SC_ZEROPAGE;
883     } else {
884         Error ("Undefined symbol: `%s'", Name);
885     }
886 }
887
888
889
890 void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...)
891 /* Write the symbol table to the given file */
892 {
893     unsigned Len;
894     const SymEntry* Entry;
895
896     /* Print the header */
897     va_list ap;
898     va_start (ap, Header);
899     fputc ('\n', F);
900     Len = vfprintf (F, Header, ap);
901     va_end (ap);
902     fputc ('\n', F);
903
904     /* Underline the header */
905     while (Len--) {
906         fputc ('=', F);
907     }
908     fputc ('\n', F);
909
910     /* Dump the table */
911     Entry = Tab->SymHead;
912     if (Entry == 0) {
913         fprintf (F, "(empty)\n");
914     } else {
915         while (Entry) {
916             DumpSymEntry (F, Entry);
917             Entry = Entry->NextSym;
918         }
919     }
920     fprintf (F, "\n\n\n");
921 }
922
923
924
925 void EmitExternals (void)
926 /* Write import/export statements for external symbols */
927 {
928     SymEntry* Entry;
929
930     Entry = SymTab->SymHead;
931     while (Entry) {
932         unsigned Flags = Entry->Flags;
933         if (Flags & SC_EXTERN) {
934             /* Only defined or referenced externs */
935             if (SymIsRef (Entry) && !SymIsDef (Entry)) {
936                 /* An import */
937                 g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
938             } else if (SymIsDef (Entry)) {
939                 /* An export */
940                 g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
941             }
942         }
943         Entry = Entry->NextSym;
944     }
945 }
946
947
948