1 /*****************************************************************************/
5 /* Parse variable and function declarations */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
61 /*****************************************************************************/
63 /*****************************************************************************/
67 static void ParseTypeSpec (DeclSpec* D, int Default);
68 /* Parse a type specificier */
70 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers);
71 /* Parse initialization of variables. Return the number of data bytes. */
75 /*****************************************************************************/
76 /* internal functions */
77 /*****************************************************************************/
81 static type OptionalQualifiers (type Q)
82 /* Read type qualifiers if we have any */
84 while (CurTok.Tok == TOK_CONST || CurTok.Tok == TOK_VOLATILE) {
89 if (Q & T_QUAL_CONST) {
90 Error ("Duplicate qualifier: `const'");
96 if (Q & T_QUAL_VOLATILE) {
97 Error ("Duplicate qualifier: `volatile'");
103 /* Keep gcc silent */
112 /* Return the qualifiers read */
118 static void optionalint (void)
119 /* Eat an optional "int" token */
121 if (CurTok.Tok == TOK_INT) {
129 static void optionalsigned (void)
130 /* Eat an optional "signed" token */
132 if (CurTok.Tok == TOK_SIGNED) {
140 static void InitDeclSpec (DeclSpec* D)
141 /* Initialize the DeclSpec struct for use */
150 static void InitDeclaration (Declaration* D)
151 /* Initialize the Declaration struct for use */
160 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
161 /* Parse a storage class */
163 /* Assume we're using an explicit storage class */
164 D->Flags &= ~DS_DEF_STORAGE;
166 /* Check the storage class given */
167 switch (CurTok.Tok) {
170 D->StorageClass = SC_EXTERN | SC_STATIC;
175 D->StorageClass = SC_STATIC;
180 D->StorageClass = SC_REGISTER | SC_STATIC;
185 D->StorageClass = SC_AUTO;
190 D->StorageClass = SC_TYPEDEF;
195 /* No storage class given, use default */
196 D->Flags |= DS_DEF_STORAGE;
197 D->StorageClass = DefStorage;
204 static void ParseEnumDecl (void)
205 /* Process an enum declaration . */
210 /* Accept forward definitions */
211 if (CurTok.Tok != TOK_LCURLY) {
215 /* Skip the opening curly brace */
218 /* Read the enum tags */
220 while (CurTok.Tok != TOK_RCURLY) {
222 /* We expect an identifier */
223 if (CurTok.Tok != TOK_IDENT) {
224 Error ("Identifier expected");
228 /* Remember the identifier and skip it */
229 strcpy (Ident, CurTok.Ident);
232 /* Check for an assigned value */
233 if (CurTok.Tok == TOK_ASSIGN) {
237 EnumVal = lval.ConstVal;
240 /* Add an entry to the symbol table */
241 AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
243 /* Check for end of definition */
244 if (CurTok.Tok != TOK_COMMA)
253 static SymEntry* ParseStructDecl (const char* Name, type StructType)
254 /* Parse a struct/union declaration. */
265 if (CurTok.Tok != TOK_LCURLY) {
266 /* Just a forward declaration. Try to find a struct with the given
267 * name. If there is none, insert a forward declaration into the
268 * current lexical level.
270 Entry = FindTagSym (Name);
272 Entry = AddStructSym (Name, 0, 0);
273 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
274 /* Already defined in the level but no struct */
275 Error ("Symbol `%s' is already different kind", Name);
280 /* Add a forward declaration for the struct in the current lexical level */
281 Entry = AddStructSym (Name, 0, 0);
283 /* Skip the curly brace */
286 /* Enter a new lexical level for the struct */
289 /* Parse struct fields */
292 while (CurTok.Tok != TOK_RCURLY) {
294 /* Get the type of the entry */
296 InitDeclSpec (&Spec);
297 ParseTypeSpec (&Spec, -1);
299 /* Read fields with this type */
304 /* If we had a flexible array member before, no other fields can
307 if (FlexibleMember) {
308 Error ("Flexible array member must be last field");
309 FlexibleMember = 0; /* Avoid further errors */
312 /* Get type and name of the struct field */
313 ParseDecl (&Spec, &Decl, 0);
315 /* Get the offset of this field */
316 Offs = (StructType == T_STRUCT)? StructSize : 0;
318 /* Calculate the sizes, handle flexible array members */
319 if (StructType == T_STRUCT) {
321 /* It's a struct. Check if this field is a flexible array
322 * member, and calculate the size of the field.
324 if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
325 /* Array with unspecified size */
326 if (StructSize == 0) {
327 Error ("Flexible array member cannot be first struct field");
330 /* Assume zero for size calculations */
331 Encode (Decl.Type + 1, FLEXIBLE);
333 StructSize += CheckedSizeOf (Decl.Type);
339 FieldSize = CheckedSizeOf (Decl.Type);
340 if (FieldSize > StructSize) {
341 StructSize = FieldSize;
345 /* Add a field entry to the table */
346 AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
348 if (CurTok.Tok != TOK_COMMA) {
356 /* Skip the closing brace */
359 /* Remember the symbol table and leave the struct level */
360 FieldTab = GetSymTab ();
363 /* Make a real entry from the forward decl and return it */
364 return AddStructSym (Name, StructSize, FieldTab);
369 static void ParseTypeSpec (DeclSpec* D, int Default)
370 /* Parse a type specificier */
375 type Qualifiers; /* Type qualifiers */
377 /* Assume we have an explicit type */
378 D->Flags &= ~DS_DEF_TYPE;
380 /* Read type qualifiers if we have any */
381 Qualifiers = OptionalQualifiers (T_QUAL_NONE);
383 /* Look at the data type */
384 switch (CurTok.Tok) {
394 D->Type[0] = GetDefaultChar();
400 if (CurTok.Tok == TOK_UNSIGNED) {
403 D->Type[0] = T_ULONG;
415 if (CurTok.Tok == TOK_UNSIGNED) {
418 D->Type[0] = T_USHORT;
423 D->Type[0] = T_SHORT;
436 switch (CurTok.Tok) {
440 D->Type[0] = T_SCHAR;
447 D->Type[0] = T_SHORT;
471 switch (CurTok.Tok) {
475 D->Type[0] = T_UCHAR;
482 D->Type[0] = T_USHORT;
489 D->Type[0] = T_ULONG;
506 StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
509 if (CurTok.Tok == TOK_IDENT) {
510 strcpy (Ident, CurTok.Ident);
513 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
515 /* Remember we have an extra type decl */
516 D->Flags |= DS_EXTRA_TYPE;
517 /* Declare the struct in the current scope */
518 Entry = ParseStructDecl (Ident, StructType);
519 /* Encode the struct entry into the type */
520 D->Type[0] = StructType;
521 EncodePtr (D->Type+1, Entry);
522 D->Type[DECODE_SIZE+1] = T_END;
527 if (CurTok.Tok != TOK_LCURLY) {
529 if (CurTok.Tok == TOK_IDENT) {
530 /* Find an entry with this name */
531 Entry = FindTagSym (CurTok.Ident);
533 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
534 Error ("Symbol `%s' is already different kind", Entry->Name);
537 /* Insert entry into table ### */
539 /* Skip the identifier */
542 Error ("Identifier expected");
545 /* Remember we have an extra type decl */
546 D->Flags |= DS_EXTRA_TYPE;
547 /* Parse the enum decl */
554 Entry = FindSym (CurTok.Ident);
555 if (Entry && SymIsTypeDef (Entry)) {
558 TypeCpy (D->Type, Entry->Type);
565 Error ("Type expected");
569 D->Flags |= DS_DEF_TYPE;
570 D->Type[0] = (type) Default;
576 /* There may also be qualifiers *after* the initial type */
577 D->Type[0] |= OptionalQualifiers (Qualifiers);
582 static type* ParamTypeCvt (type* T)
583 /* If T is an array, convert it to a pointer else do nothing. Return the
587 if (IsTypeArray (T)) {
596 static void ParseOldStyleParamList (FuncDesc* F)
597 /* Parse an old style (K&R) parameter list */
600 while (CurTok.Tok != TOK_RPAREN) {
602 /* List of identifiers expected */
603 if (CurTok.Tok != TOK_IDENT) {
604 Error ("Identifier expected");
607 /* Create a symbol table entry with type int */
608 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
610 /* Count arguments */
613 /* Skip the identifier */
616 /* Check for more parameters */
617 if (CurTok.Tok == TOK_COMMA) {
624 /* Skip right paren. We must explicitly check for one here, since some of
625 * the breaks above bail out without checking.
629 /* An optional list of type specifications follows */
630 while (CurTok.Tok != TOK_LCURLY) {
634 /* Read the declaration specifier */
635 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
637 /* We accept only auto and register as storage class specifiers, but
638 * we ignore all this, since we use auto anyway.
640 if ((Spec.StorageClass & SC_AUTO) == 0 &&
641 (Spec.StorageClass & SC_REGISTER) == 0) {
642 Error ("Illegal storage class");
645 /* Parse a comma separated variable list */
650 /* Read the parameter */
651 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
652 if (Decl.Ident[0] != '\0') {
654 /* We have a name given. Search for the symbol */
655 SymEntry* Sym = FindLocalSym (Decl.Ident);
657 /* Found it, change the default type to the one given */
658 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
660 Error ("Unknown identifier: `%s'", Decl.Ident);
664 if (CurTok.Tok == TOK_COMMA) {
672 /* Variable list must be semicolon terminated */
679 static void ParseAnsiParamList (FuncDesc* F)
680 /* Parse a new style (ANSI) parameter list */
683 while (CurTok.Tok != TOK_RPAREN) {
689 /* Allow an ellipsis as last parameter */
690 if (CurTok.Tok == TOK_ELLIPSIS) {
692 F->Flags |= FD_VARIADIC;
696 /* Read the declaration specifier */
697 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
699 /* We accept only auto and register as storage class specifiers */
700 if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
701 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
702 } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
703 Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
705 Error ("Illegal storage class");
706 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
709 /* Allow parameters without a name, but remember if we had some to
710 * eventually print an error message later.
712 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
713 if (Decl.Ident[0] == '\0') {
715 /* Unnamed symbol. Generate a name that is not user accessible,
716 * then handle the symbol normal.
718 AnonName (Decl.Ident, "param");
719 F->Flags |= FD_UNNAMED_PARAMS;
721 /* Clear defined bit on nonames */
722 Spec.StorageClass &= ~SC_DEF;
725 /* Parse an attribute ### */
726 ParseAttribute (&Decl, &Attr);
728 /* Create a symbol table entry */
729 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
731 /* Count arguments */
734 /* Check for more parameters */
735 if (CurTok.Tok == TOK_COMMA) {
742 /* Skip right paren. We must explicitly check for one here, since some of
743 * the breaks above bail out without checking.
747 /* Check if this is a function definition */
748 if (CurTok.Tok == TOK_LCURLY) {
749 /* Print an error if in strict ANSI mode and we have unnamed
752 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
753 Error ("Parameter name omitted");
760 static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
761 /* Parse the argument list of a function. */
766 /* Create a new function descriptor */
767 FuncDesc* F = NewFuncDesc ();
769 /* Enter a new lexical level */
770 EnterFunctionLevel ();
772 /* Check for several special parameter lists */
773 if (CurTok.Tok == TOK_RPAREN) {
774 /* Parameter list is empty */
775 F->Flags |= (FD_EMPTY | FD_VARIADIC);
776 } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
777 /* Parameter list declared as void */
779 F->Flags |= FD_VOID_PARAM;
780 } else if (CurTok.Tok == TOK_IDENT &&
781 (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
782 /* If the identifier is a typedef, we have a new style parameter list,
783 * if it's some other identifier, it's an old style parameter list.
785 Sym = FindSym (CurTok.Ident);
786 if (Sym == 0 || !SymIsTypeDef (Sym)) {
787 /* Old style (K&R) function. Assume variable param list. */
788 F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
792 /* Check for an implicit int return in the function */
793 if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
794 Spec->Type[0] == T_INT &&
795 Spec->Type[1] == T_END) {
796 /* Function has an implicit int return */
797 F->Flags |= FD_OLDSTYLE_INTRET;
801 if ((F->Flags & FD_OLDSTYLE) == 0) {
802 /* New style function */
803 ParseAnsiParamList (F);
805 /* Old style function */
806 ParseOldStyleParamList (F);
809 /* Assign offsets. If the function has a variable parameter list,
810 * there's one additional byte (the arg size).
812 Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
813 Sym = GetSymTab()->SymTail;
815 unsigned Size = CheckedSizeOf (Sym->Type);
816 if (SymIsRegVar (Sym)) {
817 Sym->V.R.SaveOffs = Offs;
822 F->ParamSize += Size;
826 /* Leave the lexical level remembering the symbol tables */
827 RememberFunctionLevel (F);
829 /* Return the function descriptor */
835 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
836 /* Recursively process declarators. Build a type array in reverse order. */
839 if (CurTok.Tok == TOK_STAR) {
842 /* Allow optional const or volatile qualifiers */
843 T |= OptionalQualifiers (T_QUAL_NONE);
844 Decl (Spec, D, Mode);
847 } else if (CurTok.Tok == TOK_LPAREN) {
849 Decl (Spec, D, Mode);
851 } else if (CurTok.Tok == TOK_FASTCALL) {
852 /* Remember the current type pointer */
854 /* Skip the fastcall token */
856 /* Parse the function */
857 Decl (Spec, D, Mode);
858 /* Set the fastcall flag */
859 if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
860 Error ("__fastcall__ modifier applied to non function");
861 } else if (IsVariadicFunc (T)) {
862 Error ("Cannot apply __fastcall__ to functions with variable parameter list");
864 FuncDesc* F = GetFuncDesc (T);
865 F->Flags |= FD_FASTCALL;
869 /* Things depend on Mode now:
870 * - Mode == DM_NEED_IDENT means:
871 * we *must* have a type and a variable identifer.
872 * - Mode == DM_NO_IDENT means:
873 * we must have a type but no variable identifer
874 * (if there is one, it's not read).
875 * - Mode == DM_ACCEPT_IDENT means:
876 * we *may* have an identifier. If there is an identifier,
877 * it is read, but it is no error, if there is none.
879 if (Mode == DM_NO_IDENT) {
881 } else if (CurTok.Tok == TOK_IDENT) {
882 strcpy (D->Ident, CurTok.Ident);
885 if (Mode == DM_NEED_IDENT) {
886 Error ("Identifier expected");
892 while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
893 if (CurTok.Tok == TOK_LPAREN) {
894 /* Function declaration */
897 /* Parse the function declaration */
898 F = ParseFuncDecl (Spec);
903 /* Array declaration */
904 long Size = UNSPECIFIED;
906 /* Read the size if it is given */
907 if (CurTok.Tok != TOK_RBRACK) {
910 if (lval.ConstVal <= 0) {
911 if (D->Ident[0] != '\0') {
912 Error ("Size of array `%s' is invalid", D->Ident);
914 Error ("Size of array is invalid");
918 Size = lval.ConstVal;
930 /*****************************************************************************/
932 /*****************************************************************************/
936 type* ParseType (type* Type)
937 /* Parse a complete type specification */
942 /* Get a type without a default */
943 InitDeclSpec (&Spec);
944 ParseTypeSpec (&Spec, -1);
946 /* Parse additional declarators */
947 InitDeclaration (&Decl);
948 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
950 /* Copy the type to the target buffer */
951 TypeCpy (Type, Decl.Type);
953 /* Return a pointer to the target buffer */
959 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
960 /* Parse a variable, type or function declaration */
962 /* Initialize the Declaration struct */
965 /* Get additional declarators and the identifier */
966 Decl (Spec, D, Mode);
968 /* Add the base type. */
969 TypeCpy (D->T, Spec->Type);
971 /* Check the size of the generated type */
972 if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
973 if (D->Ident[0] != '\0') {
974 Error ("Size of `%s' is invalid", D->Ident);
976 Error ("Invalid size");
983 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
984 /* Parse a declaration specification */
986 /* Initialize the DeclSpec struct */
989 /* First, get the storage class specifier for this declaration */
990 ParseStorageClass (D, DefStorage);
992 /* Parse the type specifiers */
993 ParseTypeSpec (D, DefType);
998 void CheckEmptyDecl (const DeclSpec* D)
999 /* Called after an empty type declaration (that is, a type declaration without
1000 * a variable). Checks if the declaration does really make sense and issues a
1004 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
1005 Warning ("Useless declaration");
1011 static void SkipInitializer (unsigned BracesExpected)
1012 /* Skip the remainder of an initializer in case of errors. Try to be somewhat
1013 * smart so we don't have too many following errors.
1016 while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
1017 switch (CurTok.Tok) {
1018 case TOK_RCURLY: --BracesExpected; break;
1019 case TOK_LCURLY: ++BracesExpected; break;
1028 static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
1029 /* Accept any number of opening curly braces around an initialization, skip
1030 * them and return the number. If the number of curly braces is less than
1031 * BracesNeeded, issue a warning.
1034 unsigned BraceCount = 0;
1035 while (CurTok.Tok == TOK_LCURLY) {
1039 if (BraceCount < BracesNeeded) {
1040 Error ("`{' expected");
1047 static void ClosingCurlyBraces (unsigned BracesExpected)
1048 /* Accept and skip the given number of closing curly braces together with
1049 * an optional comma. Output an error messages, if the input does not contain
1050 * the expected number of braces.
1053 while (BracesExpected) {
1054 if (CurTok.Tok == TOK_RCURLY) {
1056 } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) {
1060 Error ("`}' expected");
1069 static unsigned ParseScalarInit (type* T)
1070 /* Parse initializaton for scalar data types. Return the number of data bytes. */
1072 static const unsigned long Masks[] = {
1073 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
1075 unsigned BraceCount;
1078 /* Get the size of the expected type */
1079 unsigned Size = SizeOf (T);
1080 CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
1082 /* Optional opening brace */
1083 BraceCount = OpeningCurlyBraces (0);
1085 /* We warn if an initializer for a scalar contains braces, because this is
1086 * quite unusual and often a sign for some problem in the input.
1088 if (BraceCount > 0) {
1089 Warning ("Braces around scalar initializer");
1094 if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1095 /* Make the const value the correct size */
1096 ED.ConstVal &= Masks[Size-1];
1098 assignadjust (T, &ED);
1100 /* Output the data */
1103 /* Close eventually opening braces */
1104 ClosingCurlyBraces (BraceCount);
1112 static unsigned ParsePointerInit (type* T)
1113 /* Parse initializaton for pointer data types. Return the number of data bytes. */
1115 /* Optional opening brace */
1116 unsigned BraceCount = OpeningCurlyBraces (0);
1121 if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1122 /* Make the const value the correct size */
1123 ED.ConstVal &= 0xFFFF;
1125 assignadjust (T, &ED);
1127 /* Output the data */
1130 /* Close eventually opening braces */
1131 ClosingCurlyBraces (BraceCount);
1139 static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
1140 /* Parse initializaton for arrays. Return the number of data bytes. */
1144 /* Get the array data */
1145 type* ElementType = GetElementType (T);
1146 unsigned ElementSize = CheckedSizeOf (ElementType);
1147 long ElementCount = GetElementCount (T);
1149 /* Special handling for a character array initialized by a literal */
1150 if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) {
1152 /* Char array initialized by string constant */
1153 const char* Str = GetLiteral (CurTok.IVal);
1154 Count = GetLiteralPoolOffs () - CurTok.IVal;
1156 /* Translate into target charset */
1157 TranslateLiteralPool (CurTok.IVal);
1158 g_defbytes (Str, Count);
1160 /* Remove string from pool */
1161 ResetLiteralPoolOffs (CurTok.IVal);
1169 /* Initialize the array members */
1171 while (CurTok.Tok != TOK_RCURLY) {
1172 /* Flexible array members may not be initialized within
1173 * an array (because the size of each element may differ
1176 ParseInitInternal (ElementType, 0);
1178 if (CurTok.Tok != TOK_COMMA)
1183 /* Closing curly braces */
1188 if (ElementCount == UNSPECIFIED) {
1189 /* Number of elements determined by initializer */
1190 Encode (T + 1, Count);
1191 ElementCount = Count;
1192 } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
1193 /* In non ANSI mode, allow initialization of flexible array
1196 ElementCount = Count;
1197 } else if (Count < ElementCount) {
1198 g_zerobytes ((ElementCount - Count) * ElementSize);
1199 } else if (Count > ElementCount) {
1200 Error ("Too many initializers");
1202 return ElementCount * ElementSize;
1207 static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
1208 /* Parse initialization of a struct or union. Return the number of data bytes. */
1212 unsigned StructSize;
1216 /* Consume the opening curly brace */
1219 /* Get a pointer to the struct entry from the type */
1220 Entry = DecodePtr (Type + 1);
1222 /* Get the size of the struct from the symbol table entry */
1223 StructSize = Entry->V.S.Size;
1225 /* Check if this struct definition has a field table. If it doesn't, it
1226 * is an incomplete definition.
1228 Tab = Entry->V.S.SymTab;
1230 Error ("Cannot initialize variables with incomplete type");
1231 /* Try error recovery */
1232 SkipInitializer (1);
1233 /* Nothing initialized */
1237 /* Get a pointer to the list of symbols */
1238 Entry = Tab->SymHead;
1240 /* Initialize fields */
1242 while (CurTok.Tok != TOK_RCURLY) {
1244 Error ("Too many initializers");
1245 SkipInitializer (1);
1248 /* Parse initialization of one field. Flexible array members may
1249 * only be initialized if they are the last field (or part of the
1250 * last struct field).
1252 Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
1253 Entry = Entry->NextSym;
1254 if (CurTok.Tok != TOK_COMMA)
1259 /* Consume the closing curly brace */
1262 /* If there are struct fields left, reserve additional storage */
1263 if (Size < StructSize) {
1264 g_zerobytes (StructSize - Size);
1268 /* Return the actual number of bytes initialized. This number may be
1269 * larger than StructSize if flexible array members are present and were
1270 * initialized (possible in non ANSI mode).
1277 static unsigned ParseVoidInit (void)
1278 /* Parse an initialization of a void variable (special cc65 extension).
1279 * Return the number of bytes initialized.
1288 /* Allow an arbitrary list of values */
1292 switch (UnqualifiedType (lval.Type[0])) {
1296 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1297 /* Make it byte sized */
1298 lval.ConstVal &= 0xFF;
1301 Size += SIZEOF_CHAR;
1310 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1311 /* Make it word sized */
1312 lval.ConstVal &= 0xFFFF;
1321 Size += SIZEOF_LONG;
1325 Error ("Illegal type in initialization");
1330 if (CurTok.Tok != TOK_COMMA) {
1335 } while (CurTok.Tok != TOK_RCURLY);
1340 /* Return the number of bytes initialized */
1346 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
1347 /* Parse initialization of variables. Return the number of data bytes. */
1349 switch (UnqualifiedType (*T)) {
1359 return ParseScalarInit (T);
1362 return ParsePointerInit (T);
1365 return ParseArrayInit (T, AllowFlexibleMembers);
1369 return ParseStructInit (T, AllowFlexibleMembers);
1373 /* Special cc65 extension in non ANSI mode */
1374 return ParseVoidInit ();
1379 Error ("Illegal type");
1387 unsigned ParseInit (type* T)
1388 /* Parse initialization of variables. Return the number of data bytes. */
1390 return ParseInitInternal (T, !ANSI);