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