4 * Ullrich von Bassewitz, 20.06.1998
14 #include "../common/xmalloc.h"
32 /*****************************************************************************/
34 /*****************************************************************************/
38 static void ParseTypeSpec (DeclSpec* D, int Default);
39 /* Parse a type specificier */
43 /*****************************************************************************/
44 /* internal functions */
45 /*****************************************************************************/
49 static void optional_modifiers (void)
50 /* Eat optional "const" or "volatile" tokens */
52 while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
60 static void optionalint (void)
61 /* Eat an optional "int" token */
63 if (curtok == TOK_INT) {
71 static void optionalsigned (void)
72 /* Eat an optional "signed" token */
74 if (curtok == TOK_SIGNED) {
82 static void InitDeclSpec (DeclSpec* D)
83 /* Initialize the DeclSpec struct for use */
92 static void InitDeclaration (Declaration* D)
93 /* Initialize the Declaration struct for use */
102 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
103 /* Parse a storage class */
105 /* Assume we're using an explicit storage class */
106 D->Flags &= ~DS_DEF_STORAGE;
108 /* Check the storage class given */
112 D->StorageClass = SC_EXTERN | SC_STATIC;
117 D->StorageClass = SC_STATIC;
122 D->StorageClass = SC_REGISTER | SC_STATIC;
127 D->StorageClass = SC_AUTO;
132 D->StorageClass = SC_TYPEDEF;
137 /* No storage class given, use default */
138 D->Flags |= DS_DEF_STORAGE;
139 D->StorageClass = DefStorage;
146 static void ParseEnumDecl (void)
147 /* Process an enum declaration . */
152 /* Accept forward definitions */
153 if (curtok != TOK_LCURLY) {
157 /* Skip the opening curly brace */
160 /* Read the enum tags */
162 while (curtok != TOK_RCURLY) {
164 /* We expect an identifier */
165 if (curtok != TOK_IDENT) {
166 Error (ERR_IDENT_EXPECTED);
170 /* Remember the identifier and skip it */
171 strcpy (Ident, CurTok.Ident);
174 /* Check for an assigned value */
175 if (curtok == TOK_ASSIGN) {
179 EnumVal = lval.e_const;
182 /* Add an entry to the symbol table */
183 AddEnumSym (Ident, EnumVal++);
185 /* Check for end of definition */
186 if (curtok != TOK_COMMA)
195 static SymEntry* ParseStructDecl (const char* Name, type StructType)
196 /* Parse a struct/union declaration. */
205 if (curtok != TOK_LCURLY) {
206 /* Just a forward declaration. Try to find a struct with the given
207 * name. If there is none, insert a forward declaration into the
208 * current lexical level.
210 Entry = FindTagSym (Name);
212 Entry = AddStructSym (Name, 0, 0);
213 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
214 /* Already defined in the level but no struct */
215 Error (ERR_SYMBOL_KIND);
220 /* Add a forward declaration for the struct in the current lexical level */
221 Entry = AddStructSym (Name, 0, 0);
223 /* Skip the curly brace */
226 /* Enter a new lexical level for the struct */
229 /* Parse struct fields */
231 while (curtok != TOK_RCURLY) {
233 /* Get the type of the entry */
235 InitDeclSpec (&Spec);
236 ParseTypeSpec (&Spec, -1);
238 /* Read fields with this type */
241 /* Get type and name of the struct field */
243 ParseDecl (&Spec, &Decl, 0);
245 /* Add a field entry to the table */
246 AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
248 /* Calculate offset of next field/size of the union */
249 Offs = SizeOf (Decl.Type);
250 if (StructType == T_STRUCT) {
258 if (curtok != TOK_COMMA)
265 /* Skip the closing brace */
268 /* Remember the symbol table and leave the struct level */
269 FieldTab = GetSymTab ();
272 /* Make a real entry from the forward decl and return it */
273 return AddStructSym (Name, Size, FieldTab);
278 static void ParseTypeSpec (DeclSpec* D, int Default)
279 /* Parse a type specificier */
285 /* Assume have an explicit type */
286 D->Flags &= ~DS_DEF_TYPE;
288 /* Skip const or volatile modifiers if needed */
289 optional_modifiers ();
291 /* Look at the data type */
302 D->Type[0] = GetDefaultChar();
308 if (curtok == TOK_UNSIGNED) {
311 D->Type[0] = T_ULONG;
323 if (curtok == TOK_UNSIGNED) {
326 D->Type[0] = T_USHORT;
331 D->Type[0] = T_SHORT;
355 D->Type[0] = T_SHORT;
383 D->Type[0] = T_UCHAR;
390 D->Type[0] = T_USHORT;
397 D->Type[0] = T_ULONG;
414 StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
417 if (curtok == TOK_IDENT) {
418 strcpy (Ident, CurTok.Ident);
421 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
423 /* Remember we have an extra type decl */
424 D->Flags |= DS_EXTRA_TYPE;
425 /* Declare the struct in the current scope */
426 Entry = ParseStructDecl (Ident, StructType);
427 /* Encode the struct entry into the type */
428 D->Type[0] = StructType;
429 EncodePtr (D->Type+1, Entry);
430 D->Type[DECODE_SIZE+1] = T_END;
435 if (curtok != TOK_LCURLY) {
437 if (curtok == TOK_IDENT) {
438 /* Find an entry with this name */
439 Entry = FindTagSym (CurTok.Ident);
441 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
442 Error (ERR_SYMBOL_KIND);
445 /* Insert entry into table ### */
447 /* Skip the identifier */
450 Error (ERR_IDENT_EXPECTED);
453 /* Remember we have an extra type decl */
454 D->Flags |= DS_EXTRA_TYPE;
455 /* Parse the enum decl */
462 Entry = FindSym (CurTok.Ident);
463 if (Entry && IsTypeDef (Entry)) {
466 TypeCpy (D->Type, Entry->Type);
473 Error (ERR_TYPE_EXPECTED);
477 D->Flags |= DS_DEF_TYPE;
478 D->Type[0] = (type) Default;
487 static type* ParamTypeCvt (type* T)
488 /* If T is an array, convert it to a pointer else do nothing. Return the
501 static void ParseOldStyleParamList (FuncDesc* F)
502 /* Parse an old style (K&R) parameter list */
505 while (curtok != TOK_RPAREN) {
507 /* List of identifiers expected */
508 if (curtok != TOK_IDENT) {
509 Error (ERR_IDENT_EXPECTED);
512 /* Create a symbol table entry with type int */
513 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
515 /* Count arguments */
518 /* Skip the identifier */
521 /* Check for more parameters */
522 if (curtok == TOK_COMMA) {
529 /* Skip right paren. We must explicitly check for one here, since some of
530 * the breaks above bail out without checking.
534 /* An optional list of type specifications follows */
535 while (curtok != TOK_LCURLY) {
539 /* Read the declaration specifier */
540 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
542 /* We accept only auto and register as storage class specifiers, but
543 * we ignore all this, since we use auto anyway.
545 if ((Spec.StorageClass & SC_AUTO) == 0 &&
546 (Spec.StorageClass & SC_REGISTER) == 0) {
547 Error (ERR_ILLEGAL_STORAGE_CLASS);
550 /* Parse a comma separated variable list */
555 /* Read the parameter */
556 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
557 if (Decl.Ident[0] != '\0') {
559 /* We have a name given. Search for the symbol */
560 SymEntry* Sym = FindLocalSym (Decl.Ident);
562 /* Found it, change the default type to the one given */
563 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
565 Error (ERR_UNKNOWN_IDENT, Decl.Ident);
569 if (curtok == TOK_COMMA) {
577 /* Variable list must be semicolon terminated */
584 static void ParseAnsiParamList (FuncDesc* F)
585 /* Parse a new style (ANSI) parameter list */
588 while (curtok != TOK_RPAREN) {
594 /* Allow an ellipsis as last parameter */
595 if (curtok == TOK_ELLIPSIS) {
597 F->Flags |= FD_ELLIPSIS;
601 /* Read the declaration specifier */
602 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
604 /* We accept only auto and register as storage class specifiers, but
605 * we ignore all this and use auto.
607 if ((Spec.StorageClass & SC_AUTO) == 0 &&
608 (Spec.StorageClass & SC_REGISTER) == 0) {
609 Error (ERR_ILLEGAL_STORAGE_CLASS);
611 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
613 /* Allow parameters without a name, but remember if we had some to
614 * eventually print an error message later.
616 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
617 if (Decl.Ident[0] == '\0') {
619 /* Unnamed symbol. Generate a name that is not user accessible,
620 * then handle the symbol normal.
622 AnonName (Decl.Ident, "param");
623 F->Flags |= FD_UNNAMED_PARAMS;
625 /* Clear defined bit on nonames */
626 Spec.StorageClass &= ~SC_DEF;
629 /* Create a symbol table entry */
630 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
632 /* Count arguments */
635 /* Check for more parameters */
636 if (curtok == TOK_COMMA) {
643 /* Skip right paren. We must explicitly check for one here, since some of
644 * the breaks above bail out without checking.
648 /* Check if this is a function definition */
649 if (curtok == TOK_LCURLY) {
650 /* Print an error if in strict ANSI mode and we have unnamed
653 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
654 Error (ERR_MISSING_PARAM_NAME);
661 static FuncDesc* ParseFuncDecl (void)
662 /* Parse the argument list of a function. */
667 /* Create a new function descriptor */
668 FuncDesc* F = NewFuncDesc ();
670 /* Enter a new lexical level */
671 EnterFunctionLevel ();
673 /* Check for several special parameter lists */
674 if (curtok == TOK_RPAREN) {
675 /* Parameter list is empty */
676 F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
677 } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
678 /* Parameter list declared as void */
680 F->Flags |= FD_VOID_PARAM;
681 } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
682 /* Old style (K&R) function. Assume variable param list. */
683 F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
687 if ((F->Flags & FD_OLDSTYLE) == 0) {
688 /* New style function */
689 ParseAnsiParamList (F);
691 /* Old style function */
692 ParseOldStyleParamList (F);
695 /* Assign offsets. If the function has a variable parameter list,
696 * there's one additional byte (the arg size).
698 Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
699 Sym = GetSymTab()->SymTail;
701 unsigned Size = SizeOf (Sym->Type);
704 F->ParamSize += Size;
708 /* Leave the lexical level remembering the symbol tables */
709 RememberFunctionLevel (F);
711 /* Return the function descriptor */
717 static void Decl (Declaration* D, unsigned Mode)
718 /* Recursively process declarators. Build a type array in reverse order. */
720 if (curtok == TOK_STAR) {
722 /* Allow optional const or volatile modifiers */
723 optional_modifiers ();
727 } else if (curtok == TOK_LPAREN) {
731 } else if (curtok == TOK_FASTCALL) {
732 /* Remember the current type pointer */
734 /* Skip the fastcall token */
736 /* Parse the function */
738 /* Set the fastcall flag */
740 Error (ERR_ILLEGAL_MODIFIER);
742 FuncDesc* F = DecodePtr (T+1);
743 F->Flags |= FD_FASTCALL;
747 /* Things depend on Mode now:
748 * - Mode == DM_NEED_IDENT means:
749 * we *must* have a type and a variable identifer.
750 * - Mode == DM_NO_IDENT means:
751 * we must have a type but no variable identifer
752 * (if there is one, it's not read).
753 * - Mode == DM_ACCEPT_IDENT means:
754 * we *may* have an identifier. If there is an identifier,
755 * it is read, but it is no error, if there is none.
757 if (Mode == DM_NO_IDENT) {
759 } else if (curtok == TOK_IDENT) {
760 strcpy (D->Ident, CurTok.Ident);
763 if (Mode == DM_NEED_IDENT) {
764 Error (ERR_IDENT_EXPECTED);
771 while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
772 if (curtok == TOK_LPAREN) {
773 /* Function declaration */
776 /* Parse the function declaration */
777 F = ParseFuncDecl ();
782 /* Array declaration */
783 unsigned long Size = 0;
785 /* Read the size if it is given */
786 if (curtok != TOK_RBRACK) {
801 /*****************************************************************************/
803 /*****************************************************************************/
807 type* ParseType (type* Type)
808 /* Parse a complete type specification */
813 /* Get a type without a default */
814 InitDeclSpec (&Spec);
815 ParseTypeSpec (&Spec, -1);
817 /* Parse additional declarators */
818 InitDeclaration (&Decl);
819 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
821 /* Copy the type to the target buffer */
822 TypeCpy (Type, Decl.Type);
824 /* Return a pointer to the target buffer */
830 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
831 /* Parse a variable, type or function declaration */
833 /* Initialize the Declaration struct */
836 /* Get additional declarators and the identifier */
839 /* Add the base type. */
840 TypeCpy (D->T, Spec->Type);
842 /* Check the size of the generated type */
843 if (!IsFunc (D->Type) && SizeOf (D->Type) >= 0x10000) {
844 Error (ERR_ILLEGAL_SIZE);
850 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
851 /* Parse a declaration specification */
853 /* Initialize the DeclSpec struct */
856 /* First, get the storage class specifier for this declaration */
857 ParseStorageClass (D, DefStorage);
859 /* Parse the type specifiers */
860 ParseTypeSpec (D, DefType);
865 void CheckEmptyDecl (const DeclSpec* D)
866 /* Called after an empty type declaration (that is, a type declaration without
867 * a variable). Checks if the declaration does really make sense and issues a
871 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
872 Warning (WARN_USELESS_DECL);
878 static void ParseVoidInit (void)
879 /* Parse an initialization of a void variable (special cc65 extension) */
883 /* Allow an arbitrary list of values */
887 switch (lval.e_tptr[0]) {
891 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
892 /* Make it byte sized */
893 lval.e_const &= 0xFF;
904 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
905 /* Make it word sized */
906 lval.e_const &= 0xFFFF;
917 Error (ERR_ILLEGAL_TYPE);
922 if (curtok != TOK_COMMA) {
927 } while (curtok != TOK_RCURLY);
934 static void ParseStructInit (type* Type)
935 /* Parse initialization of a struct or union */
940 /* Consume the opening curly brace */
943 /* Get a pointer to the struct entry from the type */
944 Entry = (SymEntry*) Decode (Type + 1);
946 /* Check if this struct definition has a field table. If it doesn't, it
947 * is an incomplete definition.
949 Tab = Entry->V.S.SymTab;
951 Error (ERR_INIT_INCOMPLETE_TYPE);
952 /* Returning here will cause lots of errors, but recovery is difficult */
956 /* Get a pointer to the list of symbols */
957 Entry = Tab->SymHead;
958 while (curtok != TOK_RCURLY) {
960 Error (ERR_TOO_MANY_INITIALIZERS);
963 ParseInit (Entry->Type);
964 Entry = Entry->NextSym;
965 if (curtok != TOK_COMMA)
970 /* Consume the closing curly brace */
973 /* If there are struct fields left, reserve additional storage */
975 g_zerobytes (SizeOf (Entry->Type));
976 Entry = Entry->NextSym;
984 void ParseInit (type *tptr)
985 /* Parse initialization of variables */
998 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
999 /* Make it byte sized */
1000 lval.e_const &= 0xFF;
1002 assignadjust (tptr, &lval);
1012 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1013 /* Make it word sized */
1014 lval.e_const &= 0xFFFF;
1016 assignadjust (tptr, &lval);
1023 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1024 /* Make it long sized */
1025 lval.e_const &= 0xFFFFFFFF;
1027 assignadjust (tptr, &lval);
1032 sz = Decode (tptr + 1);
1033 t = tptr + DECODE_SIZE + 1;
1034 if ((t [0] == T_CHAR || t [0] == T_UCHAR) && curtok == TOK_SCONST) {
1035 str = GetLiteral (curval);
1036 count = strlen (str) + 1;
1037 TranslateLiteralPool (curval); /* Translate into target charset */
1038 g_defbytes (str, count);
1039 ResetLiteralOffs (curval); /* Remove string from pool */
1044 while (curtok != TOK_RCURLY) {
1045 ParseInit (tptr + DECODE_SIZE + 1);
1047 if (curtok != TOK_COMMA)
1054 Encode (tptr + 1, count);
1055 } else if (count < sz) {
1056 g_zerobytes ((sz - count) * SizeOf (tptr + DECODE_SIZE + 1));
1057 } else if (count > sz) {
1058 Error (ERR_TOO_MANY_INITIALIZERS);
1064 ParseStructInit (tptr);
1069 /* Special cc65 extension in non ANSI mode */
1076 Error (ERR_ILLEGAL_TYPE);