]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
8c40fa81b5d6bf4bcdd1994685407728ba8fd5ed
[cc65] / src / cc65 / declare.c
1 /*
2  * declare.c
3  *
4  * Ullrich von Bassewitz, 20.06.1998
5  */
6
7
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <ctype.h>
13
14 #include "anonname.h"
15 #include "codegen.h"
16 #include "datatype.h"
17 #include "error.h"
18 #include "expr.h"
19 #include "funcdesc.h"
20 #include "function.h"
21 #include "global.h"
22 #include "litpool.h"
23 #include "mem.h"
24 #include "pragma.h"
25 #include "scanner.h"
26 #include "symtab.h"
27 #include "declare.h"
28
29
30
31 /*****************************************************************************/
32 /*                                 Forwards                                  */
33 /*****************************************************************************/
34
35
36
37 static void ParseTypeSpec (DeclSpec* D, int Default);
38 /* Parse a type specificier */
39
40
41
42 /*****************************************************************************/
43 /*                            internal functions                             */
44 /*****************************************************************************/
45
46
47
48 static void optional_modifiers (void)
49 /* Eat optional "const" or "volatile" tokens */
50 {
51     while (curtok == CONST || curtok == VOLATILE) {
52         /* Skip it */
53         gettok ();
54     }
55 }
56
57
58
59 static void optionalint (void)
60 /* Eat an optional "int" token */
61 {
62     if (curtok == INT) {
63         /* Skip it */
64         gettok ();
65     }
66 }
67
68
69
70 static void optionalsigned (void)
71 /* Eat an optional "signed" token */
72 {
73     if (curtok == SIGNED) {
74         /* Skip it */
75         gettok ();
76     }
77 }
78
79
80
81 static void InitDeclSpec (DeclSpec* D)
82 /* Initialize the DeclSpec struct for use */
83 {
84     D->StorageClass     = 0;
85     D->Type[0]          = T_END;
86     D->Flags            = 0;
87 }
88
89
90
91 static void InitDeclaration (Declaration* D)
92 /* Initialize the Declaration struct for use */
93 {
94     D->Ident[0]         = '\0';
95     D->Type[0]          = T_END;
96     D->T                = D->Type;
97 }
98
99
100
101 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
102 /* Parse a storage class */
103 {
104     /* Assume we're using an explicit storage class */
105     D->Flags &= ~DS_DEF_STORAGE;
106
107     /* Check the storage class given */
108     switch (curtok) {
109
110         case EXTERN:
111             D->StorageClass = SC_EXTERN | SC_STATIC;
112             gettok ();
113             break;
114
115         case STATIC:
116             D->StorageClass = SC_STATIC;
117             gettok ();
118             break;
119
120         case REGISTER:
121             D->StorageClass = SC_REGISTER | SC_STATIC;
122             gettok ();
123             break;
124
125         case AUTO:
126             D->StorageClass = SC_AUTO;
127             gettok ();
128             break;
129
130         case TYPEDEF:
131             D->StorageClass = SC_TYPEDEF;
132             gettok ();
133             break;
134
135         default:
136             /* No storage class given, use default */
137             D->Flags |= DS_DEF_STORAGE;
138             D->StorageClass = DefStorage;
139             break;
140     }
141 }
142
143
144
145 static void ParseEnumDecl (void)
146 /* Process an enum declaration . */
147 {
148     int EnumVal;
149     ident Ident;
150
151     /* Accept forward definitions */
152     if (curtok != LCURLY) {
153         return;
154     }
155
156     /* Skip the opening curly brace */
157     gettok ();
158
159     /* Read the enum tags */
160     EnumVal = 0;
161     while (curtok != RCURLY) {
162
163         /* We expect an identifier */
164         if (curtok != IDENT) {
165             Error (ERR_IDENT_EXPECTED);
166             continue;
167         }
168
169         /* Remember the identifier and skip it */
170         strcpy (Ident, CurTok.Ident);
171         gettok ();
172
173         /* Check for an assigned value */
174         if (curtok == ASGN) {
175             struct expent lval;
176             gettok ();
177             constexpr (&lval);
178             EnumVal = lval.e_const;
179         }
180
181         /* Add an entry to the symbol table */
182         AddEnumSym (Ident, EnumVal++);
183
184         /* Check for end of definition */
185         if (curtok != COMMA)
186             break;
187         gettok ();
188     }
189     ConsumeRCurly ();
190 }
191
192
193
194 static SymEntry* ParseStructDecl (const char* Name, type StructType)
195 /* Parse a struct/union declaration. */
196 {
197
198     unsigned Size;
199     unsigned Offs;
200     SymTable* FieldTab;
201     SymEntry* Entry;
202
203
204     if (curtok != LCURLY) {
205         /* Just a forward declaration. Try to find a struct with the given
206          * name. If there is none, insert a forward declaration into the
207          * current lexical level.
208          */
209         Entry = FindStructSym (Name);
210         if (Entry == 0 || Entry->Flags != SC_STRUCT) {
211             Entry = AddStructSym (Name, 0, 0);
212         }
213         return Entry;     
214     }
215
216     /* Add a forward declaration for the struct in the current lexical level */
217     Entry = AddStructSym (Name, 0, 0);
218
219     /* Skip the curly brace */
220     gettok ();
221
222     /* Enter a new lexical level for the struct */
223     EnterStructLevel ();
224
225     /* Parse struct fields */
226     Size = 0;
227     while (curtok != RCURLY) {
228
229         /* Get the type of the entry */
230         DeclSpec Spec;
231         InitDeclSpec (&Spec);
232         ParseTypeSpec (&Spec, -1);
233
234         /* Read fields with this type */
235         while (1) {
236
237             /* Get type and name of the struct field */
238             Declaration Decl;
239             ParseDecl (&Spec, &Decl, 0);
240
241             /* Add a field entry to the table */
242             AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
243
244             /* Calculate offset of next field/size of the union */
245             Offs = SizeOf (Decl.Type);
246             if (StructType == T_STRUCT) {
247                 Size += Offs;
248             } else {
249                 if (Offs > Size) {
250                     Size = Offs;
251                 }
252             }
253
254             if (curtok != COMMA)
255                 break;
256             gettok ();
257         }
258         ConsumeSemi ();
259     }
260
261     /* Skip the closing brace */
262     gettok ();
263
264     /* Remember the symbol table and leave the struct level */
265     FieldTab = GetSymTab ();
266     LeaveStructLevel ();
267
268     /* Make a real entry from the forward decl and return it */
269     return AddStructSym (Name, Size, FieldTab);
270 }
271
272
273
274 static void ParseTypeSpec (DeclSpec* D, int Default)
275 /* Parse a type specificier */
276 {
277     ident Ident;
278     SymEntry* Entry;
279     type StructType;
280
281     /* Assume have an explicit type */
282     D->Flags &= ~DS_DEF_TYPE;
283
284     /* Skip const or volatile modifiers if needed */
285     optional_modifiers ();
286
287     /* Look at the data type */
288     switch (curtok) {
289
290         case VOID:
291             gettok ();
292             D->Type[0] = T_VOID;
293             D->Type[1] = T_END;
294             break;
295
296         case CHAR:
297             gettok ();
298             D->Type[0] = GetDefaultChar();
299             D->Type[1] = T_END;
300             break;
301
302         case LONG:
303             gettok ();
304             if (curtok == UNSIGNED) {
305                 gettok ();
306                 optionalint ();
307                 D->Type[0] = T_ULONG;
308                 D->Type[1] = T_END;
309             } else {
310                 optionalsigned ();
311                 optionalint ();
312                 D->Type[0] = T_LONG;
313                 D->Type[1] = T_END;
314             }
315             break;
316
317         case SHORT:
318             gettok ();
319             if (curtok == UNSIGNED) {
320                 gettok ();
321                 optionalint ();
322                 D->Type[0] = T_USHORT;
323                 D->Type[1] = T_END;
324             } else {
325                 optionalsigned ();
326                 optionalint ();
327                 D->Type[0] = T_SHORT;
328                 D->Type[1] = T_END;
329             }
330             break;
331
332         case INT:
333             gettok ();
334             D->Type[0] = T_INT;
335             D->Type[1] = T_END;
336             break;
337
338        case SIGNED:
339             gettok ();
340             switch (curtok) {
341
342                 case CHAR:
343                     gettok ();
344                     D->Type[0] = T_CHAR;
345                     D->Type[1] = T_END;
346                     break;
347
348                 case SHORT:
349                     gettok ();
350                     optionalint ();
351                     D->Type[0] = T_SHORT;
352                     D->Type[1] = T_END;
353                     break;
354
355                 case LONG:
356                     gettok ();
357                     optionalint ();
358                     D->Type[0] = T_LONG;
359                     D->Type[1] = T_END;
360                     break;
361
362                 case INT:
363                     gettok ();
364                     /* FALL THROUGH */
365
366                 default:
367                     D->Type[0] = T_INT;
368                     D->Type[1] = T_END;
369                     break;
370             }
371             break;
372
373         case UNSIGNED:
374             gettok ();
375             switch (curtok) {
376
377                 case CHAR:
378                     gettok ();
379                     D->Type[0] = T_UCHAR;
380                     D->Type[1] = T_END;
381                     break;
382
383                 case SHORT:
384                     gettok ();
385                     optionalint ();
386                     D->Type[0] = T_USHORT;
387                     D->Type[1] = T_END;
388                     break;
389
390                 case LONG:
391                     gettok ();
392                     optionalint ();
393                     D->Type[0] = T_ULONG;
394                     D->Type[1] = T_END;
395                     break;
396
397                 case INT:
398                     gettok ();
399                     /* FALL THROUGH */
400
401                 default:
402                     D->Type[0] = T_UINT;
403                     D->Type[1] = T_END;
404                     break;
405             }
406             break;
407
408         case STRUCT:
409         case UNION:
410             StructType = (curtok == STRUCT)? T_STRUCT : T_UNION;
411             gettok ();
412             if (curtok == IDENT) {
413                 strcpy (Ident, CurTok.Ident);
414                 gettok ();
415             } else {
416                 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
417             }
418             /* Declare the struct in the current scope */
419             Entry = ParseStructDecl (Ident, StructType);
420             /* Encode the struct entry into the type */
421             D->Type[0] = StructType;
422             EncodePtr (D->Type+1, Entry);
423             D->Type[DECODE_SIZE+1] = T_END;
424             break;
425
426         case ENUM:
427             gettok ();
428             if (curtok != LCURLY) {
429                 /* Named enum */
430                 Consume (IDENT, ERR_IDENT_EXPECTED);
431             }
432             ParseEnumDecl ();
433             D->Type[0] = T_INT;
434             D->Type[1] = T_END;
435             break;
436
437         case IDENT:
438             Entry = FindSym (CurTok.Ident);
439             if (Entry && IsTypeDef (Entry)) {
440                 /* It's a typedef */
441                 gettok ();
442                 TypeCpy (D->Type, Entry->Type);
443                 break;
444             }
445             /* FALL THROUGH */
446
447         default:
448             if (Default < 0) {
449                 Error (ERR_TYPE_EXPECTED);
450                 D->Type[0] = T_INT;
451                 D->Type[1] = T_END;
452             } else {
453                 D->Flags  |= DS_DEF_TYPE;
454                 D->Type[0] = (type) Default;
455                 D->Type[1] = T_END;
456             }
457             break;
458     }
459 }
460
461
462
463 static FuncDesc* ParseFuncDecl (void)
464 /* Parse the argument list of a function. */
465 {
466     unsigned UnnamedCount = 0;
467     unsigned Offs;
468     SymEntry* Sym;
469     type* Type;
470
471     /* Create a new function descriptor */
472     FuncDesc* F = NewFuncDesc ();
473
474     /* Enter a new lexical level */
475     EnterFunctionLevel ();
476
477     /* Check for an empty or void parameter list */
478     if (curtok == RPAREN) {
479         /* Parameter list is empty */
480         F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
481     } else if (curtok == VOID && nxttok == RPAREN) {
482         /* Parameter list declared as void */
483         gettok ();
484         F->Flags |= FD_VOID_PARAM;
485     }
486
487     /* Parse params */
488     while (curtok != RPAREN) {
489
490         DeclSpec Spec;
491         Declaration Decl;
492
493         /* Allow an ellipsis as last parameter */
494         if (curtok == ELLIPSIS) {
495             gettok ();
496             F->Flags |= FD_ELLIPSIS;
497             break;
498         }
499
500         /* Read the declaration specifier */
501         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
502
503         /* We accept only auto and register as storage class specifiers, but
504          * we ignore all this and use auto.
505          */
506         if ((Spec.StorageClass & SC_AUTO) == 0 &&
507             (Spec.StorageClass & SC_REGISTER) == 0) {
508             Error (ERR_ILLEGAL_STORAGE_CLASS);
509         }
510         Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
511
512         /* Allow parameters without a name, but remember if we had some to
513          * eventually print an error message later.
514          */
515         ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
516         if (Decl.Ident[0] == '\0') {
517
518             /* Unnamed symbol. Generate a name that is not user accessible,
519              * then handle the symbol normal.
520              */
521             AnonName (Decl.Ident, "param");
522             ++UnnamedCount;
523
524             /* Clear defined bit on nonames */
525             Spec.StorageClass &= ~SC_DEF;
526         }
527
528         /* If the parameter is an array, convert it to a pointer */
529         Type = Decl.Type;
530         if (IsArray (Type)) {
531             Type += DECODE_SIZE;
532             Type[0] = T_PTR;
533         }
534
535         /* Create a symbol table entry */
536         AddLocalSym (Decl.Ident, Type, Spec.StorageClass, 0);
537
538         /* Count arguments */
539         ++F->ParamCount;
540         F->ParamSize += SizeOf (Type);
541
542         /* Check for more parameters */
543         if (curtok == COMMA) {
544             gettok ();
545         } else {
546             break;
547         }
548     }
549
550     /* Skip right paren. We must explicitly check for one here, since some of
551      * the breaks above bail out without checking.
552      */
553     ConsumeRParen ();
554
555     /* Assign offsets. If the function has a variable parameter list,
556      * there's one additional byte (the arg size).
557      */
558     Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
559     Sym = GetSymTab()->SymTail;
560     while (Sym) {
561         Sym->V.Offs = Offs;
562         Offs += SizeOf (Sym->Type);
563         Sym = Sym->PrevSym;
564     }
565
566     /* Check if this is a function definition */
567     if (curtok == LCURLY) {
568         /* Print an error if in strict ANSI mode and we have unnamed
569          * parameters.
570          */
571         if (ANSI && UnnamedCount > 0) {
572             Error (ERR_MISSING_PARAM_NAME);
573         }
574     }
575
576     /* Leave the lexical level remembering the symbol tables */
577     RememberFunctionLevel (F);
578
579     /* Return the function descriptor */
580     return F;
581 }
582
583
584
585 static void Decl (Declaration* D, unsigned Mode)
586 /* Recursively process declarators. Build a type array in reverse order. */
587 {
588     if (curtok == STAR) {
589         gettok ();
590         /* Allow optional const or volatile modifiers */
591         optional_modifiers ();
592         Decl (D, Mode);
593         *D->T++ = T_PTR;
594         return;
595     } else if (curtok == LPAREN) {
596         gettok ();
597         Decl (D, Mode);
598         ConsumeRParen ();
599     } else if (curtok == FASTCALL) {
600         /* Remember the current type pointer */
601         type* T = D->T;
602         /* Skip the fastcall token */
603         gettok ();
604         /* Parse the function */
605         Decl (D, Mode);
606         /* Set the fastcall flag */
607         if (!IsFunc (T)) {
608             Error (ERR_ILLEGAL_MODIFIER);
609         } else {
610             FuncDesc* F = DecodePtr (T+1);
611             F->Flags |= FD_FASTCALL;
612         }
613         return;
614     } else {
615         /* Things depend on Mode now:
616          *  - Mode == DM_NEED_IDENT means:
617          *      we *must* have a type and a variable identifer.
618          *  - Mode == DM_NO_IDENT means:
619          *      we must have a type but no variable identifer
620          *      (if there is one, it's not read).
621          *  - Mode == DM_ACCEPT_IDENT means:
622          *      we *may* have an identifier. If there is an identifier,
623          *      it is read, but it is no error, if there is none.
624          */
625         if (Mode == DM_NO_IDENT) {
626             D->Ident[0] = '\0';
627         } else if (curtok == IDENT) {
628             strcpy (D->Ident, CurTok.Ident);
629             gettok ();
630         } else {
631             if (Mode == DM_NEED_IDENT) {
632                 Error (ERR_IDENT_EXPECTED);
633             }
634             D->Ident[0] = '\0';
635             return;
636         }
637     }
638
639     while (curtok == LBRACK || curtok == LPAREN) {
640         if (curtok == LPAREN) {
641             /* Function declaration */
642             FuncDesc* F;
643             gettok ();
644             /* Parse the function declaration */
645             F = ParseFuncDecl ();
646             *D->T++ = T_FUNC;
647             EncodePtr (D->T, F);
648             D->T += DECODE_SIZE;
649         } else {
650             /* Array declaration */
651             unsigned long Size = 0;
652             gettok ();
653             /* Read the size if it is given */
654             if (curtok != RBRACK) {
655                 struct expent lval;
656                 constexpr (&lval);
657                 Size = lval.e_const;
658             }
659             ConsumeRBrack ();
660             *D->T++ = T_ARRAY;
661             Encode (D->T, Size);
662             D->T += DECODE_SIZE;
663         }
664     }
665 }
666
667
668
669 /*****************************************************************************/
670 /*                                   code                                    */
671 /*****************************************************************************/
672
673
674
675 type* ParseType (type* Type)
676 /* Parse a complete type specification */
677 {
678     DeclSpec Spec;
679     Declaration Decl;
680
681     /* Get a type without a default */
682     InitDeclSpec (&Spec);
683     ParseTypeSpec (&Spec, -1);
684
685     /* Parse additional declarators */
686     InitDeclaration (&Decl);
687     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
688
689     /* Copy the type to the target buffer */
690     TypeCpy (Type, Decl.Type);
691
692     /* Return a pointer to the target buffer */
693     return Type;
694 }
695
696
697
698 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
699 /* Parse a variable, type or function declaration */
700 {
701     /* Initialize the Declaration struct */
702     InitDeclaration (D);
703
704     /* Get additional declarators and the identifier */
705     Decl (D, Mode);
706
707     /* Add the base type. */
708     TypeCpy (D->T, Spec->Type);
709
710     /* Check the size of the generated type */
711     if (!IsFunc (D->Type) && SizeOf (D->Type) >= 0x10000) {
712         Error (ERR_ILLEGAL_SIZE);
713     }
714 }
715
716
717
718 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
719 /* Parse a declaration specification */
720 {
721     /* Initialize the DeclSpec struct */
722     InitDeclSpec (D);
723
724     /* First, get the storage class specifier for this declaration */
725     ParseStorageClass (D, DefStorage);
726
727     /* Parse the type specifiers */
728     ParseTypeSpec (D, DefType);
729 }
730
731
732
733 static void ParseVoidInit (void)
734 /* Parse an initialization of a void variable (special cc65 extension) */
735 {
736     struct expent lval;
737
738     /* Allow an arbitrary list of values */
739     ConsumeLCurly ();
740     do {
741         constexpr (&lval);
742         switch (lval.e_tptr[0]) {
743
744             case T_CHAR:
745             case T_UCHAR:
746                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
747                     /* Make it byte sized */
748                     lval.e_const &= 0xFF;
749                 }
750                 DefineData (&lval);
751                 break;
752
753             case T_SHORT:
754             case T_USHORT:
755             case T_INT:
756             case T_UINT:
757             case T_PTR:
758             case T_ARRAY:
759                 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
760                     /* Make it word sized */
761                     lval.e_const &= 0xFFFF;
762                 }
763                 DefineData (&lval);
764                 break;
765
766             case T_LONG:
767             case T_ULONG:
768                 DefineData (&lval);
769                 break;
770
771             default:
772                 Error (ERR_ILLEGAL_TYPE);
773                 break;
774
775         }
776
777         if (curtok != COMMA) {
778             break;
779         }
780         gettok ();
781
782     } while (curtok != RCURLY);
783
784     ConsumeRCurly ();
785 }
786
787
788
789 static void ParseStructInit (type* Type)
790 /* Parse initialization of a struct or union */
791 {
792     SymEntry* Entry;
793     SymTable* Tab;
794
795     /* Consume the opening curly brace */
796     ConsumeLCurly ();
797
798     /* Get a pointer to the struct entry from the type */
799     Entry = (SymEntry*) Decode (Type + 1);
800
801     /* Check if this struct definition has a field table. If it doesn't, it
802      * is an incomplete definition.
803      */
804     Tab = Entry->V.S.SymTab;
805     if (Tab == 0) {
806         Error (ERR_INIT_INCOMPLETE_TYPE);
807         /* Returning here will cause lots of errors, but recovery is difficult */
808         return;
809     }
810
811     /* Get a pointer to the list of symbols */
812     Entry = Tab->SymHead;
813     while (curtok != RCURLY) {
814         if (Entry == NULL) {
815             Error (ERR_TOO_MANY_INITIALIZERS);
816             return;
817         }
818         ParseInit (Entry->Type);
819         Entry = Entry->NextSym;
820         if (curtok != COMMA)
821             break;
822         gettok ();
823     }
824
825     /* Consume the closing curly brace */
826     ConsumeRCurly ();
827
828     /* If there are struct fields left, reserve additional storage */
829     while (Entry) {
830         g_zerobytes (SizeOf (Entry->Type));
831         Entry = Entry->NextSym;
832     }
833 }
834
835
836
837
838
839 void ParseInit (type *tptr)
840 /* Parse initialization of variables */
841 {
842     int count;
843     struct expent lval;
844     type* t;
845     const char* str;
846     int sz;
847
848     switch (*tptr) {
849
850         case T_CHAR:
851         case T_UCHAR:
852             constexpr (&lval);
853             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
854                 /* Make it byte sized */
855                 lval.e_const &= 0xFF;
856             }
857             assignadjust (tptr, &lval);
858             DefineData (&lval);
859             break;
860
861         case T_SHORT:
862         case T_USHORT:
863         case T_INT:
864         case T_UINT:
865         case T_PTR:
866             constexpr (&lval);
867             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
868                 /* Make it word sized */
869                 lval.e_const &= 0xFFFF;
870             }
871             assignadjust (tptr, &lval);
872             DefineData (&lval);
873             break;
874
875         case T_LONG:
876         case T_ULONG:
877             constexpr (&lval);
878             if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
879                 /* Make it long sized */
880                 lval.e_const &= 0xFFFFFFFF;
881             }
882             assignadjust (tptr, &lval);
883             DefineData (&lval);
884             break;
885
886         case T_ARRAY:
887             sz = Decode (tptr + 1);
888             t = tptr + DECODE_SIZE + 1;
889             if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == SCONST) {
890                 str = GetLiteral (curval);
891                 count = strlen (str) + 1;
892                 TranslateLiteralPool (curval);  /* Translate into target charset */
893                 g_defbytes (str, count);
894                 ResetLiteralOffs (curval);      /* Remove string from pool */
895                 gettok ();
896             } else {
897                 ConsumeLCurly ();
898                 count = 0;
899                 while (curtok != RCURLY) {
900                     ParseInit (tptr + DECODE_SIZE + 1);
901                     ++count;
902                     if (curtok != COMMA)
903                         break;
904                     gettok ();
905                 }
906                 ConsumeRCurly ();
907             }
908             if (sz == 0) {
909                 Encode (tptr + 1, count);
910             } else if (count < sz) {
911                 g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1));
912             } else if (count > sz) {
913                 Error (ERR_TOO_MANY_INITIALIZERS);
914             }
915             break;
916
917         case T_STRUCT:
918         case T_UNION:
919             ParseStructInit (tptr);
920             break;
921
922         case T_VOID:
923             if (!ANSI) {
924                 /* Special cc65 extension in non ANSI mode */
925                 ParseVoidInit ();
926                 break;
927             }
928             /* FALLTHROUGH */
929
930         default:
931             Error (ERR_ILLEGAL_TYPE);
932             break;
933
934     }
935 }
936
937
938