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 */
72 /*****************************************************************************/
73 /* internal functions */
74 /*****************************************************************************/
78 static type OptionalQualifiers (type Q)
79 /* Read type qualifiers if we have any */
81 while (CurTok.Tok == TOK_CONST || CurTok.Tok == TOK_VOLATILE) {
86 if (Q & T_QUAL_CONST) {
87 Error ("Duplicate qualifier: `const'");
93 if (Q & T_QUAL_VOLATILE) {
94 Error ("Duplicate qualifier: `volatile'");
100 /* Keep gcc silent */
109 /* Return the qualifiers read */
115 static void optionalint (void)
116 /* Eat an optional "int" token */
118 if (CurTok.Tok == TOK_INT) {
126 static void optionalsigned (void)
127 /* Eat an optional "signed" token */
129 if (CurTok.Tok == TOK_SIGNED) {
137 static void InitDeclSpec (DeclSpec* D)
138 /* Initialize the DeclSpec struct for use */
147 static void InitDeclaration (Declaration* D)
148 /* Initialize the Declaration struct for use */
157 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
158 /* Parse a storage class */
160 /* Assume we're using an explicit storage class */
161 D->Flags &= ~DS_DEF_STORAGE;
163 /* Check the storage class given */
164 switch (CurTok.Tok) {
167 D->StorageClass = SC_EXTERN | SC_STATIC;
172 D->StorageClass = SC_STATIC;
177 D->StorageClass = SC_REGISTER | SC_STATIC;
182 D->StorageClass = SC_AUTO;
187 D->StorageClass = SC_TYPEDEF;
192 /* No storage class given, use default */
193 D->Flags |= DS_DEF_STORAGE;
194 D->StorageClass = DefStorage;
201 static void ParseEnumDecl (void)
202 /* Process an enum declaration . */
207 /* Accept forward definitions */
208 if (CurTok.Tok != TOK_LCURLY) {
212 /* Skip the opening curly brace */
215 /* Read the enum tags */
217 while (CurTok.Tok != TOK_RCURLY) {
219 /* We expect an identifier */
220 if (CurTok.Tok != TOK_IDENT) {
221 Error ("Identifier expected");
225 /* Remember the identifier and skip it */
226 strcpy (Ident, CurTok.Ident);
229 /* Check for an assigned value */
230 if (CurTok.Tok == TOK_ASSIGN) {
234 EnumVal = lval.ConstVal;
237 /* Add an entry to the symbol table */
238 AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
240 /* Check for end of definition */
241 if (CurTok.Tok != TOK_COMMA)
250 static SymEntry* ParseStructDecl (const char* Name, type StructType)
251 /* Parse a struct/union declaration. */
262 if (CurTok.Tok != TOK_LCURLY) {
263 /* Just a forward declaration. Try to find a struct with the given
264 * name. If there is none, insert a forward declaration into the
265 * current lexical level.
267 Entry = FindTagSym (Name);
269 Entry = AddStructSym (Name, 0, 0);
270 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
271 /* Already defined in the level but no struct */
272 Error ("Symbol `%s' is already different kind", Name);
277 /* Add a forward declaration for the struct in the current lexical level */
278 Entry = AddStructSym (Name, 0, 0);
280 /* Skip the curly brace */
283 /* Enter a new lexical level for the struct */
286 /* Parse struct fields */
289 while (CurTok.Tok != TOK_RCURLY) {
291 /* Get the type of the entry */
293 InitDeclSpec (&Spec);
294 ParseTypeSpec (&Spec, -1);
296 /* Read fields with this type */
301 /* If we had a flexible array member before, no other fields can
304 if (FlexibleMember) {
305 Error ("Flexible array member must be last field");
306 FlexibleMember = 0; /* Avoid further errors */
309 /* Get type and name of the struct field */
310 ParseDecl (&Spec, &Decl, 0);
312 /* Get the offset of this field */
313 Offs = (StructType == T_STRUCT)? StructSize : 0;
315 /* Calculate the sizes, handle flexible array members */
316 if (StructType == T_STRUCT) {
318 /* It's a struct. Check if this field is a flexible array
319 * member, and calculate the size of the field.
321 if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
322 /* Array with unspecified size */
323 if (StructSize == 0) {
324 Error ("Flexible array member cannot be first struct field");
327 /* Assume zero for size calculations */
328 Encode (Decl.Type + 1, 0);
330 StructSize += CheckedSizeOf (Decl.Type);
336 FieldSize = CheckedSizeOf (Decl.Type);
337 if (FieldSize > StructSize) {
338 StructSize = FieldSize;
342 /* Add a field entry to the table */
343 AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
345 if (CurTok.Tok != TOK_COMMA) {
353 /* Skip the closing brace */
356 /* Remember the symbol table and leave the struct level */
357 FieldTab = GetSymTab ();
360 /* Make a real entry from the forward decl and return it */
361 return AddStructSym (Name, StructSize, FieldTab);
366 static void ParseTypeSpec (DeclSpec* D, int Default)
367 /* Parse a type specificier */
372 type Qualifiers; /* Type qualifiers */
374 /* Assume we have an explicit type */
375 D->Flags &= ~DS_DEF_TYPE;
377 /* Read type qualifiers if we have any */
378 Qualifiers = OptionalQualifiers (T_QUAL_NONE);
380 /* Look at the data type */
381 switch (CurTok.Tok) {
391 D->Type[0] = GetDefaultChar();
397 if (CurTok.Tok == TOK_UNSIGNED) {
400 D->Type[0] = T_ULONG;
412 if (CurTok.Tok == TOK_UNSIGNED) {
415 D->Type[0] = T_USHORT;
420 D->Type[0] = T_SHORT;
433 switch (CurTok.Tok) {
437 D->Type[0] = T_SCHAR;
444 D->Type[0] = T_SHORT;
468 switch (CurTok.Tok) {
472 D->Type[0] = T_UCHAR;
479 D->Type[0] = T_USHORT;
486 D->Type[0] = T_ULONG;
503 StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
506 if (CurTok.Tok == TOK_IDENT) {
507 strcpy (Ident, CurTok.Ident);
510 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
512 /* Remember we have an extra type decl */
513 D->Flags |= DS_EXTRA_TYPE;
514 /* Declare the struct in the current scope */
515 Entry = ParseStructDecl (Ident, StructType);
516 /* Encode the struct entry into the type */
517 D->Type[0] = StructType;
518 EncodePtr (D->Type+1, Entry);
519 D->Type[DECODE_SIZE+1] = T_END;
524 if (CurTok.Tok != TOK_LCURLY) {
526 if (CurTok.Tok == TOK_IDENT) {
527 /* Find an entry with this name */
528 Entry = FindTagSym (CurTok.Ident);
530 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
531 Error ("Symbol `%s' is already different kind", Entry->Name);
534 /* Insert entry into table ### */
536 /* Skip the identifier */
539 Error ("Identifier expected");
542 /* Remember we have an extra type decl */
543 D->Flags |= DS_EXTRA_TYPE;
544 /* Parse the enum decl */
551 Entry = FindSym (CurTok.Ident);
552 if (Entry && SymIsTypeDef (Entry)) {
555 TypeCpy (D->Type, Entry->Type);
562 Error ("Type expected");
566 D->Flags |= DS_DEF_TYPE;
567 D->Type[0] = (type) Default;
573 /* There may also be qualifiers *after* the initial type */
574 D->Type[0] |= OptionalQualifiers (Qualifiers);
579 static type* ParamTypeCvt (type* T)
580 /* If T is an array, convert it to a pointer else do nothing. Return the
584 if (IsTypeArray (T)) {
593 static void ParseOldStyleParamList (FuncDesc* F)
594 /* Parse an old style (K&R) parameter list */
597 while (CurTok.Tok != TOK_RPAREN) {
599 /* List of identifiers expected */
600 if (CurTok.Tok != TOK_IDENT) {
601 Error ("Identifier expected");
604 /* Create a symbol table entry with type int */
605 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
607 /* Count arguments */
610 /* Skip the identifier */
613 /* Check for more parameters */
614 if (CurTok.Tok == TOK_COMMA) {
621 /* Skip right paren. We must explicitly check for one here, since some of
622 * the breaks above bail out without checking.
626 /* An optional list of type specifications follows */
627 while (CurTok.Tok != TOK_LCURLY) {
631 /* Read the declaration specifier */
632 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
634 /* We accept only auto and register as storage class specifiers, but
635 * we ignore all this, since we use auto anyway.
637 if ((Spec.StorageClass & SC_AUTO) == 0 &&
638 (Spec.StorageClass & SC_REGISTER) == 0) {
639 Error ("Illegal storage class");
642 /* Parse a comma separated variable list */
647 /* Read the parameter */
648 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
649 if (Decl.Ident[0] != '\0') {
651 /* We have a name given. Search for the symbol */
652 SymEntry* Sym = FindLocalSym (Decl.Ident);
654 /* Found it, change the default type to the one given */
655 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
657 Error ("Unknown identifier: `%s'", Decl.Ident);
661 if (CurTok.Tok == TOK_COMMA) {
669 /* Variable list must be semicolon terminated */
676 static void ParseAnsiParamList (FuncDesc* F)
677 /* Parse a new style (ANSI) parameter list */
680 while (CurTok.Tok != TOK_RPAREN) {
686 /* Allow an ellipsis as last parameter */
687 if (CurTok.Tok == TOK_ELLIPSIS) {
689 F->Flags |= FD_VARIADIC;
693 /* Read the declaration specifier */
694 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
696 /* We accept only auto and register as storage class specifiers */
697 if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) {
698 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
699 } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) {
700 Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF;
702 Error ("Illegal storage class");
703 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
706 /* Allow parameters without a name, but remember if we had some to
707 * eventually print an error message later.
709 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
710 if (Decl.Ident[0] == '\0') {
712 /* Unnamed symbol. Generate a name that is not user accessible,
713 * then handle the symbol normal.
715 AnonName (Decl.Ident, "param");
716 F->Flags |= FD_UNNAMED_PARAMS;
718 /* Clear defined bit on nonames */
719 Spec.StorageClass &= ~SC_DEF;
722 /* Parse an attribute ### */
723 ParseAttribute (&Decl, &Attr);
725 /* Create a symbol table entry */
726 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
728 /* Count arguments */
731 /* Check for more parameters */
732 if (CurTok.Tok == TOK_COMMA) {
739 /* Skip right paren. We must explicitly check for one here, since some of
740 * the breaks above bail out without checking.
744 /* Check if this is a function definition */
745 if (CurTok.Tok == TOK_LCURLY) {
746 /* Print an error if in strict ANSI mode and we have unnamed
749 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
750 Error ("Parameter name omitted");
757 static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
758 /* Parse the argument list of a function. */
763 /* Create a new function descriptor */
764 FuncDesc* F = NewFuncDesc ();
766 /* Enter a new lexical level */
767 EnterFunctionLevel ();
769 /* Check for several special parameter lists */
770 if (CurTok.Tok == TOK_RPAREN) {
771 /* Parameter list is empty */
772 F->Flags |= (FD_EMPTY | FD_VARIADIC);
773 } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
774 /* Parameter list declared as void */
776 F->Flags |= FD_VOID_PARAM;
777 } else if (CurTok.Tok == TOK_IDENT &&
778 (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
779 /* If the identifier is a typedef, we have a new style parameter list,
780 * if it's some other identifier, it's an old style parameter list.
782 Sym = FindSym (CurTok.Ident);
783 if (Sym == 0 || !SymIsTypeDef (Sym)) {
784 /* Old style (K&R) function. Assume variable param list. */
785 F->Flags |= (FD_OLDSTYLE | FD_VARIADIC);
789 /* Check for an implicit int return in the function */
790 if ((Spec->Flags & DS_DEF_TYPE) != 0 &&
791 Spec->Type[0] == T_INT &&
792 Spec->Type[1] == T_END) {
793 /* Function has an implicit int return */
794 F->Flags |= FD_OLDSTYLE_INTRET;
798 if ((F->Flags & FD_OLDSTYLE) == 0) {
799 /* New style function */
800 ParseAnsiParamList (F);
802 /* Old style function */
803 ParseOldStyleParamList (F);
806 /* Assign offsets. If the function has a variable parameter list,
807 * there's one additional byte (the arg size).
809 Offs = (F->Flags & FD_VARIADIC)? 1 : 0;
810 Sym = GetSymTab()->SymTail;
812 unsigned Size = CheckedSizeOf (Sym->Type);
813 if (SymIsRegVar (Sym)) {
814 Sym->V.R.SaveOffs = Offs;
819 F->ParamSize += Size;
823 /* Leave the lexical level remembering the symbol tables */
824 RememberFunctionLevel (F);
826 /* Return the function descriptor */
832 static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
833 /* Recursively process declarators. Build a type array in reverse order. */
836 if (CurTok.Tok == TOK_STAR) {
839 /* Allow optional const or volatile qualifiers */
840 T |= OptionalQualifiers (T_QUAL_NONE);
841 Decl (Spec, D, Mode);
844 } else if (CurTok.Tok == TOK_LPAREN) {
846 Decl (Spec, D, Mode);
848 } else if (CurTok.Tok == TOK_FASTCALL) {
849 /* Remember the current type pointer */
851 /* Skip the fastcall token */
853 /* Parse the function */
854 Decl (Spec, D, Mode);
855 /* Set the fastcall flag */
856 if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
857 Error ("__fastcall__ modifier applied to non function");
858 } else if (IsVariadicFunc (T)) {
859 Error ("Cannot apply __fastcall__ to functions with variable parameter list");
861 FuncDesc* F = GetFuncDesc (T);
862 F->Flags |= FD_FASTCALL;
866 /* Things depend on Mode now:
867 * - Mode == DM_NEED_IDENT means:
868 * we *must* have a type and a variable identifer.
869 * - Mode == DM_NO_IDENT means:
870 * we must have a type but no variable identifer
871 * (if there is one, it's not read).
872 * - Mode == DM_ACCEPT_IDENT means:
873 * we *may* have an identifier. If there is an identifier,
874 * it is read, but it is no error, if there is none.
876 if (Mode == DM_NO_IDENT) {
878 } else if (CurTok.Tok == TOK_IDENT) {
879 strcpy (D->Ident, CurTok.Ident);
882 if (Mode == DM_NEED_IDENT) {
883 Error ("Identifier expected");
889 while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
890 if (CurTok.Tok == TOK_LPAREN) {
891 /* Function declaration */
894 /* Parse the function declaration */
895 F = ParseFuncDecl (Spec);
900 /* Array declaration */
901 long Size = UNSPECIFIED;
903 /* Read the size if it is given */
904 if (CurTok.Tok != TOK_RBRACK) {
907 if (lval.ConstVal <= 0) {
908 if (D->Ident[0] != '\0') {
909 Error ("Size of array `%s' is invalid", D->Ident);
911 Error ("Size of array is invalid");
915 Size = lval.ConstVal;
927 /*****************************************************************************/
929 /*****************************************************************************/
933 type* ParseType (type* Type)
934 /* Parse a complete type specification */
939 /* Get a type without a default */
940 InitDeclSpec (&Spec);
941 ParseTypeSpec (&Spec, -1);
943 /* Parse additional declarators */
944 InitDeclaration (&Decl);
945 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
947 /* Copy the type to the target buffer */
948 TypeCpy (Type, Decl.Type);
950 /* Return a pointer to the target buffer */
956 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
957 /* Parse a variable, type or function declaration */
959 /* Initialize the Declaration struct */
962 /* Get additional declarators and the identifier */
963 Decl (Spec, D, Mode);
965 /* Add the base type. */
966 TypeCpy (D->T, Spec->Type);
968 /* Check the size of the generated type */
969 if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
970 if (D->Ident[0] != '\0') {
971 Error ("Size of `%s' is invalid", D->Ident);
973 Error ("Invalid size");
980 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
981 /* Parse a declaration specification */
983 /* Initialize the DeclSpec struct */
986 /* First, get the storage class specifier for this declaration */
987 ParseStorageClass (D, DefStorage);
989 /* Parse the type specifiers */
990 ParseTypeSpec (D, DefType);
995 void CheckEmptyDecl (const DeclSpec* D)
996 /* Called after an empty type declaration (that is, a type declaration without
997 * a variable). Checks if the declaration does really make sense and issues a
1001 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
1002 Warning ("Useless declaration");
1008 static unsigned ParseVoidInit (void)
1009 /* Parse an initialization of a void variable (special cc65 extension).
1010 * Return the number of bytes initialized.
1018 /* Allow an arbitrary list of values */
1022 switch (UnqualifiedType (lval.Type[0])) {
1026 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1027 /* Make it byte sized */
1028 lval.ConstVal &= 0xFF;
1031 Size += SIZEOF_CHAR;
1040 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1041 /* Make it word sized */
1042 lval.ConstVal &= 0xFFFF;
1051 Size += SIZEOF_LONG;
1055 Error ("Illegal type in initialization");
1060 if (CurTok.Tok != TOK_COMMA) {
1065 } while (CurTok.Tok != TOK_RCURLY);
1070 /* Return the number of bytes initialized */
1076 static unsigned ParseStructInit (type* Type)
1077 /* Parse initialization of a struct or union. Return the number of data bytes. */
1081 unsigned StructSize;
1084 /* Consume the opening curly brace */
1087 /* Get a pointer to the struct entry from the type */
1088 Entry = DecodePtr (Type + 1);
1090 /* Get the size of the struct from the symbol table entry */
1091 StructSize = Entry->V.S.Size;
1093 /* Check if this struct definition has a field table. If it doesn't, it
1094 * is an incomplete definition.
1096 Tab = Entry->V.S.SymTab;
1098 Error ("Cannot initialize variables with incomplete type");
1099 /* Returning here will cause lots of errors, but recovery is difficult */
1103 /* Get a pointer to the list of symbols */
1104 Entry = Tab->SymHead;
1106 /* Initialize fields */
1108 while (CurTok.Tok != TOK_RCURLY) {
1110 Error ("Too many initializers");
1113 Size += ParseInit (Entry->Type);
1114 Entry = Entry->NextSym;
1115 if (CurTok.Tok != TOK_COMMA)
1120 /* Consume the closing curly brace */
1123 /* If there are struct fields left, reserve additional storage */
1124 if (Size < StructSize) {
1125 g_zerobytes (StructSize - Size);
1128 /* Return the number of bytes initialized */
1134 unsigned ParseInit (type* T)
1135 /* Parse initialization of variables. Return the number of data bytes. */
1142 unsigned ElementSize;
1144 switch (UnqualifiedType (*T)) {
1149 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1150 /* Make it byte sized */
1151 lval.ConstVal &= 0xFF;
1153 assignadjust (T, &lval);
1163 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1164 /* Make it word sized */
1165 lval.ConstVal &= 0xFFFF;
1167 assignadjust (T, &lval);
1174 if ((lval.Flags & E_MCTYPE) == E_TCONST) {
1175 /* Make it long sized */
1176 lval.ConstVal &= 0xFFFFFFFF;
1178 assignadjust (T, &lval);
1183 ElementCount = GetElementCount (T);
1184 ElementSize = CheckedSizeOf (T + DECODE_SIZE + 1);
1185 t = T + DECODE_SIZE + 1;
1186 if (IsTypeChar (t) && CurTok.Tok == TOK_SCONST) {
1187 str = GetLiteral (CurTok.IVal);
1188 Count = GetLiteralPoolOffs () - CurTok.IVal;
1189 TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */
1190 g_defbytes (str, Count);
1191 ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */
1196 while (CurTok.Tok != TOK_RCURLY) {
1197 ParseInit (T + DECODE_SIZE + 1);
1199 if (CurTok.Tok != TOK_COMMA)
1205 if (ElementCount == UNSPECIFIED) {
1206 Encode (T + 1, Count);
1207 } else if (Count < ElementCount) {
1208 g_zerobytes ((ElementCount - Count) * ElementSize);
1209 } else if (Count > ElementCount) {
1210 Error ("Too many initializers");
1212 return ElementCount * ElementSize;
1216 return ParseStructInit (T);
1220 /* Special cc65 extension in non ANSI mode */
1221 return ParseVoidInit ();
1226 Error ("Illegal type");