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 /* Remember the last function parameter. We need it later for several
810 * purposes, for example when passing stuff to fastcall functions. Since
811 * more symbols are added to the table, it is easier if we remember it
812 * now, since it is currently the last entry in the symbol table.
814 F->LastParam = GetSymTab()->SymTail;
816 /* Assign offsets. If the function has a variable parameter list,
817 * there's one additional byte (the arg size).
819 Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
822 unsigned Size = CheckedSizeOf (Sym->Type);
823 if (SymIsRegVar (Sym)) {
824 Sym->V.R.SaveOffs = Offs;
829 F->ParamSize += Size;
833 /* Leave the lexical level remembering the symbol tables */
834 RememberFunctionLevel (F);
836 /* Return the function descriptor */
842 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
843 /* Recursively process declarators. Build a type array in reverse order. */
846 if (CurTok.Tok == TOK_STAR) {
849 /* Allow optional const or volatile qualifiers */
850 T |= OptionalQualifiers (T_QUAL_NONE);
851 Decl (Spec, D, Mode);
854 } else if (CurTok.Tok == TOK_LPAREN) {
856 Decl (Spec, D, Mode);
858 } else if (CurTok.Tok == TOK_FASTCALL) {
859 /* Remember the current type pointer */
861 /* Skip the fastcall token */
863 /* Parse the function */
864 Decl (Spec, D, Mode);
865 /* Set the fastcall flag */
866 if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
867 Error ("__fastcall__ modifier applied to non function");
868 } else if (IsVariadicFunc (T)) {
869 Error ("Cannot apply __fastcall__ to functions with variable parameter list");
871 FuncDesc* F = GetFuncDesc (T);
872 F->Flags |= FD_FASTCALL;
876 /* Things depend on Mode now:
877 * - Mode == DM_NEED_IDENT means:
878 * we *must* have a type and a variable identifer.
879 * - Mode == DM_NO_IDENT means:
880 * we must have a type but no variable identifer
881 * (if there is one, it's not read).
882 * - Mode == DM_ACCEPT_IDENT means:
883 * we *may* have an identifier. If there is an identifier,
884 * it is read, but it is no error, if there is none.
886 if (Mode == DM_NO_IDENT) {
888 } else if (CurTok.Tok == TOK_IDENT) {
889 strcpy (D->Ident, CurTok.Ident);
892 if (Mode == DM_NEED_IDENT) {
893 Error ("Identifier expected");
899 while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
900 if (CurTok.Tok == TOK_LPAREN) {
901 /* Function declaration */
904 /* Parse the function declaration */
905 F = ParseFuncDecl (Spec);
910 /* Array declaration */
911 long Size = UNSPECIFIED;
913 /* Read the size if it is given */
914 if (CurTok.Tok != TOK_RBRACK) {
917 if (lval.ConstVal <= 0) {
918 if (D->Ident[0] != '\0') {
919 Error ("Size of array `%s' is invalid", D->Ident);
921 Error ("Size of array is invalid");
925 Size = lval.ConstVal;
937 /*****************************************************************************/
939 /*****************************************************************************/
943 type* ParseType (type* Type)
944 /* Parse a complete type specification */
949 /* Get a type without a default */
950 InitDeclSpec (&Spec);
951 ParseTypeSpec (&Spec, -1);
953 /* Parse additional declarators */
954 InitDeclaration (&Decl);
955 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
957 /* Copy the type to the target buffer */
958 TypeCpy (Type, Decl.Type);
960 /* Return a pointer to the target buffer */
966 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
967 /* Parse a variable, type or function declaration */
969 /* Initialize the Declaration struct */
972 /* Get additional declarators and the identifier */
973 Decl (Spec, D, Mode);
975 /* Add the base type. */
976 TypeCpy (D->T, Spec->Type);
978 /* Check the size of the generated type */
979 if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
980 if (D->Ident[0] != '\0') {
981 Error ("Size of `%s' is invalid", D->Ident);
983 Error ("Invalid size");
990 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
991 /* Parse a declaration specification */
993 /* Initialize the DeclSpec struct */
996 /* First, get the storage class specifier for this declaration */
997 ParseStorageClass (D, DefStorage);
999 /* Parse the type specifiers */
1000 ParseTypeSpec (D, DefType);
1005 void CheckEmptyDecl (const DeclSpec* D)
1006 /* Called after an empty type declaration (that is, a type declaration without
1007 * a variable). Checks if the declaration does really make sense and issues a
1011 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
1012 Warning ("Useless declaration");
1018 static void SkipInitializer (unsigned BracesExpected)
1019 /* Skip the remainder of an initializer in case of errors. Try to be somewhat
1020 * smart so we don't have too many following errors.
1023 while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) {
1024 switch (CurTok.Tok) {
1025 case TOK_RCURLY: --BracesExpected; break;
1026 case TOK_LCURLY: ++BracesExpected; break;
1035 static unsigned OpeningCurlyBraces (unsigned BracesNeeded)
1036 /* Accept any number of opening curly braces around an initialization, skip
1037 * them and return the number. If the number of curly braces is less than
1038 * BracesNeeded, issue a warning.
1041 unsigned BraceCount = 0;
1042 while (CurTok.Tok == TOK_LCURLY) {
1046 if (BraceCount < BracesNeeded) {
1047 Error ("`{' expected");
1054 static void ClosingCurlyBraces (unsigned BracesExpected)
1055 /* Accept and skip the given number of closing curly braces together with
1056 * an optional comma. Output an error messages, if the input does not contain
1057 * the expected number of braces.
1060 while (BracesExpected) {
1061 if (CurTok.Tok == TOK_RCURLY) {
1063 } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) {
1067 Error ("`}' expected");
1076 static unsigned ParseScalarInit (type* T)
1077 /* Parse initializaton for scalar data types. Return the number of data bytes. */
1079 static const unsigned long Masks[] = {
1080 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
1082 unsigned BraceCount;
1085 /* Get the size of the expected type */
1086 unsigned Size = SizeOf (T);
1087 CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
1089 /* Optional opening brace */
1090 BraceCount = OpeningCurlyBraces (0);
1092 /* We warn if an initializer for a scalar contains braces, because this is
1093 * quite unusual and often a sign for some problem in the input.
1095 if (BraceCount > 0) {
1096 Warning ("Braces around scalar initializer");
1101 if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1102 /* Make the const value the correct size */
1103 ED.ConstVal &= Masks[Size-1];
1105 assignadjust (T, &ED);
1107 /* Output the data */
1110 /* Close eventually opening braces */
1111 ClosingCurlyBraces (BraceCount);
1119 static unsigned ParsePointerInit (type* T)
1120 /* Parse initializaton for pointer data types. Return the number of data bytes. */
1122 /* Optional opening brace */
1123 unsigned BraceCount = OpeningCurlyBraces (0);
1128 if ((ED.Flags & E_MCTYPE) == E_TCONST) {
1129 /* Make the const value the correct size */
1130 ED.ConstVal &= 0xFFFF;
1132 assignadjust (T, &ED);
1134 /* Output the data */
1137 /* Close eventually opening braces */
1138 ClosingCurlyBraces (BraceCount);
1146 static unsigned ParseArrayInit (type* T, int AllowFlexibleMembers)
1147 /* Parse initializaton for arrays. Return the number of data bytes. */
1151 /* Get the array data */
1152 type* ElementType = GetElementType (T);
1153 unsigned ElementSize = CheckedSizeOf (ElementType);
1154 long ElementCount = GetElementCount (T);
1156 /* Special handling for a character array initialized by a literal */
1157 if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) {
1159 /* Char array initialized by string constant */
1160 const char* Str = GetLiteral (CurTok.IVal);
1161 Count = GetLiteralPoolOffs () - CurTok.IVal;
1163 /* Translate into target charset */
1164 TranslateLiteralPool (CurTok.IVal);
1166 /* If the array is one too small for the string literal, omit the
1169 if (ElementCount != UNSPECIFIED &&
1170 ElementCount != FLEXIBLE &&
1171 Count == ElementCount + 1) {
1172 /* Omit the trailing zero */
1176 /* Output the data */
1177 g_defbytes (Str, Count);
1179 /* Remove string from pool */
1180 ResetLiteralPoolOffs (CurTok.IVal);
1188 /* Initialize the array members */
1190 while (CurTok.Tok != TOK_RCURLY) {
1191 /* Flexible array members may not be initialized within
1192 * an array (because the size of each element may differ
1195 ParseInitInternal (ElementType, 0);
1197 if (CurTok.Tok != TOK_COMMA)
1202 /* Closing curly braces */
1207 if (ElementCount == UNSPECIFIED) {
1208 /* Number of elements determined by initializer */
1209 Encode (T + 1, Count);
1210 ElementCount = Count;
1211 } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) {
1212 /* In non ANSI mode, allow initialization of flexible array
1215 ElementCount = Count;
1216 } else if (Count < ElementCount) {
1217 g_zerobytes ((ElementCount - Count) * ElementSize);
1218 } else if (Count > ElementCount) {
1219 Error ("Too many initializers");
1221 return ElementCount * ElementSize;
1226 static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers)
1227 /* Parse initialization of a struct or union. Return the number of data bytes. */
1231 unsigned StructSize;
1235 /* Consume the opening curly brace */
1238 /* Get a pointer to the struct entry from the type */
1239 Entry = DecodePtr (Type + 1);
1241 /* Get the size of the struct from the symbol table entry */
1242 StructSize = Entry->V.S.Size;
1244 /* Check if this struct definition has a field table. If it doesn't, it
1245 * is an incomplete definition.
1247 Tab = Entry->V.S.SymTab;
1249 Error ("Cannot initialize variables with incomplete type");
1250 /* Try error recovery */
1251 SkipInitializer (1);
1252 /* Nothing initialized */
1256 /* Get a pointer to the list of symbols */
1257 Entry = Tab->SymHead;
1259 /* Initialize fields */
1261 while (CurTok.Tok != TOK_RCURLY) {
1263 Error ("Too many initializers");
1264 SkipInitializer (1);
1267 /* Parse initialization of one field. Flexible array members may
1268 * only be initialized if they are the last field (or part of the
1269 * last struct field).
1271 Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0);
1272 Entry = Entry->NextSym;
1273 if (CurTok.Tok != TOK_COMMA)
1278 /* Consume the closing curly brace */
1281 /* If there are struct fields left, reserve additional storage */
1282 if (Size < StructSize) {
1283 g_zerobytes (StructSize - Size);
1287 /* Return the actual number of bytes initialized. This number may be
1288 * larger than StructSize if flexible array members are present and were
1289 * initialized (possible in non ANSI mode).
1296 static unsigned ParseVoidInit (void)
1297 /* Parse an initialization of a void variable (special cc65 extension).
1298 * Return the number of bytes initialized.
1307 /* Allow an arbitrary list of values */
1311 switch (UnqualifiedType (lval.Type[0])) {
1315 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1316 /* Make it byte sized */
1317 lval.ConstVal &= 0xFF;
1320 Size += SIZEOF_CHAR;
1329 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1330 /* Make it word sized */
1331 lval.ConstVal &= 0xFFFF;
1340 Size += SIZEOF_LONG;
1344 Error ("Illegal type in initialization");
1349 if (CurTok.Tok != TOK_COMMA) {
1354 } while (CurTok.Tok != TOK_RCURLY);
1359 /* Return the number of bytes initialized */
1365 static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
1366 /* Parse initialization of variables. Return the number of data bytes. */
1368 switch (UnqualifiedType (*T)) {
1378 return ParseScalarInit (T);
1381 return ParsePointerInit (T);
1384 return ParseArrayInit (T, AllowFlexibleMembers);
1388 return ParseStructInit (T, AllowFlexibleMembers);
1392 /* Special cc65 extension in non ANSI mode */
1393 return ParseVoidInit ();
1398 Error ("Illegal type");
1406 unsigned ParseInit (type* T)
1407 /* Parse initialization of variables. Return the number of data bytes. */
1409 return ParseInitInternal (T, !ANSI);