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