4 * Ullrich von Bassewitz, 20.06.1998
35 /*****************************************************************************/
37 /*****************************************************************************/
41 static void ParseTypeSpec (DeclSpec* D, int Default);
42 /* Parse a type specificier */
46 /*****************************************************************************/
47 /* internal functions */
48 /*****************************************************************************/
52 static type OptionalQualifiers (type Q)
53 /* Read type qualifiers if we have any */
55 while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
60 if (Q & T_QUAL_CONST) {
61 Error (ERR_DUPLICATE_QUALIFIER, "const");
67 if (Q & T_QUAL_VOLATILE) {
68 Error (ERR_DUPLICATE_QUALIFIER, "volatile");
83 /* Return the qualifiers read */
89 static void optionalint (void)
90 /* Eat an optional "int" token */
92 if (curtok == TOK_INT) {
100 static void optionalsigned (void)
101 /* Eat an optional "signed" token */
103 if (curtok == TOK_SIGNED) {
111 static void InitDeclSpec (DeclSpec* D)
112 /* Initialize the DeclSpec struct for use */
121 static void InitDeclaration (Declaration* D)
122 /* Initialize the Declaration struct for use */
131 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
132 /* Parse a storage class */
134 /* Assume we're using an explicit storage class */
135 D->Flags &= ~DS_DEF_STORAGE;
137 /* Check the storage class given */
141 D->StorageClass = SC_EXTERN | SC_STATIC;
146 D->StorageClass = SC_STATIC;
151 D->StorageClass = SC_REGISTER | SC_STATIC;
156 D->StorageClass = SC_AUTO;
161 D->StorageClass = SC_TYPEDEF;
166 /* No storage class given, use default */
167 D->Flags |= DS_DEF_STORAGE;
168 D->StorageClass = DefStorage;
175 static void ParseEnumDecl (void)
176 /* Process an enum declaration . */
181 /* Accept forward definitions */
182 if (curtok != TOK_LCURLY) {
186 /* Skip the opening curly brace */
189 /* Read the enum tags */
191 while (curtok != TOK_RCURLY) {
193 /* We expect an identifier */
194 if (curtok != TOK_IDENT) {
195 Error (ERR_IDENT_EXPECTED);
199 /* Remember the identifier and skip it */
200 strcpy (Ident, CurTok.Ident);
203 /* Check for an assigned value */
204 if (curtok == TOK_ASSIGN) {
208 EnumVal = lval.e_const;
211 /* Add an entry to the symbol table */
212 AddEnumSym (Ident, EnumVal++);
214 /* Check for end of definition */
215 if (curtok != TOK_COMMA)
224 static SymEntry* ParseStructDecl (const char* Name, type StructType)
225 /* Parse a struct/union declaration. */
234 if (curtok != TOK_LCURLY) {
235 /* Just a forward declaration. Try to find a struct with the given
236 * name. If there is none, insert a forward declaration into the
237 * current lexical level.
239 Entry = FindTagSym (Name);
241 Entry = AddStructSym (Name, 0, 0);
242 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
243 /* Already defined in the level but no struct */
244 Error (ERR_SYMBOL_KIND);
249 /* Add a forward declaration for the struct in the current lexical level */
250 Entry = AddStructSym (Name, 0, 0);
252 /* Skip the curly brace */
255 /* Enter a new lexical level for the struct */
258 /* Parse struct fields */
260 while (curtok != TOK_RCURLY) {
262 /* Get the type of the entry */
264 InitDeclSpec (&Spec);
265 ParseTypeSpec (&Spec, -1);
267 /* Read fields with this type */
270 /* Get type and name of the struct field */
272 ParseDecl (&Spec, &Decl, 0);
274 /* Add a field entry to the table */
275 AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
277 /* Calculate offset of next field/size of the union */
278 Offs = SizeOf (Decl.Type);
279 if (StructType == T_STRUCT) {
287 if (curtok != TOK_COMMA)
294 /* Skip the closing brace */
297 /* Remember the symbol table and leave the struct level */
298 FieldTab = GetSymTab ();
301 /* Make a real entry from the forward decl and return it */
302 return AddStructSym (Name, Size, FieldTab);
307 static void ParseTypeSpec (DeclSpec* D, int Default)
308 /* Parse a type specificier */
313 type Qualifiers; /* Type qualifiers */
315 /* Assume we have an explicit type */
316 D->Flags &= ~DS_DEF_TYPE;
318 /* Read type qualifiers if we have any */
319 Qualifiers = OptionalQualifiers (T_QUAL_NONE);
321 /* Look at the data type */
332 D->Type[0] = GetDefaultChar();
338 if (curtok == TOK_UNSIGNED) {
341 D->Type[0] = T_ULONG;
353 if (curtok == TOK_UNSIGNED) {
356 D->Type[0] = T_USHORT;
361 D->Type[0] = T_SHORT;
385 D->Type[0] = T_SHORT;
413 D->Type[0] = T_UCHAR;
420 D->Type[0] = T_USHORT;
427 D->Type[0] = T_ULONG;
444 StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
447 if (curtok == TOK_IDENT) {
448 strcpy (Ident, CurTok.Ident);
451 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
453 /* Remember we have an extra type decl */
454 D->Flags |= DS_EXTRA_TYPE;
455 /* Declare the struct in the current scope */
456 Entry = ParseStructDecl (Ident, StructType);
457 /* Encode the struct entry into the type */
458 D->Type[0] = StructType;
459 EncodePtr (D->Type+1, Entry);
460 D->Type[DECODE_SIZE+1] = T_END;
465 if (curtok != TOK_LCURLY) {
467 if (curtok == TOK_IDENT) {
468 /* Find an entry with this name */
469 Entry = FindTagSym (CurTok.Ident);
471 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
472 Error (ERR_SYMBOL_KIND);
475 /* Insert entry into table ### */
477 /* Skip the identifier */
480 Error (ERR_IDENT_EXPECTED);
483 /* Remember we have an extra type decl */
484 D->Flags |= DS_EXTRA_TYPE;
485 /* Parse the enum decl */
492 Entry = FindSym (CurTok.Ident);
493 if (Entry && IsTypeDef (Entry)) {
496 TypeCpy (D->Type, Entry->Type);
503 Error (ERR_TYPE_EXPECTED);
507 D->Flags |= DS_DEF_TYPE;
508 D->Type[0] = (type) Default;
514 /* There may also be qualifiers *after* the initial type */
515 D->Type[0] |= OptionalQualifiers (Qualifiers);
520 static type* ParamTypeCvt (type* T)
521 /* If T is an array, convert it to a pointer else do nothing. Return the
525 if (IsTypeArray (T)) {
534 static void ParseOldStyleParamList (FuncDesc* F)
535 /* Parse an old style (K&R) parameter list */
538 while (curtok != TOK_RPAREN) {
540 /* List of identifiers expected */
541 if (curtok != TOK_IDENT) {
542 Error (ERR_IDENT_EXPECTED);
545 /* Create a symbol table entry with type int */
546 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
548 /* Count arguments */
551 /* Skip the identifier */
554 /* Check for more parameters */
555 if (curtok == TOK_COMMA) {
562 /* Skip right paren. We must explicitly check for one here, since some of
563 * the breaks above bail out without checking.
567 /* An optional list of type specifications follows */
568 while (curtok != TOK_LCURLY) {
572 /* Read the declaration specifier */
573 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
575 /* We accept only auto and register as storage class specifiers, but
576 * we ignore all this, since we use auto anyway.
578 if ((Spec.StorageClass & SC_AUTO) == 0 &&
579 (Spec.StorageClass & SC_REGISTER) == 0) {
580 Error (ERR_ILLEGAL_STORAGE_CLASS);
583 /* Parse a comma separated variable list */
588 /* Read the parameter */
589 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
590 if (Decl.Ident[0] != '\0') {
592 /* We have a name given. Search for the symbol */
593 SymEntry* Sym = FindLocalSym (Decl.Ident);
595 /* Found it, change the default type to the one given */
596 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
598 Error (ERR_UNKNOWN_IDENT, Decl.Ident);
602 if (curtok == TOK_COMMA) {
610 /* Variable list must be semicolon terminated */
617 static void ParseAnsiParamList (FuncDesc* F)
618 /* Parse a new style (ANSI) parameter list */
621 while (curtok != TOK_RPAREN) {
627 /* Allow an ellipsis as last parameter */
628 if (curtok == TOK_ELLIPSIS) {
630 F->Flags |= FD_ELLIPSIS;
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 and use auto.
640 if ((Spec.StorageClass & SC_AUTO) == 0 &&
641 (Spec.StorageClass & SC_REGISTER) == 0) {
642 Error (ERR_ILLEGAL_STORAGE_CLASS);
644 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
646 /* Allow parameters without a name, but remember if we had some to
647 * eventually print an error message later.
649 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
650 if (Decl.Ident[0] == '\0') {
652 /* Unnamed symbol. Generate a name that is not user accessible,
653 * then handle the symbol normal.
655 AnonName (Decl.Ident, "param");
656 F->Flags |= FD_UNNAMED_PARAMS;
658 /* Clear defined bit on nonames */
659 Spec.StorageClass &= ~SC_DEF;
662 /* Parse an attribute */
663 ParseAttribute (&Decl, &Attr);
665 /* Create a symbol table entry */
666 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
668 /* Count arguments */
671 /* Check for more parameters */
672 if (curtok == TOK_COMMA) {
679 /* Skip right paren. We must explicitly check for one here, since some of
680 * the breaks above bail out without checking.
684 /* Check if this is a function definition */
685 if (curtok == TOK_LCURLY) {
686 /* Print an error if in strict ANSI mode and we have unnamed
689 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
690 Error (ERR_MISSING_PARAM_NAME);
697 static FuncDesc* ParseFuncDecl (void)
698 /* Parse the argument list of a function. */
703 /* Create a new function descriptor */
704 FuncDesc* F = NewFuncDesc ();
706 /* Enter a new lexical level */
707 EnterFunctionLevel ();
709 /* Check for several special parameter lists */
710 if (curtok == TOK_RPAREN) {
711 /* Parameter list is empty */
712 F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
713 } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
714 /* Parameter list declared as void */
716 F->Flags |= FD_VOID_PARAM;
717 } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
718 /* Old style (K&R) function. Assume variable param list. */
719 F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
723 if ((F->Flags & FD_OLDSTYLE) == 0) {
724 /* New style function */
725 ParseAnsiParamList (F);
727 /* Old style function */
728 ParseOldStyleParamList (F);
731 /* Assign offsets. If the function has a variable parameter list,
732 * there's one additional byte (the arg size).
734 Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
735 Sym = GetSymTab()->SymTail;
737 unsigned Size = SizeOf (Sym->Type);
740 F->ParamSize += Size;
744 /* Leave the lexical level remembering the symbol tables */
745 RememberFunctionLevel (F);
747 /* Return the function descriptor */
753 static void Decl (Declaration* D, unsigned Mode)
754 /* Recursively process declarators. Build a type array in reverse order. */
757 if (curtok == TOK_STAR) {
760 /* Allow optional const or volatile qualifiers */
761 T |= OptionalQualifiers (T_QUAL_NONE);
765 } else if (curtok == TOK_LPAREN) {
769 } else if (curtok == TOK_FASTCALL) {
770 /* Remember the current type pointer */
772 /* Skip the fastcall token */
774 /* Parse the function */
776 /* Set the fastcall flag */
777 if (!IsTypeFunc (T)) {
778 Error (ERR_ILLEGAL_MODIFIER);
780 FuncDesc* F = DecodePtr (T+1);
781 F->Flags |= FD_FASTCALL;
785 /* Things depend on Mode now:
786 * - Mode == DM_NEED_IDENT means:
787 * we *must* have a type and a variable identifer.
788 * - Mode == DM_NO_IDENT means:
789 * we must have a type but no variable identifer
790 * (if there is one, it's not read).
791 * - Mode == DM_ACCEPT_IDENT means:
792 * we *may* have an identifier. If there is an identifier,
793 * it is read, but it is no error, if there is none.
795 if (Mode == DM_NO_IDENT) {
797 } else if (curtok == TOK_IDENT) {
798 strcpy (D->Ident, CurTok.Ident);
801 if (Mode == DM_NEED_IDENT) {
802 Error (ERR_IDENT_EXPECTED);
809 while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
810 if (curtok == TOK_LPAREN) {
811 /* Function declaration */
814 /* Parse the function declaration */
815 F = ParseFuncDecl ();
820 /* Array declaration */
821 unsigned long Size = 0;
823 /* Read the size if it is given */
824 if (curtok != TOK_RBRACK) {
839 /*****************************************************************************/
841 /*****************************************************************************/
845 type* ParseType (type* Type)
846 /* Parse a complete type specification */
851 /* Get a type without a default */
852 InitDeclSpec (&Spec);
853 ParseTypeSpec (&Spec, -1);
855 /* Parse additional declarators */
856 InitDeclaration (&Decl);
857 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
859 /* Copy the type to the target buffer */
860 TypeCpy (Type, Decl.Type);
862 /* Return a pointer to the target buffer */
868 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
869 /* Parse a variable, type or function declaration */
871 /* Initialize the Declaration struct */
874 /* Get additional declarators and the identifier */
877 /* Add the base type. */
878 TypeCpy (D->T, Spec->Type);
880 /* Check the size of the generated type */
881 if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
882 Error (ERR_ILLEGAL_SIZE);
888 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
889 /* Parse a declaration specification */
891 /* Initialize the DeclSpec struct */
894 /* First, get the storage class specifier for this declaration */
895 ParseStorageClass (D, DefStorage);
897 /* Parse the type specifiers */
898 ParseTypeSpec (D, DefType);
903 void CheckEmptyDecl (const DeclSpec* D)
904 /* Called after an empty type declaration (that is, a type declaration without
905 * a variable). Checks if the declaration does really make sense and issues a
909 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
910 Warning (WARN_USELESS_DECL);
916 static void ParseVoidInit (void)
917 /* Parse an initialization of a void variable (special cc65 extension) */
921 /* Allow an arbitrary list of values */
925 switch (lval.e_tptr[0]) {
929 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
930 /* Make it byte sized */
931 lval.e_const &= 0xFF;
942 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
943 /* Make it word sized */
944 lval.e_const &= 0xFFFF;
955 Error (ERR_ILLEGAL_TYPE);
960 if (curtok != TOK_COMMA) {
965 } while (curtok != TOK_RCURLY);
972 static void ParseStructInit (type* Type)
973 /* Parse initialization of a struct or union */
978 /* Consume the opening curly brace */
981 /* Get a pointer to the struct entry from the type */
982 Entry = (SymEntry*) Decode (Type + 1);
984 /* Check if this struct definition has a field table. If it doesn't, it
985 * is an incomplete definition.
987 Tab = Entry->V.S.SymTab;
989 Error (ERR_INIT_INCOMPLETE_TYPE);
990 /* Returning here will cause lots of errors, but recovery is difficult */
994 /* Get a pointer to the list of symbols */
995 Entry = Tab->SymHead;
996 while (curtok != TOK_RCURLY) {
998 Error (ERR_TOO_MANY_INITIALIZERS);
1001 ParseInit (Entry->Type);
1002 Entry = Entry->NextSym;
1003 if (curtok != TOK_COMMA)
1008 /* Consume the closing curly brace */
1011 /* If there are struct fields left, reserve additional storage */
1013 g_zerobytes (SizeOf (Entry->Type));
1014 Entry = Entry->NextSym;
1020 void ParseInit (type* T)
1021 /* Parse initialization of variables. */
1029 switch (UnqualifiedType (*T)) {
1034 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1035 /* Make it byte sized */
1036 lval.e_const &= 0xFF;
1038 assignadjust (T, &lval);
1048 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1049 /* Make it word sized */
1050 lval.e_const &= 0xFFFF;
1052 assignadjust (T, &lval);
1059 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1060 /* Make it long sized */
1061 lval.e_const &= 0xFFFFFFFF;
1063 assignadjust (T, &lval);
1068 sz = Decode (T + 1);
1069 t = T + DECODE_SIZE + 1;
1070 if (IsTypeChar(t) && curtok == TOK_SCONST) {
1071 str = GetLiteral (curval);
1072 count = strlen (str) + 1;
1073 TranslateLiteralPool (curval); /* Translate into target charset */
1074 g_defbytes (str, count);
1075 ResetLiteralOffs (curval); /* Remove string from pool */
1080 while (curtok != TOK_RCURLY) {
1081 ParseInit (T + DECODE_SIZE + 1);
1083 if (curtok != TOK_COMMA)
1090 Encode (T + 1, count);
1091 } else if (count < sz) {
1092 g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
1093 } else if (count > sz) {
1094 Error (ERR_TOO_MANY_INITIALIZERS);
1100 ParseStructInit (T);
1105 /* Special cc65 extension in non ANSI mode */
1112 Error (ERR_ILLEGAL_TYPE);