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