]> git.sur5r.net Git - cc65/blob - src/cc65/symtab.c
6db3fc4a184be5dc46c2621ad82b62fe6d781849
[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     Ullrich von Bassewitz                                        */
10 /*              Wacholderweg 14                                              */
11 /*              D-70597 Stuttgart                                            */
12 /* EMail:       uz@musoftware.de                                             */
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 #include "asmcode.h"
42 #include "asmlabel.h"
43 #include "check.h"
44 #include "codegen.h"
45 #include "datatype.h"
46 #include "declare.h"
47 #include "error.h"
48 #include "funcdesc.h"
49 #include "global.h"
50 #include "hashstr.h"
51 #include "io.h"
52 #include "mem.h"
53 #include "symentry.h"
54 #include "symtab.h"
55
56
57
58 /*****************************************************************************/
59 /*                                   Data                                    */
60 /*****************************************************************************/
61
62
63
64 /* An empty symbol table */
65 SymTable        EmptySymTab = {
66     0,          /* PrevTab */
67     0,          /* SymHead */
68     0,          /* SymTail */
69     0,          /* SymCount */
70     1,          /* Size */
71     { 0 }       /* Tab[1] */
72 };
73
74 /* Symbol table sizes */
75 #define SYMTAB_SIZE_GLOBAL      211U
76 #define SYMTAB_SIZE_FUNCTION     29U
77 #define SYMTAB_SIZE_BLOCK        13U
78 #define SYMTAB_SIZE_STRUCT       19U
79 #define SYMTAB_SIZE_LABEL         7U
80
81 /* Predefined lexical levels */
82 #define LEX_LEVEL_GLOBAL        1U
83
84 /* The current and root symbol tables */
85 static unsigned         LexicalLevel    = 0;    /* For safety checks */
86 static SymTable*        SymTab0         = 0;
87 static SymTable*        SymTab          = 0;
88 static SymTable*        StructTab0      = 0;
89 static SymTable*        StructTab       = 0;
90 static SymTable*        EnumTab0        = 0;
91 static SymTable*        EnumTab         = 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 ((Flags & SC_TYPEDEF) != SC_TYPEDEF) {
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 ((Flags & SC_DEF) && !(Flags & SC_REF)) {
166                     if (Flags & SC_PARAM) {
167                         Warning (WARN_UNUSED_PARM, Entry->Name);
168                     } else {
169                         Warning (WARN_UNUSED_ITEM, Entry->Name);
170                     }
171                 }
172             }
173     
174             /* If the entry is a label, check if it was defined in the function */
175             if (Flags & SC_LABEL) {
176                 if ((Flags & SC_DEF) == 0) {
177                     /* Undefined label */
178                     Error (ERR_UNDEFINED_LABEL, Entry->Name);
179                 } else if ((Flags & SC_REF) == 0) {
180                     /* Defined but not used */
181                     Warning (WARN_UNUSED_ITEM, Entry->Name);
182                 }
183             }
184     
185         }
186
187         /* Next entry */
188         Entry = Entry->NextSym;
189     }
190 }
191
192
193
194 /*****************************************************************************/
195 /*                        Handling of lexical levels                         */
196 /*****************************************************************************/
197
198
199
200 void EnterGlobalLevel (void)
201 /* Enter the program global lexical level */
202 {
203     /* Safety */
204     PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL);
205
206     /* Create and assign the symbol table */
207     SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
208
209     /* Create and assign the struct table */
210     StructTab0 = StructTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
211
212     /* Create and assign the enum table */
213     EnumTab0 = EnumTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
214 }
215
216
217
218 void LeaveGlobalLevel (void)
219 /* Leave the program global lexical level */
220 {
221     /* Safety */
222     PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL);
223
224     /* Check the tables */
225     CheckSymTable (SymTab0);
226
227     /* Dump the tables if requested */
228     if (Debug) {
229         PrintSymTable (SymTab0, stdout, "Global symbol table");
230         PrintSymTable (StructTab0, stdout, "Global struct table");
231         PrintSymTable (EnumTab0, stdout, "Global enum table");
232     }
233
234     /* Don't delete the symbol and struct tables! */
235     SymTab0     = SymTab    = 0;
236     StructTab0  = StructTab = 0;
237     EnumTab0    = EnumTab   = 0;
238 }
239
240
241
242 void EnterFunctionLevel (void)
243 /* Enter function lexical level */
244 {
245     SymTable* S;
246
247     /* New lexical level */
248     ++LexicalLevel;
249
250     /* Get a new symbol table and make it current */
251     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
252     S->PrevTab = SymTab;
253     SymTab     = S;
254
255     /* Get a new struct table and make it current */
256     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
257     S->PrevTab = StructTab;
258     StructTab  = S;
259
260     /* Get a new enum table and make it current */
261     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
262     S->PrevTab = EnumTab;
263     EnumTab    = S;
264
265     /* Create and assign a new label table */
266     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
267 }
268
269
270
271 void RememberFunctionLevel (struct FuncDesc* F)
272 /* Remember the symbol tables for the level and leave the level without checks */
273 {
274     /* Leave the lexical level */
275     --LexicalLevel;
276
277     /* Remember the tables */
278     F->SymTab    = SymTab;
279     F->StructTab = StructTab;
280     F->EnumTab   = EnumTab;
281
282     /* Don't delete the tables */
283     SymTab    = SymTab->PrevTab;
284     StructTab = StructTab->PrevTab;
285     EnumTab   = EnumTab->PrevTab;
286 }
287
288
289
290 void ReenterFunctionLevel (struct FuncDesc* F)
291 /* Reenter the function lexical level using the existing tables from F */
292 {
293     /* New lexical level */
294     ++LexicalLevel;
295
296     /* Make the tables current again */
297     F->SymTab->PrevTab = SymTab;
298     SymTab = F->SymTab;
299
300     F->StructTab->PrevTab = StructTab;
301     StructTab = F->StructTab;
302
303     F->EnumTab->PrevTab = EnumTab;
304     EnumTab = F->EnumTab;
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     StructTab = StructTab->PrevTab;
330     EnumTab   = EnumTab->PrevTab;
331     LabelTab  = 0;
332 }
333
334
335
336 void EnterBlockLevel (void)
337 /* Enter a nested block in a function */
338 {
339     SymTable* S;
340
341     /* New lexical level */
342     ++LexicalLevel;
343
344     /* Get a new symbol table and make it current */
345     S = NewSymTable (SYMTAB_SIZE_BLOCK);
346     S->PrevTab  = SymTab;
347     SymTab      = S;
348
349     /* Get a new struct table and make it current */
350     S = NewSymTable (SYMTAB_SIZE_BLOCK);
351     S->PrevTab  = StructTab;
352     StructTab   = S;
353
354     /* Get a new enum table and make it current */
355     S = NewSymTable (SYMTAB_SIZE_BLOCK);
356     S->PrevTab = EnumTab;
357     EnumTab    = S;
358 }
359
360
361
362 void LeaveBlockLevel (void)
363 /* Leave a nested block in a function */
364 {
365     /* Leave the lexical level */
366     --LexicalLevel;
367
368     /* Check the tables */
369     CheckSymTable (SymTab);
370
371     /* Don't delete the tables */
372     SymTab    = SymTab->PrevTab;
373     StructTab = StructTab->PrevTab;
374     EnumTab   = EnumTab->PrevTab;
375 }
376
377
378
379 void EnterStructLevel (void)
380 /* Enter a nested block for a struct definition */
381 {
382     SymTable* S;
383
384     /* Get a new symbol table and make it current. Note: Structs and enums
385      * nested in struct scope are NOT local to the struct but visible in the
386      * outside scope. So we will NOT create a new struct or enum table.
387      */
388     S = NewSymTable (SYMTAB_SIZE_BLOCK);
389     S->PrevTab  = SymTab;
390     SymTab      = S;
391 }
392
393
394
395 void LeaveStructLevel (void)
396 /* Leave a nested block for a struct definition */
397 {
398     /* Don't delete the table */
399     SymTab = SymTab->PrevTab;
400 }
401
402
403
404 /*****************************************************************************/
405 /*                              Find functions                               */
406 /*****************************************************************************/
407
408
409
410 static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash)
411 /* Search for an entry in one table */
412 {
413     /* Get the start of the hash chain */
414     SymEntry* E = T->Tab [Hash % T->Size];
415     while (E) {
416         /* Compare the name */
417         if (strcmp (E->Name, Name) == 0) {
418             /* Found */
419             return E;
420         }
421         /* Not found, next entry in hash chain */
422         E = E->NextHash;
423     }
424
425     /* Not found */
426     return 0;
427 }
428
429
430
431 static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name)
432 /* Find the symbol with the given name in the table tree that starts with T */
433 {
434     /* Get the hash over the name */
435     unsigned Hash = HashStr (Name);
436
437     /* Check all symbol tables for the symbol */
438     while (Tab) {
439         /* Try to find the symbol in this table */
440         SymEntry* E = FindSymInTable (Tab, Name, Hash);
441
442         /* Bail out if we found it */
443         if (E != 0) {
444             return E;
445         }
446
447         /* Repeat the search in the next higher lexical level */
448         Tab = Tab->PrevTab;
449     }
450
451     /* Not found */
452     return 0;
453 }
454
455
456
457 SymEntry* FindSym (const char* Name)
458 /* Find the symbol with the given name */
459 {
460     return FindSymInTree (SymTab, Name);
461 }
462
463
464
465 SymEntry* FindStructSym (const char* Name)
466 /* Find the symbol with the given name in the struct table */
467 {
468     return FindSymInTree (StructTab, Name);
469 }
470
471
472
473 SymEntry* FindEnumSym (const char* Name)
474 /* Find the symbol with the given name in the enum table */
475 {
476     return FindSymInTree (EnumTab, Name);
477 }
478
479
480
481 SymEntry* FindStructField (const type* Type, const char* Name)
482 /* Find a struct field in the fields list */
483 {
484     SymEntry* Field = 0;
485
486     /* The given type may actually be a pointer to struct */
487     if (Type[0] == T_PTR) {
488         ++Type;
489     }
490
491     /* Non-structs do not have any struct fields... */
492     if (IsStruct (Type)) {
493
494         const SymTable* Tab;
495
496         /* Get a pointer to the struct/union type */
497         const SymEntry* Struct = (const SymEntry*) Decode (Type+1);
498         CHECK (Struct != 0);
499
500         /* Get the field symbol table from the struct entry.
501          * Beware: The table may not exist.
502          */
503         Tab = Struct->V.S.SymTab;
504
505         /* Now search in the struct symbol table */
506         if (Tab) {
507             Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
508         }
509     }
510
511     return Field;
512 }
513
514
515
516 /*****************************************************************************/
517 /*                       Add stuff to the symbol table                       */
518 /*****************************************************************************/
519
520
521
522 static void AddSymEntry (SymTable* T, SymEntry* S)
523 /* Add a symbol to a symbol table */
524 {
525     /* Get the hash value for the name */
526     unsigned Hash = HashStr (S->Name) % T->Size;
527
528     /* Insert the symbol into the list of all symbols in this level */
529     if (T->SymTail) {
530         T->SymTail->NextSym = S;
531     }
532     S->PrevSym = T->SymTail;
533     T->SymTail = S;
534     if (T->SymHead == 0) {
535         /* First symbol */
536         T->SymHead = S;
537     }
538     T->SymCount++;
539
540     /* Insert the symbol into the hash chain */
541     S->NextHash  = T->Tab[Hash];
542     T->Tab[Hash] = S;
543
544     /* Tell the symbol in which table it is */
545     S->Owner = T;
546 }
547
548
549
550 SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab)
551 /* Add a struct/union entry and return it */
552 {
553     /* Do we have an entry with this name already? */
554     SymEntry* Entry = FindSymInTable (StructTab, Name, HashStr (Name));
555     if (Entry) {
556
557         /* We do have an entry. This may be a forward, so check it. */
558         if (Entry->Flags != SC_STRUCT) {
559             /* Existing symbol is not a struct */
560             Error (ERR_SYMBOL_KIND);
561         } else if (Size > 0 && Entry->V.S.Size > 0) {
562             /* Both structs are definitions. */
563             Error (ERR_MULTIPLE_DEFINITION, Name);
564         } else {
565             /* Define the struct size if it is given */
566             if (Size > 0) {
567                 Entry->V.S.SymTab = Tab;
568                 Entry->V.S.Size   = Size;
569             }
570         }
571
572     } else {
573
574         /* Create a new entry */
575         Entry = NewSymEntry (Name, SC_STRUCT);
576
577         /* Set the struct data */
578         Entry->V.S.SymTab = Tab;
579         Entry->V.S.Size   = Size;
580
581         /* Add it to the current table */
582         AddSymEntry (StructTab, Entry);
583     }
584
585     /* Return the entry */
586     return Entry;
587 }
588
589
590
591 SymEntry* AddEnumSym (const char* Name, int Val)
592 /* Add an enum symbol to the symbol table and return it */
593 {
594     /* Do we have an entry with this name already? */
595     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
596     if (Entry) {
597         if (Entry->Flags != SC_ENUM) {
598             Error (ERR_SYMBOL_KIND);
599         } else {
600             Error (ERR_MULTIPLE_DEFINITION, Name);
601         }
602         return Entry;
603     }
604
605     /* Create a new entry */
606     Entry = NewSymEntry (Name, SC_ENUM);
607
608     /* Enum values are ints */
609     Entry->Type = TypeDup (type_int);
610
611     /* Set the enum data */
612     Entry->V.EnumVal = Val;
613
614     /* Add the entry to the symbol table */
615     AddSymEntry (SymTab, Entry);
616
617     /* Return the entry */
618     return Entry;
619 }
620
621
622
623 SymEntry* AddLabelSym (const char* Name, unsigned Flags)
624 /* Add a goto label to the label table */
625 {
626     /* Do we have an entry with this name already? */
627     SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
628     if (Entry) {
629
630         if ((Entry->Flags & SC_DEF) != 0 && (Flags & SC_DEF) != 0) {
631             /* Trying to define the label more than once */
632             Error (ERR_MULTIPLE_DEFINITION, Name);
633         }
634         Entry->Flags |= Flags;
635
636     } else {
637
638         /* Create a new entry */
639         Entry = NewSymEntry (Name, SC_LABEL | Flags);
640
641         /* Set a new label number */
642         Entry->V.Label = GetLabel ();
643
644         /* Add the entry to the label table */
645         AddSymEntry (LabelTab, Entry);
646
647     }
648
649     /* Return the entry */
650     return Entry;
651 }
652
653
654
655 SymEntry* AddLocalSym (const char* Name, type* Type, unsigned Flags, int Offs)
656 /* Add a local symbol and return the symbol entry */
657 {
658     SymEntry* Entry;
659
660     /* Functions declared inside of functions do always have external linkage */
661     if (Type != 0 && IsFunc (Type)) {
662         if ((Flags & (SC_DEFAULT | SC_EXTERN)) == 0) {
663             Warning (WARN_FUNC_MUST_BE_EXTERN);
664         }
665         Flags = SC_EXTERN;
666     }
667
668     /* Do we have an entry with this name already? */
669     Entry = FindSymInTable (SymTab, Name, HashStr (Name));
670     if (Entry) {
671
672         /* We have a symbol with this name already */
673         Error (ERR_MULTIPLE_DEFINITION, Name);
674
675     } else {
676
677         /* Create a new entry */
678         Entry = NewSymEntry (Name, Flags);
679
680         /* Set the symbol attributes */
681         Entry->Type   = TypeDup (Type);
682         Entry->V.Offs = Offs;
683
684         /* Add the entry to the symbol table */
685         AddSymEntry (SymTab, Entry);
686
687     }
688
689     /* Return the entry */
690     return Entry;
691 }
692
693
694
695 SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
696 /* Add an external or global symbol to the symbol table and return the entry */
697 {
698     /* Functions must be inserted in the global symbol table */
699     SymTable* Tab = IsFunc (Type)? SymTab0 : SymTab;
700
701     /* Do we have an entry with this name already? */
702     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
703     if (Entry) {
704
705         type* EType;
706
707         /* We have a symbol with this name already */
708         if (Entry->Flags & SC_TYPE) {
709             Error (ERR_MULTIPLE_DEFINITION, Name);
710             return Entry;
711         }
712
713         /* Get the type string of the existing symbol */
714         EType = Entry->Type;
715
716         /* If we are handling arrays, the old entry or the new entry may be an
717          * incomplete declaration. Accept this, and if the exsting entry is
718          * incomplete, complete it.
719          */
720         if (IsArray (Type) && IsArray (EType)) {
721
722             /* Get the array sizes */
723             unsigned Size  = Decode (Type + 1);
724             unsigned ESize = Decode (EType + 1);
725
726             if ((Size != 0 && ESize != 0) ||
727                 TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) != 0) {
728                 /* Types not identical: Duplicate definition */
729                 Error (ERR_MULTIPLE_DEFINITION, Name);
730             } else {
731                 /* Check if we have a size in the existing definition */
732                 if (ESize == 0) {
733                     /* Existing, size not given, use size from new def */
734                     Encode (EType + 1, Size);
735                 }
736             }
737
738         } else {
739             /* New type must be identical */
740             if (!EqualTypes (EType, Type) != 0) {
741                 Error (ERR_MULTIPLE_DEFINITION, Name);
742             }
743
744             /* In case of a function, use the new type descriptor, since it
745              * contains pointers to the new symbol tables that are needed if
746              * an actual function definition follows.
747              */
748             if (IsFunc (Type)) {
749                 CopyEncode (Type+1, EType+1);
750             }
751         }
752
753         /* Add the new flags */
754         Entry->Flags |= Flags;
755
756     } else {
757
758         /* Create a new entry */
759         Entry = NewSymEntry (Name, Flags);
760
761         /* Set the symbol attributes */
762         Entry->Type = TypeDup (Type);
763
764         /* Add the entry to the symbol table */
765         AddSymEntry (Tab, Entry);
766     }
767
768     /* Return the entry */
769     return Entry;
770 }
771
772
773
774 /*****************************************************************************/
775 /*                                   Code                                    */
776 /*****************************************************************************/
777
778
779
780 SymTable* GetSymTab (void)
781 /* Return the current symbol table */
782 {
783     return SymTab;
784 }
785
786
787
788 static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
789 /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
790 {
791     /* Compare the parameter lists */
792     SymEntry* Sym1 = Tab1->SymHead;
793     SymEntry* Sym2 = Tab2->SymHead;
794
795     /* Compare the fields */
796     while (Sym1 && Sym2) {
797
798         /* Compare this field */
799         if (!EqualTypes (Sym1->Type, Sym2->Type)) {
800             /* Field types not equal */
801             return 0;
802         }
803
804         /* Get the pointers to the next fields */
805         Sym1 = Sym1->NextSym;
806         Sym2 = Sym2->NextSym;
807     }
808
809     /* Check both pointers against NULL to compare the field count */
810     return (Sym1 == 0 && Sym2 == 0);
811 }
812
813
814
815 int EqualTypes (const type* Type1, const type* Type2)
816 /* Recursively compare two types. Return 1 if the types match, return 0
817  * otherwise.
818  */
819 {
820     int v1, v2;
821     SymEntry* Sym1;
822     SymEntry* Sym2;
823     SymTable* Tab1;
824     SymTable* Tab2;
825     FuncDesc* F1;
826     FuncDesc* F2;
827
828
829     /* Shortcut here: If the pointers are identical, the types are identical */
830     if (Type1 == Type2) {
831         return 1;
832     }
833
834     /* Compare two types. Determine, where they differ */
835     while (*Type1 == *Type2 && *Type1 != T_END) {
836
837         switch (*Type1) {
838
839             case T_FUNC:
840                 /* Compare the function descriptors */
841                 F1 = DecodePtr (Type1+1);
842                 F2 = DecodePtr (Type2+1);
843                 if ((F1->Flags & ~FD_IMPLICIT) != (F2->Flags & ~FD_IMPLICIT)) {
844                     /* Flags differ */
845                     return 0;
846                 }
847
848                 /* Compare the parameter lists */
849                 if (EqualSymTables (F1->SymTab, F2->SymTab)       == 0 ||
850                     EqualSymTables (F1->StructTab, F2->StructTab) == 0 ||
851                     EqualSymTables (F1->EnumTab, F2->EnumTab) == 0) {
852                     /* One of the tables is not identical */
853                     return 0;
854                 }
855
856                 /* Skip the FuncDesc pointers to compare the return type */
857                 Type1 += DECODE_SIZE;
858                 Type2 += DECODE_SIZE;
859                 break;
860
861             case T_ARRAY:
862                 /* Check member count */
863                 v1 = Decode (Type1+1);
864                 v2 = Decode (Type2+1);
865                 if (v1 != 0 && v2 != 0 && v1 != v2) {
866                     /* Member count given but different */
867                     return 0;
868                 }
869                 Type1 += DECODE_SIZE;
870                 Type2 += DECODE_SIZE;
871                 break;
872
873             case T_STRUCT:
874             case T_UNION:
875                 /* Compare the fields recursively. To do that, we fetch the
876                  * pointer to the struct definition from the type, and compare
877                  * the fields.
878                  */
879                 Sym1 = DecodePtr (Type1+1);
880                 Sym2 = DecodePtr (Type2+1);
881
882                 /* Get the field tables from the struct entry */
883                 Tab1 = Sym1->V.S.SymTab;
884                 Tab2 = Sym2->V.S.SymTab;
885
886                 /* One or both structs may be forward definitions. In this case,
887                  * the symbol tables are both non existant. Assume that the
888                  * structs are equal in this case.
889                  */
890                 if (Tab1 != 0 && Tab2 != 0) {
891
892                     if (EqualSymTables (Tab1, Tab2) == 0) {
893                         /* Field lists are not equal */
894                         return 0;
895                     }
896
897                 }
898
899                 /* Structs are equal */
900                 Type1 += DECODE_SIZE;
901                 Type2 += DECODE_SIZE;
902                 break;
903         }
904         ++Type1;
905         ++Type2;
906     }
907
908     /* Done, types are equal */
909     return 1;
910 }
911
912
913
914 void MakeZPSym (const char* Name)
915 /* Mark the given symbol as zero page symbol */
916 {
917     /* Get the symbol table entry */
918     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
919
920     /* Mark the symbol as zeropage */
921     if (Entry) {
922         Entry->Flags |= SC_ZEROPAGE;
923     } else {
924         Error (ERR_UNDEFINED_SYMBOL, Name);
925     }
926 }
927
928
929
930 void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...)
931 /* Write the symbol table to the given file */
932 {
933     unsigned Len;
934     const SymEntry* Entry;
935
936     /* Print the header */
937     va_list ap;
938     va_start (ap, Header);
939     fputc ('\n', F);
940     Len = vfprintf (F, Header, ap);
941     va_end (ap);
942     fputc ('\n', F);
943
944     /* Underline the header */
945     while (Len--) {
946         fputc ('=', F);
947     }
948     fputc ('\n', F);
949
950     /* Dump the table */
951     Entry = Tab->SymHead;
952     if (Entry == 0) {
953         fprintf (F, "(empty)\n");
954     } else {
955         while (Entry) {
956             DumpSymEntry (F, Entry);
957             Entry = Entry->NextSym;
958         }
959     }
960     fprintf (F, "\n\n\n");
961 }
962
963
964
965 void EmitExternals (void)
966 /* Write import/export statements for external symbols */
967 {
968     SymEntry* Entry;
969
970     AddEmptyLine ();
971
972     Entry = SymTab->SymHead;
973     while (Entry) {
974         unsigned Flags = Entry->Flags;
975         if (Flags & SC_EXTERN) {
976             /* Only defined or referenced externs */
977             if ((Flags & SC_REF) != 0 && (Flags & SC_DEF) == 0) {
978                 /* An import */
979                 g_defimport (Entry->Name, Flags & SC_ZEROPAGE);
980             } else if (Flags & SC_DEF) {
981                 /* An export */
982                 g_defexport (Entry->Name, Flags & SC_ZEROPAGE);
983             }
984         }
985         Entry = Entry->NextSym;
986     }
987 }
988
989
990