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