4 * Ullrich von Bassewitz, 20.06.1998
34 /*****************************************************************************/
36 /*****************************************************************************/
40 static void ParseTypeSpec (DeclSpec* D, int Default);
41 /* Parse a type specificier */
45 /*****************************************************************************/
46 /* internal functions */
47 /*****************************************************************************/
51 static type OptionalQualifiers (type Q)
52 /* Read type qualifiers if we have any */
54 while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
59 if (Q & T_QUAL_CONST) {
60 Error (ERR_DUPLICATE_QUALIFIER, "const");
66 if (Q & T_QUAL_VOLATILE) {
67 Error (ERR_DUPLICATE_QUALIFIER, "volatile");
82 /* Return the qualifiers read */
88 static void optionalint (void)
89 /* Eat an optional "int" token */
91 if (curtok == TOK_INT) {
99 static void optionalsigned (void)
100 /* Eat an optional "signed" token */
102 if (curtok == TOK_SIGNED) {
110 static void InitDeclSpec (DeclSpec* D)
111 /* Initialize the DeclSpec struct for use */
120 static void InitDeclaration (Declaration* D)
121 /* Initialize the Declaration struct for use */
130 static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
131 /* Parse a storage class */
133 /* Assume we're using an explicit storage class */
134 D->Flags &= ~DS_DEF_STORAGE;
136 /* Check the storage class given */
140 D->StorageClass = SC_EXTERN | SC_STATIC;
145 D->StorageClass = SC_STATIC;
150 D->StorageClass = SC_REGISTER | SC_STATIC;
155 D->StorageClass = SC_AUTO;
160 D->StorageClass = SC_TYPEDEF;
165 /* No storage class given, use default */
166 D->Flags |= DS_DEF_STORAGE;
167 D->StorageClass = DefStorage;
174 static void ParseEnumDecl (void)
175 /* Process an enum declaration . */
180 /* Accept forward definitions */
181 if (curtok != TOK_LCURLY) {
185 /* Skip the opening curly brace */
188 /* Read the enum tags */
190 while (curtok != TOK_RCURLY) {
192 /* We expect an identifier */
193 if (curtok != TOK_IDENT) {
194 Error (ERR_IDENT_EXPECTED);
198 /* Remember the identifier and skip it */
199 strcpy (Ident, CurTok.Ident);
202 /* Check for an assigned value */
203 if (curtok == TOK_ASSIGN) {
207 EnumVal = lval.e_const;
210 /* Add an entry to the symbol table */
211 AddEnumSym (Ident, EnumVal++);
213 /* Check for end of definition */
214 if (curtok != TOK_COMMA)
223 static SymEntry* ParseStructDecl (const char* Name, type StructType)
224 /* Parse a struct/union declaration. */
233 if (curtok != TOK_LCURLY) {
234 /* Just a forward declaration. Try to find a struct with the given
235 * name. If there is none, insert a forward declaration into the
236 * current lexical level.
238 Entry = FindTagSym (Name);
240 Entry = AddStructSym (Name, 0, 0);
241 } else if (SymIsLocal (Entry) && (Entry->Flags & SC_STRUCT) == 0) {
242 /* Already defined in the level but no struct */
243 Error (ERR_SYMBOL_KIND);
248 /* Add a forward declaration for the struct in the current lexical level */
249 Entry = AddStructSym (Name, 0, 0);
251 /* Skip the curly brace */
254 /* Enter a new lexical level for the struct */
257 /* Parse struct fields */
259 while (curtok != TOK_RCURLY) {
261 /* Get the type of the entry */
263 InitDeclSpec (&Spec);
264 ParseTypeSpec (&Spec, -1);
266 /* Read fields with this type */
269 /* Get type and name of the struct field */
271 ParseDecl (&Spec, &Decl, 0);
273 /* Add a field entry to the table */
274 AddLocalSym (Decl.Ident, Decl.Type, SC_SFLD, (StructType == T_STRUCT)? Size : 0);
276 /* Calculate offset of next field/size of the union */
277 Offs = SizeOf (Decl.Type);
278 if (StructType == T_STRUCT) {
286 if (curtok != TOK_COMMA)
293 /* Skip the closing brace */
296 /* Remember the symbol table and leave the struct level */
297 FieldTab = GetSymTab ();
300 /* Make a real entry from the forward decl and return it */
301 return AddStructSym (Name, Size, FieldTab);
306 static void ParseTypeSpec (DeclSpec* D, int Default)
307 /* Parse a type specificier */
312 type Qualifiers; /* Type qualifiers */
314 /* Assume we have an explicit type */
315 D->Flags &= ~DS_DEF_TYPE;
317 /* Read type qualifiers if we have any */
318 Qualifiers = OptionalQualifiers (T_QUAL_NONE);
320 /* Look at the data type */
331 D->Type[0] = GetDefaultChar();
337 if (curtok == TOK_UNSIGNED) {
340 D->Type[0] = T_ULONG;
352 if (curtok == TOK_UNSIGNED) {
355 D->Type[0] = T_USHORT;
360 D->Type[0] = T_SHORT;
384 D->Type[0] = T_SHORT;
412 D->Type[0] = T_UCHAR;
419 D->Type[0] = T_USHORT;
426 D->Type[0] = T_ULONG;
443 StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
446 if (curtok == TOK_IDENT) {
447 strcpy (Ident, CurTok.Ident);
450 AnonName (Ident, (StructType == T_STRUCT)? "struct" : "union");
452 /* Remember we have an extra type decl */
453 D->Flags |= DS_EXTRA_TYPE;
454 /* Declare the struct in the current scope */
455 Entry = ParseStructDecl (Ident, StructType);
456 /* Encode the struct entry into the type */
457 D->Type[0] = StructType;
458 EncodePtr (D->Type+1, Entry);
459 D->Type[DECODE_SIZE+1] = T_END;
464 if (curtok != TOK_LCURLY) {
466 if (curtok == TOK_IDENT) {
467 /* Find an entry with this name */
468 Entry = FindTagSym (CurTok.Ident);
470 if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) {
471 Error (ERR_SYMBOL_KIND);
474 /* Insert entry into table ### */
476 /* Skip the identifier */
479 Error (ERR_IDENT_EXPECTED);
482 /* Remember we have an extra type decl */
483 D->Flags |= DS_EXTRA_TYPE;
484 /* Parse the enum decl */
491 Entry = FindSym (CurTok.Ident);
492 if (Entry && IsTypeDef (Entry)) {
495 TypeCpy (D->Type, Entry->Type);
502 Error (ERR_TYPE_EXPECTED);
506 D->Flags |= DS_DEF_TYPE;
507 D->Type[0] = (type) Default;
513 /* There may also be qualifiers *after* the initial type */
514 D->Type[0] |= OptionalQualifiers (Qualifiers);
519 static type* ParamTypeCvt (type* T)
520 /* If T is an array, convert it to a pointer else do nothing. Return the
524 if (IsTypeArray (T)) {
533 static void ParseOldStyleParamList (FuncDesc* F)
534 /* Parse an old style (K&R) parameter list */
537 while (curtok != TOK_RPAREN) {
539 /* List of identifiers expected */
540 if (curtok != TOK_IDENT) {
541 Error (ERR_IDENT_EXPECTED);
544 /* Create a symbol table entry with type int */
545 AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF, 0);
547 /* Count arguments */
550 /* Skip the identifier */
553 /* Check for more parameters */
554 if (curtok == TOK_COMMA) {
561 /* Skip right paren. We must explicitly check for one here, since some of
562 * the breaks above bail out without checking.
566 /* An optional list of type specifications follows */
567 while (curtok != TOK_LCURLY) {
571 /* Read the declaration specifier */
572 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
574 /* We accept only auto and register as storage class specifiers, but
575 * we ignore all this, since we use auto anyway.
577 if ((Spec.StorageClass & SC_AUTO) == 0 &&
578 (Spec.StorageClass & SC_REGISTER) == 0) {
579 Error (ERR_ILLEGAL_STORAGE_CLASS);
582 /* Parse a comma separated variable list */
587 /* Read the parameter */
588 ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
589 if (Decl.Ident[0] != '\0') {
591 /* We have a name given. Search for the symbol */
592 SymEntry* Sym = FindLocalSym (Decl.Ident);
594 /* Found it, change the default type to the one given */
595 ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
597 Error (ERR_UNKNOWN_IDENT, Decl.Ident);
601 if (curtok == TOK_COMMA) {
609 /* Variable list must be semicolon terminated */
616 static void ParseAnsiParamList (FuncDesc* F)
617 /* Parse a new style (ANSI) parameter list */
620 while (curtok != TOK_RPAREN) {
626 /* Allow an ellipsis as last parameter */
627 if (curtok == TOK_ELLIPSIS) {
629 F->Flags |= FD_ELLIPSIS;
633 /* Read the declaration specifier */
634 ParseDeclSpec (&Spec, SC_AUTO, T_INT);
636 /* We accept only auto and register as storage class specifiers, but
637 * we ignore all this and use auto.
639 if ((Spec.StorageClass & SC_AUTO) == 0 &&
640 (Spec.StorageClass & SC_REGISTER) == 0) {
641 Error (ERR_ILLEGAL_STORAGE_CLASS);
643 Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF;
645 /* Allow parameters without a name, but remember if we had some to
646 * eventually print an error message later.
648 ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
649 if (Decl.Ident[0] == '\0') {
651 /* Unnamed symbol. Generate a name that is not user accessible,
652 * then handle the symbol normal.
654 AnonName (Decl.Ident, "param");
655 F->Flags |= FD_UNNAMED_PARAMS;
657 /* Clear defined bit on nonames */
658 Spec.StorageClass &= ~SC_DEF;
661 /* Create a symbol table entry */
662 AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Spec.StorageClass, 0);
664 /* Count arguments */
667 /* Check for more parameters */
668 if (curtok == TOK_COMMA) {
675 /* Skip right paren. We must explicitly check for one here, since some of
676 * the breaks above bail out without checking.
680 /* Check if this is a function definition */
681 if (curtok == TOK_LCURLY) {
682 /* Print an error if in strict ANSI mode and we have unnamed
685 if (ANSI && (F->Flags & FD_UNNAMED_PARAMS) != 0) {
686 Error (ERR_MISSING_PARAM_NAME);
693 static FuncDesc* ParseFuncDecl (void)
694 /* Parse the argument list of a function. */
699 /* Create a new function descriptor */
700 FuncDesc* F = NewFuncDesc ();
702 /* Enter a new lexical level */
703 EnterFunctionLevel ();
705 /* Check for several special parameter lists */
706 if (curtok == TOK_RPAREN) {
707 /* Parameter list is empty */
708 F->Flags |= (FD_EMPTY | FD_ELLIPSIS);
709 } else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
710 /* Parameter list declared as void */
712 F->Flags |= FD_VOID_PARAM;
713 } else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
714 /* Old style (K&R) function. Assume variable param list. */
715 F->Flags |= (FD_OLDSTYLE | FD_ELLIPSIS);
719 if ((F->Flags & FD_OLDSTYLE) == 0) {
720 /* New style function */
721 ParseAnsiParamList (F);
723 /* Old style function */
724 ParseOldStyleParamList (F);
727 /* Assign offsets. If the function has a variable parameter list,
728 * there's one additional byte (the arg size).
730 Offs = (F->Flags & FD_ELLIPSIS)? 1 : 0;
731 Sym = GetSymTab()->SymTail;
733 unsigned Size = SizeOf (Sym->Type);
736 F->ParamSize += Size;
740 /* Leave the lexical level remembering the symbol tables */
741 RememberFunctionLevel (F);
743 /* Return the function descriptor */
749 static void Decl (Declaration* D, unsigned Mode)
750 /* Recursively process declarators. Build a type array in reverse order. */
753 if (curtok == TOK_STAR) {
756 /* Allow optional const or volatile qualifiers */
757 T |= OptionalQualifiers (T_QUAL_NONE);
761 } else if (curtok == TOK_LPAREN) {
765 } else if (curtok == TOK_FASTCALL) {
766 /* Remember the current type pointer */
768 /* Skip the fastcall token */
770 /* Parse the function */
772 /* Set the fastcall flag */
773 if (!IsTypeFunc (T)) {
774 Error (ERR_ILLEGAL_MODIFIER);
776 FuncDesc* F = DecodePtr (T+1);
777 F->Flags |= FD_FASTCALL;
781 /* Things depend on Mode now:
782 * - Mode == DM_NEED_IDENT means:
783 * we *must* have a type and a variable identifer.
784 * - Mode == DM_NO_IDENT means:
785 * we must have a type but no variable identifer
786 * (if there is one, it's not read).
787 * - Mode == DM_ACCEPT_IDENT means:
788 * we *may* have an identifier. If there is an identifier,
789 * it is read, but it is no error, if there is none.
791 if (Mode == DM_NO_IDENT) {
793 } else if (curtok == TOK_IDENT) {
794 strcpy (D->Ident, CurTok.Ident);
797 if (Mode == DM_NEED_IDENT) {
798 Error (ERR_IDENT_EXPECTED);
805 while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
806 if (curtok == TOK_LPAREN) {
807 /* Function declaration */
810 /* Parse the function declaration */
811 F = ParseFuncDecl ();
816 /* Array declaration */
817 unsigned long Size = 0;
819 /* Read the size if it is given */
820 if (curtok != TOK_RBRACK) {
835 /*****************************************************************************/
837 /*****************************************************************************/
841 type* ParseType (type* Type)
842 /* Parse a complete type specification */
847 /* Get a type without a default */
848 InitDeclSpec (&Spec);
849 ParseTypeSpec (&Spec, -1);
851 /* Parse additional declarators */
852 InitDeclaration (&Decl);
853 ParseDecl (&Spec, &Decl, DM_NO_IDENT);
855 /* Copy the type to the target buffer */
856 TypeCpy (Type, Decl.Type);
858 /* Return a pointer to the target buffer */
864 void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
865 /* Parse a variable, type or function declaration */
867 /* Initialize the Declaration struct */
870 /* Get additional declarators and the identifier */
873 /* Add the base type. */
874 TypeCpy (D->T, Spec->Type);
876 /* Check the size of the generated type */
877 if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type) && SizeOf (D->Type) >= 0x10000) {
878 Error (ERR_ILLEGAL_SIZE);
884 void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, int DefType)
885 /* Parse a declaration specification */
887 /* Initialize the DeclSpec struct */
890 /* First, get the storage class specifier for this declaration */
891 ParseStorageClass (D, DefStorage);
893 /* Parse the type specifiers */
894 ParseTypeSpec (D, DefType);
899 void CheckEmptyDecl (const DeclSpec* D)
900 /* Called after an empty type declaration (that is, a type declaration without
901 * a variable). Checks if the declaration does really make sense and issues a
905 if ((D->Flags & DS_EXTRA_TYPE) == 0) {
906 Warning (WARN_USELESS_DECL);
912 static void ParseVoidInit (void)
913 /* Parse an initialization of a void variable (special cc65 extension) */
917 /* Allow an arbitrary list of values */
921 switch (lval.e_tptr[0]) {
925 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
926 /* Make it byte sized */
927 lval.e_const &= 0xFF;
938 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
939 /* Make it word sized */
940 lval.e_const &= 0xFFFF;
951 Error (ERR_ILLEGAL_TYPE);
956 if (curtok != TOK_COMMA) {
961 } while (curtok != TOK_RCURLY);
968 static void ParseStructInit (type* Type)
969 /* Parse initialization of a struct or union */
974 /* Consume the opening curly brace */
977 /* Get a pointer to the struct entry from the type */
978 Entry = (SymEntry*) Decode (Type + 1);
980 /* Check if this struct definition has a field table. If it doesn't, it
981 * is an incomplete definition.
983 Tab = Entry->V.S.SymTab;
985 Error (ERR_INIT_INCOMPLETE_TYPE);
986 /* Returning here will cause lots of errors, but recovery is difficult */
990 /* Get a pointer to the list of symbols */
991 Entry = Tab->SymHead;
992 while (curtok != TOK_RCURLY) {
994 Error (ERR_TOO_MANY_INITIALIZERS);
997 ParseInit (Entry->Type);
998 Entry = Entry->NextSym;
999 if (curtok != TOK_COMMA)
1004 /* Consume the closing curly brace */
1007 /* If there are struct fields left, reserve additional storage */
1009 g_zerobytes (SizeOf (Entry->Type));
1010 Entry = Entry->NextSym;
1016 void ParseInit (type* T)
1017 /* Parse initialization of variables. */
1025 switch (UnqualifiedType (*T)) {
1030 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1031 /* Make it byte sized */
1032 lval.e_const &= 0xFF;
1034 assignadjust (T, &lval);
1044 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1045 /* Make it word sized */
1046 lval.e_const &= 0xFFFF;
1048 assignadjust (T, &lval);
1055 if ((lval.e_flags & E_MCTYPE) == E_TCONST) {
1056 /* Make it long sized */
1057 lval.e_const &= 0xFFFFFFFF;
1059 assignadjust (T, &lval);
1064 sz = Decode (T + 1);
1065 t = T + DECODE_SIZE + 1;
1066 if (IsTypeChar(t) && curtok == TOK_SCONST) {
1067 str = GetLiteral (curval);
1068 count = strlen (str) + 1;
1069 TranslateLiteralPool (curval); /* Translate into target charset */
1070 g_defbytes (str, count);
1071 ResetLiteralOffs (curval); /* Remove string from pool */
1076 while (curtok != TOK_RCURLY) {
1077 ParseInit (T + DECODE_SIZE + 1);
1079 if (curtok != TOK_COMMA)
1086 Encode (T + 1, count);
1087 } else if (count < sz) {
1088 g_zerobytes ((sz - count) * SizeOf (T + DECODE_SIZE + 1));
1089 } else if (count > sz) {
1090 Error (ERR_TOO_MANY_INITIALIZERS);
1096 ParseStructInit (T);
1101 /* Special cc65 extension in non ANSI mode */
1108 Error (ERR_ILLEGAL_TYPE);