]> git.sur5r.net Git - cc65/blob - src/cc65/declare.c
cf3521f8fcbdfcb4cbf0f42b138dc12f1951780f
[cc65] / src / cc65 / declare.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 declare.c                                 */
4 /*                                                                           */
5 /*                 Parse variable and function declarations                  */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2008 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 <string.h>
38 #include <errno.h>
39
40 /* common */
41 #include "addrsize.h"
42 #include "mmodel.h"
43 #include "xmalloc.h"
44
45 /* cc65 */
46 #include "anonname.h"
47 #include "codegen.h"
48 #include "datatype.h"
49 #include "declare.h"
50 #include "declattr.h"
51 #include "error.h"
52 #include "expr.h"
53 #include "funcdesc.h"
54 #include "function.h"
55 #include "global.h"
56 #include "litpool.h"
57 #include "pragma.h"
58 #include "scanner.h"
59 #include "standard.h"
60 #include "symtab.h"
61 #include "typeconv.h"
62
63
64
65 /*****************************************************************************/
66 /*                                 Forwards                                  */
67 /*****************************************************************************/
68
69
70
71 static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers);
72 /* Parse a type specificier */
73
74 static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
75 /* Parse initialization of variables. Return the number of data bytes. */
76
77
78
79 /*****************************************************************************/
80 /*                            internal functions                             */
81 /*****************************************************************************/
82
83
84
85 static TypeCode OptionalQualifiers (TypeCode Q)
86 /* Read type qualifiers if we have any */
87 {
88     while (TokIsTypeQual (&CurTok)) {
89
90         switch (CurTok.Tok) {
91
92             case TOK_CONST:
93                 if (Q & T_QUAL_CONST) {
94                     Error ("Duplicate qualifier: `const'");
95                 }
96                 Q |= T_QUAL_CONST;
97                 break;
98
99             case TOK_VOLATILE:
100                 if (Q & T_QUAL_VOLATILE) {
101                     Error ("Duplicate qualifier: `volatile'");
102                 }
103                 Q |= T_QUAL_VOLATILE;
104                 break;
105
106             case TOK_RESTRICT:
107                 if (Q & T_QUAL_RESTRICT) {
108                     Error ("Duplicate qualifier: `restrict'");
109                 }
110                 Q |= T_QUAL_RESTRICT;
111                 break;
112
113             default:
114                 Internal ("Unexpected type qualifier token: %d", CurTok.Tok);
115
116         }
117
118         /* Skip the token */
119         NextToken ();
120     }
121
122     /* Return the qualifiers read */
123     return Q;
124 }
125
126
127
128 static void OptionalInt (void)
129 /* Eat an optional "int" token */
130 {
131     if (CurTok.Tok == TOK_INT) {
132         /* Skip it */
133         NextToken ();
134     }
135 }
136
137
138
139 static void OptionalSigned (void)
140 /* Eat an optional "signed" token */
141 {
142     if (CurTok.Tok == TOK_SIGNED) {
143         /* Skip it */
144         NextToken ();
145     }
146 }
147
148
149
150 static void InitDeclSpec (DeclSpec* D)
151 /* Initialize the DeclSpec struct for use */
152 {
153     D->StorageClass     = 0;
154     D->Type[0].C        = T_END;
155     D->Flags            = 0;
156 }
157
158
159
160 static void InitDeclaration (Declaration* D)
161 /* Initialize the Declaration struct for use */
162 {
163     D->Ident[0]  = '\0';
164     D->Type[0].C = T_END;
165     D->Index     = 0;
166 }
167
168
169
170 static void NeedTypeSpace (Declaration* D, unsigned Count)
171 /* Check if there is enough space for Count type specifiers within D */
172 {
173     if (D->Index + Count >= MAXTYPELEN) {
174         /* We must call Fatal() here, since calling Error() will try to
175          * continue, and the declaration type is not correctly terminated
176          * in case we come here.
177          */
178         Fatal ("Too many type specifiers");
179     }
180 }
181
182
183
184 static void AddTypeToDeclaration (Declaration* D, TypeCode T)
185 /* Add a type specifier to the type of a declaration */
186 {
187     NeedTypeSpace (D, 1);
188     D->Type[D->Index++].C = T;
189 }
190
191
192
193 static void AddFuncTypeToDeclaration (Declaration* D, FuncDesc* F)
194 /* Add a function type plus function descriptor to the type of a declaration */
195 {
196     NeedTypeSpace (D, 1);
197     D->Type[D->Index].C = T_FUNC;
198     SetFuncDesc (D->Type + D->Index, F);
199     ++D->Index;
200 }
201
202
203
204 static void AddArrayToDeclaration (Declaration* D, long Size)
205 /* Add an array type plus size to the type of a declaration */
206 {
207     NeedTypeSpace (D, 1);
208     D->Type[D->Index].C = T_ARRAY;
209     D->Type[D->Index].A.L = Size;
210     ++D->Index;
211 }
212
213
214
215 static void FixArrayQualifiers (Type* T)
216 /* Using typedefs, it is possible to generate declarations that have
217  * type qualifiers attached to an array, not the element type. Go and
218  * fix these here.
219  */
220 {
221     TypeCode Q = T_QUAL_NONE;
222     while (T->C != T_END) {
223         if (IsTypeArray (T)) {
224             /* Extract any type qualifiers */
225             Q |= T->C & T_MASK_QUAL;
226             T->C = UnqualifiedType (T->C);
227         } else {
228             /* Add extracted type qualifiers here */
229             T->C |= Q;
230             Q = T_QUAL_NONE;
231         }
232         ++T;
233     }
234
235     /* Q must be empty now */
236     CHECK (Q == T_QUAL_NONE);
237 }
238
239
240
241 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
242 /* Parse a storage class */
243 {
244     /* Assume we're using an explicit storage class */
245     D->Flags &= ~DS_DEF_STORAGE;
246
247     /* Check the storage class given */
248     switch (CurTok.Tok) {
249
250         case TOK_EXTERN:
251             D->StorageClass = SC_EXTERN | SC_STATIC;
252             NextToken ();
253             break;
254
255         case TOK_STATIC:
256             D->StorageClass = SC_STATIC;
257             NextToken ();
258             break;
259
260         case TOK_REGISTER:
261             D->StorageClass = SC_REGISTER | SC_STATIC;
262             NextToken ();
263             break;
264
265         case TOK_AUTO:
266             D->StorageClass = SC_AUTO;
267             NextToken ();
268             break;
269
270         case TOK_TYPEDEF:
271             D->StorageClass = SC_TYPEDEF;
272             NextToken ();
273             break;
274
275         default:
276             /* No storage class given, use default */
277             D->Flags |= DS_DEF_STORAGE;
278             D->StorageClass = DefStorage;
279             break;
280     }
281 }
282
283
284
285 static void ParseEnumDecl (void)
286 /* Process an enum declaration . */
287 {
288     int EnumVal;
289     ident Ident;
290
291     /* Accept forward definitions */
292     if (CurTok.Tok != TOK_LCURLY) {
293         return;
294     }
295
296     /* Skip the opening curly brace */
297     NextToken ();
298
299     /* Read the enum tags */
300     EnumVal = 0;
301     while (CurTok.Tok != TOK_RCURLY) {
302
303         /* We expect an identifier */
304         if (CurTok.Tok != TOK_IDENT) {
305             Error ("Identifier expected");
306             continue;
307         }
308
309         /* Remember the identifier and skip it */
310         strcpy (Ident, CurTok.Ident);
311         NextToken ();
312
313         /* Check for an assigned value */
314         if (CurTok.Tok == TOK_ASSIGN) {
315             ExprDesc Expr;
316             NextToken ();
317             ConstAbsIntExpr (hie1, &Expr);
318             EnumVal = Expr.IVal;
319         }
320
321         /* Add an entry to the symbol table */
322         AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
323
324         /* Check for end of definition */
325         if (CurTok.Tok != TOK_COMMA)
326             break;
327         NextToken ();
328     }
329     ConsumeRCurly ();
330 }
331
332
333
334 static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
335 /* Parse a struct/union declaration. */
336 {
337
338     unsigned  StructSize;
339     unsigned  FieldSize;
340     unsigned  Offs;
341     int       FlexibleMember;
342     SymTable* FieldTab;
343     SymEntry* Entry;
344
345
346     if (CurTok.Tok != TOK_LCURLY) {
347         /* Just a forward declaration. Try to find a struct with the given
348          * name. If there is none, insert a forward declaration into the
349          * current lexical level.
350          */
351         Entry = FindTagSym (Name);
352         if (Entry == 0) {
353             Entry = AddStructSym (Name, 0, 0);
354         } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
355             /* Already defined in the level but no struct */
356             Error ("Symbol `%s' is already different kind", Name);
357         }
358         return Entry;
359     }
360
361     /* Add a forward declaration for the struct in the current lexical level */
362     Entry = AddStructSym (Name, 0, 0);
363
364     /* Skip the curly brace */
365     NextToken ();
366
367     /* Enter a new lexical level for the struct */
368     EnterStructLevel ();
369
370     /* Parse struct fields */
371     FlexibleMember = 0;
372     StructSize     = 0;
373     while (CurTok.Tok != TOK_RCURLY) {
374
375         /* Get the type of the entry */
376         DeclSpec Spec;
377         InitDeclSpec (&Spec);
378         ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
379
380         /* Read fields with this type */
381         while (1) {
382
383             Declaration Decl;
384
385             /* If we had a flexible array member before, no other fields can
386              * follow.
387              */
388             if (FlexibleMember) {
389                 Error ("Flexible array member must be last field");
390                 FlexibleMember = 0;     /* Avoid further errors */
391             }
392
393             /* Get type and name of the struct field */
394             ParseDecl (&Spec, &Decl, 0);
395
396             /* Get the offset of this field */
397             Offs = (StructType == T_STRUCT)? StructSize : 0;
398
399             /* Calculate the sizes, handle flexible array members */
400             if (StructType == T_STRUCT) {
401
402                 /* It's a struct. Check if this field is a flexible array
403                  * member, and calculate the size of the field.
404                  */
405                 if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
406                     /* Array with unspecified size */
407                     if (StructSize == 0) {
408                         Error ("Flexible array member cannot be first struct field");
409                     }
410                     FlexibleMember = 1;
411                     /* Assume zero for size calculations */
412                     SetElementCount (Decl.Type, FLEXIBLE);
413                 } else {
414                     StructSize += CheckedSizeOf (Decl.Type);
415                 }
416
417             } else {
418
419                 /* It's a union */
420                 FieldSize = CheckedSizeOf (Decl.Type);
421                 if (FieldSize > StructSize) {
422                     StructSize = FieldSize;
423                 }
424             }
425
426             /* Add a field entry to the table */
427             AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
428
429             if (CurTok.Tok != TOK_COMMA) {
430                 break;
431             }
432             NextToken ();
433         }
434         ConsumeSemi ();
435     }
436
437     /* Skip the closing brace */
438     NextToken ();
439
440     /* Remember the symbol table and leave the struct level */
441     FieldTab = GetSymTab ();
442     LeaveStructLevel ();
443
444     /* Make a real entry from the forward decl and return it */
445     return AddStructSym (Name, StructSize, FieldTab);
446 }
447
448
449
450 static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
451 /* Parse a type specificier */
452 {
453     ident       Ident;
454     SymEntry*   Entry;
455     TypeCode    StructType;
456
457     /* Assume we have an explicit type */
458     D->Flags &= ~DS_DEF_TYPE;
459
460     /* Read type qualifiers if we have any */
461     Qualifiers = OptionalQualifiers (Qualifiers);
462
463     /* Look at the data type */
464     switch (CurTok.Tok) {
465
466         case TOK_VOID:
467             NextToken ();
468             D->Type[0].C = T_VOID;
469             D->Type[1].C = T_END;
470             break;
471
472         case TOK_CHAR:
473             NextToken ();
474             D->Type[0].C = GetDefaultChar();
475             D->Type[1].C = T_END;
476             break;
477
478         case TOK_LONG:
479             NextToken ();
480             if (CurTok.Tok == TOK_UNSIGNED) {
481                 NextToken ();
482                 OptionalInt ();
483                 D->Type[0].C = T_ULONG;
484                 D->Type[1].C = T_END;
485             } else {
486                 OptionalSigned ();
487                 OptionalInt ();
488                 D->Type[0].C = T_LONG;
489                 D->Type[1].C = T_END;
490             }
491             break;
492
493         case TOK_SHORT:
494             NextToken ();
495             if (CurTok.Tok == TOK_UNSIGNED) {
496                 NextToken ();
497                 OptionalInt ();
498                 D->Type[0].C = T_USHORT;
499                 D->Type[1].C = T_END;
500             } else {
501                 OptionalSigned ();
502                 OptionalInt ();
503                 D->Type[0].C = T_SHORT;
504                 D->Type[1].C = T_END;
505             }
506             break;
507
508         case TOK_INT:
509             NextToken ();
510             D->Type[0].C = T_INT;
511             D->Type[1].C = T_END;
512             break;
513
514        case TOK_SIGNED:
515             NextToken ();
516             switch (CurTok.Tok) {
517
518                 case TOK_CHAR:
519                     NextToken ();
520                     D->Type[0].C = T_SCHAR;
521                     D->Type[1].C = T_END;
522                     break;
523
524                 case TOK_SHORT:
525                     NextToken ();
526                     OptionalInt ();
527                     D->Type[0].C = T_SHORT;
528                     D->Type[1].C = T_END;
529                     break;
530
531                 case TOK_LONG:
532                     NextToken ();
533                     OptionalInt ();
534                     D->Type[0].C = T_LONG;
535                     D->Type[1].C = T_END;
536                     break;
537
538                 case TOK_INT:
539                     NextToken ();
540                     /* FALL THROUGH */
541
542                 default:
543                     D->Type[0].C = T_INT;
544                     D->Type[1].C = T_END;
545                     break;
546             }
547             break;
548
549         case TOK_UNSIGNED:
550             NextToken ();
551             switch (CurTok.Tok) {
552
553                 case TOK_CHAR:
554                     NextToken ();
555                     D->Type[0].C = T_UCHAR;
556                     D->Type[1].C = T_END;
557                     break;
558
559                 case TOK_SHORT:
560                     NextToken ();
561                     OptionalInt ();
562                     D->Type[0].C = T_USHORT;
563                     D->Type[1].C = T_END;
564                     break;
565
566                 case TOK_LONG:
567                     NextToken ();
568                     OptionalInt ();
569                     D->Type[0].C = T_ULONG;
570                     D->Type[1].C = T_END;
571                     break;
572
573                 case TOK_INT:
574                     NextToken ();
575                     /* FALL THROUGH */
576
577                 default:
578                     D->Type[0].C = T_UINT;
579                     D->Type[1].C = T_END;
580                     break;
581             }
582             break;
583
584         case TOK_FLOAT:
585             NextToken ();
586             D->Type[0].C = T_FLOAT;
587             D->Type[1].C = T_END;
588             break;
589
590         case TOK_DOUBLE:
591             NextToken ();
592             D->Type[0].C = T_DOUBLE;
593             D->Type[1].C = T_END;
594             break;
595
596         case TOK_STRUCT:
597         case TOK_UNION:
598             StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
599             NextToken ();
600             /* */
601             if (CurTok.Tok == TOK_IDENT) {
602                 strcpy (Ident, CurTok.Ident);
603                 NextToken ();
604             } else {
605                 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
606             }
607             /* Remember we have an extra type decl */
608             D->Flags |= DS_EXTRA_TYPE;
609             /* Declare the struct in the current scope */
610             Entry = ParseStructDecl (Ident, StructType);
611             /* Encode the struct entry into the type */
612             D->Type[0].C = StructType;
613             SetSymEntry (D->Type, Entry);
614             D->Type[1].C = T_END;
615             break;
616
617         case TOK_ENUM:
618             NextToken ();
619             if (CurTok.Tok != TOK_LCURLY) {
620                 /* Named enum */
621                 if (CurTok.Tok == TOK_IDENT) {
622                     /* Find an entry with this name */
623                     Entry = FindTagSym (CurTok.Ident);
624                     if (Entry) {
625                         if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
626                             Error ("Symbol `%s' is already different kind", Entry->Name);
627                         }
628                     } else {
629                         /* Insert entry into table ### */
630                     }
631                     /* Skip the identifier */
632                     NextToken ();
633                 } else {
634                     Error ("Identifier expected");
635                 }
636             }
637             /* Remember we have an extra type decl */
638             D->Flags |= DS_EXTRA_TYPE;
639             /* Parse the enum decl */
640             ParseEnumDecl ();
641             D->Type[0].C = T_INT;
642             D->Type[1].C = T_END;
643             break;
644
645         case TOK_IDENT:
646             Entry = FindSym (CurTok.Ident);
647             if (Entry && SymIsTypeDef (Entry)) {
648                 /* It's a typedef */
649                 NextToken ();
650                 TypeCpy (D->Type, Entry->Type);
651                 break;
652             }
653             /* FALL THROUGH */
654
655         default:
656             if (Default < 0) {
657                 Error ("Type expected");
658                 D->Type[0].C = T_INT;
659                 D->Type[1].C = T_END;
660             } else {
661                 D->Flags |= DS_DEF_TYPE;
662                 D->Type[0].C = (TypeCode) Default;
663                 D->Type[1].C = T_END;
664             }
665             break;
666     }
667
668     /* There may also be qualifiers *after* the initial type */
669     D->Type[0].C |= OptionalQualifiers (Qualifiers);
670 }
671
672
673
674 static Type* ParamTypeCvt (Type* T)
675 /* If T is an array, convert it to a pointer else do nothing. Return the
676  * resulting type.
677  */
678 {
679     if (IsTypeArray (T)) {
680         T->C = T_PTR;
681     }
682     return T;
683 }
684
685
686
687 static void ParseOldStyleParamList (FuncDesc* F)
688 /* Parse an old style (K&R) parameter list */
689 {
690     /* Parse params */
691     while (CurTok.Tok != TOK_RPAREN) {
692
693         /* List of identifiers expected */
694         if (CurTok.Tok != TOK_IDENT) {
695             Error ("Identifier expected");
696         }
697
698         /* Create a symbol table entry with type int */
699         AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF | SC_DEFTYPE, 0);
700
701         /* Count arguments */
702         ++F->ParamCount;
703
704         /* Skip the identifier */
705         NextToken ();
706
707         /* Check for more parameters */
708         if (CurTok.Tok == TOK_COMMA) {
709             NextToken ();
710         } else {
711             break;
712         }
713     }
714
715     /* Skip right paren. We must explicitly check for one here, since some of
716      * the breaks above bail out without checking.
717      */
718     ConsumeRParen ();
719
720     /* An optional list of type specifications follows */
721     while (CurTok.Tok != TOK_LCURLY) {
722
723         DeclSpec        Spec;
724
725         /* Read the declaration specifier */
726         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
727
728         /* We accept only auto and register as storage class specifiers, but
729          * we ignore all this, since we use auto anyway.
730          */
731         if ((Spec.StorageClass & SC_AUTO) == 0 &&
732             (Spec.StorageClass & SC_REGISTER) == 0) {
733             Error ("Illegal storage class");
734         }
735
736         /* Parse a comma separated variable list */
737         while (1) {
738
739             Declaration         Decl;
740
741             /* Read the parameter */
742             ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
743             if (Decl.Ident[0] != '\0') {
744
745                 /* We have a name given. Search for the symbol */
746                 SymEntry* Sym = FindLocalSym (Decl.Ident);
747                 if (Sym) {
748                     /* Check if we already changed the type for this
749                      * parameter
750                      */
751                     if (Sym->Flags & SC_DEFTYPE) {
752                         /* Found it, change the default type to the one given */
753                         ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
754                         /* Reset the "default type" flag */
755                         Sym->Flags &= ~SC_DEFTYPE;
756                     } else {
757                         /* Type has already been changed */
758                         Error ("Redefinition for parameter `%s'", Sym->Name);
759                     }
760                 } else {
761                     Error ("Unknown identifier: `%s'", Decl.Ident);
762                 }
763             }
764
765             if (CurTok.Tok == TOK_COMMA) {
766                 NextToken ();
767             } else {
768                 break;
769             }
770
771         }
772
773         /* Variable list must be semicolon terminated */
774         ConsumeSemi ();
775     }
776 }
777
778
779
780 static void ParseAnsiParamList (FuncDesc* F)
781 /* Parse a new style (ANSI) parameter list */
782 {
783     /* Parse params */
784     while (CurTok.Tok != TOK_RPAREN) {
785
786         DeclSpec        Spec;
787         Declaration     Decl;
788         DeclAttr        Attr;
789
790         /* Allow an ellipsis as last parameter */
791         if (CurTok.Tok == TOK_ELLIPSIS) {
792             NextToken ();
793             F->Flags |= FD_VARIADIC;
794             break;
795         }
796
797         /* Read the declaration specifier */
798         ParseDeclSpec (&Spec, SC_AUTO, T_INT);
799
800         /* We accept only auto and register as storage class specifiers */
801         if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
802             Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
803         } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
804             Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
805         } else {
806             Error ("Illegal storage class");
807             Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
808         }
809
810         /* Allow parameters without a name, but remember if we had some to
811          * eventually print an error message later.
812          */
813         ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
814         if (Decl.Ident[0] == '\0') {
815
816             /* Unnamed symbol. Generate a name that is not user accessible,
817              * then handle the symbol normal.
818              */
819             AnonName (Decl.Ident, "param");
820             F->Flags |= FD_UNNAMED_PARAMS;
821
822             /* Clear defined bit on nonames */
823             Decl.StorageClass &= ~SC_DEF;
824         }
825
826         /* Parse an attribute ### */
827         ParseAttribute (&Decl, &Attr);
828
829         /* Create a symbol table entry */
830         AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
831
832         /* Count arguments */
833         ++F->ParamCount;
834
835         /* Check for more parameters */
836         if (CurTok.Tok == TOK_COMMA) {
837             NextToken ();
838         } else {
839             break;
840         }
841     }
842
843     /* Skip right paren. We must explicitly check for one here, since some of
844      * the breaks above bail out without checking.
845      */
846     ConsumeRParen ();
847
848     /* Check if this is a function definition */
849     if (CurTok.Tok == TOK_LCURLY) {
850         /* Print an error if we have unnamed parameters and cc65 extensions
851          * are disabled.
852          */
853         if (IS_Get (&Standard) != STD_CC65 &&
854             (F->Flags & FD_UNNAMED_PARAMS) != 0) {
855             Error ("Parameter name omitted");
856         }
857     }
858 }
859
860
861
862 static FuncDesc* ParseFuncDecl (void)
863 /* Parse the argument list of a function. */
864 {
865     unsigned Offs;
866     SymEntry* Sym;
867
868     /* Create a new function descriptor */
869     FuncDesc* F = NewFuncDesc ();
870
871     /* Enter a new lexical level */
872     EnterFunctionLevel ();
873
874     /* Check for several special parameter lists */
875     if (CurTok.Tok == TOK_RPAREN) {
876         /* Parameter list is empty */
877         F->Flags |= (FD_EMPTY | FD_VARIADIC);
878     } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
879         /* Parameter list declared as void */
880         NextToken ();
881         F->Flags |= FD_VOID_PARAM;
882     } else if (CurTok.Tok == TOK_IDENT &&
883                (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
884         /* If the identifier is a typedef, we have a new style parameter list,
885          * if it's some other identifier, it's an old style parameter list.
886          */
887         Sym = FindSym (CurTok.Ident);
888         if (Sym == 0 || !SymIsTypeDef (Sym)) {
889             /* Old style (K&R) function. */
890             F->Flags |= FD_OLDSTYLE;
891         }
892     }
893
894     /* Parse params */
895     if ((F->Flags & FD_OLDSTYLE) == 0) {
896         /* New style function */
897         ParseAnsiParamList (F);
898     } else {
899         /* Old style function */
900         ParseOldStyleParamList (F);
901     }
902
903     /* Remember the last function parameter. We need it later for several
904      * purposes, for example when passing stuff to fastcall functions. Since
905      * more symbols are added to the table, it is easier if we remember it
906      * now, since it is currently the last entry in the symbol table.
907      */
908     F->LastParam = GetSymTab()->SymTail;
909
910     /* Assign offsets. If the function has a variable parameter list,
911      * there's one additional byte (the arg size).
912      */
913     Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
914     Sym = F->LastParam;
915     while (Sym) {
916         unsigned Size = CheckedSizeOf (Sym->Type);
917         if (SymIsRegVar (Sym)) {
918             Sym->V.R.SaveOffs = Offs;
919         } else {
920             Sym->V.Offs = Offs;
921         }
922         Offs += Size;
923         F->ParamSize += Size;
924         Sym = Sym->PrevSym;
925     }
926
927     /* Add the default address size for the function */
928     if (CodeAddrSize == ADDR_SIZE_FAR) {
929         F->Flags |= FD_FAR;
930     } else {
931         F->Flags |= FD_NEAR;
932     }
933
934     /* Leave the lexical level remembering the symbol tables */
935     RememberFunctionLevel (F);
936
937     /* Return the function descriptor */
938     return F;
939 }
940
941
942
943 static unsigned FunctionModifierFlags (void)
944 /* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
945 {
946     /* Read the flags */
947     unsigned Flags = FD_NONE;
948     while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
949
950         /* Get the flag bit for the next token */
951         unsigned F = FD_NONE;
952         switch (CurTok.Tok) {
953             case TOK_FASTCALL:  F = FD_FASTCALL; break;
954             case TOK_NEAR:      F = FD_NEAR;     break;
955             case TOK_FAR:       F = FD_FAR;      break;
956             default:            Internal ("Unexpected token: %d", CurTok.Tok);
957         }
958
959         /* Remember the flag for this modifier */
960         if (Flags & F) {
961             Error ("Duplicate modifier");
962         }
963         Flags |= F;
964
965         /* Skip the token */
966         NextToken ();
967     }
968
969     /* Sanity check */
970     if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) {
971         Error ("Cannot specify both, `__near__' and `__far__' modifiers");
972         Flags &= ~(FD_NEAR | FD_FAR);
973     }
974
975     /* Return the flags read */
976     return Flags;
977 }
978
979
980
981 static void ApplyFunctionModifiers (Type* T, unsigned Flags)
982 /* Apply a set of function modifier flags to a function */
983 {
984     /* Get the function descriptor */
985     FuncDesc* F = GetFuncDesc (T);
986
987     /* Special check for __fastcall__ */
988     if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) {
989         Error ("Cannot apply `__fastcall__' to functions with "
990                "variable parameter list");
991         Flags &= ~FD_FASTCALL;
992     }
993
994     /* Remove the default function address size modifiers */
995     F->Flags &= ~(FD_NEAR | FD_FAR);
996
997     /* Add the new modifers */
998     F->Flags |= Flags;
999 }
1000
1001
1002
1003 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
1004 /* Recursively process declarators. Build a type array in reverse order. */
1005 {
1006     /* Pointer to something */
1007     if (CurTok.Tok == TOK_STAR) {
1008
1009         TypeCode C;
1010
1011         /* Skip the star */
1012         NextToken ();
1013
1014         /* Allow optional const or volatile qualifiers */
1015         C = T_PTR | OptionalQualifiers (T_QUAL_NONE);
1016
1017         /* Parse the type, the pointer points to */
1018         Decl (Spec, D, Mode);
1019
1020         /* Add the type */
1021         AddTypeToDeclaration (D, C);
1022         return;
1023     }
1024
1025     /* Function modifiers */
1026     if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
1027
1028         /* Remember the current type pointer */
1029         Type* T = D->Type + D->Index;
1030
1031         /* Read the flags */
1032         unsigned Flags = FunctionModifierFlags ();
1033
1034         /* Parse the function */
1035         Decl (Spec, D, Mode);
1036
1037         /* Check that we have a function */
1038         if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
1039             Error ("Function modifier applied to non function");
1040         } else {
1041             ApplyFunctionModifiers (T, Flags);
1042         }
1043
1044         /* Done */
1045         return;
1046     }
1047
1048     if (CurTok.Tok == TOK_LPAREN) {
1049         NextToken ();
1050         Decl (Spec, D, Mode);
1051         ConsumeRParen ();
1052     } else {
1053         /* Things depend on Mode now:
1054          *  - Mode == DM_NEED_IDENT means:
1055          *      we *must* have a type and a variable identifer.
1056          *  - Mode == DM_NO_IDENT means:
1057          *      we must have a type but no variable identifer
1058          *      (if there is one, it's not read).
1059          *  - Mode == DM_ACCEPT_IDENT means:
1060          *      we *may* have an identifier. If there is an identifier,
1061          *      it is read, but it is no error, if there is none.
1062          */
1063         if (Mode == DM_NO_IDENT) {
1064             D->Ident[0] = '\0';
1065         } else if (CurTok.Tok == TOK_IDENT) {
1066             strcpy (D->Ident, CurTok.Ident);
1067             NextToken ();
1068         } else {
1069             if (Mode == DM_NEED_IDENT) {
1070                 Error ("Identifier expected");
1071             }
1072             D->Ident[0] = '\0';
1073         }
1074     }
1075
1076     while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
1077         if (CurTok.Tok == TOK_LPAREN) {
1078
1079             /* Function declaration */
1080             FuncDesc* F;
1081             NextToken ();
1082
1083             /* Parse the function declaration */
1084             F = ParseFuncDecl ();
1085
1086             /* Add the function type. Be sure to bounds check the type buffer */
1087             AddFuncTypeToDeclaration (D, F);
1088         } else {
1089             /* Array declaration */
1090             long Size = UNSPECIFIED;
1091             NextToken ();
1092             /* Read the size if it is given */
1093             if (CurTok.Tok != TOK_RBRACK) {
1094                 ExprDesc Expr;
1095                 ConstAbsIntExpr (hie1, &Expr);
1096                 if (Expr.IVal <= 0) {
1097                     if (D->Ident[0] != '\0') {
1098                         Error ("Size of array `%s' is invalid", D->Ident);
1099                     } else {
1100                         Error ("Size of array is invalid");
1101                     }
1102                     Expr.IVal = 1;
1103                 }
1104                 Size = Expr.IVal;
1105             }
1106             ConsumeRBrack ();
1107
1108             /* Add the array type with the size */
1109             AddArrayToDeclaration (D, Size);
1110         }
1111     }
1112 }
1113
1114
1115
1116 /*****************************************************************************/
1117 /*                                   code                                    */
1118 /*****************************************************************************/
1119
1120
1121
1122 Type* ParseType (Type* T)
1123 /* Parse a complete type specification */
1124 {
1125     DeclSpec Spec;
1126     Declaration Decl;
1127
1128     /* Get a type without a default */
1129     InitDeclSpec (&Spec);
1130     ParseTypeSpec (&Spec, -1, T_QUAL_NONE);
1131
1132     /* Parse additional declarators */
1133     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
1134
1135     /* Copy the type to the target buffer */
1136     TypeCpy (T, Decl.Type);
1137
1138     /* Return a pointer to the target buffer */
1139     return T;
1140 }
1141
1142
1143
1144 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
1145 /* Parse a variable, type or function declaration */
1146 {
1147     /* Initialize the Declaration struct */
1148     InitDeclaration (D);
1149
1150     /* Get additional declarators and the identifier */
1151     Decl (Spec, D, Mode);
1152
1153     /* Add the base type. */
1154     NeedTypeSpace (D, TypeLen (Spec->Type) + 1);        /* Bounds check */
1155     TypeCpy (D->Type + D->Index, Spec->Type);
1156
1157     /* Use the storage class from the declspec */
1158     D->StorageClass = Spec->StorageClass;
1159
1160     /* Fix any type qualifiers attached to an array type */
1161     FixArrayQualifiers (D->Type);
1162
1163     /* If we have a function, add a special storage class */
1164     if (IsTypeFunc (D->Type)) {
1165         D->StorageClass |= SC_FUNC;
1166     }
1167
1168     /* Check several things for function or function pointer types */
1169     if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) {
1170
1171         /* A function. Check the return type */
1172         Type* RetType = GetFuncReturn (D->Type);
1173
1174         /* Functions may not return functions or arrays */
1175         if (IsTypeFunc (RetType)) {
1176             Error ("Functions are not allowed to return functions");
1177         } else if (IsTypeArray (RetType)) {
1178             Error ("Functions are not allowed to return arrays");
1179         }
1180
1181         /* The return type must not be qualified */
1182         if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) {
1183
1184             if (GetType (RetType) == T_TYPE_VOID) {
1185                 /* A qualified void type is always an error */
1186                 Error ("function definition has qualified void return type");
1187             } else {
1188                 /* For others, qualifiers are ignored */
1189                 Warning ("type qualifiers ignored on function return type");
1190                 RetType[0].C = UnqualifiedType (RetType[0].C);
1191             }
1192         }
1193
1194         /* Warn about an implicit int return in the function */
1195         if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
1196             RetType[0].C == T_INT && RetType[1].C == T_END) {
1197             /* Function has an implicit int return. Output a warning if we don't
1198              * have the C89 standard enabled explicitly.
1199              */
1200             if (IS_Get (&Standard) >= STD_C99) {
1201                 Warning ("Implicit `int' return type is an obsolete feature");
1202             }
1203             GetFuncDesc (D->Type)->Flags |= FD_OLDSTYLE_INTRET;
1204         }
1205
1206     }
1207
1208     /* For anthing that is not a function or typedef, check for an implicit
1209      * int declaration.
1210      */
1211     if ((D->StorageClass & SC_FUNC) != SC_FUNC &&
1212         (D->StorageClass & SC_TYPEDEF) != SC_TYPEDEF) {
1213         /* If the standard was not set explicitly to C89, print a warning
1214          * for variables with implicit int type.
1215          */
1216         if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) {
1217             Warning ("Implicit `int' is an obsolete feature");
1218         }
1219     }
1220
1221     /* Check the size of the generated type */
1222     if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type)) {
1223         unsigned Size = SizeOf (D->Type);
1224         if (Size >= 0x10000) {
1225             if (D->Ident[0] != '\0') {
1226                 Error ("Size of `%s' is invalid (0x%06X)", D->Ident, Size);
1227             } else {
1228                 Error ("Invalid size in declaration (0x%06X)", Size);
1229             }
1230         }
1231     }
1232
1233 }
1234
1235
1236
1237 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
1238 /* Parse a declaration specification */
1239 {
1240     TypeCode Qualifiers;
1241
1242     /* Initialize the DeclSpec struct */
1243     InitDeclSpec (D);
1244
1245     /* There may be qualifiers *before* the storage class specifier */
1246     Qualifiers = OptionalQualifiers (T_QUAL_NONE);
1247
1248     /* Now get the storage class specifier for this declaration */
1249     ParseStorageClass (D, DefStorage);
1250
1251     /* Parse the type specifiers passing any initial type qualifiers */
1252     ParseTypeSpec (D, DefType, Qualifiers);
1253 }
1254
1255
1256
1257 void CheckEmptyDecl (const DeclSpec* D)
1258 /* Called after an empty type declaration (that is, a type declaration without
1259  * a variable). Checks if the declaration does really make sense and issues a
1260  * warning if not.
1261  */
1262 {
1263     if ((D->Flags & DS_EXTRA_TYPE) == 0) {
1264         Warning ("Useless declaration");
1265     }
1266 }
1267
1268
1269
1270 static void SkipInitializer (unsigned BracesExpected)
1271 /* Skip the remainder of an initializer in case of errors. Try to be somewhat
1272  * smart so we don't have too many following errors.
1273  */
1274 {
1275     while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
1276         switch (CurTok.Tok) {
1277             case TOK_RCURLY:    --BracesExpected;   break;
1278             case TOK_LCURLY:    ++BracesExpected;   break;
1279             default:                                break;
1280         }
1281         NextToken ();
1282     }
1283 }
1284
1285
1286
1287 static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
1288 /* Accept any number of opening curly braces around an initialization, skip
1289  * them and return the number. If the number of curly braces is less than
1290  * BracesNeeded, issue a warning.
1291  */
1292 {
1293     unsigned BraceCount = 0;
1294     while (CurTok.Tok == TOK_LCURLY) {
1295         ++BraceCount;
1296         NextToken ();
1297     }
1298     if (BraceCount < BracesNeeded) {
1299         Error ("`{' expected");
1300     }
1301     return BraceCount;
1302 }
1303
1304
1305
1306 static void ClosingCurlyBraces (unsigned BracesExpected)
1307 /* Accept and skip the given number of closing curly braces together with
1308  * an optional comma. Output an error messages, if the input does not contain
1309  * the expected number of braces.
1310  */
1311 {
1312     while (BracesExpected) {
1313         if (CurTok.Tok == TOK_RCURLY) {
1314             NextToken ();
1315         } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) {
1316             NextToken ();
1317             NextToken ();
1318         } else {
1319             Error ("`}' expected");
1320             return;
1321         }
1322         --BracesExpected;
1323     }
1324 }
1325
1326
1327
1328 static void DefineData (ExprDesc* Expr)
1329 /* Output a data definition for the given expression */
1330 {
1331     switch (ED_GetLoc (Expr)) {
1332
1333         case E_LOC_ABS:
1334             /* Absolute: numeric address or const */
1335             g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
1336             break;
1337
1338         case E_LOC_GLOBAL:
1339             /* Global variable */
1340             g_defdata (CF_EXTERNAL, Expr->Name, Expr->IVal);
1341             break;
1342
1343         case E_LOC_STATIC:
1344         case E_LOC_LITERAL:
1345             /* Static variable or literal in the literal pool */
1346             g_defdata (CF_STATIC, Expr->Name, Expr->IVal);
1347             break;
1348
1349         case E_LOC_REGISTER:
1350             /* Register variable. Taking the address is usually not
1351              * allowed.
1352              */
1353             if (IS_Get (&AllowRegVarAddr) == 0) {
1354                 Error ("Cannot take the address of a register variable");
1355             }
1356             g_defdata (CF_REGVAR, Expr->Name, Expr->IVal);
1357             break;
1358
1359         case E_LOC_STACK:
1360         case E_LOC_PRIMARY:
1361         case E_LOC_EXPR:
1362             Error ("Non constant initializer");
1363             break;
1364
1365         default:
1366             Internal ("Unknown constant type: 0x%04X", ED_GetLoc (Expr));
1367     }
1368 }
1369
1370
1371
1372 static unsigned ParseScalarInit (Type* T)
1373 /* Parse initializaton for scalar data types. Return the number of data bytes. */
1374 {
1375     ExprDesc ED;
1376
1377     /* Optional opening brace */
1378     unsigned BraceCount = OpeningCurlyBraces (0);
1379
1380     /* We warn if an initializer for a scalar contains braces, because this is
1381      * quite unusual and often a sign for some problem in the input.
1382      */
1383     if (BraceCount > 0) {
1384         Warning ("Braces around scalar initializer");
1385     }
1386
1387     /* Get the expression and convert it to the target type */
1388     ConstExpr (hie1, &ED);
1389     TypeConversion (&ED, T);
1390
1391     /* Output the data */
1392     DefineData (&ED);
1393
1394     /* Close eventually opening braces */
1395     ClosingCurlyBraces (BraceCount);
1396
1397     /* Done */
1398     return SizeOf (T);
1399 }
1400
1401
1402
1403 static unsigned ParsePointerInit (Type* T)
1404 /* Parse initializaton for pointer data types. Return the number of data bytes. */
1405 {
1406     /* Optional opening brace */
1407     unsigned BraceCount = OpeningCurlyBraces (0);
1408
1409     /* Expression */
1410     ExprDesc ED;
1411     ConstExpr (hie1, &ED);
1412     TypeConversion (&ED, T);
1413
1414     /* Output the data */
1415     DefineData (&ED);
1416
1417     /* Close eventually opening braces */
1418     ClosingCurlyBraces (BraceCount);
1419
1420     /* Done */
1421     return SIZEOF_PTR;
1422 }
1423
1424
1425
1426 static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers)
1427 /* Parse initializaton for arrays. Return the number of data bytes. */
1428 {
1429     int Count;
1430
1431     /* Get the array data */
1432     Type* ElementType    = GetElementType (T);
1433     unsigned ElementSize = CheckedSizeOf (ElementType);
1434     long ElementCount    = GetElementCount (T);
1435
1436     /* Special handling for a character array initialized by a literal */
1437     if (IsTypeChar (ElementType) &&
1438         (CurTok.Tok == TOK_SCONST ||
1439         (CurTok.Tok == TOK_LCURLY && NextTok.Tok == TOK_SCONST))) {
1440
1441         /* Char array initialized by string constant */
1442         int NeedParen;
1443         const char* Str;
1444
1445         /* If we initializer is enclosed in brackets, remember this fact and
1446          * skip the opening bracket.
1447          */
1448         NeedParen = (CurTok.Tok == TOK_LCURLY);
1449         if (NeedParen) {
1450             NextToken ();
1451         }
1452
1453         /* Get the initializer string and its size */
1454         Str = GetLiteral (CurTok.IVal);
1455         Count = GetLiteralPoolOffs () - CurTok.IVal;
1456
1457         /* Translate into target charset */
1458         TranslateLiteralPool (CurTok.IVal);
1459
1460         /* If the array is one too small for the string literal, omit the
1461          * trailing zero.
1462          */
1463         if (ElementCount != UNSPECIFIED &&
1464             ElementCount != FLEXIBLE    &&
1465             Count        == ElementCount + 1) {
1466             /* Omit the trailing zero */
1467             --Count;
1468         }
1469
1470         /* Output the data */
1471         g_defbytes (Str, Count);
1472
1473         /* Remove string from pool */
1474         ResetLiteralPoolOffs (CurTok.IVal);
1475         NextToken ();
1476
1477         /* If the initializer was enclosed in curly braces, we need a closing
1478          * one.
1479          */
1480         if (NeedParen) {
1481             ConsumeRCurly ();
1482         }
1483
1484     } else {
1485
1486         /* Curly brace */
1487         ConsumeLCurly ();
1488
1489         /* Initialize the array members */
1490         Count = 0;
1491         while (CurTok.Tok != TOK_RCURLY) {
1492             /* Flexible array members may not be initialized within
1493              * an array (because the size of each element may differ
1494              * otherwise).
1495              */
1496             ParseInitInternal (ElementType, 0);
1497             ++Count;
1498             if (CurTok.Tok != TOK_COMMA)
1499                 break;
1500             NextToken ();
1501         }
1502
1503         /* Closing curly braces */
1504         ConsumeRCurly ();
1505     }
1506
1507     if (ElementCount == UNSPECIFIED) {
1508         /* Number of elements determined by initializer */
1509         SetElementCount (T, Count);
1510         ElementCount = Count;
1511     } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
1512         /* In non ANSI mode, allow initialization of flexible array
1513          * members.
1514          */
1515         ElementCount = Count;
1516     } else if (Count < ElementCount) {
1517         g_zerobytes ((ElementCount - Count) * ElementSize);
1518     } else if (Count > ElementCount) {
1519         Error ("Too many initializers");
1520     }
1521     return ElementCount * ElementSize;
1522 }
1523
1524
1525
1526 static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers)
1527 /* Parse initialization of a struct or union. Return the number of data bytes. */
1528 {
1529     SymEntry* Entry;
1530     SymTable* Tab;
1531     unsigned  StructSize;
1532     unsigned  Size;
1533
1534
1535     /* Consume the opening curly brace */
1536     ConsumeLCurly ();
1537
1538     /* Get a pointer to the struct entry from the type */
1539     Entry = GetSymEntry (T);
1540
1541     /* Get the size of the struct from the symbol table entry */
1542     StructSize = Entry->V.S.Size;
1543
1544     /* Check if this struct definition has a field table. If it doesn't, it
1545      * is an incomplete definition.
1546      */
1547     Tab = Entry->V.S.SymTab;
1548     if (Tab == 0) {
1549         Error ("Cannot initialize variables with incomplete type");
1550         /* Try error recovery */
1551         SkipInitializer (1);
1552         /* Nothing initialized */
1553         return 0;
1554     }
1555
1556     /* Get a pointer to the list of symbols */
1557     Entry = Tab->SymHead;
1558
1559     /* Initialize fields */
1560     Size = 0;
1561     while (CurTok.Tok != TOK_RCURLY) {
1562         if (Entry == 0) {
1563             Error ("Too many initializers");
1564             SkipInitializer (1);
1565             return Size;
1566         }
1567         /* Parse initialization of one field. Flexible array members may
1568          * only be initialized if they are the last field (or part of the
1569          * last struct field).
1570          */
1571         Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
1572         Entry = Entry->NextSym;
1573         if (CurTok.Tok != TOK_COMMA)
1574             break;
1575         NextToken ();
1576     }
1577
1578     /* Consume the closing curly brace */
1579     ConsumeRCurly ();
1580
1581     /* If there are struct fields left, reserve additional storage */
1582     if (Size < StructSize) {
1583         g_zerobytes (StructSize - Size);
1584         Size = StructSize;
1585     }
1586
1587     /* Return the actual number of bytes initialized. This number may be
1588      * larger than StructSize if flexible array members are present and were
1589      * initialized (possible in non ANSI mode).
1590      */
1591     return Size;
1592 }
1593
1594
1595
1596 static unsigned ParseVoidInit (void)
1597 /* Parse an initialization of a void variable (special cc65 extension).
1598  * Return the number of bytes initialized.
1599  */
1600 {
1601     ExprDesc Expr;
1602     unsigned Size;
1603
1604     /* Opening brace */
1605     ConsumeLCurly ();
1606
1607     /* Allow an arbitrary list of values */
1608     Size = 0;
1609     do {
1610         ConstExpr (hie1, &Expr);
1611         switch (UnqualifiedType (Expr.Type[0].C)) {
1612
1613             case T_SCHAR:
1614             case T_UCHAR:
1615                 if (ED_IsConstAbsInt (&Expr)) {
1616                     /* Make it byte sized */
1617                     Expr.IVal &= 0xFF;
1618                 }
1619                 DefineData (&Expr);
1620                 Size += SIZEOF_CHAR;
1621                 break;
1622
1623             case T_SHORT:
1624             case T_USHORT:
1625             case T_INT:
1626             case T_UINT:
1627             case T_PTR:
1628             case T_ARRAY:
1629                 if (ED_IsConstAbsInt (&Expr)) {
1630                     /* Make it word sized */
1631                     Expr.IVal &= 0xFFFF;
1632                 }
1633                 DefineData (&Expr);
1634                 Size += SIZEOF_INT;
1635                 break;
1636
1637             case T_LONG:
1638             case T_ULONG:
1639                 if (ED_IsConstAbsInt (&Expr)) {
1640                     /* Make it dword sized */
1641                     Expr.IVal &= 0xFFFFFFFF;
1642                 }
1643                 DefineData (&Expr);
1644                 Size += SIZEOF_LONG;
1645                 break;
1646
1647             default:
1648                 Error ("Illegal type in initialization");
1649                 break;
1650
1651         }
1652
1653         if (CurTok.Tok != TOK_COMMA) {
1654             break;
1655         }
1656         NextToken ();
1657
1658     } while (CurTok.Tok != TOK_RCURLY);
1659
1660     /* Closing brace */
1661     ConsumeRCurly ();
1662
1663     /* Return the number of bytes initialized */
1664     return Size;
1665 }
1666
1667
1668
1669 static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
1670 /* Parse initialization of variables. Return the number of data bytes. */
1671 {
1672     switch (UnqualifiedType (T->C)) {
1673
1674         case T_SCHAR:
1675         case T_UCHAR:
1676         case T_SHORT:
1677         case T_USHORT:
1678         case T_INT:
1679         case T_UINT:
1680         case T_LONG:
1681         case T_ULONG:
1682         case T_FLOAT:
1683         case T_DOUBLE:
1684             return ParseScalarInit (T);
1685
1686         case T_PTR:
1687             return ParsePointerInit (T);
1688
1689         case T_ARRAY:
1690             return ParseArrayInit (T, AllowFlexibleMembers);
1691
1692         case T_STRUCT:
1693         case T_UNION:
1694             return ParseStructInit (T, AllowFlexibleMembers);
1695
1696         case T_VOID:
1697             if (IS_Get (&Standard) == STD_CC65) {
1698                 /* Special cc65 extension in non ANSI mode */
1699                 return ParseVoidInit ();
1700             }
1701             /* FALLTHROUGH */
1702
1703         default:
1704             Error ("Illegal type");
1705             return SIZEOF_CHAR;
1706
1707     }
1708 }
1709
1710
1711
1712 unsigned ParseInit (Type* T)
1713 /* Parse initialization of variables. Return the number of data bytes. */
1714 {
1715     /* Parse the initialization. Flexible array members can only be initialized
1716      * in cc65 mode.
1717      */
1718     unsigned Size = ParseInitInternal (T, IS_Get (&Standard) == STD_CC65);
1719
1720     /* The initialization may not generate code on global level, because code
1721      * outside function scope will never get executed.
1722      */
1723     if (HaveGlobalCode ()) {
1724         Error ("Non constant initializers");
1725         RemoveGlobalCode ();
1726     }
1727
1728     /* Return the size needed for the initialization */
1729     return Size;
1730 }
1731
1732
1733